diff --git a/docs/Project.toml b/docs/Project.toml index 488971847..1a05eeaf1 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -2,6 +2,7 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DelaunayTriangulation = "927a84f5-c5f4-47a5-9785-b46e178433df" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DocumenterTools = "35a29f4d-8980-5a13-9543-d66fff28ecb8" ElasticArrays = "fdbdab4c-e67f-52f5-8c3f-e7b388dad3d4" diff --git a/docs/liveserver.jl b/docs/liveserver.jl index 3761df289..d27f7ef32 100644 --- a/docs/liveserver.jl +++ b/docs/liveserver.jl @@ -5,12 +5,13 @@ Pkg.instantiate() import LiveServer withenv("LIVESERVER_ACTIVE" => "true") do LiveServer.servedocs(; - launch_browser=true, - foldername=joinpath(repo_root, "docs"), - include_dirs=[joinpath(repo_root, "src")], - skip_dirs=[joinpath(repo_root, "docs/src/tutorials"), + launch_browser = true, + foldername = joinpath(repo_root, "docs"), + include_dirs = [joinpath(repo_root, "src")], + skip_dirs = [ + joinpath(repo_root, "docs/src/tutorials"), joinpath(repo_root, "docs/src/applications"), joinpath(repo_root, "docs/src/figures"), ], ) -end \ No newline at end of file +end diff --git a/docs/make.jl b/docs/make.jl index 9b6e568db..16a9a92bd 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,8 +4,10 @@ using Literate using Test using Dates -DocMeta.setdocmeta!(DelaunayTriangulation, :DocTestSetup, :(using DelaunayTriangulation, Test); - recursive=true) +DocMeta.setdocmeta!( + DelaunayTriangulation, :DocTestSetup, :(using DelaunayTriangulation, Test); + recursive = true, +) const IS_LIVESERVER = false && get(ENV, "LIVESERVER_ACTIVE", "false") == "true" if IS_LIVESERVER @@ -41,7 +43,7 @@ function add_just_the_code_section(dir, file) file_name, file_ext = splitext(file) file_path = joinpath(dir, file) new_file_path = joinpath(session_tmp, file_name * "_just_the_code" * file_ext) - cp(file_path, new_file_path, force=true) + cp(file_path, new_file_path, force = true) folder = splitpath(dir)[end] # literate_tutorials or literate_applications open(new_file_path, "a") do io write(io, "\n") @@ -74,7 +76,7 @@ for folder in ("tutorials", "applications") # end #end new_file_path = add_just_the_code_section(dir, file) - script = Literate.script(file_path, session_tmp, name=splitext(file)[1] * "_just_the_code_cleaned") + script = Literate.script(file_path, session_tmp, name = splitext(file)[1] * "_just_the_code_cleaned") code = strip(read(script, String)) @info "[$(ct())] Processing $file: Converting markdown script" line_ending_symbol = occursin(code, "\r\n") ? "\r\n" : "\n" @@ -86,12 +88,12 @@ for folder in ("tutorials", "applications") Literate.markdown( new_file_path, outputdir; - documenter=true, - postprocess=editurl_update ∘ post_strip, - credit=true, - name=splitext(file)[1], - execute=false, - flavor=Literate.DocumenterFlavor(), + documenter = true, + postprocess = editurl_update ∘ post_strip, + credit = true, + name = splitext(file)[1], + execute = false, + flavor = Literate.DocumenterFlavor(), ) end end @@ -127,7 +129,7 @@ const _PAGES = [ "Voronoi Tessellations" => "tutorials/voronoi.md", "Clipped Voronoi Tessellations" => [ "Clipping to the Convex Hull" => "tutorials/clipped.md", - "Clipping to a Rectangle" => "tutorials/clipped_rectangle.md" + "Clipping to a Rectangle" => "tutorials/clipped_rectangle.md", ], "Centroidal Voronoi Tessellations" => "tutorials/centroidal.md", "Point Location" => "tutorials/point_location.md", @@ -135,7 +137,7 @@ const _PAGES = [ "Convex Hulls" => "tutorials/convex_hull.md", "Pole of Inaccessibility" => "tutorials/pole_of_inaccessibility.md", "Point-in-Polygon Testing" => "tutorials/point_in_polygon.md", - "Using Custom Structs for Primitives and Boundaries" => "tutorials/custom_primitive.md" + "Using Custom Structs for Primitives and Boundaries" => "tutorials/custom_primitive.md", ], "Manual" => [ "Overview" => "manual/overview.md", @@ -168,7 +170,7 @@ const _PAGES = [ "Data Structures" => "extended/data_structures.md", "Algorithm Internals" => "extended/algorithms.md", "Utility Functions" => "extended/utils.md", - ], + ], "Mathematical Details" => [ "Overview" => "math/overview.md", "Delaunay Triangulations" => "math/delaunay.md", @@ -221,34 +223,38 @@ end # Make and deploy makedocs(; - modules=[DelaunayTriangulation], - authors="Daniel VandenHeuvel ", - sitename="DelaunayTriangulation.jl", - format=Documenter.HTML(; - prettyurls=IS_CI, - canonical="https://JuliaGeometry.github.io/DelaunayTriangulation.jl", - edit_link="main", - size_threshold=8000 * 2^10, - size_threshold_warn=1000 * 2^10, - size_threshold_ignore=["api/triangulation.md", "extended/data_structures.md"], - collapselevel=1, - assets=String[], - mathengine=MathJax3(Dict( - :loader => Dict("load" => ["[tex]/physics"]), - :tex => Dict( - "inlineMath" => [["\$", "\$"], ["\\(", "\\)"]], - "tags" => "ams", - "packages" => ["base", "ams", "autoload", "physics"], + modules = [DelaunayTriangulation], + authors = "Daniel VandenHeuvel ", + sitename = "DelaunayTriangulation.jl", + format = Documenter.HTML(; + prettyurls = IS_CI, + canonical = "https://JuliaGeometry.github.io/DelaunayTriangulation.jl", + edit_link = "main", + size_threshold = 8000 * 2^10, + size_threshold_warn = 1000 * 2^10, + size_threshold_ignore = ["api/triangulation.md", "extended/data_structures.md"], + collapselevel = 1, + assets = String[], + mathengine = MathJax3( + Dict( + :loader => Dict("load" => ["[tex]/physics"]), + :tex => Dict( + "inlineMath" => [["\$", "\$"], ["\\(", "\\)"]], + "tags" => "ams", + "packages" => ["base", "ams", "autoload", "physics"], + ), ), - ))), - linkcheck=false, - warnonly=true, - draft=IS_LIVESERVER, - pages=_PAGES, - pagesonly=true, + ), + ), + linkcheck = false, + warnonly = true, + draft = IS_LIVESERVER, + pages = _PAGES, + pagesonly = true, ) deploydocs(; - repo="github.com/JuliaGeometry/DelaunayTriangulation.jl", - devbranch="main", - push_preview=true) + repo = "github.com/JuliaGeometry/DelaunayTriangulation.jl", + devbranch = "main", + push_preview = true, +) diff --git a/docs/src/api/triangulation.md b/docs/src/api/triangulation.md index 2896d9f61..c9eeab83f 100644 --- a/docs/src/api/triangulation.md +++ b/docs/src/api/triangulation.md @@ -45,7 +45,6 @@ get_section_index map_ghost_vertex get_ghost_vertex_range all_ghost_vertices -get_point num_points get_representative_point_coordinates compute_representative_points! diff --git a/docs/src/applications/cell_simulations.md b/docs/src/applications/cell_simulations.md index b5385a9d4..931b5af34 100644 --- a/docs/src/applications/cell_simulations.md +++ b/docs/src/applications/cell_simulations.md @@ -54,7 +54,7 @@ using StatsBase using CairoMakie Base.@kwdef mutable struct CellModel{P} tri::Triangulation{P} - new_r_cache::Vector{NTuple{2,Float64}} # for r(t + Δt) + new_r_cache::Vector{NTuple{2, Float64}} # for r(t + Δt) α::Float64 s::Float64 Δt::Float64 @@ -103,7 +103,7 @@ function polygon_area(points) # this is the same function from the Interpolation rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -113,7 +113,7 @@ function polygon_area(points) # this is the same function from the Interpolation return area / 2 end function get_voronoi_area(tri::Triangulation, i) - points = NTuple{2,Float64}[] + points = NTuple{2, Float64}[] !DelaunayTriangulation.has_vertex(tri, i) && return (0.0, points) # might not be included anymore due to retriangulation DelaunayTriangulation.is_boundary_node(tri, i)[1] && return (0.0, points) # to prevent boundary cells from proliferating N = get_neighbours(tri, i) @@ -157,7 +157,7 @@ function proliferate_cells!(cells::CellModel) δ = DelaunayTriangulation.distance_to_polygon(p, get_points(tri), poly) s, c = sincos(θ) q = p .+ (δ * cells.ϵ) .* (c, s) - add_point!(tri, q; rng=cells.rng) + add_point!(tri, q; rng = cells.rng) push!(cells.new_r_cache, q) end return nothing @@ -174,7 +174,7 @@ function perform_step!(cells::CellModel) end function simulate_cells(cells::CellModel) t = 0.0 - all_points = Vector{Vector{NTuple{2,Float64}}}() + all_points = Vector{Vector{NTuple{2, Float64}}}() push!(all_points, deepcopy(get_points(cells.tri))) while t < cells.final_time perform_step!(cells) @@ -194,23 +194,27 @@ $\beta = 0.25$, $K = 100^2$, and $\epsilon = 0.5$. rng = StableRNG(123444) a, b, c, d = -2.0, 2.0, -5.0, 5.0 points = [(a + (b - a) * rand(rng), c + (d - c) * rand(rng)) for _ in 1:10] -tri = triangulate(points; rng=rng) -cells = CellModel(; tri=tri, new_r_cache=similar(points), α=5.0, s=2.0, Δt=1e-3, - β=0.25, K=100.0^2, rng, final_time=25.0, ϵ=0.5) +tri = triangulate(points; rng = rng) +cells = CellModel(; + tri = tri, new_r_cache = similar(points), α = 5.0, s = 2.0, Δt = 1.0e-3, + β = 0.25, K = 100.0^2, rng, final_time = 25.0, ϵ = 0.5, +) results = simulate_cells(cells); -fig = Figure(fontsize=26) +fig = Figure(fontsize = 26) title_obs = Observable(L"t = %$(0.0)") -ax1 = Axis(fig[1, 1], width=1200, height=400, title=title_obs, titlealign=:left) +ax1 = Axis(fig[1, 1], width = 1200, height = 400, title = title_obs, titlealign = :left) Δt = cells.Δt i = Observable(1) -voronoiplot!(ax1, @lift(voronoi(triangulate(results[$i]; rng), clip=true, rng=rng)), - color=:darkgreen, strokecolor=:black, strokewidth=2, show_generators=false) +voronoiplot!( + ax1, @lift(voronoi(triangulate(results[$i]; rng), clip = true, rng = rng)), + color = :darkgreen, strokecolor = :black, strokewidth = 2, show_generators = false, +) xlims!(ax1, -12, 12) ylims!(ax1, -12, 12) resize_to_layout!(fig) t = 0:Δt:cells.final_time -record(fig, "cell_simulation.mp4", 1:10:length(t); framerate=60) do ii +record(fig, "cell_simulation.mp4", 1:10:length(t); framerate = 60) do ii i[] = ii title_obs[] = L"t = %$(((ii-1) * Δt))" end; @@ -231,7 +235,7 @@ using StatsBase using CairoMakie Base.@kwdef mutable struct CellModel{P} tri::Triangulation{P} - new_r_cache::Vector{NTuple{2,Float64}} # for r(t + Δt) + new_r_cache::Vector{NTuple{2, Float64}} # for r(t + Δt) α::Float64 s::Float64 Δt::Float64 @@ -270,7 +274,7 @@ function polygon_area(points) # this is the same function from the Interpolation rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -280,7 +284,7 @@ function polygon_area(points) # this is the same function from the Interpolation return area / 2 end function get_voronoi_area(tri::Triangulation, i) - points = NTuple{2,Float64}[] + points = NTuple{2, Float64}[] !DelaunayTriangulation.has_vertex(tri, i) && return (0.0, points) # might not be included anymore due to retriangulation DelaunayTriangulation.is_boundary_node(tri, i)[1] && return (0.0, points) # to prevent boundary cells from proliferating N = get_neighbours(tri, i) @@ -319,7 +323,7 @@ function proliferate_cells!(cells::CellModel) δ = DelaunayTriangulation.distance_to_polygon(p, get_points(tri), poly) s, c = sincos(θ) q = p .+ (δ * cells.ϵ) .* (c, s) - add_point!(tri, q; rng=cells.rng) + add_point!(tri, q; rng = cells.rng) push!(cells.new_r_cache, q) end return nothing @@ -332,7 +336,7 @@ function perform_step!(cells::CellModel) end function simulate_cells(cells::CellModel) t = 0.0 - all_points = Vector{Vector{NTuple{2,Float64}}}() + all_points = Vector{Vector{NTuple{2, Float64}}}() push!(all_points, deepcopy(get_points(cells.tri))) while t < cells.final_time perform_step!(cells) @@ -345,23 +349,27 @@ end rng = StableRNG(123444) a, b, c, d = -2.0, 2.0, -5.0, 5.0 points = [(a + (b - a) * rand(rng), c + (d - c) * rand(rng)) for _ in 1:10] -tri = triangulate(points; rng=rng) -cells = CellModel(; tri=tri, new_r_cache=similar(points), α=5.0, s=2.0, Δt=1e-3, - β=0.25, K=100.0^2, rng, final_time=25.0, ϵ=0.5) +tri = triangulate(points; rng = rng) +cells = CellModel(; + tri = tri, new_r_cache = similar(points), α = 5.0, s = 2.0, Δt = 1.0e-3, + β = 0.25, K = 100.0^2, rng, final_time = 25.0, ϵ = 0.5, +) results = simulate_cells(cells); -fig = Figure(fontsize=26) +fig = Figure(fontsize = 26) title_obs = Observable(L"t = %$(0.0)") -ax1 = Axis(fig[1, 1], width=1200, height=400, title=title_obs, titlealign=:left) +ax1 = Axis(fig[1, 1], width = 1200, height = 400, title = title_obs, titlealign = :left) Δt = cells.Δt i = Observable(1) -voronoiplot!(ax1, @lift(voronoi(triangulate(results[$i]; rng), clip=true, rng=rng)), - color=:darkgreen, strokecolor=:black, strokewidth=2, show_generators=false) +voronoiplot!( + ax1, @lift(voronoi(triangulate(results[$i]; rng), clip = true, rng = rng)), + color = :darkgreen, strokecolor = :black, strokewidth = 2, show_generators = false, +) xlims!(ax1, -12, 12) ylims!(ax1, -12, 12) resize_to_layout!(fig) t = 0:Δt:cells.final_time -record(fig, "cell_simulation.mp4", 1:10:length(t); framerate=60) do ii +record(fig, "cell_simulation.mp4", 1:10:length(t); framerate = 60) do ii i[] = ii title_obs[] = L"t = %$(((ii-1) * Δt))" end; diff --git a/docs/src/applications/interpolation.md b/docs/src/applications/interpolation.md index 3cbef179f..4bb64bf21 100644 --- a/docs/src/applications/interpolation.md +++ b/docs/src/applications/interpolation.md @@ -26,29 +26,29 @@ using CairoMakie #hide A, B, C, D, E, F, G, H = (0.3, 1.1), (-0.1, 0.8), (0.2, 0.3), (0.6, 0.2), (0.8, 0.8), (0.3, 0.9), (0.5503600264347, 0.6814266789918), (1.1, 0.5) #hide G2 = (0.5496217775447, 0.7146478790414) #hide fig = Figure() #hide -ax = Axis(fig[1, 1], width=400, height=400, title="Original") #hide +ax = Axis(fig[1, 1], width = 400, height = 400, title = "Original") #hide xlims!(ax, -0.2, 1.3) #hide ylims!(ax, 0.1, 1.2) #hide points = [A, B, C, D, E, F, G, H] #hide -triplot!(ax, points, show_points=true) #hide -scatter!(ax, [G], color=:red, markersize=14) #hide +triplot!(ax, points, show_points = true) #hide +scatter!(ax, [G], color = :red, markersize = 14) #hide hidedecorations!(ax) #hide -ax2 = Axis(fig[2, 1], width=400, height=400) #hide -voronoiplot!(ax2, points, clip=(-0.2, 1.3, 0.1, 1.2)) #hide +ax2 = Axis(fig[2, 1], width = 400, height = 400) #hide +voronoiplot!(ax2, points, clip = (-0.2, 1.3, 0.1, 1.2)) #hide xlims!(ax2, -0.2, 1.3) #hide ylims!(ax2, 0.1, 1.2) #hide -scatter!(ax2, [G], color=:red, markersize=14) #hide +scatter!(ax2, [G], color = :red, markersize = 14) #hide hidedecorations!(ax2) #hide -ax3 = Axis(fig[1, 2], width=400, height=400, title="Perturbed") #hide +ax3 = Axis(fig[1, 2], width = 400, height = 400, title = "Perturbed") #hide points = [A, B, C, D, E, F, G2, H] #hide -triplot!(ax3, points, show_points=true) #hide +triplot!(ax3, points, show_points = true) #hide hidedecorations!(ax3) #hide xlims!(ax3, -0.2, 1.3) #hide ylims!(ax3, 0.1, 1.2) #hide -scatter!(ax3, [G2], color=:red, markersize=14) #hide -ax4 = Axis(fig[2, 2], width=400, height=400) #hide -voronoiplot!(ax4, points, clip=(-0.2, 1.3, 0.1, 1.2)) #hide -scatter!(ax4, [G2], color=:red, markersize=14) #hide +scatter!(ax3, [G2], color = :red, markersize = 14) #hide +ax4 = Axis(fig[2, 2], width = 400, height = 400) #hide +voronoiplot!(ax4, points, clip = (-0.2, 1.3, 0.1, 1.2)) #hide +scatter!(ax4, [G2], color = :red, markersize = 14) #hide xlims!(ax4, -0.2, 1.3) #hide ylims!(ax4, 0.1, 1.2) #hide hidedecorations!(ax4) #hide @@ -126,13 +126,13 @@ points = ElasticMatrix(randn(rng, 2, 50)) # so that the points are mutable tri = triangulate(points; rng) envelope_vertices, envelope_points = compute_envelope(tri, (0.5, 0.5)) -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -ax2 = Axis(fig[1, 2], width=400, height=400) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +ax2 = Axis(fig[1, 2], width = 400, height = 400) add_point!(tri, 0.5, 0.5) -triplot!(ax2, tri, show_points=true) -poly!(ax2, envelope_points, color=(:red, 0.2)) +triplot!(ax2, tri, show_points = true) +poly!(ax2, envelope_points, color = (:red, 0.2)) resize_to_layout!(fig) fig ```` @@ -155,25 +155,25 @@ envelope is unchanged. If we included the entire area, then the area that we sub would just cancel it out anyway. Let's zoom in on the envelope and consider a specific example of how we can do this computation. ````@example interpolation -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -lines!(ax, envelope_points, color=:red) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +lines!(ax, envelope_points, color = :red) j = 7 # example vertex v = envelope_vertices[j] -scatter!(ax, [get_point(tri, v)], color=:blue) -first_neighbour = envelope_vertices[j-1] +scatter!(ax, [get_point(tri, v)], color = :blue) +first_neighbour = envelope_vertices[j - 1] next_triangle = get_adjacent(tri, first_neighbour, v) -next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j+1]) -last_neighbour = envelope_vertices[j+1] +next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j + 1]) +last_neighbour = envelope_vertices[j + 1] polygon_points = [ get_point(tri, v), (get_point(tri, v) .+ get_point(tri, last_neighbour)) ./ 2, - DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j+1], next_triangle_2)), + DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j + 1], next_triangle_2)), DelaunayTriangulation.triangle_circumcenter(tri, (first_neighbour, v, next_triangle)), - (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2 + (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2, ] -poly!(ax, polygon_points, color=(:blue, 0.5), strokecolor=:blue, strokewidth=2) +poly!(ax, polygon_points, color = (:blue, 0.5), strokecolor = :blue, strokewidth = 2) xlims!(ax, -0.5, 1.4) ylims!(ax, -0.15, 1.4) resize_to_layout!(fig) @@ -193,7 +193,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -203,7 +203,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae return area / 2 end function pre_insertion_area(tri::Triangulation, i, envelope_vertices) # area from the envelope[i]th generator - poly_points = NTuple{2,Float64}[] + poly_points = NTuple{2, Float64}[] u = envelope_vertices[i] prev_index = i == 1 ? length(envelope_vertices) - 1 : i - 1 next_index = i == length(envelope_vertices) ? 1 : i + 1 @@ -257,7 +257,7 @@ Now that we can compute the pre- and post-insertion areas, we can start computin function compute_sibson_coordinates(tri::Triangulation, envelope_vertices, point) coordinates = zeros(length(envelope_vertices) - 1) w = 0.0 - for i in firstindex(envelope_vertices):(lastindex(envelope_vertices)-1) + for i in firstindex(envelope_vertices):(lastindex(envelope_vertices) - 1) pre = max(0.0, pre_insertion_area(tri, i, envelope_vertices)) post = max(0.0, post_insertion_area(tri, i, envelope_vertices, point)) if isnan(post) # need to return the the vector λ = [1] since we are exactly at a data site @@ -304,9 +304,9 @@ zz = [f(x, y) for (x, y) in DelaunayTriangulation.each_point(trit)] xx = LinRange(0.001, 0.999, 20) # handling points on the boundary requires more care than we have discussed here yy = LinRange(0.001, 0.999, 20) fig = Figure(fontsize = 24) -ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"y", title="True function", titlealign=:left, width=400, height=400) +ax = Axis(fig[1, 1], xlabel = L"x", ylabel = L"y", title = "True function", titlealign = :left, width = 400, height = 400) contourf!(ax, xx, yy, f.(xx, yy')) -ax2 = Axis(fig[1, 2], xlabel=L"x", ylabel=L"y", title="Interpolant", titlealign=:left, width=400, height=400) +ax2 = Axis(fig[1, 2], xlabel = L"x", ylabel = L"y", title = "Interpolant", titlealign = :left, width = 400, height = 400) zi = [evaluate_sibson_interpolant(trit, zz, (xᵢ, yᵢ)) for xᵢ in xx, yᵢ in yy] contourf!(ax2, xx, yy, zi) resize_to_layout!(fig) @@ -314,6 +314,7 @@ fig ```` Works perfectly! + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_applications/interpolation.jl). @@ -340,35 +341,35 @@ points = ElasticMatrix(randn(rng, 2, 50)) # so that the points are mutable tri = triangulate(points; rng) envelope_vertices, envelope_points = compute_envelope(tri, (0.5, 0.5)) -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -ax2 = Axis(fig[1, 2], width=400, height=400) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +ax2 = Axis(fig[1, 2], width = 400, height = 400) add_point!(tri, 0.5, 0.5) -triplot!(ax2, tri, show_points=true) -poly!(ax2, envelope_points, color=(:red, 0.2)) +triplot!(ax2, tri, show_points = true) +poly!(ax2, envelope_points, color = (:red, 0.2)) resize_to_layout!(fig) fig -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -lines!(ax, envelope_points, color=:red) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +lines!(ax, envelope_points, color = :red) j = 7 # example vertex v = envelope_vertices[j] -scatter!(ax, [get_point(tri, v)], color=:blue) -first_neighbour = envelope_vertices[j-1] +scatter!(ax, [get_point(tri, v)], color = :blue) +first_neighbour = envelope_vertices[j - 1] next_triangle = get_adjacent(tri, first_neighbour, v) -next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j+1]) -last_neighbour = envelope_vertices[j+1] +next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j + 1]) +last_neighbour = envelope_vertices[j + 1] polygon_points = [ get_point(tri, v), (get_point(tri, v) .+ get_point(tri, last_neighbour)) ./ 2, - DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j+1], next_triangle_2)), + DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j + 1], next_triangle_2)), DelaunayTriangulation.triangle_circumcenter(tri, (first_neighbour, v, next_triangle)), - (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2 + (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2, ] -poly!(ax, polygon_points, color=(:blue, 0.5), strokecolor=:blue, strokewidth=2) +poly!(ax, polygon_points, color = (:blue, 0.5), strokecolor = :blue, strokewidth = 2) xlims!(ax, -0.5, 1.4) ylims!(ax, -0.15, 1.4) resize_to_layout!(fig) @@ -382,7 +383,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -392,7 +393,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae return area / 2 end function pre_insertion_area(tri::Triangulation, i, envelope_vertices) # area from the envelope[i]th generator - poly_points = NTuple{2,Float64}[] + poly_points = NTuple{2, Float64}[] u = envelope_vertices[i] prev_index = i == 1 ? length(envelope_vertices) - 1 : i - 1 next_index = i == length(envelope_vertices) ? 1 : i + 1 @@ -437,7 +438,7 @@ end function compute_sibson_coordinates(tri::Triangulation, envelope_vertices, point) coordinates = zeros(length(envelope_vertices) - 1) w = 0.0 - for i in firstindex(envelope_vertices):(lastindex(envelope_vertices)-1) + for i in firstindex(envelope_vertices):(lastindex(envelope_vertices) - 1) pre = max(0.0, pre_insertion_area(tri, i, envelope_vertices)) post = max(0.0, post_insertion_area(tri, i, envelope_vertices, point)) if isnan(post) # need to return the the vector λ = [1] since we are exactly at a data site @@ -472,9 +473,9 @@ zz = [f(x, y) for (x, y) in DelaunayTriangulation.each_point(trit)] xx = LinRange(0.001, 0.999, 20) # handling points on the boundary requires more care than we have discussed here yy = LinRange(0.001, 0.999, 20) fig = Figure(fontsize = 24) -ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"y", title="True function", titlealign=:left, width=400, height=400) +ax = Axis(fig[1, 1], xlabel = L"x", ylabel = L"y", title = "True function", titlealign = :left, width = 400, height = 400) contourf!(ax, xx, yy, f.(xx, yy')) -ax2 = Axis(fig[1, 2], xlabel=L"x", ylabel=L"y", title="Interpolant", titlealign=:left, width=400, height=400) +ax2 = Axis(fig[1, 2], xlabel = L"x", ylabel = L"y", title = "Interpolant", titlealign = :left, width = 400, height = 400) zi = [evaluate_sibson_interpolant(trit, zz, (xᵢ, yᵢ)) for xᵢ in xx, yᵢ in yy] contourf!(ax2, xx, yy, zi) resize_to_layout!(fig) diff --git a/docs/src/applications/pde_discretisation.md b/docs/src/applications/pde_discretisation.md index 744985b5b..fc8208fb0 100644 --- a/docs/src/applications/pde_discretisation.md +++ b/docs/src/applications/pde_discretisation.md @@ -36,11 +36,11 @@ rng = StableRNG(123) R₁ = 1.0 R₂ = 2.0 outer_circle = CircularArc((R₂, 0.0), (R₂, 0.0), (0.0, 0.0)) -inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive=false) -points = NTuple{2,Float64}[] -tri = triangulate(points; rng, boundary_nodes=[[[outer_circle]], [[inner_circle]]]) +inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive = false) +points = NTuple{2, Float64}[] +tri = triangulate(points; rng, boundary_nodes = [[[outer_circle]], [[inner_circle]]]) A = 2π * (R₂^2 - R₁^2) -refine!(tri; max_area=2e-3A, min_angle=33.0, rng) +refine!(tri; max_area = 2.0e-3A, min_angle = 33.0, rng) fig, ax, sc = triplot(tri) fig ```` @@ -51,14 +51,14 @@ each point. In particular, connect the centroids of each triangle to the midpoin $\Omega_i$ around each point $\vb x_i$, as shown below in blue. ````@example pde_discretisation -points = NTuple{2,Float64}[] #hide +points = NTuple{2, Float64}[] #hide for T in each_solid_triangle(tri) #hide u, v, w = triangle_vertices(T) #hide p, q, r = get_point(tri, u, v, w) #hide c = DelaunayTriangulation.triangle_centroid(p, q, r) #hide push!(points, c, (p .+ q) ./ 2, c, (q .+ r) ./ 2, c, (r .+ p) ./ 2) #hide end #hide -linesegments!(ax, points, color=:blue) #hide +linesegments!(ax, points, color = :blue) #hide fig #hide ```` @@ -125,8 +125,8 @@ using SparseArrays function solve_met_problem(tri::Triangulation, D) # To start, we need to build a map that takes the vertices from tri # into a range of consecutive integers, since not all vertices are used. - vertex_map = Dict{Int,Int}() - inverse_vertex_map = Dict{Int,Int}() + vertex_map = Dict{Int, Int}() + inverse_vertex_map = Dict{Int, Int}() cur_idx = 1 for i in DelaunayTriangulation.each_point_index(tri) if DelaunayTriangulation.has_vertex(tri, i) @@ -140,10 +140,10 @@ function solve_met_problem(tri::Triangulation, D) nt = num_solid_triangles(tri) cv_volumes = zeros(nv) Ttype = DelaunayTriangulation.triangle_type(tri) - shape_function_coefficients = Dict{Ttype,NTuple{9,Float64}}() - cv_edge_midpoints = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_normals = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_lengths = Dict{Ttype,NTuple{3,Float64}}() + shape_function_coefficients = Dict{Ttype, NTuple{9, Float64}}() + cv_edge_midpoints = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_normals = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_lengths = Dict{Ttype, NTuple{3, Float64}}() sizehint!.((cv_volumes, shape_function_coefficients, cv_edge_midpoints, cv_edge_normals, cv_edge_lengths), nt) for T in each_solid_triangle(tri) u, v, w = triangle_vertices(T) @@ -211,9 +211,11 @@ function solve_met_problem(tri::Triangulation, D) nx, ny = cv_edge_normals[T][edge_index] ℓ = cv_edge_lengths[T][edge_index] Dℓ = D * ℓ - a123 = (Dℓ * (s₁₁ * nx + s₂₁ * ny), + a123 = ( + Dℓ * (s₁₁ * nx + s₂₁ * ny), Dℓ * (s₁₂ * nx + s₂₂ * ny), - Dℓ * (s₁₃ * nx + s₂₃ * ny)) + Dℓ * (s₁₃ * nx + s₂₃ * ny), + ) e1_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₁)[1] e2_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₂)[1] for vert in 1:3 @@ -248,7 +250,7 @@ Let's now solve this problem, taking $D = 6.25 \times 10^{-4}$. ````@example pde_discretisation D = 6.25e-4 T = solve_met_problem(tri, D) -fig, ax, sc = tricontourf(tri, T, levels=0:5:200, extendhigh=:auto) +fig, ax, sc = tricontourf(tri, T, levels = 0:5:200, extendhigh = :auto) fig ```` @@ -264,11 +266,11 @@ rng = StableRNG(123) R₁ = 1.0 R₂ = 2.0 outer_circle = CircularArc((R₂, 0.0), (R₂, 0.0), (0.0, 0.0)) -inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive=false) -points = NTuple{2,Float64}[] -tri = triangulate(points; rng, boundary_nodes=[[[outer_circle]], [[inner_circle]]]) +inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive = false) +points = NTuple{2, Float64}[] +tri = triangulate(points; rng, boundary_nodes = [[[outer_circle]], [[inner_circle]]]) A = 2π * (R₂^2 - R₁^2) -refine!(tri; max_area=2e-3A, min_angle=33.0, rng) +refine!(tri; max_area = 2.0e-3A, min_angle = 33.0, rng) fig, ax, sc = triplot(tri) fig @@ -278,8 +280,8 @@ using SparseArrays function solve_met_problem(tri::Triangulation, D) # To start, we need to build a map that takes the vertices from tri # into a range of consecutive integers, since not all vertices are used. - vertex_map = Dict{Int,Int}() - inverse_vertex_map = Dict{Int,Int}() + vertex_map = Dict{Int, Int}() + inverse_vertex_map = Dict{Int, Int}() cur_idx = 1 for i in DelaunayTriangulation.each_point_index(tri) if DelaunayTriangulation.has_vertex(tri, i) @@ -293,10 +295,10 @@ function solve_met_problem(tri::Triangulation, D) nt = num_solid_triangles(tri) cv_volumes = zeros(nv) Ttype = DelaunayTriangulation.triangle_type(tri) - shape_function_coefficients = Dict{Ttype,NTuple{9,Float64}}() - cv_edge_midpoints = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_normals = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_lengths = Dict{Ttype,NTuple{3,Float64}}() + shape_function_coefficients = Dict{Ttype, NTuple{9, Float64}}() + cv_edge_midpoints = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_normals = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_lengths = Dict{Ttype, NTuple{3, Float64}}() sizehint!.((cv_volumes, shape_function_coefficients, cv_edge_midpoints, cv_edge_normals, cv_edge_lengths), nt) for T in each_solid_triangle(tri) u, v, w = triangle_vertices(T) @@ -364,9 +366,11 @@ function solve_met_problem(tri::Triangulation, D) nx, ny = cv_edge_normals[T][edge_index] ℓ = cv_edge_lengths[T][edge_index] Dℓ = D * ℓ - a123 = (Dℓ * (s₁₁ * nx + s₂₁ * ny), + a123 = ( + Dℓ * (s₁₁ * nx + s₂₁ * ny), Dℓ * (s₁₂ * nx + s₂₂ * ny), - Dℓ * (s₁₃ * nx + s₂₃ * ny)) + Dℓ * (s₁₃ * nx + s₂₃ * ny), + ) e1_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₁)[1] e2_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₂)[1] for vert in 1:3 @@ -396,7 +400,7 @@ end D = 6.25e-4 T = solve_met_problem(tri, D) -fig, ax, sc = tricontourf(tri, T, levels=0:5:200, extendhigh=:auto) +fig, ax, sc = tricontourf(tri, T, levels = 0:5:200, extendhigh = :auto) fig ``` diff --git a/docs/src/literate_applications/cell_simulations.jl b/docs/src/literate_applications/cell_simulations.jl index 6d4b318cc..862d0a35c 100644 --- a/docs/src/literate_applications/cell_simulations.jl +++ b/docs/src/literate_applications/cell_simulations.jl @@ -48,7 +48,7 @@ using StatsBase using CairoMakie Base.@kwdef mutable struct CellModel{P} tri::Triangulation{P} - new_r_cache::Vector{NTuple{2,Float64}} # for r(t + Δt) + new_r_cache::Vector{NTuple{2, Float64}} # for r(t + Δt) α::Float64 s::Float64 Δt::Float64 @@ -91,7 +91,7 @@ function polygon_area(points) # this is the same function from the Interpolation rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -101,7 +101,7 @@ function polygon_area(points) # this is the same function from the Interpolation return area / 2 end function get_voronoi_area(tri::Triangulation, i) - points = NTuple{2,Float64}[] + points = NTuple{2, Float64}[] !DelaunayTriangulation.has_vertex(tri, i) && return (0.0, points) # might not be included anymore due to retriangulation DelaunayTriangulation.is_boundary_node(tri, i)[1] && return (0.0, points) # to prevent boundary cells from proliferating N = get_neighbours(tri, i) @@ -142,7 +142,7 @@ function proliferate_cells!(cells::CellModel) δ = DelaunayTriangulation.distance_to_polygon(p, get_points(tri), poly) s, c = sincos(θ) q = p .+ (δ * cells.ϵ) .* (c, s) - add_point!(tri, q; rng=cells.rng) + add_point!(tri, q; rng = cells.rng) push!(cells.new_r_cache, q) end return nothing @@ -156,7 +156,7 @@ function perform_step!(cells::CellModel) end function simulate_cells(cells::CellModel) t = 0.0 - all_points = Vector{Vector{NTuple{2,Float64}}}() + all_points = Vector{Vector{NTuple{2, Float64}}}() push!(all_points, deepcopy(get_points(cells.tri))) while t < cells.final_time perform_step!(cells) @@ -173,23 +173,27 @@ end rng = StableRNG(123444) a, b, c, d = -2.0, 2.0, -5.0, 5.0 points = [(a + (b - a) * rand(rng), c + (d - c) * rand(rng)) for _ in 1:10] -tri = triangulate(points; rng=rng) -cells = CellModel(; tri=tri, new_r_cache=similar(points), α=5.0, s=2.0, Δt=1e-3, - β=0.25, K=100.0^2, rng, final_time=25.0, ϵ=0.5) +tri = triangulate(points; rng = rng) +cells = CellModel(; + tri = tri, new_r_cache = similar(points), α = 5.0, s = 2.0, Δt = 1.0e-3, + β = 0.25, K = 100.0^2, rng, final_time = 25.0, ϵ = 0.5, +) results = simulate_cells(cells); -fig = Figure(fontsize=26) +fig = Figure(fontsize = 26) title_obs = Observable(L"t = %$(0.0)") -ax1 = Axis(fig[1, 1], width=1200, height=400, title=title_obs, titlealign=:left) +ax1 = Axis(fig[1, 1], width = 1200, height = 400, title = title_obs, titlealign = :left) Δt = cells.Δt i = Observable(1) -voronoiplot!(ax1, @lift(voronoi(triangulate(results[$i]; rng), clip=true, rng=rng)), - color=:darkgreen, strokecolor=:black, strokewidth=2, show_generators=false) +voronoiplot!( + ax1, @lift(voronoi(triangulate(results[$i]; rng), clip = true, rng = rng)), + color = :darkgreen, strokecolor = :black, strokewidth = 2, show_generators = false, +) xlims!(ax1, -12, 12) ylims!(ax1, -12, 12) resize_to_layout!(fig) t = 0:Δt:cells.final_time -record(fig, "cell_simulation.mp4", 1:10:length(t); framerate=60) do ii +record(fig, "cell_simulation.mp4", 1:10:length(t); framerate = 60) do ii i[] = ii title_obs[] = L"t = %$(((ii-1) * Δt))" end; diff --git a/docs/src/literate_applications/interpolation.jl b/docs/src/literate_applications/interpolation.jl index c271d8e18..bece9cef3 100644 --- a/docs/src/literate_applications/interpolation.jl +++ b/docs/src/literate_applications/interpolation.jl @@ -20,29 +20,29 @@ using CairoMakie #hide A, B, C, D, E, F, G, H = (0.3, 1.1), (-0.1, 0.8), (0.2, 0.3), (0.6, 0.2), (0.8, 0.8), (0.3, 0.9), (0.5503600264347, 0.6814266789918), (1.1, 0.5) #hide G2 = (0.5496217775447, 0.7146478790414) #hide fig = Figure() #hide -ax = Axis(fig[1, 1], width=400, height=400, title="Original") #hide +ax = Axis(fig[1, 1], width = 400, height = 400, title = "Original") #hide xlims!(ax, -0.2, 1.3) #hide ylims!(ax, 0.1, 1.2) #hide points = [A, B, C, D, E, F, G, H] #hide -triplot!(ax, points, show_points=true) #hide -scatter!(ax, [G], color=:red, markersize=14) #hide +triplot!(ax, points, show_points = true) #hide +scatter!(ax, [G], color = :red, markersize = 14) #hide hidedecorations!(ax) #hide -ax2 = Axis(fig[2, 1], width=400, height=400) #hide -voronoiplot!(ax2, points, clip=(-0.2, 1.3, 0.1, 1.2)) #hide +ax2 = Axis(fig[2, 1], width = 400, height = 400) #hide +voronoiplot!(ax2, points, clip = (-0.2, 1.3, 0.1, 1.2)) #hide xlims!(ax2, -0.2, 1.3) #hide ylims!(ax2, 0.1, 1.2) #hide -scatter!(ax2, [G], color=:red, markersize=14) #hide +scatter!(ax2, [G], color = :red, markersize = 14) #hide hidedecorations!(ax2) #hide -ax3 = Axis(fig[1, 2], width=400, height=400, title="Perturbed") #hide +ax3 = Axis(fig[1, 2], width = 400, height = 400, title = "Perturbed") #hide points = [A, B, C, D, E, F, G2, H] #hide -triplot!(ax3, points, show_points=true) #hide +triplot!(ax3, points, show_points = true) #hide hidedecorations!(ax3) #hide xlims!(ax3, -0.2, 1.3) #hide ylims!(ax3, 0.1, 1.2) #hide -scatter!(ax3, [G2], color=:red, markersize=14) #hide -ax4 = Axis(fig[2, 2], width=400, height=400) #hide -voronoiplot!(ax4, points, clip=(-0.2, 1.3, 0.1, 1.2)) #hide -scatter!(ax4, [G2], color=:red, markersize=14) #hide +scatter!(ax3, [G2], color = :red, markersize = 14) #hide +ax4 = Axis(fig[2, 2], width = 400, height = 400) #hide +voronoiplot!(ax4, points, clip = (-0.2, 1.3, 0.1, 1.2)) #hide +scatter!(ax4, [G2], color = :red, markersize = 14) #hide xlims!(ax4, -0.2, 1.3) #hide ylims!(ax4, 0.1, 1.2) #hide hidedecorations!(ax4) #hide @@ -114,13 +114,13 @@ points = ElasticMatrix(randn(rng, 2, 50)) # so that the points are mutable tri = triangulate(points; rng) envelope_vertices, envelope_points = compute_envelope(tri, (0.5, 0.5)) -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -ax2 = Axis(fig[1, 2], width=400, height=400) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +ax2 = Axis(fig[1, 2], width = 400, height = 400) add_point!(tri, 0.5, 0.5) -triplot!(ax2, tri, show_points=true) -poly!(ax2, envelope_points, color=(:red, 0.2)) +triplot!(ax2, tri, show_points = true) +poly!(ax2, envelope_points, color = (:red, 0.2)) resize_to_layout!(fig) fig @@ -140,25 +140,25 @@ fig # to compute the part of the area that is contained within the envelope, since everything outside of that # envelope is unchanged. If we included the entire area, then the area that we subtract off for the intersection we compute later # would just cancel it out anyway. Let's zoom in on the envelope and consider a specific example of how we can do this computation. -fig = Figure(fontsize=24) -ax = Axis(fig[1, 1], width=400, height=400) -triplot!(ax, tri, show_points=true) -lines!(ax, envelope_points, color=:red) +fig = Figure(fontsize = 24) +ax = Axis(fig[1, 1], width = 400, height = 400) +triplot!(ax, tri, show_points = true) +lines!(ax, envelope_points, color = :red) j = 7 # example vertex v = envelope_vertices[j] -scatter!(ax, [get_point(tri, v)], color=:blue) -first_neighbour = envelope_vertices[j-1] +scatter!(ax, [get_point(tri, v)], color = :blue) +first_neighbour = envelope_vertices[j - 1] next_triangle = get_adjacent(tri, first_neighbour, v) -next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j+1]) -last_neighbour = envelope_vertices[j+1] +next_triangle_2 = get_adjacent(tri, v, envelope_vertices[j + 1]) +last_neighbour = envelope_vertices[j + 1] polygon_points = [ get_point(tri, v), (get_point(tri, v) .+ get_point(tri, last_neighbour)) ./ 2, - DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j+1], next_triangle_2)), + DelaunayTriangulation.triangle_circumcenter(tri, (v, envelope_vertices[j + 1], next_triangle_2)), DelaunayTriangulation.triangle_circumcenter(tri, (first_neighbour, v, next_triangle)), - (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2 + (get_point(tri, v) .+ get_point(tri, first_neighbour)) ./ 2, ] -poly!(ax, polygon_points, color=(:blue, 0.5), strokecolor=:blue, strokewidth=2) +poly!(ax, polygon_points, color = (:blue, 0.5), strokecolor = :blue, strokewidth = 2) xlims!(ax, -0.5, 1.4) ylims!(ax, -0.15, 1.4) resize_to_layout!(fig) @@ -175,7 +175,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae rx, ry = getxy(r) sx, sy = getxy(s) area = px * (qy - ry) + rx * (py - sy) - for i in 2:(n-1) + for i in 2:(n - 1) p, q, r = get_point(points, i, i + 1, i - 1) px, py = getxy(p) qx, qy = getxy(q) @@ -185,7 +185,7 @@ function polygon_area(points) # this is the first formula in the "Other formulae return area / 2 end function pre_insertion_area(tri::Triangulation, i, envelope_vertices) # area from the envelope[i]th generator - poly_points = NTuple{2,Float64}[] + poly_points = NTuple{2, Float64}[] u = envelope_vertices[i] prev_index = i == 1 ? length(envelope_vertices) - 1 : i - 1 next_index = i == length(envelope_vertices) ? 1 : i + 1 @@ -233,7 +233,7 @@ end function compute_sibson_coordinates(tri::Triangulation, envelope_vertices, point) coordinates = zeros(length(envelope_vertices) - 1) w = 0.0 - for i in firstindex(envelope_vertices):(lastindex(envelope_vertices)-1) + for i in firstindex(envelope_vertices):(lastindex(envelope_vertices) - 1) pre = max(0.0, pre_insertion_area(tri, i, envelope_vertices)) post = max(0.0, post_insertion_area(tri, i, envelope_vertices, point)) if isnan(post) # need to return the the vector λ = [1] since we are exactly at a data site @@ -274,12 +274,12 @@ zz = [f(x, y) for (x, y) in DelaunayTriangulation.each_point(trit)] xx = LinRange(0.001, 0.999, 20) # handling points on the boundary requires more care than we have discussed here yy = LinRange(0.001, 0.999, 20) fig = Figure(fontsize = 24) -ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"y", title="True function", titlealign=:left, width=400, height=400) +ax = Axis(fig[1, 1], xlabel = L"x", ylabel = L"y", title = "True function", titlealign = :left, width = 400, height = 400) contourf!(ax, xx, yy, f.(xx, yy')) -ax2 = Axis(fig[1, 2], xlabel=L"x", ylabel=L"y", title="Interpolant", titlealign=:left, width=400, height=400) +ax2 = Axis(fig[1, 2], xlabel = L"x", ylabel = L"y", title = "Interpolant", titlealign = :left, width = 400, height = 400) zi = [evaluate_sibson_interpolant(trit, zz, (xᵢ, yᵢ)) for xᵢ in xx, yᵢ in yy] contourf!(ax2, xx, yy, zi) resize_to_layout!(fig) fig -# Works perfectly! \ No newline at end of file +# Works perfectly! diff --git a/docs/src/literate_applications/pde_discretisation.jl b/docs/src/literate_applications/pde_discretisation.jl index 511ae73cc..1bd53fc8d 100644 --- a/docs/src/literate_applications/pde_discretisation.jl +++ b/docs/src/literate_applications/pde_discretisation.jl @@ -30,11 +30,11 @@ rng = StableRNG(123) R₁ = 1.0 R₂ = 2.0 outer_circle = CircularArc((R₂, 0.0), (R₂, 0.0), (0.0, 0.0)) -inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive=false) -points = NTuple{2,Float64}[] -tri = triangulate(points; rng, boundary_nodes=[[[outer_circle]], [[inner_circle]]]) +inner_circle = CircularArc((R₁, 0.0), (R₁, 0.0), (0.0, 0.0), positive = false) +points = NTuple{2, Float64}[] +tri = triangulate(points; rng, boundary_nodes = [[[outer_circle]], [[inner_circle]]]) A = 2π * (R₂^2 - R₁^2) -refine!(tri; max_area=2e-3A, min_angle=33.0, rng) +refine!(tri; max_area = 2.0e-3A, min_angle = 33.0, rng) fig, ax, sc = triplot(tri) fig @@ -42,14 +42,14 @@ fig # Now let's determine how we can use the discretisation above to solve the PDE. Central to this approach is the idea of a _control volume_ around # each point. In particular, connect the centroids of each triangle to the midpoints of the edges of the triangle. This defines a collection of polygons # $\Omega_i$ around each point $\vb x_i$, as shown below in blue. -points = NTuple{2,Float64}[] #hide +points = NTuple{2, Float64}[] #hide for T in each_solid_triangle(tri) #hide u, v, w = triangle_vertices(T) #hide p, q, r = get_point(tri, u, v, w) #hide c = DelaunayTriangulation.triangle_centroid(p, q, r) #hide push!(points, c, (p .+ q) ./ 2, c, (q .+ r) ./ 2, c, (r .+ p) ./ 2) #hide end #hide -linesegments!(ax, points, color=:blue) #hide +linesegments!(ax, points, color = :blue) #hide fig #hide # Consider a particular control volume $\Omega_i$. We integrate our PDE over this domain, writing @@ -113,8 +113,8 @@ using SparseArrays function solve_met_problem(tri::Triangulation, D) ## To start, we need to build a map that takes the vertices from tri ## into a range of consecutive integers, since not all vertices are used. - vertex_map = Dict{Int,Int}() - inverse_vertex_map = Dict{Int,Int}() + vertex_map = Dict{Int, Int}() + inverse_vertex_map = Dict{Int, Int}() cur_idx = 1 for i in DelaunayTriangulation.each_point_index(tri) if DelaunayTriangulation.has_vertex(tri, i) @@ -128,10 +128,10 @@ function solve_met_problem(tri::Triangulation, D) nt = num_solid_triangles(tri) cv_volumes = zeros(nv) Ttype = DelaunayTriangulation.triangle_type(tri) - shape_function_coefficients = Dict{Ttype,NTuple{9,Float64}}() - cv_edge_midpoints = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_normals = Dict{Ttype,NTuple{3,NTuple{2,Float64}}}() - cv_edge_lengths = Dict{Ttype,NTuple{3,Float64}}() + shape_function_coefficients = Dict{Ttype, NTuple{9, Float64}}() + cv_edge_midpoints = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_normals = Dict{Ttype, NTuple{3, NTuple{2, Float64}}}() + cv_edge_lengths = Dict{Ttype, NTuple{3, Float64}}() sizehint!.((cv_volumes, shape_function_coefficients, cv_edge_midpoints, cv_edge_normals, cv_edge_lengths), nt) for T in each_solid_triangle(tri) u, v, w = triangle_vertices(T) @@ -199,9 +199,11 @@ function solve_met_problem(tri::Triangulation, D) nx, ny = cv_edge_normals[T][edge_index] ℓ = cv_edge_lengths[T][edge_index] Dℓ = D * ℓ - a123 = (Dℓ * (s₁₁ * nx + s₂₁ * ny), + a123 = ( + Dℓ * (s₁₁ * nx + s₂₁ * ny), Dℓ * (s₁₂ * nx + s₂₂ * ny), - Dℓ * (s₁₃ * nx + s₂₃ * ny)) + Dℓ * (s₁₃ * nx + s₂₃ * ny), + ) e1_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₁)[1] e2_is_bnd = DelaunayTriangulation.is_boundary_node(tri, e₂)[1] for vert in 1:3 @@ -233,5 +235,5 @@ end # Let's now solve this problem, taking $D = 6.25 \times 10^{-4}$. D = 6.25e-4 T = solve_met_problem(tri, D) -fig, ax, sc = tricontourf(tri, T, levels=0:5:200, extendhigh=:auto) -fig \ No newline at end of file +fig, ax, sc = tricontourf(tri, T, levels = 0:5:200, extendhigh = :auto) +fig diff --git a/docs/src/literate_tutorials/centroidal.jl b/docs/src/literate_tutorials/centroidal.jl index 9991dc158..e839ffbef 100644 --- a/docs/src/literate_tutorials/centroidal.jl +++ b/docs/src/literate_tutorials/centroidal.jl @@ -16,7 +16,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src rng = StableRNG(123) points = 25randn(rng, 2, 500) tri = triangulate(points; rng) -vorn = voronoi(tri, clip=true) +vorn = voronoi(tri, clip = true) # To now compute the centroidal tessellation, use [`centroidal_smooth`](@ref). ( # If you want to straight from a triangulation to a centroidal tessellation, you @@ -25,10 +25,10 @@ smooth_vorn = centroidal_smooth(vorn; rng) # Let us now compare the two tessellations. fig = Figure() -ax1 = Axis(fig[1, 1], title="Original", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Smoothed", width=600, height=400) -voronoiplot!(ax1, vorn, colormap=:matter, strokewidth=2) -voronoiplot!(ax2, smooth_vorn, colormap=:matter, strokewidth=2) +ax1 = Axis(fig[1, 1], title = "Original", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Smoothed", width = 600, height = 400) +voronoiplot!(ax1, vorn, colormap = :matter, strokewidth = 2) +voronoiplot!(ax2, smooth_vorn, colormap = :matter, strokewidth = 2) resize_to_layout!(fig) fig @test_reference joinpath(fig_path, "voronoi_ex_5.png") fig #src @@ -37,4 +37,4 @@ fig # do look to be near the centroid of their corresponding tile. Note that # this function `centroidal_smooth` is iterative, and you can control the iteration limits # and the tolerance of the iterations (based on the maximum displacement of any generator at -# each iteration) using the `maxiters` and `tol` keyword arguments. \ No newline at end of file +# each iteration) using the `maxiters` and `tol` keyword arguments. diff --git a/docs/src/literate_tutorials/clipped.jl b/docs/src/literate_tutorials/clipped.jl index 22b2ad8f1..e42f1e9b1 100644 --- a/docs/src/literate_tutorials/clipped.jl +++ b/docs/src/literate_tutorials/clipped.jl @@ -27,13 +27,13 @@ clipped_vorn = voronoi(tri, clip = true) # Note that the clipping has put more polygon vertices in. We compare # the clipped tessellations below. fig = Figure() -ax1 = Axis(fig[1, 1], title="Unclipped", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Clipped", width=600, height=400) -voronoiplot!(ax1, vorn, show_generators=false, colormap=:matter, strokewidth=4) -voronoiplot!(ax2, clipped_vorn, show_generators=false, colormap=:matter, strokewidth=4) +ax1 = Axis(fig[1, 1], title = "Unclipped", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Clipped", width = 600, height = 400) +voronoiplot!(ax1, vorn, show_generators = false, colormap = :matter, strokewidth = 4) +voronoiplot!(ax2, clipped_vorn, show_generators = false, colormap = :matter, strokewidth = 4) resize_to_layout!(fig) fig @test_reference joinpath(fig_path, "voronoi_ex_2.png") fig #src # As you can see, the unbounded polygons, and any polygons that included points -# outside of the convex hull, have now been clipped to the convex hull. \ No newline at end of file +# outside of the convex hull, have now been clipped to the convex hull. diff --git a/docs/src/literate_tutorials/clipped_rectangle.jl b/docs/src/literate_tutorials/clipped_rectangle.jl index 0175e0fda..62399cd89 100644 --- a/docs/src/literate_tutorials/clipped_rectangle.jl +++ b/docs/src/literate_tutorials/clipped_rectangle.jl @@ -11,7 +11,7 @@ # Let us now demonstrate. First, we construct a tessellation of # some example point set. -using DelaunayTriangulation +using DelaunayTriangulation using CairoMakie using ReferenceTests #src using Test #src @@ -32,7 +32,7 @@ vorn = voronoi(tri) # the tessellation to. fig, ax, sc = voronoiplot(vorn) a, b, c, d = -2.0, 3.0, 0.0, 7.0 -lines!(ax, [(a,c),(b,c),(b,d),(a,d),(a,c)], color = :black, linewidth = 4) +lines!(ax, [(a, c), (b, c), (b, d), (a, d), (a, c)], color = :black, linewidth = 4) fig @test_reference joinpath(fig_path, "voronoi_ex_3.png") fig #src @@ -43,11 +43,11 @@ bounding_box = (a, b, c, d) # You can obtain some reasonable defaults for this bounding box using # [DelaunayTriangulation.polygon_bounds(vorn)](@ref polygon_bounds). # The coordinates for each polygon clipped to this box can be obtained as follows. -clipped_coords = Vector{Vector{NTuple{2,Float64}}}(undef, num_polygons(vorn)) +clipped_coords = Vector{Vector{NTuple{2, Float64}}}(undef, num_polygons(vorn)) for i in each_polygon_index(vorn) clipped_coords[i] = get_polygon_coordinates(vorn, i, bounding_box) end -clipped_coords +clipped_coords # Now let's plot these. fig, ax, sc = poly(clipped_coords, color = :white, strokewidth = 4) @@ -56,4 +56,4 @@ fig # As we can see, the polygons have been clipped to the rectangle. # Note that if you just want this for plotting, you can also call `voronoiplot` with the -# `bounding_box` keyword argument. \ No newline at end of file +# `bounding_box` keyword argument. diff --git a/docs/src/literate_tutorials/constrained_edges.jl b/docs/src/literate_tutorials/constrained_edges.jl index 02d565b2a..ba2efb72f 100644 --- a/docs/src/literate_tutorials/constrained_edges.jl +++ b/docs/src/literate_tutorials/constrained_edges.jl @@ -37,16 +37,20 @@ C = Set([(2, 1), (2, 11), (2, 7), (2, 5)]) tri = triangulate(pts) #- -cons_tri = triangulate(pts; segments=C) +cons_tri = triangulate(pts; segments = C) #- fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) triplot!(ax2, cons_tri, show_constrained_edges = true) resize_to_layout!(fig) diff --git a/docs/src/literate_tutorials/constrained_interior_within_interiors.jl b/docs/src/literate_tutorials/constrained_interior_within_interiors.jl index c010b6da4..c6b126470 100644 --- a/docs/src/literate_tutorials/constrained_interior_within_interiors.jl +++ b/docs/src/literate_tutorials/constrained_interior_within_interiors.jl @@ -23,16 +23,18 @@ curve_1 = [ [(0.0, 0.0), (5.0, 0.0), (10.0, 0.0), (15.0, 0.0), (20.0, 0.0), (25.0, 0.0)], [(25.0, 0.0), (25.0, 5.0), (25.0, 10.0), (25.0, 15.0), (25.0, 20.0), (25.0, 25.0)], [(25.0, 25.0), (20.0, 25.0), (15.0, 25.0), (10.0, 25.0), (5.0, 25.0), (0.0, 25.0)], - [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)] + [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)], ] # outer-most boundary: counter-clockwise curve_2 = [ [(4.0, 6.0), (4.0, 14.0), (4.0, 20.0), (18.0, 20.0), (20.0, 20.0)], [(20.0, 20.0), (20.0, 16.0), (20.0, 12.0), (20.0, 8.0), (20.0, 4.0)], - [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)] + [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)], ] # inner boundary: clockwise curve_3 = [ - [(12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), - (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912)] + [ + (12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), + (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912), + ], ] # this is inside curve_2, so it's counter-clockwise curves = [curve_1, curve_2, curve_3] points = [ @@ -42,9 +44,9 @@ points = [ (6.0, 2.0), (6.2, 3.0), (2.0, 3.0), (2.6, 6.2), (2.0, 8.0), (2.0, 11.0), (5.0, 12.0), (2.0, 17.0), (3.0, 19.0), (6.0, 18.0), (6.5, 14.5), (13.0, 19.0), (13.0, 12.0), (16.0, 8.0), (9.8, 8.0), (7.5, 6.0), - (12.0, 13.0), (19.0, 15.0) + (12.0, 13.0), (19.0, 15.0), ] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) # To now triangulate: diff --git a/docs/src/literate_tutorials/constrained_multiply_connected.jl b/docs/src/literate_tutorials/constrained_multiply_connected.jl index 3cc9f4acc..9532dda5c 100644 --- a/docs/src/literate_tutorials/constrained_multiply_connected.jl +++ b/docs/src/literate_tutorials/constrained_multiply_connected.jl @@ -6,7 +6,7 @@ # load the packages. using DelaunayTriangulation using CairoMakie -using StableRNGs +using StableRNGs using ReferenceTests #src using Test #src fig_path = joinpath(@__DIR__, "../figures") #src @@ -23,29 +23,29 @@ fig_path = joinpath(@__DIR__, "../figures") #src # that neighbouring segments must connect. curve_1 = [ ## first segment - [ + [ (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), - (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0) + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), ], ## second segment - [ + [ (12.0, 28.0), (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), (-4.0, 0.0), (0.0, 0.0), - ] + ], ] # outer: counter-clockwise curve_2 = [ ## first segment - [ + [ (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), - (10.0, 22.0), (10.0, 20.0) + (10.0, 22.0), (10.0, 20.0), ], ## second segment - [ + [ (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ] + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], ] # inner: clockwise curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] # inner: clockwise curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] # inner: clockwise @@ -61,8 +61,9 @@ points = [ (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points); + (7.0, 7.8), (7.0, 7.4), +] +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points); # Notice that `curve_1` and `curve_2` are split up into multiple segments. For `curve_3` # and `curve_4`, note that we have to wrap the entire vector in a vector, essentially @@ -71,7 +72,7 @@ boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_poi # Now let us triangulate. rng = StableRNG(123) # the triangulation is not unique due to cocircular points tri = triangulate(points; boundary_nodes, rng) -fig, ax, sc = triplot(tri, show_constrained_edges=true, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_constrained_edges = true, show_convex_hull = true) fig @test_reference joinpath(fig_path, "constrained_ex_5.png") fig #src @@ -110,25 +111,25 @@ DelaunayTriangulation.get_all_boundary_nodes(tri) # for demonstration). For this, the order of the boundary edges is appropriate, so we must iterate # in a way that respects the ordering. function get_triangulation_area(tri) - A = 0.0 + A = 0.0 nc = DelaunayTriangulation.num_curves(tri) - for curve_index in 1:nc + for curve_index in 1:nc bn = get_boundary_nodes(tri, curve_index) ns = DelaunayTriangulation.num_sections(bn) - for segment_index in 1:ns + for segment_index in 1:ns bnn = get_boundary_nodes(bn, segment_index) ne = num_boundary_edges(bnn) for i in 1:ne vᵢ = get_boundary_nodes(bnn, i) - vᵢ₊₁ = get_boundary_nodes(bnn, i+1) + vᵢ₊₁ = get_boundary_nodes(bnn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end end end - return A/2 + return A / 2 end A = get_triangulation_area(tri) @test A ≈ get_area(tri) #src @@ -142,7 +143,7 @@ function get_perimeters(tri) total_perimeter = 0.0 nc = DelaunayTriangulation.num_curves(tri) curve_perimeters = zeros(nc) # curve_index => perimeter - segment_perimeters = Dict{NTuple{2,Int},Float64}() # (curve_index, segment_index) => perimeter + segment_perimeters = Dict{NTuple{2, Int}, Float64}() # (curve_index, segment_index) => perimeter for (e, ((curve_index, section_index), node_index)) in get_boundary_edge_map(tri) u, v = edge_vertices(e) p, q = get_point(tri, u, v) @@ -156,7 +157,7 @@ function get_perimeters(tri) end end return total_perimeter, curve_perimeters, segment_perimeters -end +end ℓ, cℓ, sℓ = get_perimeters(tri) @test ℓ ≈ sum(cℓ) #src -@test ℓ ≈ sum(sum.(values(sℓ))) #src \ No newline at end of file +@test ℓ ≈ sum(sum.(values(sℓ))) #src diff --git a/docs/src/literate_tutorials/constrained_multipolygon.jl b/docs/src/literate_tutorials/constrained_multipolygon.jl index 5d2470924..cd15e1899 100644 --- a/docs/src/literate_tutorials/constrained_multipolygon.jl +++ b/docs/src/literate_tutorials/constrained_multipolygon.jl @@ -13,7 +13,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -24,7 +24,7 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) fig, ax, sc = triplot(tri) fig @test_reference joinpath(fig_path, "constrained_ex_7.png") fig #src @@ -174,10 +174,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -185,7 +188,7 @@ dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] nodes, points = convert_boundary_points_to_indices(curves) -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "constrained_ex_8.png") fig by=psnr_equality(12) #src \ No newline at end of file +@test_reference joinpath(fig_path, "constrained_ex_8.png") fig by = psnr_equality(12) #src diff --git a/docs/src/literate_tutorials/constrained_outer_boundary.jl b/docs/src/literate_tutorials/constrained_outer_boundary.jl index d16deacb7..6beedd33a 100644 --- a/docs/src/literate_tutorials/constrained_outer_boundary.jl +++ b/docs/src/literate_tutorials/constrained_outer_boundary.jl @@ -19,7 +19,7 @@ pts = [ (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), - (1.34, 6.77), (1.24, 4.15) + (1.34, 6.77), (1.24, 4.15), ] # To define a boundary, we need to provide a counter-clockwise sequence @@ -35,9 +35,9 @@ boundary_points = [ (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), - (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0) + (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0), ] -boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=pts); +boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = pts); # The keyword argument `existing_points` is so that the points in `boundary_points` get appended (in-place) to # `pts`, as we see: @@ -53,14 +53,18 @@ cons_tri = triangulate(pts; boundary_nodes) #- fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) -triplot!(ax2, cons_tri, show_constrained_edges=true, show_convex_hull=true) +triplot!(ax2, cons_tri, show_constrained_edges = true, show_convex_hull = true) resize_to_layout!(fig) fig @test_reference joinpath(fig_path, "constrained_ex_2.png") fig #src @@ -71,8 +75,8 @@ fig # no longer contains every point in `pts`, as by default all triangles away # from the boundary are deleted, so that we do actually have a boundary. If for # some reason you do not want this behaviour, use `delete_holes = false`: -full_tri = triangulate(pts; boundary_nodes, delete_holes=false) -fig, ax, sc = triplot(full_tri, show_constrained_edges=true, show_convex_hull=true) +full_tri = triangulate(pts; boundary_nodes, delete_holes = false) +fig, ax, sc = triplot(full_tri, show_constrained_edges = true, show_convex_hull = true) @test_reference joinpath(fig_path, "constrained_ex_3.png") fig #src # This default behaviour does mean you need to be careful if you use [`DelaunayTriangulation.each_point`](@ref) @@ -83,7 +87,7 @@ fig, ax, sc = triplot(full_tri, show_constrained_edges=true, show_convex_hull=tr # There are multiple methods available for working directly # with the boundary nodes. You can get the boundary nodes # using `get_boundary_nodes(tri)`: -get_boundary_nodes(cons_tri) +get_boundary_nodes(cons_tri) # Later tutorials also consider other methods for working with the boundary # where care needs to be taken with the boundary, or part of the boundary, @@ -98,15 +102,15 @@ function shoelace_area(tri) bn = get_boundary_nodes(tri) n = num_boundary_edges(bn) # length(bn) - 1 in this case since bn[1] = bn[end] A = 0.0 - for i in 1:n + for i in 1:n vᵢ = get_boundary_nodes(bn, i) - vᵢ₊₁ = get_boundary_nodes(bn, i+1) + vᵢ₊₁ = get_boundary_nodes(bn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end - return A/2 + return A / 2 end shoelace_area(cons_tri) @test shoelace_area(cons_tri) ≈ get_area(cons_tri) #src @@ -127,8 +131,8 @@ bn = get_boundary_nodes(cons_tri, I) # same as boundary_nodes for this problem; bn_j = get_boundary_nodes(bn, J) # This returns `23`, which is the start of the edge `e`. The full edge is given by -get_boundary_nodes.(Ref(bn), (J, J+1)) # Ref to not broadcast over bn -@test e == get_boundary_nodes.(Ref(bn), (J, J+1)) #src +get_boundary_nodes.(Ref(bn), (J, J + 1)) # Ref to not broadcast over bn +@test e == get_boundary_nodes.(Ref(bn), (J, J + 1)) #src # To give an example, here's how we compute the perimeter of the triangulation. This only # needs the edges, so we only consider the `keys` of the map. @@ -142,5 +146,5 @@ function get_perimeter(tri) end return ℓ end -get_perimeter(cons_tri) -@test get_perimeter(cons_tri) ≈ sum(norm(get_point(cons_tri, boundary_nodes[i+1]) .- get_point(cons_tri, boundary_nodes[i])) for i in 1:(length(boundary_nodes)-1)) #src +get_perimeter(cons_tri) +@test get_perimeter(cons_tri) ≈ sum(norm(get_point(cons_tri, boundary_nodes[i + 1]) .- get_point(cons_tri, boundary_nodes[i])) for i in 1:(length(boundary_nodes) - 1)) #src diff --git a/docs/src/literate_tutorials/constrained_outer_boundary_segmented.jl b/docs/src/literate_tutorials/constrained_outer_boundary_segmented.jl index 7811ea623..0ff92eec3 100644 --- a/docs/src/literate_tutorials/constrained_outer_boundary_segmented.jl +++ b/docs/src/literate_tutorials/constrained_outer_boundary_segmented.jl @@ -16,7 +16,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src # Now, we define some of the points we will be triangulating. points = [ (2.0, 8.0), (6.0, 4.0), (2.0, 6.0), - (2.0, 4.0), (8.0, 2.0) + (2.0, 4.0), (8.0, 2.0), ] # We now want to define our boundary. The method for providing a boundary to be @@ -33,14 +33,14 @@ boundary_points = [section_1, section_2, section_3] # [`convert_boundary_points_to_indices`](@ref), and then we triangulate. # We also add a constrained edge. E = Set(((6, 9),)) # (0, 0) → (4, 6) -boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points=points) -tri = triangulate(points; boundary_nodes, segments=E) +boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points = points) +tri = triangulate(points; boundary_nodes, segments = E) #- -fig, ax, sc = triplot(tri, show_constrained_edges=true, constrained_edge_linewidth=6) -lines!(ax, section_1, color=:red, linewidth=6) -lines!(ax, section_2, color=:green, linewidth=6) -lines!(ax, section_3, color=:blue, linewidth=6) +fig, ax, sc = triplot(tri, show_constrained_edges = true, constrained_edge_linewidth = 6) +lines!(ax, section_1, color = :red, linewidth = 6) +lines!(ax, section_2, color = :green, linewidth = 6) +lines!(ax, section_3, color = :blue, linewidth = 6) fig @test_reference joinpath(fig_path, "constrained_ex_4.png") fig #src @@ -128,7 +128,7 @@ get_adjacent2vertex(tri, -3) function compute_sum_2(tri) edges = get_adjacent2vertex(tri, -2) s = 0.0 - for e in edges + for e in edges u, v = edge_vertices(e) p, q = get_point(tri, u, v) px, py = getxy(p) @@ -151,4 +151,4 @@ get_neighbours(tri, -2) get_ghost_vertex_map(tri) # In this case, the `i`th section just has the ghost vertex `-i`, but this is typically used -# to deal with the case of multiple boundaries so that we know where a ghost vertex belongs. \ No newline at end of file +# to deal with the case of multiple boundaries so that we know where a ghost vertex belongs. diff --git a/docs/src/literate_tutorials/convex.jl b/docs/src/literate_tutorials/convex.jl index 9f59b36a9..b8507120a 100644 --- a/docs/src/literate_tutorials/convex.jl +++ b/docs/src/literate_tutorials/convex.jl @@ -13,14 +13,14 @@ fig_path = joinpath(@__DIR__, "../figures") #src points = [ (10.0, 12.0), (7.0, 11.0), (8.0, 6.0), (10.0, 3.0), (14.0, 5.0), (15.0, 10.0), - (13.0, 12.0) + (13.0, 12.0), ] S = 1:7 tri = triangulate_convex(points, 1:7) #- fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "convex_ex_1.png") fig #src # This `tri` is our triangulation of the convex polygon. @@ -33,7 +33,7 @@ fig # Let us give a larger example. For simplicity, we triangulate a # a discretised circle. -θ = LinRange(0, 2π, 5000) |> collect +θ = LinRange(0, 2π, 5000) |> collect pop!(θ) x = cos.(θ) y = sin.(θ) @@ -43,16 +43,16 @@ tri = triangulate_convex(points, S) #- fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "convex_ex_2.png") fig #src # Here is a comparison of the time it takes to triangulate this # using `triangulate_convex` or `triangulate`. -using BenchmarkTools -@benchmark triangulate_convex($points, $S) +using BenchmarkTools +@benchmark triangulate_convex($points, $S) #- -@benchmark triangulate($points) +@benchmark triangulate($points) # For the smaller example that we started with above, `triangulate_convex` is also -# faster, although not by much (≈15.10 μs versus ≈10.7 μs). \ No newline at end of file +# faster, although not by much (≈15.10 μs versus ≈10.7 μs). diff --git a/docs/src/literate_tutorials/convex_hull.jl b/docs/src/literate_tutorials/convex_hull.jl index 2e1a77f72..65be85435 100644 --- a/docs/src/literate_tutorials/convex_hull.jl +++ b/docs/src/literate_tutorials/convex_hull.jl @@ -35,7 +35,7 @@ get_convex_hull_vertices(tri) # from the points without constructing the triangulation, use [`convex_hull`](@ref): ch = convex_hull(points) ch_points = [get_point(tri, i) for i in DelaunayTriangulation.get_vertices(ch)] -fig, ax, sc = lines(ch_points, color=:red, linewidth=4) +fig, ax, sc = lines(ch_points, color = :red, linewidth = 4) scatter!(ax, points) fig @test_reference joinpath(fig_path, "convex_hull_ex_1.png") fig #src diff --git a/docs/src/literate_tutorials/curve_bounded.jl b/docs/src/literate_tutorials/curve_bounded.jl index 290c23e15..048e57693 100644 --- a/docs/src/literate_tutorials/curve_bounded.jl +++ b/docs/src/literate_tutorials/curve_bounded.jl @@ -37,7 +37,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src n = 50 r = 2.0 xc, yc = 1 / 2, 2.0 -θ = range(0, 2π, length=n + 1) |> collect; +θ = range(0, 2π, length = n + 1) |> collect; θ[end] = θ[begin]; x = xc .+ r * cos.(θ) y = yc .+ r * sin.(θ); @@ -61,9 +61,9 @@ fig, ax, sc = lines(points) # Let's now triangulate this domain. We need to put the arc into its own vector, and we still need to pass a set of # points into `triangulate`: -points = NTuple{2,Float64}[] +points = NTuple{2, Float64}[] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=[arc], rng) +tri = triangulate(points; boundary_nodes = [arc], rng) #- fig, ax, sc = triplot(tri) @@ -78,7 +78,7 @@ fig # # This is probably not what we actually want, though. Instead, we need to refine the domain using mesh refinement. # The syntax for this is the same as in the [refinement tutorial](../tutorials/refinement.md): -refine!(tri; max_area=1e-1, rng) +refine!(tri; max_area = 1.0e-1, rng) fig, ax, sc = triplot(tri) fig @test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_2.png") fig #src @@ -113,53 +113,55 @@ fig # to the origin to be smaller than those outside of it. curve = [[arc], [bspl], pce] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; max_area=1e-2, rng, custom_constraint=(_tri, T) -> begin - i, j, k = triangle_vertices(T) - p, q, r = get_point(_tri, i, j, k) - c = (p .+ q .+ r) ./ 3 - return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1e-3 -end) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!( + tri; max_area = 1.0e-2, rng, custom_constraint = (_tri, T) -> begin + i, j, k = triangle_vertices(T) + p, q, r = get_point(_tri, i, j, k) + c = (p .+ q .+ r) ./ 3 + return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1.0e-3 + end, +) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_3.png") fig by=psnr_equality(8) #src +@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_3.png") fig by = psnr_equality(8) #src # ## A Complicated Multiply-Connected Disjoint Domain # For our last example, we take a complicated case with a domain that is disjoint, and where the individual # domains are multiply-connected. Let us give the domain followed by an explanation of how it is defined: curve = [ [ - [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])] + [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] t = LinRange(0, 1, 1000) fig fig = Figure() ax = Axis(fig[1, 1]) -lines!(ax, [get_point(points, curve[1][1]...)...], color=:red, label="(1, 2, 3)") -lines!(ax, curve[1][2][1].(t), color=:red, linestyle=:dashdot, label="EllipticalArc") -lines!(ax, curve[2][1][1].(t), color=:green, label="BSpline") -lines!(ax, [get_point(points, curve[3][1]...)...], color=:blue, label="(4, 5, 6, 7, 4)") -lines!(ax, curve[4][1][1].(t), color=:purple, label="BezierCurve") -lines!(ax, curve[4][2][1].(t), color=:purple, linestyle=:dashdot, label="CatmullRomSpline") -lines!(ax, [get_point(points, curve[5][1]...)...], color=:orange, label="(12, 11, 10, 12)") -lines!(ax, curve[6][1][1].(t), color=:black, label="CircularArc") +lines!(ax, [get_point(points, curve[1][1]...)...], color = :red, label = "(1, 2, 3)") +lines!(ax, curve[1][2][1].(t), color = :red, linestyle = :dashdot, label = "EllipticalArc") +lines!(ax, curve[2][1][1].(t), color = :green, label = "BSpline") +lines!(ax, [get_point(points, curve[3][1]...)...], color = :blue, label = "(4, 5, 6, 7, 4)") +lines!(ax, curve[4][1][1].(t), color = :purple, label = "BezierCurve") +lines!(ax, curve[4][2][1].(t), color = :purple, linestyle = :dashdot, label = "CatmullRomSpline") +lines!(ax, [get_point(points, curve[5][1]...)...], color = :orange, label = "(12, 11, 10, 12)") +lines!(ax, curve[6][1][1].(t), color = :black, label = "CircularArc") fig[1, 2] = Legend(fig, ax, "Curve") fig @@ -182,11 +184,11 @@ fig # # Let's now triangulate. rng = StableRNG(123) -tri = triangulate(copy(points); boundary_nodes=curve, rng) # copying so that we don't mutate for the next section -refine!(tri; max_area=1e-2) +tri = triangulate(copy(points); boundary_nodes = curve, rng) # copying so that we don't mutate for the next section +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_4.png") fig by=psnr_equality(15) #src +@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_4.png") fig by = psnr_equality(15) #src # ### Using Custom Constraints to Control Refinement # Let's give another example of using custom constraints to better control the refinement within different domains. Referencing the @@ -205,18 +207,18 @@ poly_constraint = (_tri, T) -> begin return true end max_area = if idx == 1 # coarse - 1e-1 + 1.0e-1 elseif idx == 3 # medium - 1e-2 + 1.0e-2 else # dense - 1e-3 + 1.0e-3 end area = DelaunayTriangulation.triangle_area(p, q, r) return area > max_area end rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; custom_constraint=poly_constraint, rng) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!(tri; custom_constraint = poly_constraint, rng) fig, ax, sc = triplot(tri) fig @test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_5.png") fig #src @@ -240,7 +242,7 @@ fig # # Let's now meet these requirements. struct Astroid <: DelaunayTriangulation.AbstractParametricCurve - lookup_table::Vector{NTuple{2,Float64}} + lookup_table::Vector{NTuple{2, Float64}} end function (c::Astroid)(t) if t == 0.0 || t == 1.0 @@ -268,7 +270,7 @@ end # Let's now define an astroid curve and triangulate it. function Astroid(n::Int) - lookup_table = Vector{NTuple{2,Float64}}(undef, n) + lookup_table = Vector{NTuple{2, Float64}}(undef, n) c = Astroid(lookup_table) for i in 1:n lookup_table[i] = c((i - 1) / (n - 1)) @@ -277,8 +279,8 @@ function Astroid(n::Int) end rng = StableRNG(123) curve = Astroid(1000) -tri = triangulate(NTuple{2,Float64}[]; boundary_nodes=[curve], rng) -refine!(tri; max_area=1e-2) +tri = triangulate(NTuple{2, Float64}[]; boundary_nodes = [curve], rng) +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) -fig -@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_6.png") fig #src \ No newline at end of file +fig +@test_reference joinpath(fig_path, "triangulate_curve_bounded_ex_6.png") fig #src diff --git a/docs/src/literate_tutorials/custom_primitive.jl b/docs/src/literate_tutorials/custom_primitive.jl index 51aa0988b..d3b232f5f 100644 --- a/docs/src/literate_tutorials/custom_primitive.jl +++ b/docs/src/literate_tutorials/custom_primitive.jl @@ -48,7 +48,7 @@ struct CustomPolygon segments::Vector{CustomPolygonSegment} end struct CustomPolygons{N} - polygons::NTuple{N,CustomPolygon} + polygons::NTuple{N, CustomPolygon} end # Now, depending on your application you might not need to define all possible methods. For example, if you just want an unconstrained triangulation, all you need are `CustomPoint` @@ -102,8 +102,8 @@ DT.num_sections(poly::CustomPolygon) = length(poly.segments) DT.num_boundary_edges(seg::CustomPolygonSegment) = length(seg.segments) DT.get_boundary_nodes(poly::CustomPolygons, m::Integer) = poly.polygons[m] # go down to the mth polygon DT.get_boundary_nodes(poly::CustomPolygon, m::Integer) = poly.segments[m] # go down to the mth segment -DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m-1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node -DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2,Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) +DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m - 1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node +DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2, Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) # We now have all that we need for defining our custom primitives for constrained triangulations. We can go further and define methods # for working with Voronoi tessellations and centroidal Voronoi tessellations. For these methods, note that these only apply to unconstrained @@ -125,9 +125,9 @@ DT.contains_edge(e::CustomSegment, Es::CustomSegments) = e ∈ Es.segments Base.empty!(triangles::CustomTriangles) = empty!(triangles.triangles) function Base.insert!(seg::CustomPolygonSegment, index, node) - cur_segment = seg.segments[index-1] + cur_segment = seg.segments[index - 1] u, v = edge_vertices(cur_segment) - seg.segments[index-1] = CustomSegment(u, node) + seg.segments[index - 1] = CustomSegment(u, node) insert!(seg.segments, index, CustomSegment(node, v)) return seg end @@ -144,26 +144,31 @@ p8 = CustomPoint(0.75, 0.75) p9 = CustomPoint(0.25, 0.75) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) segments = CustomSegments(Set{CustomSegment}((CustomSegment(2, 7), CustomSegment(8, 3)))) -outer_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), - CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), -]) -inner_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), -]) +outer_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), + CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), + ], +) +inner_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), + ], +) polygons = CustomPolygons((outer_polygon, inner_polygon)); # Now we triangulate and refine. rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=polygons, segments, - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng +tri = triangulate( + points; boundary_nodes = polygons, segments, + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, ) -refine!(tri; max_area=1e-3, rng) +refine!(tri; max_area = 1.0e-3, rng) fig, ax, sc = triplot(tri) fig @test_reference joinpath(fig_path, "custom_structs_ex_1.png") fig by = psnr_equality(5.0) #src @@ -172,14 +177,16 @@ fig # this all works. rng = StableRNG(123) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) -tri = triangulate(points; - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng) -vorn = voronoi(tri; clip=true, smooth=true, rng) +tri = triangulate( + points; + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, +) +vorn = voronoi(tri; clip = true, smooth = true, rng) fig, ax, sc = voronoiplot(vorn) fig -@test_reference joinpath(fig_path, "custom_structs_ex_2.png") fig by = psnr_equality(5.0) #src \ No newline at end of file +@test_reference joinpath(fig_path, "custom_structs_ex_2.png") fig by = psnr_equality(5.0) #src diff --git a/docs/src/literate_tutorials/lattice.jl b/docs/src/literate_tutorials/lattice.jl index 352b769b6..66bea1069 100644 --- a/docs/src/literate_tutorials/lattice.jl +++ b/docs/src/literate_tutorials/lattice.jl @@ -23,7 +23,7 @@ fig # lattice manually and `triangulate` those. Here's a comparison of the times. using BenchmarkTools points = get_points(tri) -@benchmark triangulate($points; randomise=$false) # randomise=false because points are already in lattice order, i.e. spatially sorted +@benchmark triangulate($points; randomise = $false) # randomise=false because points are already in lattice order, i.e. spatially sorted #- @benchmark triangulate_rectangle($a, $b, $c, $d, $nx, $ny) @@ -44,11 +44,11 @@ tri @test DelaunayTriangulation.has_ghost_triangles(tri) #src # You can opt into not having these by using `delete_ghosts=true`: -tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary=true, delete_ghosts=true) +tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary = true, delete_ghosts = true) tri #- get_boundary_nodes(tri) #- -DelaunayTriangulation.has_ghost_triangles(tri) \ No newline at end of file +DelaunayTriangulation.has_ghost_triangles(tri) diff --git a/docs/src/literate_tutorials/nearest.jl b/docs/src/literate_tutorials/nearest.jl index d1201e724..7e636ce26 100644 --- a/docs/src/literate_tutorials/nearest.jl +++ b/docs/src/literate_tutorials/nearest.jl @@ -18,13 +18,13 @@ using Test #src points = [ (-3.0, 7.0), (2.0, 6.0), (0.0, 3.0), (0.0, 0.0), (-5.0, 5.0), (-3.0, 1.0), - (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0) + (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0), ] tri = triangulate(points) vorn = voronoi(tri) p, q = (-2.0, 7.5), (0.0, 4.0) -fig, ax, sc = voronoiplot(vorn, markersize=14) -scatter!(ax,[p,q],color=:white,strokecolor=:black,strokewidth=2,markersize=14) +fig, ax, sc = voronoiplot(vorn, markersize = 14) +scatter!(ax, [p, q], color = :white, strokecolor = :black, strokewidth = 2, markersize = 14) fig # To get the nearest neighbour of a point, we use [`get_nearest_neighbour`](@ref). @@ -45,4 +45,4 @@ np_tri = get_nearest_neighbour(tri, p) nq_tri = get_nearest_neighbour(tri, q) @test nq_tri == 3 #src -# Both methods lead to the same results because they use the same algorithm. \ No newline at end of file +# Both methods lead to the same results because they use the same algorithm. diff --git a/docs/src/literate_tutorials/operations_convex_hull_locking.jl b/docs/src/literate_tutorials/operations_convex_hull_locking.jl index 4ba479d8d..82edc205c 100644 --- a/docs/src/literate_tutorials/operations_convex_hull_locking.jl +++ b/docs/src/literate_tutorials/operations_convex_hull_locking.jl @@ -44,4 +44,4 @@ get_boundary_nodes(tri) # Note that this locking/unlocking doesn't actually change anything about the triangulation, # it just adds information into `tri` to treat it as if you had provided -# the convex hull as a constrained boundary to start with. \ No newline at end of file +# the convex hull as a constrained boundary to start with. diff --git a/docs/src/literate_tutorials/operations_flip_edge.jl b/docs/src/literate_tutorials/operations_flip_edge.jl index 39e77aa17..98c70e379 100644 --- a/docs/src/literate_tutorials/operations_flip_edge.jl +++ b/docs/src/literate_tutorials/operations_flip_edge.jl @@ -13,15 +13,15 @@ T4 = points[[2, 3, 4]] #hide fig = Figure() #hide ax1 = Axis(fig[1, 1], width = 600, height = 400) #hide ax2 = Axis(fig[1, 2], width = 600, height = 400) #hide -poly!(ax1, [T1; T2], color=(:white, 0.0), strokewidth=3) #hide -poly!(ax2, [T3; T4], color=(:white, 0.0), strokewidth=3) #hide +poly!(ax1, [T1; T2], color = (:white, 0.0), strokewidth = 3) #hide +poly!(ax2, [T3; T4], color = (:white, 0.0), strokewidth = 3) #hide for ax in (ax1, ax2) #hide hidedecorations!(ax) #hide hidespines!(ax) #hide - text!(ax, [(0.05, -1.1)]; text=[L"p_j"], fontsize=43) #hide - text!(ax, [(0.9, 0.1)]; text=[L"p_k"], fontsize=43) #hide - text!(ax, [(0.05, 1.0)]; text=[L"p_i"], fontsize=43) #hide - text!(ax, [(-1.05, 0.05)]; text=[L"p_\ell"], fontsize=43) #hide + text!(ax, [(0.05, -1.1)]; text = [L"p_j"], fontsize = 43) #hide + text!(ax, [(0.9, 0.1)]; text = [L"p_k"], fontsize = 43) #hide + text!(ax, [(0.05, 1.0)]; text = [L"p_i"], fontsize = 43) #hide + text!(ax, [(-1.05, 0.05)]; text = [L"p_\ell"], fontsize = 43) #hide xlims!(ax, -1.1, 1.1) #hide ylims!(ax, -1.3, 1.3) #hide end #hide @@ -43,7 +43,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src # Let us now define our initial triangulation. points = [(0.0, 0.0), (0.8, 0.0), (1.3, 1.0), (0.0, 1.0)] -tri = triangulate(points); +tri = triangulate(points); # Now, flipping the edge is simple. We simply provide the indices `i` and `j` # for the edge we want to flip. Let us flip the edge `(2, 4)`. @@ -57,4 +57,4 @@ fig # As simple as that. Note that no checks are made for whether the edge is actually in the # triangulation, on the boundary, or if the associated quadrilateral is convex. It is # up to you to check this if needed; one way to check would be to use [`DelaunayTriangulation.is_legal`](@ref), -# as is done inside [`legalise_edge!`](@ref) -- see the [next tutorial](operations_legalise_edge.md). \ No newline at end of file +# as is done inside [`legalise_edge!`](@ref) -- see the [next tutorial](operations_legalise_edge.md). diff --git a/docs/src/literate_tutorials/operations_legalise_edge.jl b/docs/src/literate_tutorials/operations_legalise_edge.jl index ded10c965..417daeec5 100644 --- a/docs/src/literate_tutorials/operations_legalise_edge.jl +++ b/docs/src/literate_tutorials/operations_legalise_edge.jl @@ -32,12 +32,12 @@ points = [ (-1.0, 2.0), (4.0, 6.0), (4.0, 3.0), (-3.0, 7.0), (-6.0, -1.0), (9.0, 5.0), (5.0, -5.0), (-6.0, 7.0), (0.0, 0.0), (-3.0, 4.0), (-5.0, 5.0), (-3.0, -4.0), - (5.0, -1.0), (2.0, -2.0) + (5.0, -1.0), (2.0, -2.0), ] p = (3.0, 2.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig @test_reference joinpath(fig_path, "triangulation_operations_13.png") fig #src @@ -56,7 +56,7 @@ fig # This splitting introduces some new illegal edges, shown in red below. function get_all_illegal_edges(tri) #hide - T = NTuple{2,Float64}[] #hide + T = NTuple{2, Float64}[] #hide for E in each_edge(tri) #hide cert = DelaunayTriangulation.is_legal(tri, E...) #hide if DelaunayTriangulation.is_illegal(cert) #hide @@ -67,7 +67,7 @@ function get_all_illegal_edges(tri) #hide end #hide fig, ax, sc = triplot(tri) #hide T = get_all_illegal_edges(tri) #hide -linesegments!(ax, T, color=:red, linewidth=3) #hide +linesegments!(ax, T, color = :red, linewidth = 3) #hide fig #hide @test_reference joinpath(fig_path, "triangulation_operations_15.png") fig #src @@ -82,4 +82,4 @@ fig, ax, sc = triplot(tri) fig @test_reference joinpath(fig_path, "triangulation_operations_16.png") fig #src -# The triangulation is now Delaunay, and there are no more illegal edges. \ No newline at end of file +# The triangulation is now Delaunay, and there are no more illegal edges. diff --git a/docs/src/literate_tutorials/operations_segment_insertion.jl b/docs/src/literate_tutorials/operations_segment_insertion.jl index 37fdb2489..972f17b6e 100644 --- a/docs/src/literate_tutorials/operations_segment_insertion.jl +++ b/docs/src/literate_tutorials/operations_segment_insertion.jl @@ -9,8 +9,10 @@ using Test #src fig_path = joinpath(@__DIR__, "../figures") #src # Let us now define our initial triangulation. -points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), -(0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8)] +points = [ + (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), + (0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8), +] tri = triangulate(points) fig, ax, sc = triplot(tri) fig @@ -23,7 +25,7 @@ add_segment!(tri, 1, 3) fig, ax, sc = triplot(tri, show_constrained_edges = true) fig @test_reference joinpath(fig_path, "triangulation_operations_9.png") fig #src - + # Of course, this changed nothing since the segment was already there. We do note, # though, that if we look at the constrained edges get_interior_segments(tri) @@ -44,7 +46,7 @@ fig # if we do this: add_segment!(tri, 8, 2) fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "triangulation_operations_11.png") fig #src -# The other constrained edge was partially removed. \ No newline at end of file +# The other constrained edge was partially removed. diff --git a/docs/src/literate_tutorials/operations_split_edge.jl b/docs/src/literate_tutorials/operations_split_edge.jl index 9f21a239f..e33deb977 100644 --- a/docs/src/literate_tutorials/operations_split_edge.jl +++ b/docs/src/literate_tutorials/operations_split_edge.jl @@ -11,13 +11,15 @@ using ReferenceTests #src using Test #src fig_path = joinpath(@__DIR__, "../figures") #src -points = [(0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), +points = [ + (0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), (-2.0, 7.0), (3.0, 6.0), (2.0, -2.0), (-4.0, 1.0), - (1.0, 5.0)] + (1.0, 5.0), +] p = (0.0, 3.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig @test_reference joinpath(fig_path, "triangulation_operations_17.png") fig #src @@ -28,7 +30,7 @@ r = length(points) i, j = 1, 2 split_edge!(tri, i, j, r) fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "triangulation_operations_18.png") fig #src # Notice that this has only split the edge in one direction. This is because the @@ -36,7 +38,7 @@ fig # direction, we simply swap the indices. split_edge!(tri, j, i, r) fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "triangulation_operations_19.png") fig #src # If you also want to restore the Delaunay property of the triangulation @@ -50,4 +52,4 @@ legalise_edge!(tri, i, k, r) legalise_edge!(tri, k, j, r) # These steps, in particular the steps of splitting both sides of the edge and then -# legalising, are also implemented in [`DelaunayTriangulation.complete_split_edge_and_legalise!`](@ref). \ No newline at end of file +# legalising, are also implemented in [`DelaunayTriangulation.complete_split_edge_and_legalise!`](@ref). diff --git a/docs/src/literate_tutorials/operations_split_triangle.jl b/docs/src/literate_tutorials/operations_split_triangle.jl index d6ff9b15d..f7c443988 100644 --- a/docs/src/literate_tutorials/operations_split_triangle.jl +++ b/docs/src/literate_tutorials/operations_split_triangle.jl @@ -17,7 +17,7 @@ points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] p = (0.2, 0.5) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig @test_reference joinpath(fig_path, "triangulation_operations_20.png") fig #src @@ -36,4 +36,4 @@ fig # See the [`legalise_edge!` tutorial](operations_legalise_edge.md) for more discussion # about restoring the Delaunay property of the triangulation after using -# `split_triangle!`. \ No newline at end of file +# `split_triangle!`. diff --git a/docs/src/literate_tutorials/operations_vertex_insertion_deletion.jl b/docs/src/literate_tutorials/operations_vertex_insertion_deletion.jl index c5c34a5ad..bce30a9ef 100644 --- a/docs/src/literate_tutorials/operations_vertex_insertion_deletion.jl +++ b/docs/src/literate_tutorials/operations_vertex_insertion_deletion.jl @@ -35,16 +35,16 @@ fig # small number of points. We can also add points that are outside of the triangulation: add_point!(tri, 0.0, 1.0) fig, ax, sc = triplot(tri) -fig +fig @test_reference joinpath(fig_path, "triangulation_operations_3.png") fig #src # One important thing to note here is that, if not for the ghost triangles inside `tri`, # adding a point outside of the triangulation would not work. Here is an example of this failing. delete_ghost_triangles!(tri) try #hide -add_point!(tri, 2.0, 1.5) + add_point!(tri, 2.0, 1.5) catch e #hide -println(e) #hide + println(e) #hide end #hide # This is a `BoundsError`, because the triangulation has had to @@ -67,7 +67,7 @@ get_convex_hull_vertices(tri) # If we do want to fix the convex hull, we can use [`convex_hull!(tri)`](@ref). convex_hull!(tri) -fig, ax, sc = triplot(tri, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_convex_hull = true) fig @test_reference joinpath(fig_path, "triangulation_operations_4.png") fig #src @@ -101,4 +101,4 @@ fig # Note that in this situation, `points` still contains those points that we have now deleted. # This is the reason to be careful about using, say, [`DelaunayTriangulation.each_point`](@ref) rather than [`each_solid_vertex`](@ref). -# This triangulation is also still Delaunay. \ No newline at end of file +# This triangulation is also still Delaunay. diff --git a/docs/src/literate_tutorials/point_in_polygon.jl b/docs/src/literate_tutorials/point_in_polygon.jl index 19e0cf98c..0eb2a5d15 100644 --- a/docs/src/literate_tutorials/point_in_polygon.jl +++ b/docs/src/literate_tutorials/point_in_polygon.jl @@ -154,10 +154,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -172,7 +175,7 @@ fig = Figure() ax = Axis(fig[1, 1]) scatter!(ax, query_points) for nodes in nodes - lines!(ax, points[reduce(vcat, nodes)], color=:magenta, linewidth=3) + lines!(ax, points[reduce(vcat, nodes)], color = :magenta, linewidth = 3) end fig @@ -187,23 +190,23 @@ fig # here do not use exact arithmetic, unlike other predicates in this package, so there may be some robustness issues # for points very close to the boundary. Here is the first approach: is_inside = [DelaunayTriangulation.distance_to_polygon(q, points, nodes) > 0 for q in query_points] -scatter!(ax, query_points[is_inside], color=:blue) -scatter!(ax, query_points[.!is_inside], color=:red) +scatter!(ax, query_points[is_inside], color = :blue) +scatter!(ax, query_points[.!is_inside], color = :red) fig @test_reference joinpath(fig_path, "point_in_polygon_ex_1.png") fig #src # Here is the second method. -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) is_inside_2 = [DelaunayTriangulation.dist(tri, q) > 0 for q in query_points]; @test is_inside == is_inside_2 #src # The third method is to use [`find_polygon`](@ref) to find the polygon containing the point. If no such polygon exists, `find_polygon` returns # `0`, so this is what we use to determine if a point is inside or outside the polygon. is_inside_3 = [find_polygon(tri, q) ≠ 0 for q in query_points]; -@test mean(is_inside) ≈ mean(is_inside_3) atol = 1e-2 #src +@test mean(is_inside) ≈ mean(is_inside_3) atol = 1.0e-2 #src # This test is not exactly the same as the previous one (with a difference of about five points) due to points near the boundary. # The fourth method is: hierarchy = DelaunayTriangulation.construct_polygon_hierarchy(points, nodes) is_inside_4 = [find_polygon(hierarchy, points, nodes, q) ≠ 0 for q in query_points]; -@test is_inside_4 == is_inside_3 #src \ No newline at end of file +@test is_inside_4 == is_inside_3 #src diff --git a/docs/src/literate_tutorials/point_location.jl b/docs/src/literate_tutorials/point_location.jl index 0ca4aeeb2..8c16c791c 100644 --- a/docs/src/literate_tutorials/point_location.jl +++ b/docs/src/literate_tutorials/point_location.jl @@ -25,7 +25,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src points = [ (-3.0, 6.0), (5.0, 1.0), (-5.0, 3.0), (2.0, -3.0), (5.0, 8.0), (0.0, 0.0), (2.0, 5.0), (-3.0, 1.0), - (-2.0, -1.0), (-1.0, 4.0) + (-2.0, -1.0), (-1.0, 4.0), ] tri = triangulate(points) q = (3.0, 3.0) @@ -45,14 +45,14 @@ DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) # sample some number of points (defaults to $\lceil \sqrt[3]{n}\rceil$, where $n$ is the number of points), # and then start at the point that is closest to `q` out of those sampled, then marching along the triangulation # until `q` is found. This number of samples can be changed using the `m` keyword argument. For example, -V = find_triangle(tri, q, m=10) +V = find_triangle(tri, q, m = 10) @test DelaunayTriangulation.is_inside(DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)) #src # means that we get a sample of size 10, and start at whichever point is the closest. # (For technical reasons, this sampling is with replacement, so it is possible that the same point is sampled more than once.) # You could also instead specify the point to start at using the `k` keyword argument, in which case no points are sampled. # For example, -V = find_triangle(tri, q, k=6) +V = find_triangle(tri, q, k = 6) @test DelaunayTriangulation.is_inside(DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)) #src # starts the algorithm at the point `6`. @@ -75,7 +75,7 @@ V = find_triangle(tri, q) # this can be interpreted as meaning that `q` is between the two lines through the points `1` and `5` that # start at a central point of the triangulation. (The index `-1` is just the ghost vertex.) This can # be visualised. -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) scatter!(ax, q) fig @test_reference joinpath(fig_path, "point_location_ex_1.png") fig #src @@ -98,13 +98,13 @@ inner = [[r, z, v, u, w, t, s, r]] boundary_nodes, points = convert_boundary_points_to_indices([outer, inner]) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.01get_area(tri), rng); +refine!(tri; max_area = 0.01get_area(tri), rng); # The issue with concavity is that the ghost triangles can no longer be sensibly defined. # To demonstrate this, see the following plot: -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) fig -@test_reference joinpath(fig_path, "point_location_ex_2.png") fig by=psnr_equality(15) #src +@test_reference joinpath(fig_path, "point_location_ex_2.png") fig by = psnr_equality(15) #src # The ghost edges now intersect the boundary, which doesn't make sense, and creates difficulties. # Let us now demonstrate how the function still works here. We try finding the blue points shown below. @@ -112,12 +112,12 @@ qs = [ (4.0, 5.0), (1.0, 5.6), (0.2, 5.0), (0.0, -1.0), (0.5, 3.5), (2.5, 1.5), (1.0, 2.0), (4.5, 1.0), (6.0, 1.5), - (0.5, 8.5), (1.0, 7.5), (1.2, 1.6) + (0.5, 8.5), (1.0, 7.5), (1.2, 1.6), ] -fig, ax, sc = triplot(tri, show_ghost_edges=false) -scatter!(ax, qs, color=:blue, markersize=16) +fig, ax, sc = triplot(tri, show_ghost_edges = false) +scatter!(ax, qs, color = :blue, markersize = 16) fig -@test_reference joinpath(fig_path, "point_location_ex_3.png") fig by=psnr_equality(15) #src +@test_reference joinpath(fig_path, "point_location_ex_3.png") fig by = psnr_equality(15) #src # Now let's find the triangles. Vs = [find_triangle(tri, q; rng) for q in qs] @@ -131,7 +131,7 @@ Vs[end] # will enable a check to be made that the point is actually outside the triangulation whenever # a ghost triangle is to be returned. If the check finds this to not be the case, it # restarts. With these results, we now compute: -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] # Here is how we can actually test that these results are now correct. We cannot directly # use [`DelaunayTriangulation.point_position_relative_to_triangle`](@ref) because it does not @@ -167,24 +167,24 @@ v₁, w₁ = (5.0, 3.0), (4.0, 3.0) new_domain₁ = [[m₁, q₁, o₁, p₁, r₁, s₁, n₁, m₁]] new_domain₂ = [[t₁, w₁, v₁, u₁, t₁]] boundary_nodes, points = convert_boundary_points_to_indices( - [outer, inner, new_domain₁, new_domain₂] + [outer, inner, new_domain₁, new_domain₂], ) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.001get_area(tri), rng) +refine!(tri; max_area = 0.001get_area(tri), rng) qs = [ (0.6, 6.4), (1.4, 0.8), (3.1, 2.9), (6.3, 4.9), (4.6, 3.5), (7.0, 7.0), (8.9, 5.1), (5.8, 0.8), (1.0, 1.5), - (1.5, 2.0), (8.15, 6.0) + (1.5, 2.0), (8.15, 6.0), ] fig, ax, sc = triplot(tri) -scatter!(ax, qs, color=:blue, markersize=16) +scatter!(ax, qs, color = :blue, markersize = 16) fig -@test_reference joinpath(fig_path, "point_location_ex_4.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "point_location_ex_4.png") fig by = psnr_equality(10) #src # Here are the `find_triangle` results. -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] # Again, we can verify that these are all correct as follows. Without `concavity_protection=true`, # these would not be all correct. @@ -201,4 +201,4 @@ for (j, (q, δ, V)) in (enumerate ∘ zip)(qs, δs, Vs) end end results -@test all(results) #src \ No newline at end of file +@test all(results) #src diff --git a/docs/src/literate_tutorials/pole_of_inaccessibility.jl b/docs/src/literate_tutorials/pole_of_inaccessibility.jl index 340471fae..7094860cd 100644 --- a/docs/src/literate_tutorials/pole_of_inaccessibility.jl +++ b/docs/src/literate_tutorials/pole_of_inaccessibility.jl @@ -46,25 +46,26 @@ points = [ 2.12497 9.42582 7.27436 2.7979 3.0 4.0 - 5.33697 1.88019]' -outer_boundary = [ + 5.33697 1.88019 +]' +outer_boundary = [ ## split into segments for demonstration purposes [1, 4, 3, 2], [2, 9, 10, 11, 8, 7, 12], [12, 6, 13, 5, 14, 15, 16, 17, 16], - [16, 17, 18, 19, 20, 21, 22, 23, 1] + [16, 17, 18, 19, 20, 21, 22, 23, 1], ] inner_1 = [ - [26, 25, 24], [24, 28, 27, 26] + [26, 25, 24], [24, 28, 27, 26], ] inner_2 = [ - [29, 30, 31, 29] + [29, 30, 31, 29], ] boundary_nodes = [outer_boundary, inner_1, inner_2] fig = Figure() ax = Axis(fig[1, 1]) for i in eachindex(boundary_nodes) - lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color=:red) + lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color = :red) end fig @@ -74,7 +75,7 @@ pole = DelaunayTriangulation.pole_of_inaccessibility(points, boundary_nodes) @test pole[2] ≈ 5.372597499999995 #src #- -scatter!(ax, pole, color=:blue, markersize=16) +scatter!(ax, pole, color = :blue, markersize = 16) fig @test_reference joinpath(fig_path, "pole_of_inaccessibility_ex_1.png") fig #src @@ -86,7 +87,7 @@ fig # we get the triangulation. θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -97,19 +98,19 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) # To see the poles, called representative points, we use DelaunayTriangulation.get_representative_point_list(tri) # The keys of the `Dict` refer to the curve index, and the values contain # the coordinates. -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) colors = (:red, :blue, :darkgreen, :purple) for i in eachindex(boundary_nodes) - lines!(ax, points[reduce(vcat, boundary_nodes[i])], color=colors[i], linewidth=6) + lines!(ax, points[reduce(vcat, boundary_nodes[i])], color = colors[i], linewidth = 6) coords = DelaunayTriangulation.get_representative_point_coordinates(tri, i) - scatter!(ax, coords, color=colors[i], markersize=16) + scatter!(ax, coords, color = colors[i], markersize = 16) end fig @test_reference joinpath(fig_path, "pole_of_inaccessibility_ex_2.png") fig #src @@ -117,4 +118,4 @@ fig # Note that the green and purple boundaries have the same pole of inaccessibility. The # first curve, the red curve, is the only one that has the pole of inaccessibility computed # with respect to all other boundaries. You can also see that indeed the ghost edges are all -# oriented relative to the representative points. \ No newline at end of file +# oriented relative to the representative points. diff --git a/docs/src/literate_tutorials/refinement.jl b/docs/src/literate_tutorials/refinement.jl index 235e80aa1..22a50972e 100644 --- a/docs/src/literate_tutorials/refinement.jl +++ b/docs/src/literate_tutorials/refinement.jl @@ -34,7 +34,7 @@ points = tuple.(x, y) tri = triangulate(points; rng) orig_tri = deepcopy(tri) A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.01A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.01A, rng) # The [`refine!`](@ref) function operates on `tri` in-place. If we wanted to review the # statistics of the refined mesh, we can use [`statistics`](@ref): @@ -45,20 +45,20 @@ statistics(tri) # which is about 0.0067. Moreover, the smallest angle is indeed greater than 30. # Let us compare the triangulation pre- and post-refinement. -fig, ax, sc = triplot(orig_tri, axis=(title="Pre-refinement",)) -ax = Axis(fig[1, 2], title="Post-refinement") +fig, ax, sc = triplot(orig_tri, axis = (title = "Pre-refinement",)) +ax = Axis(fig[1, 2], title = "Post-refinement") triplot!(ax, tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_1.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_1.png") fig by = psnr_equality(10) #src # The triangulation is now much finer. There are still some parts with # many more triangles than other regions, but these are mostly near a boundary # or where was a cluster of random points. If we wanted, we could refine again # to try and improve this. -refine!(tri; min_angle=30.0, max_area=0.001A, rng) # 0.1% instead of 1% +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) # 0.1% instead of 1% fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_2.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_2.png") fig by = psnr_equality(10) #src # The quality has now been improved. We could also try improving the minimum # angle further, but even 30 is a bit closer to the limit of convergence (which is @@ -66,7 +66,7 @@ fig # the algorithm just doesn't even converge, instead it reaches the maximum # number of points. test_tri = deepcopy(tri) -refine!(test_tri; min_angle=35.0, max_area=0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going +refine!(test_tri; min_angle = 35.0, max_area = 0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going statistics(test_tri) # As we can see, the smallest angle is about 29 degrees instead of @@ -74,7 +74,7 @@ statistics(test_tri) # resulting triangulation is given below: fig, ax, sc = triplot(test_tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_3.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_3.png") fig by = psnr_equality(10) #src # This is certainly not a suitable triangulation. @@ -82,17 +82,17 @@ fig # that look at the areas and angles. Looking to `tri`, we can plot # these as follows: stats = statistics(tri) -fig = Figure(fontsize=33) +fig = Figure(fontsize = 33) areas = get_all_stat(stats, :area) ./ A angles = first.(get_all_stat(stats, :angles)) # the first is the smallest -ax = Axis(fig[1, 1], xlabel="A/A(Ω)", ylabel="Count", title="Area histogram", width=400, height=400, titlealign=:left) -hist!(ax, areas, bins=0:0.0001:0.0005) -ax = Axis(fig[1, 2], xlabel="θₘᵢₙ", ylabel="Count", title="Angle histogram", width=400, height=400, titlealign=:left) -hist!(ax, rad2deg.(angles), bins=20:2:60) -vlines!(ax, [30.0], color=:red) +ax = Axis(fig[1, 1], xlabel = "A/A(Ω)", ylabel = "Count", title = "Area histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, areas, bins = 0:0.0001:0.0005) +ax = Axis(fig[1, 2], xlabel = "θₘᵢₙ", ylabel = "Count", title = "Angle histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, rad2deg.(angles), bins = 20:2:60) +vlines!(ax, [30.0], color = :red) resize_to_layout!(fig) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_4.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_4.png") fig by = psnr_equality(10) #src # We see that indeed many of the triangle areas are very small, and the angles # are all greater than 30 degrees. @@ -119,14 +119,14 @@ rng = StableRNG(456) tri = triangulate(points; boundary_nodes, rng) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_5.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_5.png") fig by = psnr_equality(10) #src # Let us now refine this triangulation. A = get_area(tri) -refine!(tri; min_angle=27.3, max_area=0.01A, rng) +refine!(tri; min_angle = 27.3, max_area = 0.01A, rng) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_6.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_6.png") fig by = psnr_equality(10) #src # We inspect the plot, and we might think that it's perhaps not fine enough. # Let's use finer constraints and see what happens. Since @@ -134,10 +134,10 @@ fig # with the constraints below is going to take roughly # the same amount of time as if we had refined it with these # constraints in the first place. -refine!(tri; min_angle=33.9, max_area=0.001A, rng) +refine!(tri; min_angle = 33.9, max_area = 0.001A, rng) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_7.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_7.png") fig by = psnr_equality(10) #src # This is indeed much better, but notice that the inner hole # is much more fine than the outer. This is because we are applying the same @@ -173,10 +173,10 @@ end boundary_nodes, points = convert_boundary_points_to_indices(x, y) rng = StableRNG(456) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=30.0, custom_constraint=area_constraint, rng) +refine!(tri; min_angle = 30.0, custom_constraint = area_constraint, rng) fig, ax, sc = triplot(tri) -fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_8.png") fig by=psnr_equality(12) #src +fig +@test_reference joinpath(fig_path, "mesh_refinement_ex_8.png") fig by = psnr_equality(12) #src # This is now much better, and the two parts of the domain are # appropriately refined. Let us extend our custom constraint function to also @@ -196,8 +196,8 @@ rng = StableRNG(456) tri = triangulate(points; boundary_nodes, rng) refine!(tri; custom_constraint, rng) fig, ax, sc = triplot(tri) -fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_9.png") fig by=psnr_equality(10.0) #src +fig +@test_reference joinpath(fig_path, "mesh_refinement_ex_9.png") fig by = psnr_equality(10.0) #src # Indeed, the inner domain is much finer. These examples could be extended # to more complicated cases, for example using adaptive mesh refinement for a numerical @@ -215,7 +215,7 @@ using Downloads using DelimitedFiles boundary_url = "https://gist.githubusercontent.com/DanielVandH/13687b0918e45a416a5c93cd52c91449/raw/a8da6cdc94859fd66bcff85a2307f0f9cd57a18c/boundary.txt" boundary_dir = Downloads.download(boundary_url) -boundary = readdlm(boundary_dir, skipstart=6) +boundary = readdlm(boundary_dir, skipstart = 6) boundary_points = [(boundary[i, 1], boundary[i, 2]) for i in axes(boundary, 1)] reverse!(boundary_points) @@ -225,16 +225,16 @@ rng = StableRNG(789) tri = triangulate(points; boundary_nodes, rng) fig, ax, sc = triplot(tri) fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_10.png") fig by=psnr_equality(10) #src +@test_reference joinpath(fig_path, "mesh_refinement_ex_10.png") fig by = psnr_equality(10) #src # Now let's refine. A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.001A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) #- fig, ax, sc = triplot(tri) -fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_11.png") fig by=psnr_equality(10) #src +fig +@test_reference joinpath(fig_path, "mesh_refinement_ex_11.png") fig by = psnr_equality(10) #src # We see that the triangulation is now adequately refined. There are # still triangles near the boundaries whose minimum angle is less @@ -245,15 +245,15 @@ stats = statistics(tri) angles = first.(get_all_stat(stats, :angles)) # the first is the smallest fig, ax, sc = scatter(rad2deg.(angles)) hlines!(ax, [30.0], color = :red, linewidth = 4) -fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_12.png") fig by=psnr_equality(10) #src +fig +@test_reference joinpath(fig_path, "mesh_refinement_ex_12.png") fig by = psnr_equality(10) #src # As we can see, the vast majority of the triangles satisfy the constraint, # but there are still some that do not. Here is another set of results with a lower minimum angle constraint. boundary_nodes, points = convert_boundary_points_to_indices(boundary_points) rng = StableRNG(789) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=18.73, max_area=0.001A, rng) +refine!(tri; min_angle = 18.73, max_area = 0.001A, rng) fig = Figure(fontsize = 43) ax = Axis(fig[1, 1], width = 600, height = 400) triplot!(tri) @@ -263,8 +263,8 @@ angles = first.(get_all_stat(stats, :angles)) # the first is the smallest scatter!(ax, rad2deg.(angles)) hlines!(ax, [18.73], color = :red, linewidth = 4) resize_to_layout!(fig) -fig -@test_reference joinpath(fig_path, "mesh_refinement_ex_13.png") fig by=psnr_equality(10) #src +fig +@test_reference joinpath(fig_path, "mesh_refinement_ex_13.png") fig by = psnr_equality(10) #src # In this case, all the triangles satisfy the constraint, of course -# at the expense of some other triangles having lesser quality. \ No newline at end of file +# at the expense of some other triangles having lesser quality. diff --git a/docs/src/literate_tutorials/unconstrained.jl b/docs/src/literate_tutorials/unconstrained.jl index d4e0949dd..d817b503b 100644 --- a/docs/src/literate_tutorials/unconstrained.jl +++ b/docs/src/literate_tutorials/unconstrained.jl @@ -21,7 +21,7 @@ points = rand(rng, 2, 500) # just do rand(2, 500) if you are not concerned about # We now triangulate these points by using [`triangulate`](@ref). We pass the `rng` # as a keyword argument, but again if you are not concerned about the RNG (or # set the seed using `Random.seed!`) then you can ignore this. -tri = triangulate(points; rng=rng) +tri = triangulate(points; rng = rng) #- fig, ax, sc = triplot(tri) @@ -43,7 +43,7 @@ function compute_centroid(tri) return s end s = compute_centroid(tri) -@test s ≈ [sum(points[1, :]) / 500, sum(points[2, :]) / 500] atol = 1e-10 #src +@test s ≈ [sum(points[1, :]) / 500, sum(points[2, :]) / 500] atol = 1.0e-10 #src # We need to use the `solid` identifier because triangulations are made up of both _solid_ # and _ghost_ vertices/edges/triangles, for reasons described in the [manual](../manual/ghost_triangles.md). @@ -165,4 +165,4 @@ get_adjacent(tri, 398, 258) # means that `(398, 258)` is a boundary edge and `(398, 258, -1)` is a ghost triangle. # You can test for this case using [`DelaunayTriangulation.is_boundary_edge`](@ref): DelaunayTriangulation.is_boundary_edge(tri, 258, 398) -@test DelaunayTriangulation.is_boundary_edge(tri, 258, 398) #src \ No newline at end of file +@test DelaunayTriangulation.is_boundary_edge(tri, 258, 398) #src diff --git a/docs/src/literate_tutorials/voronoi.jl b/docs/src/literate_tutorials/voronoi.jl index 918a160d0..68182eaaf 100644 --- a/docs/src/literate_tutorials/voronoi.jl +++ b/docs/src/literate_tutorials/voronoi.jl @@ -18,7 +18,7 @@ fig_path = joinpath(@__DIR__, "../figures") #src points = [ (-3.0, 7.0), (1.0, 6.0), (-1.0, 3.0), (-2.0, 4.0), (3.0, -2.0), (5.0, 5.0), - (-4.0, -3.0), (3.0, 8.0) + (-4.0, -3.0), (3.0, 8.0), ] rng = StableRNG(123) tri = triangulate(points; rng) @@ -26,7 +26,7 @@ vorn = voronoi(tri) # To visualise the tessellation, you can use `voronoiplot`. Here, # we also compare the tessellation with its dual triangulation. -fig, ax, sc = voronoiplot(vorn, markersize=13, colormap=:matter, strokecolor=:white, strokewidth=5) +fig, ax, sc = voronoiplot(vorn, markersize = 13, colormap = :matter, strokecolor = :white, strokewidth = 5) triplot!(ax, tri) fig @test_reference joinpath(fig_path, "voronoi_ex_1.png") fig #src @@ -146,7 +146,7 @@ function get_polygon_area(vorn, i) vⱼ = vertices[begin] pⱼ = get_polygon_point(vorn, vⱼ) xⱼ, yⱼ = getxy(pⱼ) - for j in (firstindex(vertices)+1):lastindex(vertices) # same as 2:length(vertices) + for j in (firstindex(vertices) + 1):lastindex(vertices) # same as 2:length(vertices) vⱼ₊₁ = vertices[j] pⱼ₊₁ = get_polygon_point(vorn, vⱼ₊₁) xⱼ₊₁, yⱼ₊₁ = getxy(pⱼ₊₁) diff --git a/docs/src/manual/triangulation_output.md b/docs/src/manual/triangulation_output.md index 394f97663..9830c51d9 100644 --- a/docs/src/manual/triangulation_output.md +++ b/docs/src/manual/triangulation_output.md @@ -151,16 +151,16 @@ This field stores the adjacent map, mapping each edge `(u, v)` in the triangulat get_adjacent(tri) ``` -For example, the mapping `(1079, 1416) => 1926` implies that the triangle `(1079, 1416, 1926)` is in the triangulation and is positively oriented, which we can verify: +For example, the mapping `(2019, 2020) => 985` implies that the triangle `(2019, 2020, 985)` is in the triangulation and is positively oriented, which we can verify: ```@example curvout -DelaunayTriangulation.contains_triangle(tri, 1079, 1416, 1926) +DelaunayTriangulation.contains_triangle(tri, 2019, 2020, 985) ``` It is important to note that, for any triangle `(u, v, w)`, the mappings `(u, v) => w`, `(v, w) => u`, and `(w, u) => v` will all appear in the adjacent map. For example: ```@example curvout -get_adjacent(tri, 1079, 1416), get_adjacent(tri, 1416, 1926), get_adjacent(tri, 1926, 1079) +get_adjacent(tri, 2019, 2020), get_adjacent(tri, 2020, 985), get_adjacent(tri, 985, 2019) ``` You can use `get_adjacent(tri, u, v)` to find this vertex `w`, as we demonstrated above. For cases where the edge does not exist, you will get `0`: @@ -172,10 +172,10 @@ get_adjacent(tri, 1, 2) One last thing to notice is that some of the vertices `w` will be ghost vertices, and similarly some of the edges `(u, v)` will be ghost edges. For example, ```@example curvout -get_adjacent(tri, 423, 97) +get_adjacent(tri, 1690, 853) ``` -This vertex `-3` means that `(423, 97)` is an edge of the boundary associated with the ghost vertex `-3`. +This vertex `-8` means that `(1690, 853)` is an edge of the boundary associated with the ghost vertex `-8`. ### [`get_adjacent2vertex(tri)`](@ref get_adjacent2vertex) @@ -188,10 +188,10 @@ get_adjacent2vertex(tri) An example of this mapping is: ```@example curvout -get_adjacent2vertex(tri, 719) +get_adjacent2vertex(tri, 700) ``` -This output means that `(1632, 1656, 719)`, `(1055, 1687, 719)`, `(1687, 2056, 719)`, `(1162, 1055, 719)`, `(2056, 1632, 719)`, and `(1656, 1162, 719)` are all positively oriented triangles in the triangulation, and these are the only triangles that contain the vertex `719`. In contrast to `get_adjacent`, calling `get_adjacent2vertex` on a vertex not in the triangulation will throw a `KeyError`. For ghost vertices, you will get the set of all edges on the boundary associated with that vertex, for example +This output means that `(700, 1583, 933)`, `(700, 1445, 1986)`, `(700, 1986, 2017)`, `(700, 1581, 1583)`, `(700, 1604, 1445)`, `(700, 2017, 1581)`, and `(700, 933, 1604)` are all positively oriented triangles in the triangulation, and these are the only triangles that contain the vertex `700`. In contrast to `get_adjacent`, calling `get_adjacent2vertex` on a vertex not in the triangulation will throw a `KeyError`. For ghost vertices, you will get the set of all edges on the boundary associated with that vertex, for example ```@example curvout get_adjacent2vertex(tri, -1) @@ -257,7 +257,7 @@ This mapping shows the neighbours for each vertex in the triangulation. For exam get_neighbours(tri, 1) ``` -shows that the vertices of `1` are `-1`, `18`, `524`, and `-2`. These two ghost vertices, `-1` and `-2`, imply that `1` is on the boundary of the triangulation and is also at the corner of the two sections of the boundary associated with the ghost vertices `-1` and `-2`. Similarly, +shows that the vertices sharing edge with `1` are `-1`, `18`, `483`, and `-2`. These two ghost vertices, `-1` and `-2`, imply that `1` is on the boundary of the triangulation and is also at the corner of the two sections of the boundary associated with the ghost vertices `-1` and `-2`. Similarly, ```@example curvout get_neighbours(tri, -2) @@ -301,10 +301,10 @@ get_boundary_edge_map(tri) Since our domain has multiple curves, the `pos` values are `Tuple`s of the form `(m, n)`, where `m` is the curve and `n` is the section of that curve. So, for example, we have ```@example curvout -pos, ℓ = get_boundary_edge_map(tri, 1245, 1402) +pos, ℓ = get_boundary_edge_map(tri, 853, 1690) ``` -This means that `(1245, 1402)` is the `7`th edge of the first section on the third boundary: +This means that `(853, 1690)` is the `2`nd edge of the first section on the sixth boundary: ```@example curvout bn = get_boundary_nodes(tri, pos) # notice that we can pass Tuples (m, n) as a single argument diff --git a/docs/src/tutorials/centroidal.md b/docs/src/tutorials/centroidal.md index c55a52275..4191fdc53 100644 --- a/docs/src/tutorials/centroidal.md +++ b/docs/src/tutorials/centroidal.md @@ -19,7 +19,7 @@ using StableRNGs rng = StableRNG(123) points = 25randn(rng, 2, 500) tri = triangulate(points; rng) -vorn = voronoi(tri, clip=true) +vorn = voronoi(tri, clip = true) ```` To now compute the centroidal tessellation, use [`centroidal_smooth`](@ref). ( @@ -34,10 +34,10 @@ Let us now compare the two tessellations. ````@example centroidal fig = Figure() -ax1 = Axis(fig[1, 1], title="Original", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Smoothed", width=600, height=400) -voronoiplot!(ax1, vorn, colormap=:matter, strokewidth=2) -voronoiplot!(ax2, smooth_vorn, colormap=:matter, strokewidth=2) +ax1 = Axis(fig[1, 1], title = "Original", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Smoothed", width = 600, height = 400) +voronoiplot!(ax1, vorn, colormap = :matter, strokewidth = 2) +voronoiplot!(ax2, smooth_vorn, colormap = :matter, strokewidth = 2) resize_to_layout!(fig) fig ```` @@ -47,6 +47,7 @@ do look to be near the centroid of their corresponding tile. Note that this function `centroidal_smooth` is iterative, and you can control the iteration limits and the tolerance of the iterations (based on the maximum displacement of any generator at each iteration) using the `maxiters` and `tol` keyword arguments. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/centroidal.jl). @@ -58,15 +59,15 @@ using StableRNGs rng = StableRNG(123) points = 25randn(rng, 2, 500) tri = triangulate(points; rng) -vorn = voronoi(tri, clip=true) +vorn = voronoi(tri, clip = true) smooth_vorn = centroidal_smooth(vorn; rng) fig = Figure() -ax1 = Axis(fig[1, 1], title="Original", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Smoothed", width=600, height=400) -voronoiplot!(ax1, vorn, colormap=:matter, strokewidth=2) -voronoiplot!(ax2, smooth_vorn, colormap=:matter, strokewidth=2) +ax1 = Axis(fig[1, 1], title = "Original", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Smoothed", width = 600, height = 400) +voronoiplot!(ax1, vorn, colormap = :matter, strokewidth = 2) +voronoiplot!(ax2, smooth_vorn, colormap = :matter, strokewidth = 2) resize_to_layout!(fig) fig ``` diff --git a/docs/src/tutorials/clipped.md b/docs/src/tutorials/clipped.md index 596139572..9326ed870 100644 --- a/docs/src/tutorials/clipped.md +++ b/docs/src/tutorials/clipped.md @@ -33,16 +33,17 @@ the clipped tessellations below. ````@example clipped fig = Figure() -ax1 = Axis(fig[1, 1], title="Unclipped", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Clipped", width=600, height=400) -voronoiplot!(ax1, vorn, show_generators=false, colormap=:matter, strokewidth=4) -voronoiplot!(ax2, clipped_vorn, show_generators=false, colormap=:matter, strokewidth=4) +ax1 = Axis(fig[1, 1], title = "Unclipped", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Clipped", width = 600, height = 400) +voronoiplot!(ax1, vorn, show_generators = false, colormap = :matter, strokewidth = 4) +voronoiplot!(ax2, clipped_vorn, show_generators = false, colormap = :matter, strokewidth = 4) resize_to_layout!(fig) fig ```` As you can see, the unbounded polygons, and any polygons that included points outside of the convex hull, have now been clipped to the convex hull. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/clipped.jl). @@ -60,10 +61,10 @@ vorn = voronoi(tri) clipped_vorn = voronoi(tri, clip = true) fig = Figure() -ax1 = Axis(fig[1, 1], title="Unclipped", width=600, height=400) -ax2 = Axis(fig[1, 2], title="Clipped", width=600, height=400) -voronoiplot!(ax1, vorn, show_generators=false, colormap=:matter, strokewidth=4) -voronoiplot!(ax2, clipped_vorn, show_generators=false, colormap=:matter, strokewidth=4) +ax1 = Axis(fig[1, 1], title = "Unclipped", width = 600, height = 400) +ax2 = Axis(fig[1, 2], title = "Clipped", width = 600, height = 400) +voronoiplot!(ax1, vorn, show_generators = false, colormap = :matter, strokewidth = 4) +voronoiplot!(ax2, clipped_vorn, show_generators = false, colormap = :matter, strokewidth = 4) resize_to_layout!(fig) fig ``` diff --git a/docs/src/tutorials/clipped_rectangle.md b/docs/src/tutorials/clipped_rectangle.md index 121cfa287..a9c1ab9bb 100644 --- a/docs/src/tutorials/clipped_rectangle.md +++ b/docs/src/tutorials/clipped_rectangle.md @@ -37,7 +37,7 @@ the tessellation to. ````@example clipped_rectangle fig, ax, sc = voronoiplot(vorn) a, b, c, d = -2.0, 3.0, 0.0, 7.0 -lines!(ax, [(a,c),(b,c),(b,d),(a,d),(a,c)], color = :black, linewidth = 4) +lines!(ax, [(a, c), (b, c), (b, d), (a, d), (a, c)], color = :black, linewidth = 4) fig ```` @@ -53,7 +53,7 @@ You can obtain some reasonable defaults for this bounding box using The coordinates for each polygon clipped to this box can be obtained as follows. ````@example clipped_rectangle -clipped_coords = Vector{Vector{NTuple{2,Float64}}}(undef, num_polygons(vorn)) +clipped_coords = Vector{Vector{NTuple{2, Float64}}}(undef, num_polygons(vorn)) for i in each_polygon_index(vorn) clipped_coords[i] = get_polygon_coordinates(vorn, i, bounding_box) end @@ -70,6 +70,7 @@ fig As we can see, the polygons have been clipped to the rectangle. Note that if you just want this for plotting, you can also call `voronoiplot` with the `bounding_box` keyword argument. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/clipped_rectangle.jl). @@ -91,12 +92,12 @@ vorn = voronoi(tri) fig, ax, sc = voronoiplot(vorn) a, b, c, d = -2.0, 3.0, 0.0, 7.0 -lines!(ax, [(a,c),(b,c),(b,d),(a,d),(a,c)], color = :black, linewidth = 4) +lines!(ax, [(a, c), (b, c), (b, d), (a, d), (a, c)], color = :black, linewidth = 4) fig bounding_box = (a, b, c, d) -clipped_coords = Vector{Vector{NTuple{2,Float64}}}(undef, num_polygons(vorn)) +clipped_coords = Vector{Vector{NTuple{2, Float64}}}(undef, num_polygons(vorn)) for i in each_polygon_index(vorn) clipped_coords[i] = get_polygon_coordinates(vorn, i, bounding_box) end diff --git a/docs/src/tutorials/constrained_edges.md b/docs/src/tutorials/constrained_edges.md index 7c3f82dfa..f82b99cf3 100644 --- a/docs/src/tutorials/constrained_edges.md +++ b/docs/src/tutorials/constrained_edges.md @@ -50,17 +50,21 @@ tri = triangulate(pts) ```` ````@example constrained_edges -cons_tri = triangulate(pts; segments=C) +cons_tri = triangulate(pts; segments = C) ```` ````@example constrained_edges fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) triplot!(ax2, cons_tri, show_constrained_edges = true) resize_to_layout!(fig) @@ -109,15 +113,19 @@ C = Set([(2, 1), (2, 11), (2, 7), (2, 5)]) tri = triangulate(pts) -cons_tri = triangulate(pts; segments=C) +cons_tri = triangulate(pts; segments = C) fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) triplot!(ax2, cons_tri, show_constrained_edges = true) resize_to_layout!(fig) diff --git a/docs/src/tutorials/constrained_interior_within_interiors.md b/docs/src/tutorials/constrained_interior_within_interiors.md index 20178710d..7e988127c 100644 --- a/docs/src/tutorials/constrained_interior_within_interiors.md +++ b/docs/src/tutorials/constrained_interior_within_interiors.md @@ -29,16 +29,18 @@ curve_1 = [ [(0.0, 0.0), (5.0, 0.0), (10.0, 0.0), (15.0, 0.0), (20.0, 0.0), (25.0, 0.0)], [(25.0, 0.0), (25.0, 5.0), (25.0, 10.0), (25.0, 15.0), (25.0, 20.0), (25.0, 25.0)], [(25.0, 25.0), (20.0, 25.0), (15.0, 25.0), (10.0, 25.0), (5.0, 25.0), (0.0, 25.0)], - [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)] + [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)], ] # outer-most boundary: counter-clockwise curve_2 = [ [(4.0, 6.0), (4.0, 14.0), (4.0, 20.0), (18.0, 20.0), (20.0, 20.0)], [(20.0, 20.0), (20.0, 16.0), (20.0, 12.0), (20.0, 8.0), (20.0, 4.0)], - [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)] + [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)], ] # inner boundary: clockwise curve_3 = [ - [(12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), - (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912)] + [ + (12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), + (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912), + ], ] # this is inside curve_2, so it's counter-clockwise curves = [curve_1, curve_2, curve_3] points = [ @@ -48,9 +50,9 @@ points = [ (6.0, 2.0), (6.2, 3.0), (2.0, 3.0), (2.6, 6.2), (2.0, 8.0), (2.0, 11.0), (5.0, 12.0), (2.0, 17.0), (3.0, 19.0), (6.0, 18.0), (6.5, 14.5), (13.0, 19.0), (13.0, 12.0), (16.0, 8.0), (9.8, 8.0), (7.5, 6.0), - (12.0, 13.0), (19.0, 15.0) + (12.0, 13.0), (19.0, 15.0), ] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) ```` To now triangulate: @@ -75,16 +77,18 @@ curve_1 = [ [(0.0, 0.0), (5.0, 0.0), (10.0, 0.0), (15.0, 0.0), (20.0, 0.0), (25.0, 0.0)], [(25.0, 0.0), (25.0, 5.0), (25.0, 10.0), (25.0, 15.0), (25.0, 20.0), (25.0, 25.0)], [(25.0, 25.0), (20.0, 25.0), (15.0, 25.0), (10.0, 25.0), (5.0, 25.0), (0.0, 25.0)], - [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)] + [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)], ] # outer-most boundary: counter-clockwise curve_2 = [ [(4.0, 6.0), (4.0, 14.0), (4.0, 20.0), (18.0, 20.0), (20.0, 20.0)], [(20.0, 20.0), (20.0, 16.0), (20.0, 12.0), (20.0, 8.0), (20.0, 4.0)], - [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)] + [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)], ] # inner boundary: clockwise curve_3 = [ - [(12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), - (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912)] + [ + (12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), + (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912), + ], ] # this is inside curve_2, so it's counter-clockwise curves = [curve_1, curve_2, curve_3] points = [ @@ -94,9 +98,9 @@ points = [ (6.0, 2.0), (6.2, 3.0), (2.0, 3.0), (2.6, 6.2), (2.0, 8.0), (2.0, 11.0), (5.0, 12.0), (2.0, 17.0), (3.0, 19.0), (6.0, 18.0), (6.5, 14.5), (13.0, 19.0), (13.0, 12.0), (16.0, 8.0), (9.8, 8.0), (7.5, 6.0), - (12.0, 13.0), (19.0, 15.0) + (12.0, 13.0), (19.0, 15.0), ] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) rng = StableRNG(123) # triangulation is not unique when there are cocircular points tri = triangulate(points; boundary_nodes, rng) diff --git a/docs/src/tutorials/constrained_multiply_connected.md b/docs/src/tutorials/constrained_multiply_connected.md index e6887f69a..c1eb0fa3b 100644 --- a/docs/src/tutorials/constrained_multiply_connected.md +++ b/docs/src/tutorials/constrained_multiply_connected.md @@ -28,26 +28,30 @@ that neighbouring segments must connect. ````@example constrained_multiply_connected curve_1 = [ - [ # first segment + # first segment + [ (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), - (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0) + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), ], - [ # second segment + # second segment + [ (12.0, 28.0), (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), (-4.0, 0.0), (0.0, 0.0), - ] + ], ] # outer: counter-clockwise curve_2 = [ - [ # first segment + # first segment + [ (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), - (10.0, 22.0), (10.0, 20.0) + (10.0, 22.0), (10.0, 20.0), ], - [ # second segment + # second segment + [ (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ] + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], ] # inner: clockwise curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] # inner: clockwise curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] # inner: clockwise @@ -63,8 +67,9 @@ points = [ (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points); + (7.0, 7.8), (7.0, 7.4), +] +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points); nothing #hide ```` @@ -77,7 +82,7 @@ Now let us triangulate. ````@example constrained_multiply_connected rng = StableRNG(123) # the triangulation is not unique due to cocircular points tri = triangulate(points; boundary_nodes, rng) -fig, ax, sc = triplot(tri, show_constrained_edges=true, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_constrained_edges = true, show_convex_hull = true) fig ```` @@ -143,15 +148,15 @@ function get_triangulation_area(tri) ne = num_boundary_edges(bnn) for i in 1:ne vᵢ = get_boundary_nodes(bnn, i) - vᵢ₊₁ = get_boundary_nodes(bnn, i+1) + vᵢ₊₁ = get_boundary_nodes(bnn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end end end - return A/2 + return A / 2 end A = get_triangulation_area(tri) ```` @@ -167,7 +172,7 @@ function get_perimeters(tri) total_perimeter = 0.0 nc = DelaunayTriangulation.num_curves(tri) curve_perimeters = zeros(nc) # curve_index => perimeter - segment_perimeters = Dict{NTuple{2,Int},Float64}() # (curve_index, segment_index) => perimeter + segment_perimeters = Dict{NTuple{2, Int}, Float64}() # (curve_index, segment_index) => perimeter for (e, ((curve_index, section_index), node_index)) in get_boundary_edge_map(tri) u, v = edge_vertices(e) p, q = get_point(tri, u, v) @@ -195,26 +200,30 @@ using CairoMakie using StableRNGs curve_1 = [ - [ # first segment + # first segment + [ (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), - (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0) + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), ], - [ # second segment + # second segment + [ (12.0, 28.0), (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), (-4.0, 0.0), (0.0, 0.0), - ] + ], ] # outer: counter-clockwise curve_2 = [ - [ # first segment + # first segment + [ (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), - (10.0, 22.0), (10.0, 20.0) + (10.0, 22.0), (10.0, 20.0), ], - [ # second segment + # second segment + [ (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ] + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], ] # inner: clockwise curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] # inner: clockwise curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] # inner: clockwise @@ -230,12 +239,13 @@ points = [ (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] -boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points); + (7.0, 7.8), (7.0, 7.4), +] +boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points); rng = StableRNG(123) # the triangulation is not unique due to cocircular points tri = triangulate(points; boundary_nodes, rng) -fig, ax, sc = triplot(tri, show_constrained_edges=true, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_constrained_edges = true, show_convex_hull = true) fig get_boundary_edge_map(tri) @@ -259,15 +269,15 @@ function get_triangulation_area(tri) ne = num_boundary_edges(bnn) for i in 1:ne vᵢ = get_boundary_nodes(bnn, i) - vᵢ₊₁ = get_boundary_nodes(bnn, i+1) + vᵢ₊₁ = get_boundary_nodes(bnn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end end end - return A/2 + return A / 2 end A = get_triangulation_area(tri) @@ -275,7 +285,7 @@ function get_perimeters(tri) total_perimeter = 0.0 nc = DelaunayTriangulation.num_curves(tri) curve_perimeters = zeros(nc) # curve_index => perimeter - segment_perimeters = Dict{NTuple{2,Int},Float64}() # (curve_index, segment_index) => perimeter + segment_perimeters = Dict{NTuple{2, Int}, Float64}() # (curve_index, segment_index) => perimeter for (e, ((curve_index, section_index), node_index)) in get_boundary_edge_map(tri) u, v = edge_vertices(e) p, q = get_point(tri, u, v) diff --git a/docs/src/tutorials/constrained_multipolygon.md b/docs/src/tutorials/constrained_multipolygon.md index 83e264d05..8a33f0f7c 100644 --- a/docs/src/tutorials/constrained_multipolygon.md +++ b/docs/src/tutorials/constrained_multipolygon.md @@ -17,7 +17,7 @@ using CairoMakie θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -28,7 +28,7 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) fig, ax, sc = triplot(tri) fig ```` @@ -180,10 +180,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -191,7 +194,7 @@ dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] nodes, points = convert_boundary_points_to_indices(curves) -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) fig, ax, sc = triplot(tri) fig ```` @@ -206,7 +209,7 @@ using CairoMakie θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -217,7 +220,7 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) fig, ax, sc = triplot(tri) fig @@ -365,10 +368,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -376,7 +382,7 @@ dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] nodes, points = convert_boundary_points_to_indices(curves) -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) fig, ax, sc = triplot(tri) fig ``` diff --git a/docs/src/tutorials/constrained_outer_boundary.md b/docs/src/tutorials/constrained_outer_boundary.md index 88a24b171..0f28002a8 100644 --- a/docs/src/tutorials/constrained_outer_boundary.md +++ b/docs/src/tutorials/constrained_outer_boundary.md @@ -24,7 +24,7 @@ pts = [ (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), - (1.34, 6.77), (1.24, 4.15) + (1.34, 6.77), (1.24, 4.15), ] ```` @@ -43,9 +43,9 @@ boundary_points = [ (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), - (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0) + (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0), ] -boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=pts); +boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = pts); nothing #hide ```` @@ -72,14 +72,18 @@ cons_tri = triangulate(pts; boundary_nodes) ````@example constrained_outer_boundary fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) -triplot!(ax2, cons_tri, show_constrained_edges=true, show_convex_hull=true) +triplot!(ax2, cons_tri, show_constrained_edges = true, show_convex_hull = true) resize_to_layout!(fig) fig ```` @@ -92,8 +96,8 @@ from the boundary are deleted, so that we do actually have a boundary. If for some reason you do not want this behaviour, use `delete_holes = false`: ````@example constrained_outer_boundary -full_tri = triangulate(pts; boundary_nodes, delete_holes=false) -fig, ax, sc = triplot(full_tri, show_constrained_edges=true, show_convex_hull=true) +full_tri = triangulate(pts; boundary_nodes, delete_holes = false) +fig, ax, sc = triplot(full_tri, show_constrained_edges = true, show_convex_hull = true) ```` This default behaviour does mean you need to be careful if you use [`DelaunayTriangulation.each_point`](@ref) @@ -126,13 +130,13 @@ function shoelace_area(tri) A = 0.0 for i in 1:n vᵢ = get_boundary_nodes(bn, i) - vᵢ₊₁ = get_boundary_nodes(bn, i+1) + vᵢ₊₁ = get_boundary_nodes(bn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end - return A/2 + return A / 2 end shoelace_area(cons_tri) ```` @@ -162,7 +166,7 @@ bn_j = get_boundary_nodes(bn, J) This returns `23`, which is the start of the edge `e`. The full edge is given by ````@example constrained_outer_boundary -get_boundary_nodes.(Ref(bn), (J, J+1)) # Ref to not broadcast over bn +get_boundary_nodes.(Ref(bn), (J, J + 1)) # Ref to not broadcast over bn ```` To give an example, here's how we compute the perimeter of the triangulation. This only @@ -196,7 +200,7 @@ pts = [ (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), - (1.34, 6.77), (1.24, 4.15) + (1.34, 6.77), (1.24, 4.15), ] boundary_points = [ @@ -204,9 +208,9 @@ boundary_points = [ (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), - (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0) + (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0), ] -boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=pts); +boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = pts); pts @@ -216,19 +220,23 @@ tri = triangulate(pts) cons_tri = triangulate(pts; boundary_nodes) fig = Figure() -ax1 = Axis(fig[1, 1], xlabel="x", ylabel=L"y", - title="(a): Unconstrained", titlealign=:left, - width=300, height=300) -ax2 = Axis(fig[1, 2], xlabel="x", ylabel=L"y", - title="(b): Constrained", titlealign=:left, - width=300, height=300) +ax1 = Axis( + fig[1, 1], xlabel = "x", ylabel = L"y", + title = "(a): Unconstrained", titlealign = :left, + width = 300, height = 300, +) +ax2 = Axis( + fig[1, 2], xlabel = "x", ylabel = L"y", + title = "(b): Constrained", titlealign = :left, + width = 300, height = 300, +) triplot!(ax1, tri) -triplot!(ax2, cons_tri, show_constrained_edges=true, show_convex_hull=true) +triplot!(ax2, cons_tri, show_constrained_edges = true, show_convex_hull = true) resize_to_layout!(fig) fig -full_tri = triangulate(pts; boundary_nodes, delete_holes=false) -fig, ax, sc = triplot(full_tri, show_constrained_edges=true, show_convex_hull=true) +full_tri = triangulate(pts; boundary_nodes, delete_holes = false) +fig, ax, sc = triplot(full_tri, show_constrained_edges = true, show_convex_hull = true) get_boundary_nodes(cons_tri) @@ -238,13 +246,13 @@ function shoelace_area(tri) A = 0.0 for i in 1:n vᵢ = get_boundary_nodes(bn, i) - vᵢ₊₁ = get_boundary_nodes(bn, i+1) + vᵢ₊₁ = get_boundary_nodes(bn, i + 1) pᵢ, pᵢ₊₁ = get_point(tri, vᵢ, vᵢ₊₁) xᵢ, yᵢ = getxy(pᵢ) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) - A += (yᵢ + yᵢ₊₁)*(xᵢ - xᵢ₊₁) + A += (yᵢ + yᵢ₊₁) * (xᵢ - xᵢ₊₁) end - return A/2 + return A / 2 end shoelace_area(cons_tri) @@ -256,7 +264,7 @@ e, (I, J) = first(bem) bn = get_boundary_nodes(cons_tri, I) # same as boundary_nodes for this problem; see the later tutorials bn_j = get_boundary_nodes(bn, J) -get_boundary_nodes.(Ref(bn), (J, J+1)) # Ref to not broadcast over bn +get_boundary_nodes.(Ref(bn), (J, J + 1)) # Ref to not broadcast over bn function get_perimeter(tri) bem = get_boundary_edge_map(tri) diff --git a/docs/src/tutorials/constrained_outer_boundary_segmented.md b/docs/src/tutorials/constrained_outer_boundary_segmented.md index 233304d30..14e3a98b9 100644 --- a/docs/src/tutorials/constrained_outer_boundary_segmented.md +++ b/docs/src/tutorials/constrained_outer_boundary_segmented.md @@ -22,7 +22,7 @@ Now, we define some of the points we will be triangulating. ````@example constrained_outer_boundary_segmented points = [ (2.0, 8.0), (6.0, 4.0), (2.0, 6.0), - (2.0, 4.0), (8.0, 2.0) + (2.0, 4.0), (8.0, 2.0), ] ```` @@ -45,15 +45,15 @@ We also add a constrained edge. ````@example constrained_outer_boundary_segmented E = Set(((6, 9),)) # (0, 0) → (4, 6) -boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points=points) -tri = triangulate(points; boundary_nodes, segments=E) +boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points = points) +tri = triangulate(points; boundary_nodes, segments = E) ```` ````@example constrained_outer_boundary_segmented -fig, ax, sc = triplot(tri, show_constrained_edges=true, constrained_edge_linewidth=6) -lines!(ax, section_1, color=:red, linewidth=6) -lines!(ax, section_2, color=:green, linewidth=6) -lines!(ax, section_3, color=:blue, linewidth=6) +fig, ax, sc = triplot(tri, show_constrained_edges = true, constrained_edge_linewidth = 6) +lines!(ax, section_1, color = :red, linewidth = 6) +lines!(ax, section_2, color = :green, linewidth = 6) +lines!(ax, section_3, color = :blue, linewidth = 6) fig ```` @@ -185,6 +185,7 @@ get_ghost_vertex_map(tri) In this case, the `i`th section just has the ghost vertex `-i`, but this is typically used to deal with the case of multiple boundaries so that we know where a ghost vertex belongs. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/constrained_outer_boundary_segmented.jl). @@ -195,7 +196,7 @@ using CairoMakie points = [ (2.0, 8.0), (6.0, 4.0), (2.0, 6.0), - (2.0, 4.0), (8.0, 2.0) + (2.0, 4.0), (8.0, 2.0), ] section_1 = [(0.0, 0.0), (14.0, 0.0)] @@ -204,13 +205,13 @@ section_3 = [(0.0, 14.0), (0.0, 0.0)] boundary_points = [section_1, section_2, section_3] E = Set(((6, 9),)) # (0, 0) → (4, 6) -boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points=points) -tri = triangulate(points; boundary_nodes, segments=E) +boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points = points) +tri = triangulate(points; boundary_nodes, segments = E) -fig, ax, sc = triplot(tri, show_constrained_edges=true, constrained_edge_linewidth=6) -lines!(ax, section_1, color=:red, linewidth=6) -lines!(ax, section_2, color=:green, linewidth=6) -lines!(ax, section_3, color=:blue, linewidth=6) +fig, ax, sc = triplot(tri, show_constrained_edges = true, constrained_edge_linewidth = 6) +lines!(ax, section_1, color = :red, linewidth = 6) +lines!(ax, section_2, color = :green, linewidth = 6) +lines!(ax, section_3, color = :blue, linewidth = 6) fig get_interior_segments(tri) diff --git a/docs/src/tutorials/convex.md b/docs/src/tutorials/convex.md index 684efabcf..555e4ecab 100644 --- a/docs/src/tutorials/convex.md +++ b/docs/src/tutorials/convex.md @@ -15,7 +15,7 @@ using CairoMakie points = [ (10.0, 12.0), (7.0, 11.0), (8.0, 6.0), (10.0, 3.0), (14.0, 5.0), (15.0, 10.0), - (13.0, 12.0) + (13.0, 12.0), ] S = 1:7 tri = triangulate_convex(points, 1:7) @@ -66,6 +66,7 @@ using BenchmarkTools For the smaller example that we started with above, `triangulate_convex` is also faster, although not by much (≈15.10 μs versus ≈10.7 μs). + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/convex.jl). @@ -77,7 +78,7 @@ using CairoMakie points = [ (10.0, 12.0), (7.0, 11.0), (8.0, 6.0), (10.0, 3.0), (14.0, 5.0), (15.0, 10.0), - (13.0, 12.0) + (13.0, 12.0), ] S = 1:7 tri = triangulate_convex(points, 1:7) diff --git a/docs/src/tutorials/convex_hull.md b/docs/src/tutorials/convex_hull.md index a4a2dec5d..aef0aaf8e 100644 --- a/docs/src/tutorials/convex_hull.md +++ b/docs/src/tutorials/convex_hull.md @@ -47,7 +47,7 @@ from the points without constructing the triangulation, use [`convex_hull`](@ref ````@example convex_hull ch = convex_hull(points) ch_points = [get_point(tri, i) for i in DelaunayTriangulation.get_vertices(ch)] -fig, ax, sc = lines(ch_points, color=:red, linewidth=4) +fig, ax, sc = lines(ch_points, color = :red, linewidth = 4) scatter!(ax, points) fig ```` @@ -71,7 +71,7 @@ get_convex_hull_vertices(tri) ch = convex_hull(points) ch_points = [get_point(tri, i) for i in DelaunayTriangulation.get_vertices(ch)] -fig, ax, sc = lines(ch_points, color=:red, linewidth=4) +fig, ax, sc = lines(ch_points, color = :red, linewidth = 4) scatter!(ax, points) fig ``` diff --git a/docs/src/tutorials/curve_bounded.md b/docs/src/tutorials/curve_bounded.md index cf245ff55..2df4dfcab 100644 --- a/docs/src/tutorials/curve_bounded.md +++ b/docs/src/tutorials/curve_bounded.md @@ -42,7 +42,7 @@ domain like this by a set of points around a boundary, e.g.: n = 50 r = 2.0 xc, yc = 1 / 2, 2.0 -θ = range(0, 2π, length=n + 1) |> collect; +θ = range(0, 2π, length = n + 1) |> collect; θ[end] = θ[begin]; x = xc .+ r * cos.(θ) y = yc .+ r * sin.(θ); @@ -80,9 +80,9 @@ Let's now triangulate this domain. We need to put the arc into its own vector, a points into `triangulate`: ````@example curve_bounded -points = NTuple{2,Float64}[] +points = NTuple{2, Float64}[] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=[arc], rng) +tri = triangulate(points; boundary_nodes = [arc], rng) ```` ````@example curve_bounded @@ -100,7 +100,7 @@ This is probably not what we actually want, though. Instead, we need to refine t The syntax for this is the same as in the [refinement tutorial](../tutorials/refinement.md): ````@example curve_bounded -refine!(tri; max_area=1e-1, rng) +refine!(tri; max_area = 1.0e-1, rng) fig, ax, sc = triplot(tri) fig ```` @@ -146,13 +146,15 @@ to the origin to be smaller than those outside of it. ````@example curve_bounded curve = [[arc], [bspl], pce] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; max_area=1e-2, rng, custom_constraint=(_tri, T) -> begin - i, j, k = triangle_vertices(T) - p, q, r = get_point(_tri, i, j, k) - c = (p .+ q .+ r) ./ 3 - return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1e-3 -end) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!( + tri; max_area = 1.0e-2, rng, custom_constraint = (_tri, T) -> begin + i, j, k = triangle_vertices(T) + p, q, r = get_point(_tri, i, j, k) + c = (p .+ q .+ r) ./ 3 + return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1.0e-3 + end, +) fig, ax, sc = triplot(tri) fig ```` @@ -164,37 +166,37 @@ domains are multiply-connected. Let us give the domain followed by an explanatio ````@example curve_bounded curve = [ [ - [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])] + [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] t = LinRange(0, 1, 1000) fig fig = Figure() ax = Axis(fig[1, 1]) -lines!(ax, [get_point(points, curve[1][1]...)...], color=:red, label="(1, 2, 3)") -lines!(ax, curve[1][2][1].(t), color=:red, linestyle=:dashdot, label="EllipticalArc") -lines!(ax, curve[2][1][1].(t), color=:green, label="BSpline") -lines!(ax, [get_point(points, curve[3][1]...)...], color=:blue, label="(4, 5, 6, 7, 4)") -lines!(ax, curve[4][1][1].(t), color=:purple, label="BezierCurve") -lines!(ax, curve[4][2][1].(t), color=:purple, linestyle=:dashdot, label="CatmullRomSpline") -lines!(ax, [get_point(points, curve[5][1]...)...], color=:orange, label="(12, 11, 10, 12)") -lines!(ax, curve[6][1][1].(t), color=:black, label="CircularArc") +lines!(ax, [get_point(points, curve[1][1]...)...], color = :red, label = "(1, 2, 3)") +lines!(ax, curve[1][2][1].(t), color = :red, linestyle = :dashdot, label = "EllipticalArc") +lines!(ax, curve[2][1][1].(t), color = :green, label = "BSpline") +lines!(ax, [get_point(points, curve[3][1]...)...], color = :blue, label = "(4, 5, 6, 7, 4)") +lines!(ax, curve[4][1][1].(t), color = :purple, label = "BezierCurve") +lines!(ax, curve[4][2][1].(t), color = :purple, linestyle = :dashdot, label = "CatmullRomSpline") +lines!(ax, [get_point(points, curve[5][1]...)...], color = :orange, label = "(12, 11, 10, 12)") +lines!(ax, curve[6][1][1].(t), color = :black, label = "CircularArc") fig[1, 2] = Legend(fig, ax, "Curve") fig ```` @@ -220,8 +222,8 @@ Let's now triangulate. ````@example curve_bounded rng = StableRNG(123) -tri = triangulate(copy(points); boundary_nodes=curve, rng) # copying so that we don't mutate for the next section -refine!(tri; max_area=1e-2) +tri = triangulate(copy(points); boundary_nodes = curve, rng) # copying so that we don't mutate for the next section +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) fig ```` @@ -245,18 +247,18 @@ poly_constraint = (_tri, T) -> begin return true end max_area = if idx == 1 # coarse - 1e-1 + 1.0e-1 elseif idx == 3 # medium - 1e-2 + 1.0e-2 else # dense - 1e-3 + 1.0e-3 end area = DelaunayTriangulation.triangle_area(p, q, r) return area > max_area end rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; custom_constraint=poly_constraint, rng) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!(tri; custom_constraint = poly_constraint, rng) fig, ax, sc = triplot(tri) fig ```` @@ -282,7 +284,7 @@ Let's now meet these requirements. ````@example curve_bounded struct Astroid <: DelaunayTriangulation.AbstractParametricCurve - lookup_table::Vector{NTuple{2,Float64}} + lookup_table::Vector{NTuple{2, Float64}} end function (c::Astroid)(t) if t == 0.0 || t == 1.0 @@ -313,7 +315,7 @@ Let's now define an astroid curve and triangulate it. ````@example curve_bounded function Astroid(n::Int) - lookup_table = Vector{NTuple{2,Float64}}(undef, n) + lookup_table = Vector{NTuple{2, Float64}}(undef, n) c = Astroid(lookup_table) for i in 1:n lookup_table[i] = c((i - 1) / (n - 1)) @@ -322,8 +324,8 @@ function Astroid(n::Int) end rng = StableRNG(123) curve = Astroid(1000) -tri = triangulate(NTuple{2,Float64}[]; boundary_nodes=[curve], rng) -refine!(tri; max_area=1e-2) +tri = triangulate(NTuple{2, Float64}[]; boundary_nodes = [curve], rng) +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) fig ```` @@ -342,7 +344,7 @@ using LinearAlgebra n = 50 r = 2.0 xc, yc = 1 / 2, 2.0 -θ = range(0, 2π, length=n + 1) |> collect; +θ = range(0, 2π, length = n + 1) |> collect; θ[end] = θ[begin]; x = xc .+ r * cos.(θ) y = yc .+ r * sin.(θ); @@ -358,14 +360,14 @@ points = arc.(t) fig, ax, sc = lines(points) -points = NTuple{2,Float64}[] +points = NTuple{2, Float64}[] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=[arc], rng) +tri = triangulate(points; boundary_nodes = [arc], rng) fig, ax, sc = triplot(tri) fig -refine!(tri; max_area=1e-1, rng) +refine!(tri; max_area = 1.0e-1, rng) fig, ax, sc = triplot(tri) fig @@ -382,55 +384,57 @@ fig curve = [[arc], [bspl], pce] rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; max_area=1e-2, rng, custom_constraint=(_tri, T) -> begin - i, j, k = triangle_vertices(T) - p, q, r = get_point(_tri, i, j, k) - c = (p .+ q .+ r) ./ 3 - return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1e-3 -end) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!( + tri; max_area = 1.0e-2, rng, custom_constraint = (_tri, T) -> begin + i, j, k = triangle_vertices(T) + p, q, r = get_point(_tri, i, j, k) + c = (p .+ q .+ r) ./ 3 + return norm(c) < 1 / 2 && DelaunayTriangulation.triangle_area(p, q, r) > 1.0e-3 + end, +) fig, ax, sc = triplot(tri) fig curve = [ [ - [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])] + [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] t = LinRange(0, 1, 1000) fig fig = Figure() ax = Axis(fig[1, 1]) -lines!(ax, [get_point(points, curve[1][1]...)...], color=:red, label="(1, 2, 3)") -lines!(ax, curve[1][2][1].(t), color=:red, linestyle=:dashdot, label="EllipticalArc") -lines!(ax, curve[2][1][1].(t), color=:green, label="BSpline") -lines!(ax, [get_point(points, curve[3][1]...)...], color=:blue, label="(4, 5, 6, 7, 4)") -lines!(ax, curve[4][1][1].(t), color=:purple, label="BezierCurve") -lines!(ax, curve[4][2][1].(t), color=:purple, linestyle=:dashdot, label="CatmullRomSpline") -lines!(ax, [get_point(points, curve[5][1]...)...], color=:orange, label="(12, 11, 10, 12)") -lines!(ax, curve[6][1][1].(t), color=:black, label="CircularArc") +lines!(ax, [get_point(points, curve[1][1]...)...], color = :red, label = "(1, 2, 3)") +lines!(ax, curve[1][2][1].(t), color = :red, linestyle = :dashdot, label = "EllipticalArc") +lines!(ax, curve[2][1][1].(t), color = :green, label = "BSpline") +lines!(ax, [get_point(points, curve[3][1]...)...], color = :blue, label = "(4, 5, 6, 7, 4)") +lines!(ax, curve[4][1][1].(t), color = :purple, label = "BezierCurve") +lines!(ax, curve[4][2][1].(t), color = :purple, linestyle = :dashdot, label = "CatmullRomSpline") +lines!(ax, [get_point(points, curve[5][1]...)...], color = :orange, label = "(12, 11, 10, 12)") +lines!(ax, curve[6][1][1].(t), color = :black, label = "CircularArc") fig[1, 2] = Legend(fig, ax, "Curve") fig rng = StableRNG(123) -tri = triangulate(copy(points); boundary_nodes=curve, rng) # copying so that we don't mutate for the next section -refine!(tri; max_area=1e-2) +tri = triangulate(copy(points); boundary_nodes = curve, rng) # copying so that we don't mutate for the next section +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) fig @@ -443,23 +447,23 @@ poly_constraint = (_tri, T) -> begin return true end max_area = if idx == 1 # coarse - 1e-1 + 1.0e-1 elseif idx == 3 # medium - 1e-2 + 1.0e-2 else # dense - 1e-3 + 1.0e-3 end area = DelaunayTriangulation.triangle_area(p, q, r) return area > max_area end rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=curve, rng) -refine!(tri; custom_constraint=poly_constraint, rng) +tri = triangulate(points; boundary_nodes = curve, rng) +refine!(tri; custom_constraint = poly_constraint, rng) fig, ax, sc = triplot(tri) fig struct Astroid <: DelaunayTriangulation.AbstractParametricCurve - lookup_table::Vector{NTuple{2,Float64}} + lookup_table::Vector{NTuple{2, Float64}} end function (c::Astroid)(t) if t == 0.0 || t == 1.0 @@ -486,7 +490,7 @@ function DelaunayTriangulation.thrice_differentiate(c::Astroid, t) end function Astroid(n::Int) - lookup_table = Vector{NTuple{2,Float64}}(undef, n) + lookup_table = Vector{NTuple{2, Float64}}(undef, n) c = Astroid(lookup_table) for i in 1:n lookup_table[i] = c((i - 1) / (n - 1)) @@ -495,8 +499,8 @@ function Astroid(n::Int) end rng = StableRNG(123) curve = Astroid(1000) -tri = triangulate(NTuple{2,Float64}[]; boundary_nodes=[curve], rng) -refine!(tri; max_area=1e-2) +tri = triangulate(NTuple{2, Float64}[]; boundary_nodes = [curve], rng) +refine!(tri; max_area = 1.0e-2) fig, ax, sc = triplot(tri) fig ``` diff --git a/docs/src/tutorials/custom_primitive.md b/docs/src/tutorials/custom_primitive.md index 576392a13..8dfe9445e 100644 --- a/docs/src/tutorials/custom_primitive.md +++ b/docs/src/tutorials/custom_primitive.md @@ -54,7 +54,7 @@ struct CustomPolygon segments::Vector{CustomPolygonSegment} end struct CustomPolygons{N} - polygons::NTuple{N,CustomPolygon} + polygons::NTuple{N, CustomPolygon} end ```` @@ -117,8 +117,8 @@ DT.num_sections(poly::CustomPolygon) = length(poly.segments) DT.num_boundary_edges(seg::CustomPolygonSegment) = length(seg.segments) DT.get_boundary_nodes(poly::CustomPolygons, m::Integer) = poly.polygons[m] # go down to the mth polygon DT.get_boundary_nodes(poly::CustomPolygon, m::Integer) = poly.segments[m] # go down to the mth segment -DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m-1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node -DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2,Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) +DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m - 1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node +DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2, Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) ```` We now have all that we need for defining our custom primitives for constrained triangulations. We can go further and define methods @@ -149,9 +149,9 @@ DT.contains_edge(e::CustomSegment, Es::CustomSegments) = e ∈ Es.segments Base.empty!(triangles::CustomTriangles) = empty!(triangles.triangles) function Base.insert!(seg::CustomPolygonSegment, index, node) - cur_segment = seg.segments[index-1] + cur_segment = seg.segments[index - 1] u, v = edge_vertices(cur_segment) - seg.segments[index-1] = CustomSegment(u, node) + seg.segments[index - 1] = CustomSegment(u, node) insert!(seg.segments, index, CustomSegment(node, v)) return seg end @@ -171,13 +171,17 @@ p8 = CustomPoint(0.75, 0.75) p9 = CustomPoint(0.25, 0.75) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) segments = CustomSegments(Set{CustomSegment}((CustomSegment(2, 7), CustomSegment(8, 3)))) -outer_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), - CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), -]) -inner_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), -]) +outer_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), + CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), + ], +) +inner_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), + ], +) polygons = CustomPolygons((outer_polygon, inner_polygon)); nothing #hide ```` @@ -186,15 +190,16 @@ Now we triangulate and refine. ````@example custom_primitive rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=polygons, segments, - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng +tri = triangulate( + points; boundary_nodes = polygons, segments, + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, ) -refine!(tri; max_area=1e-3, rng) +refine!(tri; max_area = 1.0e-3, rng) fig, ax, sc = triplot(tri) fig ```` @@ -205,14 +210,16 @@ this all works. ````@example custom_primitive rng = StableRNG(123) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) -tri = triangulate(points; - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng) -vorn = voronoi(tri; clip=true, smooth=true, rng) +tri = triangulate( + points; + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, +) +vorn = voronoi(tri; clip = true, smooth = true, rng) fig, ax, sc = voronoiplot(vorn) fig ```` @@ -257,7 +264,7 @@ struct CustomPolygon segments::Vector{CustomPolygonSegment} end struct CustomPolygons{N} - polygons::NTuple{N,CustomPolygon} + polygons::NTuple{N, CustomPolygon} end DT.getx(p::CustomPoint) = p.x @@ -307,8 +314,8 @@ DT.num_sections(poly::CustomPolygon) = length(poly.segments) DT.num_boundary_edges(seg::CustomPolygonSegment) = length(seg.segments) DT.get_boundary_nodes(poly::CustomPolygons, m::Integer) = poly.polygons[m] # go down to the mth polygon DT.get_boundary_nodes(poly::CustomPolygon, m::Integer) = poly.segments[m] # go down to the mth segment -DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m-1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node -DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2,Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) +DT.get_boundary_nodes(seg::CustomPolygonSegment, m::Integer) = m > length(seg.segments) ? DT.terminal(seg.segments[m - 1]) : DT.initial(seg.segments[m]) # go down to the mth edge and extract the left node +DT.get_boundary_nodes(poly::CustomPolygons, (m, n)::NTuple{2, Int32}) = DT.get_boundary_nodes(DT.get_boundary_nodes(poly, m), n) Base.empty!(segments::CustomSegments) = empty!(segments.segments) @@ -322,9 +329,9 @@ DT.contains_edge(e::CustomSegment, Es::CustomSegments) = e ∈ Es.segments Base.empty!(triangles::CustomTriangles) = empty!(triangles.triangles) function Base.insert!(seg::CustomPolygonSegment, index, node) - cur_segment = seg.segments[index-1] + cur_segment = seg.segments[index - 1] u, v = edge_vertices(cur_segment) - seg.segments[index-1] = CustomSegment(u, node) + seg.segments[index - 1] = CustomSegment(u, node) insert!(seg.segments, index, CustomSegment(node, v)) return seg end @@ -340,38 +347,45 @@ p8 = CustomPoint(0.75, 0.75) p9 = CustomPoint(0.25, 0.75) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) segments = CustomSegments(Set{CustomSegment}((CustomSegment(2, 7), CustomSegment(8, 3)))) -outer_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), - CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), -]) -inner_polygon = CustomPolygon([ - CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), -]) +outer_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(1, 2), CustomSegment(2, 3)]), + CustomPolygonSegment([CustomSegment(3, 4), CustomSegment(4, 1)]), + ], +) +inner_polygon = CustomPolygon( + [ + CustomPolygonSegment([CustomSegment(6, 9), CustomSegment(9, 8), CustomSegment(8, 7), CustomSegment(7, 6)]), + ], +) polygons = CustomPolygons((outer_polygon, inner_polygon)); rng = StableRNG(123) -tri = triangulate(points; boundary_nodes=polygons, segments, - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng +tri = triangulate( + points; boundary_nodes = polygons, segments, + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, ) -refine!(tri; max_area=1e-3, rng) +refine!(tri; max_area = 1.0e-3, rng) fig, ax, sc = triplot(tri) fig rng = StableRNG(123) points = CustomPoints([p1, p2, p3, p4, p5, p6, p7, p8, p9]) -tri = triangulate(points; - IntegerType=Int32, - EdgeType=CustomSegment, - TriangleType=CustomTriangle, - EdgesType=CustomSegments, - TrianglesType=CustomTriangles, - rng) -vorn = voronoi(tri; clip=true, smooth=true, rng) +tri = triangulate( + points; + IntegerType = Int32, + EdgeType = CustomSegment, + TriangleType = CustomTriangle, + EdgesType = CustomSegments, + TrianglesType = CustomTriangles, + rng, +) +vorn = voronoi(tri; clip = true, smooth = true, rng) fig, ax, sc = voronoiplot(vorn) fig ``` diff --git a/docs/src/tutorials/lattice.md b/docs/src/tutorials/lattice.md index a4cb9b0a2..4277b2daa 100644 --- a/docs/src/tutorials/lattice.md +++ b/docs/src/tutorials/lattice.md @@ -27,7 +27,7 @@ lattice manually and `triangulate` those. Here's a comparison of the times. ````@example lattice using BenchmarkTools points = get_points(tri) -@benchmark triangulate($points; randomise=$false) # randomise=false because points are already in lattice order, i.e. spatially sorted +@benchmark triangulate($points; randomise = $false) # randomise=false because points are already in lattice order, i.e. spatially sorted ```` ````@example lattice @@ -55,7 +55,7 @@ tri You can opt into not having these by using `delete_ghosts=true`: ````@example lattice -tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary=true, delete_ghosts=true) +tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary = true, delete_ghosts = true) tri ```` @@ -83,7 +83,7 @@ fig using BenchmarkTools points = get_points(tri) -@benchmark triangulate($points; randomise=$false) # randomise=false because points are already in lattice order, i.e. spatially sorted +@benchmark triangulate($points; randomise = $false) # randomise=false because points are already in lattice order, i.e. spatially sorted @benchmark triangulate_rectangle($a, $b, $c, $d, $nx, $ny) @@ -91,7 +91,7 @@ get_boundary_nodes(tri) tri -tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary=true, delete_ghosts=true) +tri = triangulate_rectangle(a, b, c, d, nx, ny; single_boundary = true, delete_ghosts = true) tri get_boundary_nodes(tri) diff --git a/docs/src/tutorials/nearest.md b/docs/src/tutorials/nearest.md index cd3974818..1d29e15ff 100644 --- a/docs/src/tutorials/nearest.md +++ b/docs/src/tutorials/nearest.md @@ -24,13 +24,13 @@ shown are the points that we will query. points = [ (-3.0, 7.0), (2.0, 6.0), (0.0, 3.0), (0.0, 0.0), (-5.0, 5.0), (-3.0, 1.0), - (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0) + (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0), ] tri = triangulate(points) vorn = voronoi(tri) p, q = (-2.0, 7.5), (0.0, 4.0) -fig, ax, sc = voronoiplot(vorn, markersize=14) -scatter!(ax,[p,q],color=:white,strokecolor=:black,strokewidth=2,markersize=14) +fig, ax, sc = voronoiplot(vorn, markersize = 14) +scatter!(ax, [p, q], color = :white, strokecolor = :black, strokewidth = 2, markersize = 14) fig ```` @@ -57,6 +57,7 @@ nq_tri = get_nearest_neighbour(tri, q) ```` Both methods lead to the same results because they use the same algorithm. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/nearest.jl). @@ -68,13 +69,13 @@ using CairoMakie points = [ (-3.0, 7.0), (2.0, 6.0), (0.0, 3.0), (0.0, 0.0), (-5.0, 5.0), (-3.0, 1.0), - (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0) + (2.0, -3.0), (5.0, 5.0), (-4.0, 3.0), ] tri = triangulate(points) vorn = voronoi(tri) p, q = (-2.0, 7.5), (0.0, 4.0) -fig, ax, sc = voronoiplot(vorn, markersize=14) -scatter!(ax,[p,q],color=:white,strokecolor=:black,strokewidth=2,markersize=14) +fig, ax, sc = voronoiplot(vorn, markersize = 14) +scatter!(ax, [p, q], color = :white, strokecolor = :black, strokewidth = 2, markersize = 14) fig np = get_nearest_neighbour(vorn, p) diff --git a/docs/src/tutorials/operations_convex_hull_locking.md b/docs/src/tutorials/operations_convex_hull_locking.md index 845a2eb05..1c0cdcbfb 100644 --- a/docs/src/tutorials/operations_convex_hull_locking.md +++ b/docs/src/tutorials/operations_convex_hull_locking.md @@ -48,6 +48,7 @@ isn't actually equal to the convex hull. Note that this locking/unlocking doesn't actually change anything about the triangulation, it just adds information into `tri` to treat it as if you had provided the convex hull as a constrained boundary to start with. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_convex_hull_locking.jl). diff --git a/docs/src/tutorials/operations_flip_edge.md b/docs/src/tutorials/operations_flip_edge.md index 197ac1672..d3b4f97ef 100644 --- a/docs/src/tutorials/operations_flip_edge.md +++ b/docs/src/tutorials/operations_flip_edge.md @@ -19,15 +19,15 @@ T4 = points[[2, 3, 4]] #hide fig = Figure() #hide ax1 = Axis(fig[1, 1], width = 600, height = 400) #hide ax2 = Axis(fig[1, 2], width = 600, height = 400) #hide -poly!(ax1, [T1; T2], color=(:white, 0.0), strokewidth=3) #hide -poly!(ax2, [T3; T4], color=(:white, 0.0), strokewidth=3) #hide +poly!(ax1, [T1; T2], color = (:white, 0.0), strokewidth = 3) #hide +poly!(ax2, [T3; T4], color = (:white, 0.0), strokewidth = 3) #hide for ax in (ax1, ax2) #hide hidedecorations!(ax) #hide hidespines!(ax) #hide - text!(ax, [(0.05, -1.1)]; text=[L"p_j"], fontsize=43) #hide - text!(ax, [(0.9, 0.1)]; text=[L"p_k"], fontsize=43) #hide - text!(ax, [(0.05, 1.0)]; text=[L"p_i"], fontsize=43) #hide - text!(ax, [(-1.05, 0.05)]; text=[L"p_\ell"], fontsize=43) #hide + text!(ax, [(0.05, -1.1)]; text = [L"p_j"], fontsize = 43) #hide + text!(ax, [(0.9, 0.1)]; text = [L"p_k"], fontsize = 43) #hide + text!(ax, [(0.05, 1.0)]; text = [L"p_i"], fontsize = 43) #hide + text!(ax, [(-1.05, 0.05)]; text = [L"p_\ell"], fontsize = 43) #hide xlims!(ax, -1.1, 1.1) #hide ylims!(ax, -1.3, 1.3) #hide end #hide @@ -71,6 +71,7 @@ As simple as that. Note that no checks are made for whether the edge is actually triangulation, on the boundary, or if the associated quadrilateral is convex. It is up to you to check this if needed; one way to check would be to use [`DelaunayTriangulation.is_legal`](@ref), as is done inside [`legalise_edge!`](@ref) -- see the [next tutorial](operations_legalise_edge.md). + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_flip_edge.jl). diff --git a/docs/src/tutorials/operations_legalise_edge.md b/docs/src/tutorials/operations_legalise_edge.md index 87f7f5a03..3b20ebd93 100644 --- a/docs/src/tutorials/operations_legalise_edge.md +++ b/docs/src/tutorials/operations_legalise_edge.md @@ -35,12 +35,12 @@ points = [ (-1.0, 2.0), (4.0, 6.0), (4.0, 3.0), (-3.0, 7.0), (-6.0, -1.0), (9.0, 5.0), (5.0, -5.0), (-6.0, 7.0), (0.0, 0.0), (-3.0, 4.0), (-5.0, 5.0), (-3.0, -4.0), - (5.0, -1.0), (2.0, -2.0) + (5.0, -1.0), (2.0, -2.0), ] p = (3.0, 2.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig ```` @@ -63,7 +63,7 @@ This splitting introduces some new illegal edges, shown in red below. ````@example operations_legalise_edge function get_all_illegal_edges(tri) #hide - T = NTuple{2,Float64}[] #hide + T = NTuple{2, Float64}[] #hide for E in each_edge(tri) #hide cert = DelaunayTriangulation.is_legal(tri, E...) #hide if DelaunayTriangulation.is_illegal(cert) #hide @@ -74,7 +74,7 @@ function get_all_illegal_edges(tri) #hide end #hide fig, ax, sc = triplot(tri) #hide T = get_all_illegal_edges(tri) #hide -linesegments!(ax, T, color=:red, linewidth=3) #hide +linesegments!(ax, T, color = :red, linewidth = 3) #hide fig #hide ```` @@ -92,6 +92,7 @@ fig ```` The triangulation is now Delaunay, and there are no more illegal edges. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_legalise_edge.jl). @@ -104,12 +105,12 @@ points = [ (-1.0, 2.0), (4.0, 6.0), (4.0, 3.0), (-3.0, 7.0), (-6.0, -1.0), (9.0, 5.0), (5.0, -5.0), (-6.0, 7.0), (0.0, 0.0), (-3.0, 4.0), (-5.0, 5.0), (-3.0, -4.0), - (5.0, -1.0), (2.0, -2.0) + (5.0, -1.0), (2.0, -2.0), ] p = (3.0, 2.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig push!(points, p) diff --git a/docs/src/tutorials/operations_segment_insertion.md b/docs/src/tutorials/operations_segment_insertion.md index 666f79175..1293bb579 100644 --- a/docs/src/tutorials/operations_segment_insertion.md +++ b/docs/src/tutorials/operations_segment_insertion.md @@ -15,8 +15,10 @@ using CairoMakie Let us now define our initial triangulation. ````@example operations_segment_insertion -points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), -(0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8)] +points = [ + (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), + (0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8), +] tri = triangulate(points) fig, ax, sc = triplot(tri) fig @@ -63,6 +65,7 @@ fig ```` The other constrained edge was partially removed. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_segment_insertion.jl). @@ -71,8 +74,10 @@ You can view the source code for this file [here](https://github.com/JuliaGeomet using DelaunayTriangulation using CairoMakie -points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), -(0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8)] +points = [ + (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), + (0.9, 0.9), (0.5, 0.5), (0.2, 0.5), (0.5, 0.8), +] tri = triangulate(points) fig, ax, sc = triplot(tri) fig diff --git a/docs/src/tutorials/operations_split_edge.md b/docs/src/tutorials/operations_split_edge.md index 66ad0a5c9..ea714fc2b 100644 --- a/docs/src/tutorials/operations_split_edge.md +++ b/docs/src/tutorials/operations_split_edge.md @@ -14,13 +14,15 @@ edge. First, let us consider the following triangulation. using DelaunayTriangulation using CairoMakie -points = [(0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), +points = [ + (0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), (-2.0, 7.0), (3.0, 6.0), (2.0, -2.0), (-4.0, 1.0), - (1.0, 5.0)] + (1.0, 5.0), +] p = (0.0, 3.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig ```` @@ -61,6 +63,7 @@ legalise_edge!(tri, k, j, r) These steps, in particular the steps of splitting both sides of the edge and then legalising, are also implemented in [`DelaunayTriangulation.complete_split_edge_and_legalise!`](@ref). + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_split_edge.jl). @@ -69,13 +72,15 @@ You can view the source code for this file [here](https://github.com/JuliaGeomet using DelaunayTriangulation using CairoMakie -points = [(0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), +points = [ + (0.0, 0.0), (0.0, 4.0), (2.0, 3.0), (-2.0, 3.0), (-2.0, 7.0), (3.0, 6.0), (2.0, -2.0), (-4.0, 1.0), - (1.0, 5.0)] + (1.0, 5.0), +] p = (0.0, 3.0) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig push!(points, p) diff --git a/docs/src/tutorials/operations_split_triangle.md b/docs/src/tutorials/operations_split_triangle.md index ab25037f5..5bbdbba64 100644 --- a/docs/src/tutorials/operations_split_triangle.md +++ b/docs/src/tutorials/operations_split_triangle.md @@ -20,7 +20,7 @@ points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] p = (0.2, 0.5) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig ```` @@ -42,6 +42,7 @@ fig See the [`legalise_edge!` tutorial](operations_legalise_edge.md) for more discussion about restoring the Delaunay property of the triangulation after using `split_triangle!`. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_split_triangle.jl). @@ -54,7 +55,7 @@ points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] p = (0.2, 0.5) tri = triangulate(points) fig, ax, sc = triplot(tri) -scatter!(ax, [p], markersize=14) +scatter!(ax, [p], markersize = 14) fig push!(points, p) diff --git a/docs/src/tutorials/operations_vertex_insertion_deletion.md b/docs/src/tutorials/operations_vertex_insertion_deletion.md index f36d3e3c2..8160e9128 100644 --- a/docs/src/tutorials/operations_vertex_insertion_deletion.md +++ b/docs/src/tutorials/operations_vertex_insertion_deletion.md @@ -54,9 +54,9 @@ adding a point outside of the triangulation would not work. Here is an example o ````@example operations_vertex_insertion_deletion delete_ghost_triangles!(tri) try #hide -add_point!(tri, 2.0, 1.5) + add_point!(tri, 2.0, 1.5) catch e #hide -println(e) #hide + println(e) #hide end #hide ```` @@ -90,7 +90,7 @@ If we do want to fix the convex hull, we can use [`convex_hull!(tri)`](@ref). ````@example operations_vertex_insertion_deletion convex_hull!(tri) -fig, ax, sc = triplot(tri, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_convex_hull = true) fig ```` @@ -129,6 +129,7 @@ fig Note that in this situation, `points` still contains those points that we have now deleted. This is the reason to be careful about using, say, [`DelaunayTriangulation.each_point`](@ref) rather than [`each_solid_vertex`](@ref). This triangulation is also still Delaunay. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/operations_vertex_insertion_deletion.jl). @@ -152,7 +153,7 @@ fig, ax, sc = triplot(tri) fig delete_ghost_triangles!(tri) -add_point!(tri, 2.0, 1.5) + add_point!(tri, 2.0, 1.5) DelaunayTriangulation.has_ghost_triangles(tri) @@ -163,7 +164,7 @@ DelaunayTriangulation.has_ghost_triangles(tri) get_convex_hull_vertices(tri) convex_hull!(tri) -fig, ax, sc = triplot(tri, show_convex_hull=true) +fig, ax, sc = triplot(tri, show_convex_hull = true) fig rng = StableRNG(123) diff --git a/docs/src/tutorials/point_in_polygon.md b/docs/src/tutorials/point_in_polygon.md index b8a9bb6f0..789a88f41 100644 --- a/docs/src/tutorials/point_in_polygon.md +++ b/docs/src/tutorials/point_in_polygon.md @@ -156,10 +156,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -174,7 +177,7 @@ fig = Figure() ax = Axis(fig[1, 1]) scatter!(ax, query_points) for nodes in nodes - lines!(ax, points[reduce(vcat, nodes)], color=:magenta, linewidth=3) + lines!(ax, points[reduce(vcat, nodes)], color = :magenta, linewidth = 3) end fig ```` @@ -192,15 +195,15 @@ for points very close to the boundary. Here is the first approach: ````@example point_in_polygon is_inside = [DelaunayTriangulation.distance_to_polygon(q, points, nodes) > 0 for q in query_points] -scatter!(ax, query_points[is_inside], color=:blue) -scatter!(ax, query_points[.!is_inside], color=:red) +scatter!(ax, query_points[is_inside], color = :blue) +scatter!(ax, query_points[.!is_inside], color = :red) fig ```` Here is the second method. ````@example point_in_polygon -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) is_inside_2 = [DelaunayTriangulation.dist(tri, q) > 0 for q in query_points]; nothing #hide ```` @@ -375,10 +378,13 @@ J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] -A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] +A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], +] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -393,16 +399,16 @@ fig = Figure() ax = Axis(fig[1, 1]) scatter!(ax, query_points) for nodes in nodes - lines!(ax, points[reduce(vcat, nodes)], color=:magenta, linewidth=3) + lines!(ax, points[reduce(vcat, nodes)], color = :magenta, linewidth = 3) end fig is_inside = [DelaunayTriangulation.distance_to_polygon(q, points, nodes) > 0 for q in query_points] -scatter!(ax, query_points[is_inside], color=:blue) -scatter!(ax, query_points[.!is_inside], color=:red) +scatter!(ax, query_points[is_inside], color = :blue) +scatter!(ax, query_points[.!is_inside], color = :red) fig -tri = triangulate(points; boundary_nodes=nodes) +tri = triangulate(points; boundary_nodes = nodes) is_inside_2 = [DelaunayTriangulation.dist(tri, q) > 0 for q in query_points]; is_inside_3 = [find_polygon(tri, q) ≠ 0 for q in query_points]; diff --git a/docs/src/tutorials/point_location.md b/docs/src/tutorials/point_location.md index a490b361f..becd56543 100644 --- a/docs/src/tutorials/point_location.md +++ b/docs/src/tutorials/point_location.md @@ -27,7 +27,7 @@ using StableRNGs points = [ (-3.0, 6.0), (5.0, 1.0), (-5.0, 3.0), (2.0, -3.0), (5.0, 8.0), (0.0, 0.0), (2.0, 5.0), (-3.0, 1.0), - (-2.0, -1.0), (-1.0, 4.0) + (-2.0, -1.0), (-1.0, 4.0), ] tri = triangulate(points) q = (3.0, 3.0) @@ -55,7 +55,7 @@ and then start at the point that is closest to `q` out of those sampled, then ma until `q` is found. This number of samples can be changed using the `m` keyword argument. For example, ````@example point_location -V = find_triangle(tri, q, m=10) +V = find_triangle(tri, q, m = 10) ```` means that we get a sample of size 10, and start at whichever point is the closest. @@ -64,7 +64,7 @@ You could also instead specify the point to start at using the `k` keyword argum For example, ````@example point_location -V = find_triangle(tri, q, k=6) +V = find_triangle(tri, q, k = 6) ```` starts the algorithm at the point `6`. @@ -94,7 +94,7 @@ start at a central point of the triangulation. (The index `-1` is just the ghost be visualised. ````@example point_location -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) scatter!(ax, q) fig ```` @@ -119,7 +119,7 @@ inner = [[r, z, v, u, w, t, s, r]] boundary_nodes, points = convert_boundary_points_to_indices([outer, inner]) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.01get_area(tri), rng); +refine!(tri; max_area = 0.01get_area(tri), rng); nothing #hide ```` @@ -127,7 +127,7 @@ The issue with concavity is that the ghost triangles can no longer be sensibly d To demonstrate this, see the following plot: ````@example point_location -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) fig ```` @@ -139,10 +139,10 @@ qs = [ (4.0, 5.0), (1.0, 5.6), (0.2, 5.0), (0.0, -1.0), (0.5, 3.5), (2.5, 1.5), (1.0, 2.0), (4.5, 1.0), (6.0, 1.5), - (0.5, 8.5), (1.0, 7.5), (1.2, 1.6) + (0.5, 8.5), (1.0, 7.5), (1.2, 1.6), ] -fig, ax, sc = triplot(tri, show_ghost_edges=false) -scatter!(ax, qs, color=:blue, markersize=16) +fig, ax, sc = triplot(tri, show_ghost_edges = false) +scatter!(ax, qs, color = :blue, markersize = 16) fig ```` @@ -166,7 +166,7 @@ a ghost triangle is to be returned. If the check finds this to not be the case, restarts. With these results, we now compute: ````@example point_location -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] ```` Here is how we can actually test that these results are now correct. We cannot directly @@ -207,26 +207,26 @@ v₁, w₁ = (5.0, 3.0), (4.0, 3.0) new_domain₁ = [[m₁, q₁, o₁, p₁, r₁, s₁, n₁, m₁]] new_domain₂ = [[t₁, w₁, v₁, u₁, t₁]] boundary_nodes, points = convert_boundary_points_to_indices( - [outer, inner, new_domain₁, new_domain₂] + [outer, inner, new_domain₁, new_domain₂], ) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.001get_area(tri), rng) +refine!(tri; max_area = 0.001get_area(tri), rng) qs = [ (0.6, 6.4), (1.4, 0.8), (3.1, 2.9), (6.3, 4.9), (4.6, 3.5), (7.0, 7.0), (8.9, 5.1), (5.8, 0.8), (1.0, 1.5), - (1.5, 2.0), (8.15, 6.0) + (1.5, 2.0), (8.15, 6.0), ] fig, ax, sc = triplot(tri) -scatter!(ax, qs, color=:blue, markersize=16) +scatter!(ax, qs, color = :blue, markersize = 16) fig ```` Here are the `find_triangle` results. ````@example point_location -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] ```` Again, we can verify that these are all correct as follows. Without `concavity_protection=true`, @@ -260,7 +260,7 @@ using StableRNGs points = [ (-3.0, 6.0), (5.0, 1.0), (-5.0, 3.0), (2.0, -3.0), (5.0, 8.0), (0.0, 0.0), (2.0, 5.0), (-3.0, 1.0), - (-2.0, -1.0), (-1.0, 4.0) + (-2.0, -1.0), (-1.0, 4.0), ] tri = triangulate(points) q = (3.0, 3.0) @@ -272,9 +272,9 @@ V = find_triangle(tri, q) DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) -V = find_triangle(tri, q, m=10) +V = find_triangle(tri, q, m = 10) -V = find_triangle(tri, q, k=6) +V = find_triangle(tri, q, k = 6) q = (-5.0, 8.0) fig, ax, sc = triplot(tri) @@ -283,7 +283,7 @@ fig V = find_triangle(tri, q) -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) scatter!(ax, q) fig @@ -300,26 +300,26 @@ inner = [[r, z, v, u, w, t, s, r]] boundary_nodes, points = convert_boundary_points_to_indices([outer, inner]) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.01get_area(tri), rng); +refine!(tri; max_area = 0.01get_area(tri), rng); -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) fig qs = [ (4.0, 5.0), (1.0, 5.6), (0.2, 5.0), (0.0, -1.0), (0.5, 3.5), (2.5, 1.5), (1.0, 2.0), (4.5, 1.0), (6.0, 1.5), - (0.5, 8.5), (1.0, 7.5), (1.2, 1.6) + (0.5, 8.5), (1.0, 7.5), (1.2, 1.6), ] -fig, ax, sc = triplot(tri, show_ghost_edges=false) -scatter!(ax, qs, color=:blue, markersize=16) +fig, ax, sc = triplot(tri, show_ghost_edges = false) +scatter!(ax, qs, color = :blue, markersize = 16) fig Vs = [find_triangle(tri, q; rng) for q in qs] Vs[end] -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] δs = [DelaunayTriangulation.dist(tri, q) for q in qs] results = Vector{Bool}(undef, length(qs)) @@ -342,22 +342,22 @@ v₁, w₁ = (5.0, 3.0), (4.0, 3.0) new_domain₁ = [[m₁, q₁, o₁, p₁, r₁, s₁, n₁, m₁]] new_domain₂ = [[t₁, w₁, v₁, u₁, t₁]] boundary_nodes, points = convert_boundary_points_to_indices( - [outer, inner, new_domain₁, new_domain₂] + [outer, inner, new_domain₁, new_domain₂], ) rng = StableRNG(125123) tri = triangulate(points; rng, boundary_nodes) -refine!(tri; max_area=0.001get_area(tri), rng) +refine!(tri; max_area = 0.001get_area(tri), rng) qs = [ (0.6, 6.4), (1.4, 0.8), (3.1, 2.9), (6.3, 4.9), (4.6, 3.5), (7.0, 7.0), (8.9, 5.1), (5.8, 0.8), (1.0, 1.5), - (1.5, 2.0), (8.15, 6.0) + (1.5, 2.0), (8.15, 6.0), ] fig, ax, sc = triplot(tri) -scatter!(ax, qs, color=:blue, markersize=16) +scatter!(ax, qs, color = :blue, markersize = 16) fig -Vs = [find_triangle(tri, q; rng, concavity_protection=true) for q in qs] +Vs = [find_triangle(tri, q; rng, concavity_protection = true) for q in qs] δs = [DelaunayTriangulation.dist(tri, q) for q in qs] results = Vector{Bool}(undef, length(qs)) diff --git a/docs/src/tutorials/pole_of_inaccessibility.md b/docs/src/tutorials/pole_of_inaccessibility.md index 6a1d546ec..a827ee4e1 100644 --- a/docs/src/tutorials/pole_of_inaccessibility.md +++ b/docs/src/tutorials/pole_of_inaccessibility.md @@ -48,24 +48,26 @@ points = [ 2.12497 9.42582 7.27436 2.7979 3.0 4.0 - 5.33697 1.88019]' -outer_boundary = [ # split into segments for demonstration purposes + 5.33697 1.88019 +]' +outer_boundary = [ + # split into segments for demonstration purposes [1, 4, 3, 2], [2, 9, 10, 11, 8, 7, 12], [12, 6, 13, 5, 14, 15, 16, 17, 16], - [16, 17, 18, 19, 20, 21, 22, 23, 1] + [16, 17, 18, 19, 20, 21, 22, 23, 1], ] inner_1 = [ - [26, 25, 24], [24, 28, 27, 26] + [26, 25, 24], [24, 28, 27, 26], ] inner_2 = [ - [29, 30, 31, 29] + [29, 30, 31, 29], ] boundary_nodes = [outer_boundary, inner_1, inner_2] fig = Figure() ax = Axis(fig[1, 1]) for i in eachindex(boundary_nodes) - lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color=:red) + lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color = :red) end fig ```` @@ -77,7 +79,7 @@ pole = DelaunayTriangulation.pole_of_inaccessibility(points, boundary_nodes) ```` ````@example pole_of_inaccessibility -scatter!(ax, pole, color=:blue, markersize=16) +scatter!(ax, pole, color = :blue, markersize = 16) fig ```` @@ -91,7 +93,7 @@ we get the triangulation. ````@example pole_of_inaccessibility θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -102,7 +104,7 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) ```` To see the poles, called representative points, we use @@ -115,12 +117,12 @@ The keys of the `Dict` refer to the curve index, and the values contain the coordinates. ````@example pole_of_inaccessibility -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) colors = (:red, :blue, :darkgreen, :purple) for i in eachindex(boundary_nodes) - lines!(ax, points[reduce(vcat, boundary_nodes[i])], color=colors[i], linewidth=6) + lines!(ax, points[reduce(vcat, boundary_nodes[i])], color = colors[i], linewidth = 6) coords = DelaunayTriangulation.get_representative_point_coordinates(tri, i) - scatter!(ax, coords, color=colors[i], markersize=16) + scatter!(ax, coords, color = colors[i], markersize = 16) end fig ```` @@ -129,6 +131,7 @@ Note that the green and purple boundaries have the same pole of inaccessibility. first curve, the red curve, is the only one that has the pole of inaccessibility computed with respect to all other boundaries. You can also see that indeed the ghost edges are all oriented relative to the representative points. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/pole_of_inaccessibility.jl). @@ -168,35 +171,37 @@ points = [ 2.12497 9.42582 7.27436 2.7979 3.0 4.0 - 5.33697 1.88019]' -outer_boundary = [ # split into segments for demonstration purposes + 5.33697 1.88019 +]' +outer_boundary = [ + # split into segments for demonstration purposes [1, 4, 3, 2], [2, 9, 10, 11, 8, 7, 12], [12, 6, 13, 5, 14, 15, 16, 17, 16], - [16, 17, 18, 19, 20, 21, 22, 23, 1] + [16, 17, 18, 19, 20, 21, 22, 23, 1], ] inner_1 = [ - [26, 25, 24], [24, 28, 27, 26] + [26, 25, 24], [24, 28, 27, 26], ] inner_2 = [ - [29, 30, 31, 29] + [29, 30, 31, 29], ] boundary_nodes = [outer_boundary, inner_1, inner_2] fig = Figure() ax = Axis(fig[1, 1]) for i in eachindex(boundary_nodes) - lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color=:red) + lines!(ax, points[:, reduce(vcat, boundary_nodes[i])], color = :red) end fig pole = DelaunayTriangulation.pole_of_inaccessibility(points, boundary_nodes) -scatter!(ax, pole, color=:blue, markersize=16) +scatter!(ax, pole, color = :blue, markersize = 16) fig θ = LinRange(0, 2π, 20) |> collect θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 -xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() +xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 global cx @@ -207,16 +212,16 @@ for i in 1:2 cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) -tri = triangulate(points; boundary_nodes=boundary_nodes) +tri = triangulate(points; boundary_nodes = boundary_nodes) DelaunayTriangulation.get_representative_point_list(tri) -fig, ax, sc = triplot(tri, show_ghost_edges=true) +fig, ax, sc = triplot(tri, show_ghost_edges = true) colors = (:red, :blue, :darkgreen, :purple) for i in eachindex(boundary_nodes) - lines!(ax, points[reduce(vcat, boundary_nodes[i])], color=colors[i], linewidth=6) + lines!(ax, points[reduce(vcat, boundary_nodes[i])], color = colors[i], linewidth = 6) coords = DelaunayTriangulation.get_representative_point_coordinates(tri, i) - scatter!(ax, coords, color=colors[i], markersize=16) + scatter!(ax, coords, color = colors[i], markersize = 16) end fig ``` diff --git a/docs/src/tutorials/refinement.md b/docs/src/tutorials/refinement.md index ff83b9455..e2fa025a8 100644 --- a/docs/src/tutorials/refinement.md +++ b/docs/src/tutorials/refinement.md @@ -38,7 +38,7 @@ points = tuple.(x, y) tri = triangulate(points; rng) orig_tri = deepcopy(tri) A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.01A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.01A, rng) ```` The [`refine!`](@ref) function operates on `tri` in-place. If we wanted to review the @@ -55,8 +55,8 @@ which is about 0.0067. Moreover, the smallest angle is indeed greater than 30. Let us compare the triangulation pre- and post-refinement. ````@example refinement -fig, ax, sc = triplot(orig_tri, axis=(title="Pre-refinement",)) -ax = Axis(fig[1, 2], title="Post-refinement") +fig, ax, sc = triplot(orig_tri, axis = (title = "Pre-refinement",)) +ax = Axis(fig[1, 2], title = "Post-refinement") triplot!(ax, tri) fig ```` @@ -67,7 +67,7 @@ or where was a cluster of random points. If we wanted, we could refine again to try and improve this. ````@example refinement -refine!(tri; min_angle=30.0, max_area=0.001A, rng) # 0.1% instead of 1% +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) # 0.1% instead of 1% fig, ax, sc = triplot(tri) fig ```` @@ -80,7 +80,7 @@ number of points. ````@example refinement test_tri = deepcopy(tri) -refine!(test_tri; min_angle=35.0, max_area=0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going +refine!(test_tri; min_angle = 35.0, max_area = 0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going statistics(test_tri) ```` @@ -101,14 +101,14 @@ these as follows: ````@example refinement stats = statistics(tri) -fig = Figure(fontsize=33) +fig = Figure(fontsize = 33) areas = get_all_stat(stats, :area) ./ A angles = first.(get_all_stat(stats, :angles)) # the first is the smallest -ax = Axis(fig[1, 1], xlabel="A/A(Ω)", ylabel="Count", title="Area histogram", width=400, height=400, titlealign=:left) -hist!(ax, areas, bins=0:0.0001:0.0005) -ax = Axis(fig[1, 2], xlabel="θₘᵢₙ", ylabel="Count", title="Angle histogram", width=400, height=400, titlealign=:left) -hist!(ax, rad2deg.(angles), bins=20:2:60) -vlines!(ax, [30.0], color=:red) +ax = Axis(fig[1, 1], xlabel = "A/A(Ω)", ylabel = "Count", title = "Area histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, areas, bins = 0:0.0001:0.0005) +ax = Axis(fig[1, 2], xlabel = "θₘᵢₙ", ylabel = "Count", title = "Angle histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, rad2deg.(angles), bins = 20:2:60) +vlines!(ax, [30.0], color = :red) resize_to_layout!(fig) fig ```` @@ -146,7 +146,7 @@ Let us now refine this triangulation. ````@example refinement A = get_area(tri) -refine!(tri; min_angle=27.3, max_area=0.01A, rng) +refine!(tri; min_angle = 27.3, max_area = 0.01A, rng) fig, ax, sc = triplot(tri) fig ```` @@ -159,7 +159,7 @@ the same amount of time as if we had refined it with these constraints in the first place. ````@example refinement -refine!(tri; min_angle=33.9, max_area=0.001A, rng) +refine!(tri; min_angle = 33.9, max_area = 0.001A, rng) fig, ax, sc = triplot(tri) fig ```` @@ -203,7 +203,7 @@ the new results. boundary_nodes, points = convert_boundary_points_to_indices(x, y) rng = StableRNG(456) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=30.0, custom_constraint=area_constraint, rng) +refine!(tri; min_angle = 30.0, custom_constraint = area_constraint, rng) fig, ax, sc = triplot(tri) fig ```` @@ -249,7 +249,7 @@ using Downloads using DelimitedFiles boundary_url = "https://gist.githubusercontent.com/DanielVandH/13687b0918e45a416a5c93cd52c91449/raw/a8da6cdc94859fd66bcff85a2307f0f9cd57a18c/boundary.txt" boundary_dir = Downloads.download(boundary_url) -boundary = readdlm(boundary_dir, skipstart=6) +boundary = readdlm(boundary_dir, skipstart = 6) boundary_points = [(boundary[i, 1], boundary[i, 2]) for i in axes(boundary, 1)] reverse!(boundary_points) ```` @@ -268,7 +268,7 @@ Now let's refine. ````@example refinement A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.001A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) ```` ````@example refinement @@ -297,7 +297,7 @@ but there are still some that do not. Here is another set of results with a lowe boundary_nodes, points = convert_boundary_points_to_indices(boundary_points) rng = StableRNG(789) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=18.73, max_area=0.001A, rng) +refine!(tri; min_angle = 18.73, max_area = 0.001A, rng) fig = Figure(fontsize = 43) ax = Axis(fig[1, 1], width = 600, height = 400) triplot!(tri) @@ -312,6 +312,7 @@ fig In this case, all the triangles satisfy the constraint, of course at the expense of some other triangles having lesser quality. + ## Just the code An uncommented version of this example is given below. You can view the source code for this file [here](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/docs/src/literate_tutorials/refinement.jl). @@ -328,35 +329,35 @@ points = tuple.(x, y) tri = triangulate(points; rng) orig_tri = deepcopy(tri) A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.01A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.01A, rng) statistics(tri) -fig, ax, sc = triplot(orig_tri, axis=(title="Pre-refinement",)) -ax = Axis(fig[1, 2], title="Post-refinement") +fig, ax, sc = triplot(orig_tri, axis = (title = "Pre-refinement",)) +ax = Axis(fig[1, 2], title = "Post-refinement") triplot!(ax, tri) fig -refine!(tri; min_angle=30.0, max_area=0.001A, rng) # 0.1% instead of 1% +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) # 0.1% instead of 1% fig, ax, sc = triplot(tri) fig test_tri = deepcopy(tri) -refine!(test_tri; min_angle=35.0, max_area=0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going +refine!(test_tri; min_angle = 35.0, max_area = 0.001A, max_points = 5_000, rng) # 20_000 so that it doesn't just keep going statistics(test_tri) fig, ax, sc = triplot(test_tri) fig stats = statistics(tri) -fig = Figure(fontsize=33) +fig = Figure(fontsize = 33) areas = get_all_stat(stats, :area) ./ A angles = first.(get_all_stat(stats, :angles)) # the first is the smallest -ax = Axis(fig[1, 1], xlabel="A/A(Ω)", ylabel="Count", title="Area histogram", width=400, height=400, titlealign=:left) -hist!(ax, areas, bins=0:0.0001:0.0005) -ax = Axis(fig[1, 2], xlabel="θₘᵢₙ", ylabel="Count", title="Angle histogram", width=400, height=400, titlealign=:left) -hist!(ax, rad2deg.(angles), bins=20:2:60) -vlines!(ax, [30.0], color=:red) +ax = Axis(fig[1, 1], xlabel = "A/A(Ω)", ylabel = "Count", title = "Area histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, areas, bins = 0:0.0001:0.0005) +ax = Axis(fig[1, 2], xlabel = "θₘᵢₙ", ylabel = "Count", title = "Angle histogram", width = 400, height = 400, titlealign = :left) +hist!(ax, rad2deg.(angles), bins = 20:2:60) +vlines!(ax, [30.0], color = :red) resize_to_layout!(fig) fig @@ -379,11 +380,11 @@ fig, ax, sc = triplot(tri) fig A = get_area(tri) -refine!(tri; min_angle=27.3, max_area=0.01A, rng) +refine!(tri; min_angle = 27.3, max_area = 0.01A, rng) fig, ax, sc = triplot(tri) fig -refine!(tri; min_angle=33.9, max_area=0.001A, rng) +refine!(tri; min_angle = 33.9, max_area = 0.001A, rng) fig, ax, sc = triplot(tri) fig @@ -407,7 +408,7 @@ end boundary_nodes, points = convert_boundary_points_to_indices(x, y) rng = StableRNG(456) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=30.0, custom_constraint=area_constraint, rng) +refine!(tri; min_angle = 30.0, custom_constraint = area_constraint, rng) fig, ax, sc = triplot(tri) fig @@ -431,7 +432,7 @@ using Downloads using DelimitedFiles boundary_url = "https://gist.githubusercontent.com/DanielVandH/13687b0918e45a416a5c93cd52c91449/raw/a8da6cdc94859fd66bcff85a2307f0f9cd57a18c/boundary.txt" boundary_dir = Downloads.download(boundary_url) -boundary = readdlm(boundary_dir, skipstart=6) +boundary = readdlm(boundary_dir, skipstart = 6) boundary_points = [(boundary[i, 1], boundary[i, 2]) for i in axes(boundary, 1)] reverse!(boundary_points) @@ -442,7 +443,7 @@ fig, ax, sc = triplot(tri) fig A = get_area(tri) -refine!(tri; min_angle=30.0, max_area=0.001A, rng) +refine!(tri; min_angle = 30.0, max_area = 0.001A, rng) fig, ax, sc = triplot(tri) fig @@ -456,7 +457,7 @@ fig boundary_nodes, points = convert_boundary_points_to_indices(boundary_points) rng = StableRNG(789) tri = triangulate(points; boundary_nodes, rng) -refine!(tri; min_angle=18.73, max_area=0.001A, rng) +refine!(tri; min_angle = 18.73, max_area = 0.001A, rng) fig = Figure(fontsize = 43) ax = Axis(fig[1, 1], width = 600, height = 400) triplot!(tri) diff --git a/docs/src/tutorials/unconstrained.md b/docs/src/tutorials/unconstrained.md index 0a4ccb3ee..aa414b86c 100644 --- a/docs/src/tutorials/unconstrained.md +++ b/docs/src/tutorials/unconstrained.md @@ -28,7 +28,7 @@ as a keyword argument, but again if you are not concerned about the RNG (or set the seed using `Random.seed!`) then you can ignore this. ````@example unconstrained -tri = triangulate(points; rng=rng) +tri = triangulate(points; rng = rng) ```` ````@example unconstrained @@ -225,7 +225,7 @@ using LinearAlgebra # used for computing norms later rng = StableRNG(123) points = rand(rng, 2, 500) # just do rand(2, 500) if you are not concerned about the RNG -tri = triangulate(points; rng=rng) +tri = triangulate(points; rng = rng) fig, ax, sc = triplot(tri) fig diff --git a/docs/src/tutorials/voronoi.md b/docs/src/tutorials/voronoi.md index bff13b686..a93a3ef16 100644 --- a/docs/src/tutorials/voronoi.md +++ b/docs/src/tutorials/voronoi.md @@ -22,7 +22,7 @@ and then passing that triangulation into `voronoi`. points = [ (-3.0, 7.0), (1.0, 6.0), (-1.0, 3.0), (-2.0, 4.0), (3.0, -2.0), (5.0, 5.0), - (-4.0, -3.0), (3.0, 8.0) + (-4.0, -3.0), (3.0, 8.0), ] rng = StableRNG(123) tri = triangulate(points; rng) @@ -33,7 +33,7 @@ To visualise the tessellation, you can use `voronoiplot`. Here, we also compare the tessellation with its dual triangulation. ````@example voronoi -fig, ax, sc = voronoiplot(vorn, markersize=13, colormap=:matter, strokecolor=:white, strokewidth=5) +fig, ax, sc = voronoiplot(vorn, markersize = 13, colormap = :matter, strokecolor = :white, strokewidth = 5) triplot!(ax, tri) fig ```` @@ -179,7 +179,7 @@ function get_polygon_area(vorn, i) vⱼ = vertices[begin] pⱼ = get_polygon_point(vorn, vⱼ) xⱼ, yⱼ = getxy(pⱼ) - for j in (firstindex(vertices)+1):lastindex(vertices) # same as 2:length(vertices) + for j in (firstindex(vertices) + 1):lastindex(vertices) # same as 2:length(vertices) vⱼ₊₁ = vertices[j] pⱼ₊₁ = get_polygon_point(vorn, vⱼ₊₁) xⱼ₊₁, yⱼ₊₁ = getxy(pⱼ₊₁) @@ -262,13 +262,13 @@ using StableRNGs points = [ (-3.0, 7.0), (1.0, 6.0), (-1.0, 3.0), (-2.0, 4.0), (3.0, -2.0), (5.0, 5.0), - (-4.0, -3.0), (3.0, 8.0) + (-4.0, -3.0), (3.0, 8.0), ] rng = StableRNG(123) tri = triangulate(points; rng) vorn = voronoi(tri) -fig, ax, sc = voronoiplot(vorn, markersize=13, colormap=:matter, strokecolor=:white, strokewidth=5) +fig, ax, sc = voronoiplot(vorn, markersize = 13, colormap = :matter, strokecolor = :white, strokewidth = 5) triplot!(ax, tri) fig @@ -322,7 +322,7 @@ function get_polygon_area(vorn, i) vⱼ = vertices[begin] pⱼ = get_polygon_point(vorn, vⱼ) xⱼ, yⱼ = getxy(pⱼ) - for j in (firstindex(vertices)+1):lastindex(vertices) # same as 2:length(vertices) + for j in (firstindex(vertices) + 1):lastindex(vertices) # same as 2:length(vertices) vⱼ₊₁ = vertices[j] pⱼ₊₁ = get_polygon_point(vorn, vⱼ₊₁) xⱼ₊₁, yⱼ₊₁ = getxy(pⱼ₊₁) diff --git a/src/DelaunayTriangulation.jl b/src/DelaunayTriangulation.jl index e02f60c89..ab6c7c0ab 100644 --- a/src/DelaunayTriangulation.jl +++ b/src/DelaunayTriangulation.jl @@ -35,4 +35,4 @@ include("validation.jl") include("exports.jl") include("public.jl") -end \ No newline at end of file +end diff --git a/src/algorithms.jl b/src/algorithms.jl index cad5be78d..2524922ff 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -35,4 +35,4 @@ include("algorithms/voronoi/centroidal.jl") include("algorithms/voronoi/clipped_coordinates.jl") include("algorithms/voronoi/clipped.jl") include("algorithms/voronoi/main.jl") -include("algorithms/voronoi/unbounded.jl") \ No newline at end of file +include("algorithms/voronoi/unbounded.jl") diff --git a/src/algorithms/convex_hull.jl b/src/algorithms/convex_hull.jl index adf1fba57..0bd288214 100644 --- a/src/algorithms/convex_hull.jl +++ b/src/algorithms/convex_hull.jl @@ -13,7 +13,7 @@ Computes the convex hull of `points`. The monotone chain algorithm is used. # Output - `ch`: The [`ConvexHull`](@ref). """ -function convex_hull(points; predicates::AbstractPredicateKernel=AdaptiveKernel(), IntegerType::Type{I}=Int) where {I} +function convex_hull(points; predicates::AbstractPredicateKernel = AdaptiveKernel(), IntegerType::Type{I} = Int) where {I} ch = ConvexHull(points, I[]) sizehint!(ch, num_points(points)) return convex_hull!(ch; predicates) @@ -30,7 +30,7 @@ See the documentation for more information about these choices. See also [`convex_hull`](@ref). """ -function convex_hull!(ch::ConvexHull{P,I}; predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P,I} +function convex_hull!(ch::ConvexHull{P, I}; predicates::AbstractPredicateKernel = AdaptiveKernel()) where {P, I} indices = get_vertices(ch) points = get_points(ch) empty!(indices) @@ -42,10 +42,10 @@ function convex_hull!(ch::ConvexHull{P,I}; predicates::AbstractPredicateKernel=A push!(indices, insertion_order[begin]) return ch elseif n == 2 - push!(indices, insertion_order[begin], insertion_order[begin+1], insertion_order[begin]) + push!(indices, insertion_order[begin], insertion_order[begin + 1], insertion_order[begin]) return ch elseif n == 3 - i, j, k = construct_positively_oriented_triangle(NTuple{3,I}, insertion_order[begin], insertion_order[begin+1], insertion_order[begin+2], points, predicates) + i, j, k = construct_positively_oriented_triangle(NTuple{3, I}, insertion_order[begin], insertion_order[begin + 1], insertion_order[begin + 2], points, predicates) push!(indices, i, j, k, i) return ch end @@ -54,13 +54,13 @@ function convex_hull!(ch::ConvexHull{P,I}; predicates::AbstractPredicateKernel=A sizehint!(lower, max(4, floor(I, cbrt(n)))) sizehint!(upper, max(4, floor(I, cbrt(n)))) for i in eachindex(insertion_order) - while length(upper) ≥ 2 && is_left(point_position_relative_to_line(predicates, get_point(points, upper[end-1]), get_point(points, upper[end]), get_point(points, insertion_order[i]))) + while length(upper) ≥ 2 && is_left(point_position_relative_to_line(predicates, get_point(points, upper[end - 1]), get_point(points, upper[end]), get_point(points, insertion_order[i]))) pop!(upper) end push!(upper, insertion_order[i]) end for i in lastindex(insertion_order):-1:firstindex(insertion_order) - while length(lower) ≥ 2 && is_left(point_position_relative_to_line(predicates, get_point(points, lower[end-1]), get_point(points, lower[end]), get_point(points, insertion_order[i]))) + while length(lower) ≥ 2 && is_left(point_position_relative_to_line(predicates, get_point(points, lower[end - 1]), get_point(points, lower[end]), get_point(points, insertion_order[i]))) pop!(lower) end push!(lower, insertion_order[i]) @@ -72,4 +72,4 @@ function convex_hull!(ch::ConvexHull{P,I}; predicates::AbstractPredicateKernel=A unique!(indices) push!(indices, indices[begin]) return ch -end \ No newline at end of file +end diff --git a/src/algorithms/intersections/rtree.jl b/src/algorithms/intersections/rtree.jl index 5a511233f..ff022d560 100644 --- a/src/algorithms/intersections/rtree.jl +++ b/src/algorithms/intersections/rtree.jl @@ -80,10 +80,10 @@ end Returns the subtree of `tree` at `level` that `bounding_box` should be inserted into. """ function find_subtree(tree, bounding_box, level) - node = get_root(tree)::Union{Branch,Leaf{Branch}} + node = get_root(tree)::Union{Branch, Leaf{Branch}} while get_level(node) > level min_enlargement = minimise_enlargement(node, bounding_box) - node = get_child(node, min_enlargement.idx)::Union{Branch,Leaf{Branch}} + node = get_child(node, min_enlargement.idx)::Union{Branch, Leaf{Branch}} end return node end @@ -350,7 +350,7 @@ end Returns the leaf node and the index in the leaf node's children that `id_bounding_box` is associated with. """ function find_bounding_box(tree::RTree, id_bounding_box::DiametralBoundingBox) - idx_leaf = find_bounding_box(get_root(tree), id_bounding_box)::Tuple{Leaf{Branch},Int} + idx_leaf = find_bounding_box(get_root(tree), id_bounding_box)::Tuple{Leaf{Branch}, Int} return idx_leaf[1]::Leaf{Branch}, idx_leaf[2]::Int end function find_bounding_box(branch::Branch, id_bounding_box::DiametralBoundingBox) @@ -450,7 +450,7 @@ Given the `detached` nodes from [`collapse_after_deletion!`](@ref), inserts them """ function insert_detached!(tree::RTree, detached) isempty(detached) && return tree - sort!(detached, by=get_level, rev=true) + sort!(detached, by = get_level, rev = true) for node in detached for child in get_children(node) insert!(tree, child, get_level(node)) @@ -467,7 +467,7 @@ end Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that intersect with `bounding_box`. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::RTree, bounding_box::BoundingBox; cache_id=1) +function get_intersections(tree::RTree, bounding_box::BoundingBox; cache_id = 1) return RTreeIntersectionIterator(tree, bounding_box, cache_id) end @@ -478,7 +478,7 @@ Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that as a [`BoundingBox`](@ref) with zero width and height centered at `point`. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::RTree, point::NTuple{2,<:Number}; cache_id=1) +function get_intersections(tree::RTree, point::NTuple{2, <:Number}; cache_id = 1) return RTreeIntersectionIterator(tree, BoundingBox(point), cache_id) end @@ -586,4 +586,4 @@ function _iterate(itr::RTreeIntersectionIterator, node, node_indices, need_tests end end end -end \ No newline at end of file +end diff --git a/src/algorithms/point_location/brute_force.jl b/src/algorithms/point_location/brute_force.jl index 978333d4d..dc0a309ab 100644 --- a/src/algorithms/point_location/brute_force.jl +++ b/src/algorithms/point_location/brute_force.jl @@ -1,4 +1,4 @@ -struct PointNotFoundError{T,P} <: Exception +struct PointNotFoundError{T, P} <: Exception tri::T q::P end @@ -29,7 +29,7 @@ See also [`find_triangle`](@ref). # Output - `V`: The triangle containing the point `q`. """ -function brute_force_search(tri::Triangulation, q; itr=each_triangle(tri), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function brute_force_search(tri::Triangulation, q; itr = each_triangle(tri), predicates::AbstractPredicateKernel = AdaptiveKernel()) for V in itr cert = point_position_relative_to_triangle(predicates, tri, V, q) !is_outside(cert) && return V @@ -45,12 +45,12 @@ Searches for a triangle in `tri` containing the vertex `i` in its circumcircle u below its witness plane. If no such triangle exists, `($∅, $∅, $∅)` is returned. You can control the method used for computing predicates via the `predicates` argument. """ -function brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function brute_force_search_enclosing_circumcircle(tri::Triangulation, i, predicates::AbstractPredicateKernel = AdaptiveKernel()) for V in each_triangle(tri) cert = point_position_relative_to_circumcircle(predicates, tri, V, i) !is_outside(cert) && return V end - tri_type=triangle_type(tri) + tri_type = triangle_type(tri) V = construct_triangle(tri_type, ∅, ∅, ∅) return V -end \ No newline at end of file +end diff --git a/src/algorithms/point_location/find_polygon.jl b/src/algorithms/point_location/find_polygon.jl index 57edd6d13..5b1be37a9 100644 --- a/src/algorithms/point_location/find_polygon.jl +++ b/src/algorithms/point_location/find_polygon.jl @@ -21,4 +21,4 @@ end function find_polygon(hierarchy::PolygonHierarchy, points, boundary_nodes, q) tree = find_tree(hierarchy, points, boundary_nodes, q) return isnothing(tree) ? 0 : get_index(tree) -end \ No newline at end of file +end diff --git a/src/algorithms/point_location/jump_and_march.jl b/src/algorithms/point_location/jump_and_march.jl index e09301b67..685973286 100644 --- a/src/algorithms/point_location/jump_and_march.jl +++ b/src/algorithms/point_location/jump_and_march.jl @@ -53,12 +53,14 @@ Selects the initial point for [`find_triangle`](@ref) to start from. - `i`: The index of the point closest to `q` out of those queried. """ select_initial_point -function select_initial_point(tri::Triangulation, _q; - point_indices=each_solid_vertex(tri), - m=default_num_samples(num_vertices(point_indices)), - try_points=(), - allow_boundary_points=!is_disjoint(tri), - rng::Random.AbstractRNG=Random.default_rng()) +function select_initial_point( + tri::Triangulation, _q; + point_indices = each_solid_vertex(tri), + m = default_num_samples(num_vertices(point_indices)), + try_points = (), + allow_boundary_points = !is_disjoint(tri), + rng::Random.AbstractRNG = Random.default_rng(), + ) F = number_type(tri) I = integer_type(tri) current_dist = typemax(F) @@ -77,12 +79,14 @@ function select_initial_point(tri::Triangulation, _q; end return I(current_idx) end -function select_initial_point(tri::Triangulation, q::Integer; - point_indices=each_solid_vertex(tri), - m=default_num_samples(num_vertices(tri)), - allow_boundary_points=!is_disjoint(tri), - try_points=(), - rng::Random.AbstractRNG=Random.default_rng()) +function select_initial_point( + tri::Triangulation, q::Integer; + point_indices = each_solid_vertex(tri), + m = default_num_samples(num_vertices(tri)), + allow_boundary_points = !is_disjoint(tri), + try_points = (), + rng::Random.AbstractRNG = Random.default_rng(), + ) return select_initial_point(tri, get_point(tri, q); point_indices, m, try_points, allow_boundary_points, rng) end @@ -102,7 +106,7 @@ Selects a random edge from the set of edges `edges`. - `pᵢ`: The point corresponding to `i`. - `pⱼ`: The point corresponding to `j`. """ -function select_random_edge(tri::Triangulation, edges, rng::Random.AbstractRNG=Random.default_rng()) +function select_random_edge(tri::Triangulation, edges, rng::Random.AbstractRNG = Random.default_rng()) edge = random_edge(rng, edges) i, j = edge_vertices(edge) pᵢ, pⱼ = get_point(tri, i, j) @@ -130,10 +134,10 @@ Selects a random edge from the set of edges `edges` and computes the certificate - `line_cert_i`: The [`Certificate`](@ref) for `pᵢ`'s position relative to the oriented line `pq`. - `line_cert_j`: The [`Certificate`](@ref) for `pⱼ`'s position relative to the oriented line `pq`. """ -function prepare_initial_edge(tri::Triangulation, edges, p, q, rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function prepare_initial_edge(tri::Triangulation, edges, p, q, rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) i, j, pᵢ, pⱼ = select_random_edge(tri, edges, rng) line_cert_i = point_position_relative_to_line(predicates, p, q, pᵢ) - line_cert_j = point_position_relative_to_line(predicates,p, q, pⱼ) + line_cert_j = point_position_relative_to_line(predicates, p, q, pⱼ) return i, j, pᵢ, pⱼ, line_cert_i, line_cert_j end @@ -181,7 +185,7 @@ respectively. In case the initial edge is collinear with the line `pq`, where `p = get_point(tri, q)`, then `fix_initial_collinear_edge_for_interior_vertex` to find a non-collinear edge resample more edges from [`prepare_initial_edge`](@ref) if necessary. """ -function select_initial_triangle_interior_vertex(tri::Triangulation, k, q, predicates::AbstractPredicateKernel=AdaptiveKernel(), store_history::F=Val(false), history=nothing, rng::Random.AbstractRNG=Random.default_rng()) where {F} +function select_initial_triangle_interior_vertex(tri::Triangulation, k, q, predicates::AbstractPredicateKernel = AdaptiveKernel(), store_history::F = Val(false), history = nothing, rng::Random.AbstractRNG = Random.default_rng()) where {F} p = get_point(tri, k) ## Select the initial edge to rotate about neighbouring_edges = get_adjacent2vertex(tri, k) @@ -201,7 +205,7 @@ function select_initial_triangle_interior_vertex(tri::Triangulation, k, q, predi pᵢ, pⱼ = pⱼ, pᵢ # pᵢ is left of pq, pⱼ is right of pq return p, i, j, pᵢ, pⱼ end -function select_initial_triangle_clockwise(tri::Triangulation, p, q, pᵢ, pⱼ, i, j, k, predicates::AbstractPredicateKernel=AdaptiveKernel(), store_history::F=Val(false), history=nothing) where {F} +function select_initial_triangle_clockwise(tri::Triangulation, p, q, pᵢ, pⱼ, i, j, k, predicates::AbstractPredicateKernel = AdaptiveKernel(), store_history::F = Val(false), history = nothing) where {F} line_cert_i = point_position_relative_to_line(predicates, p, q, pᵢ) if is_true(store_history) && is_collinear(line_cert_i) add_edge!(history, k, i) @@ -226,7 +230,7 @@ function select_initial_triangle_clockwise(tri::Triangulation, p, q, pᵢ, pⱼ, return i, j, pᵢ, pⱼ end end -function select_initial_triangle_counterclockwise(tri::Triangulation, line_cert_j, p, q, pᵢ, pⱼ, i, j, k, predicates::AbstractPredicateKernel=AdaptiveKernel(), store_history::F=Val(false), history=nothing) where {F} +function select_initial_triangle_counterclockwise(tri::Triangulation, line_cert_j, p, q, pᵢ, pⱼ, i, j, k, predicates::AbstractPredicateKernel = AdaptiveKernel(), store_history::F = Val(false), history = nothing) where {F} if is_true(store_history) && is_collinear(line_cert_j) add_edge!(history, k, j) end @@ -317,7 +321,7 @@ straight boundary in case `q` is collinear with it. - `right_cert`: The [`Certificate`](@ref) for the position of `q` relative to the boundary edge right of `k`. - `left_cert`: The [`Certificate`](@ref) for the position of `q` relative to the boundary edge left of `k`. """ -function check_for_intersections_with_adjacent_boundary_edges(tri::Triangulation{P,T,BN,W,I}, k, q, ghost_vertex=I(𝒢), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P,T,BN,W,I} +function check_for_intersections_with_adjacent_boundary_edges(tri::Triangulation{P, T, BN, W, I}, k, q, ghost_vertex = I(𝒢), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {P, T, BN, W, I} p = get_point(tri, k) right = get_right_boundary_node(tri, k, ghost_vertex) left = get_left_boundary_node(tri, k, ghost_vertex) @@ -379,7 +383,7 @@ This function works by stepping along vertices on the boundaries in the directio if `is_right(direction_cert)` and `search_left_down_adjacent_boundary_edges` otherwise. In these functions, a `while` loop is used to keep stepping until `q_pos_cert`, which is updated at each iteration, changes value. """ -function search_down_adjacent_boundary_edges(tri::Triangulation, k, q, direction, q_pos, next_vertex, predicates::AbstractPredicateKernel=AdaptiveKernel(), store_history::F=Val(false), history=nothing, ghost_vertex=integer_type(tri)(𝒢)) where {F} +function search_down_adjacent_boundary_edges(tri::Triangulation, k, q, direction, q_pos, next_vertex, predicates::AbstractPredicateKernel = AdaptiveKernel(), store_history::F = Val(false), history = nothing, ghost_vertex = integer_type(tri)(𝒢)) where {F} i = k j = next_vertex pⱼ = get_point(tri, j) @@ -479,7 +483,7 @@ the vertex `k`, rotating counter-clockwise until we find an intersection or reac the vertex `k`. By keeping track of the positions of `pq` relative to the current vertex and the previous, we can identify when an intersection is found. If no intersection is found before reaching the boundary edge left of `k`, then `check_for_intersections_with_triangle_left_to_boundary_vertex` is used to check the remaining triangle. """ -function check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri::Triangulation, k, q, right_cert, left_cert, predicates::AbstractPredicateKernel=AdaptiveKernel(), store_history::F=Val(false), history=nothing, ghost_vertex=integer_type(tri)(𝒢)) where {F} +function check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri::Triangulation, k, q, right_cert, left_cert, predicates::AbstractPredicateKernel = AdaptiveKernel(), store_history::F = Val(false), history = nothing, ghost_vertex = integer_type(tri)(𝒢)) where {F} I = integer_type(tri) p = get_point(tri, k) other_boundary_node = get_left_boundary_node(tri, k, ghost_vertex) @@ -498,7 +502,7 @@ function check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex end # Now, we've made it to this point, but we still need to check the triangle that contains the boundary vertex to the left of p. # This case is kept separate so that we can reuse left_cert - return_flag, _i, _j, edge_cert, triangle_cert = check_for_intersections_with_triangle_left_to_boundary_vertex(tri, k, q, left_cert, predicates, store_history, history, p, other_boundary_node, num_interior_neighbours, i, pᵢ, certᵢ) + return_flag, _i, _j, edge_cert, triangle_cert = check_for_intersections_with_triangle_left_to_boundary_vertex(tri, k, q, left_cert, predicates, store_history, history, p, other_boundary_node, num_interior_neighbours, i, pᵢ, certᵢ) return_flag && return _i, _j, edge_cert, triangle_cert # If we've made it to this point in the algorithm, then the point is outside of the triangulation. Again, # this is using the assumption that the geometry is convex. @@ -627,7 +631,7 @@ left of the line using `exterior_find_triangle_rotate_left` and clockwise otherw By keeping track of the current position of `q` and its position relative to the next ghost edge, we can identify when `q` resides inside a ghost triangle. """ -function exterior_find_triangle(tri::Triangulation, k, q, ghost_vertex=integer_type(tri)(𝒢), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function exterior_find_triangle(tri::Triangulation, k, q, ghost_vertex = integer_type(tri)(𝒢), predicates::AbstractPredicateKernel = AdaptiveKernel()) pₘ, pᵢ = get_point(tri, ghost_vertex, k) i = k q_position = point_position_relative_to_line(predicates, pₘ, pᵢ, q) @@ -746,18 +750,20 @@ Some notes about the output: While this function does still work for non-convex geometries, it may be significantly slower than for convex geometries, as most of the details of the algorithm assume that the geometry is convex, and so the algorithm may have to restart many times at new initial vertices `k`. """ -function find_triangle(tri::Triangulation, _q; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - point_indices=each_solid_vertex(tri), - m=default_num_samples(num_vertices(point_indices)), - try_points=(), - rng::Random.AbstractRNG=Random.default_rng(), - k=select_initial_point(tri, _q; point_indices, m, try_points, rng), - store_history::F=Val(false), - history=nothing, - maxiters=2 + num_exterior_curves(tri) - num_solid_vertices(tri) + num_solid_edges(tri), - concavity_protection=false, - use_barriers::Val{U}=Val(false)) where {F,U} +function find_triangle( + tri::Triangulation, _q; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + point_indices = each_solid_vertex(tri), + m = default_num_samples(num_vertices(point_indices)), + try_points = (), + rng::Random.AbstractRNG = Random.default_rng(), + k = select_initial_point(tri, _q; point_indices, m, try_points, rng), + store_history::F = Val(false), + history = nothing, + maxiters = 2 + num_exterior_curves(tri) - num_solid_vertices(tri) + num_solid_edges(tri), + concavity_protection = false, + use_barriers::Val{U} = Val(false), + ) where {F, U} I = integer_type(tri) maxiters = Int(maxiters) G = number_type(tri) @@ -916,8 +922,8 @@ function find_triangle_return_on_vertex(tri::Triangulation, q, k, p, pᵢ, pⱼ, # vertices, but without meaning that it is actually in that triangle. So, # we need to also check for the type of indices we have. safety_check = (q == p && !is_ghost_vertex(k)) || - (q == pᵢ && !is_ghost_vertex(i)) || - (q == pⱼ && !is_ghost_vertex(j)) + (q == pᵢ && !is_ghost_vertex(i)) || + (q == pⱼ && !is_ghost_vertex(j)) if safety_check orientation = triangle_orientation(predicates, pᵢ, pⱼ, p) if is_positively_oriented(orientation) @@ -1127,7 +1133,7 @@ function find_triangle_degenerate_arrangement(tri::Triangulation, q, k, predicat return is_outside(in_cert) # if outside, we need to reinitialise. Otherwise, we're all good. end -function _find_triangle(tri::Triangulation, q, k, store_history::F, history, rng::Random.AbstractRNG, maxiters, cur_iter, concavity_protection, num_restarts, use_barriers::Val{U}, predicates::AbstractPredicateKernel) where {F,U} +function _find_triangle(tri::Triangulation, q, k, store_history::F, history, rng::Random.AbstractRNG, maxiters, cur_iter, concavity_protection, num_restarts, use_barriers::Val{U}, predicates::AbstractPredicateKernel) where {F, U} is_bnd, ghost_vertex = is_boundary_node(tri, k) I = integer_type(tri) trit = triangle_type(tri) @@ -1228,7 +1234,7 @@ and also checks the position of `q` relative to `V` via [`point_position_relativ then `need_to_restart = true`. If `q` is inside this triangle, then issues can still arise due to overlapping ghost triangles from the non-convexity. Thus, depending on the result from [`dist`](@ref) and whether `V` is a ghost triangle, `need_to_restart` will be set accordingly. """ -function concavity_protection_check(tri::Triangulation, concavity_protection, V, q, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function concavity_protection_check(tri::Triangulation, concavity_protection, V, q, predicates::AbstractPredicateKernel = AdaptiveKernel()) !concavity_protection && return false cert = point_position_relative_to_triangle(predicates, tri, V, q) is_outside(cert) && return true @@ -1266,16 +1272,16 @@ function restart_find_triangle(tri, q, store_history, history, rng, maxiters, cu if num_restarts < RESTART_LIMIT m = num_solid_vertices(tri) point_indices = each_solid_vertex(tri) - k = select_initial_point(tri, q; m=(m >> 1) + 1, point_indices, rng) # don't want to try all points, still want to give the algorithm a chance + k = select_initial_point(tri, q; m = (m >> 1) + 1, point_indices, rng) # don't want to try all points, still want to give the algorithm a chance return _find_triangle(tri, q, k, store_history, history, rng, maxiters, zero(cur_iter), concavity_protection, num_restarts, use_barriers, predicates) else - V = brute_force_search(tri, q;predicates) + V = brute_force_search(tri, q; predicates) V_is_bad = concavity_protection_check(tri, concavity_protection, V, q, predicates) if V_is_bad if is_ghost_triangle(V) - V = brute_force_search(tri, q; itr=each_solid_triangle(tri), predicates) + V = brute_force_search(tri, q; itr = each_solid_triangle(tri), predicates) else - V = brute_force_search(tri, q; itr=each_ghost_triangle(tri), predicates) + V = brute_force_search(tri, q; itr = each_ghost_triangle(tri), predicates) end end if is_true(use_barriers) @@ -1284,4 +1290,4 @@ function restart_find_triangle(tri, q, store_history, history, rng, maxiters, cu return V end end -end \ No newline at end of file +end diff --git a/src/algorithms/point_location/nearest_neighbour.jl b/src/algorithms/point_location/nearest_neighbour.jl index 1737a1fb0..955d22ae9 100644 --- a/src/algorithms/point_location/nearest_neighbour.jl +++ b/src/algorithms/point_location/nearest_neighbour.jl @@ -59,4 +59,4 @@ function jump_to_voronoi_polygon(tri::Triangulation, q; kwargs...) end end return current_idx -end \ No newline at end of file +end diff --git a/src/algorithms/pole_of_inaccessibility.jl b/src/algorithms/pole_of_inaccessibility.jl index e38b2a891..becf48d5a 100644 --- a/src/algorithms/pole_of_inaccessibility.jl +++ b/src/algorithms/pole_of_inaccessibility.jl @@ -22,7 +22,7 @@ a centroid which is not always inside the polygon. Some useful links are [this b and the [the original repo](https://github.com/mapbox/polylabel). Our implementation is partially based on on [the python implementation](https://github.com/Twista/python-polylabel) and [this other Julia implementation](https://github.com/asinghvi17/Polylabel.jl). """ -function pole_of_inaccessibility(points, boundary_nodes; precision=one(number_type(points))) +function pole_of_inaccessibility(points, boundary_nodes; precision = one(number_type(points))) ## Initiate xmin, xmax, ymin, ymax = polygon_bounds(points, boundary_nodes) width = xmax - xmin @@ -67,8 +67,10 @@ function pole_of_inaccessibility(points, boundary_nodes; precision=one(number_ty ## We are done, and the last best_cell is the solution return best_cell.x, best_cell.y end -function process_cell!(queue::CellQueue{F}, best_cell::Cell{F}, points, boundary_nodes, - precision) where {F} +function process_cell!( + queue::CellQueue{F}, best_cell::Cell{F}, points, boundary_nodes, + precision, + ) where {F} next_cell = get_next_cell!(queue) if next_cell.dist > best_cell.dist best_cell = next_cell # This cell will have a large circle, so let's choose it @@ -89,4 +91,4 @@ function process_cell!(queue::CellQueue{F}, best_cell::Cell{F}, points, boundary insert_cell!(queue, cell_3) insert_cell!(queue, cell_4) return best_cell -end \ No newline at end of file +end diff --git a/src/algorithms/polygon_clipping/sutherland_hodgman.jl b/src/algorithms/polygon_clipping/sutherland_hodgman.jl index a6e206e1c..e2a121ce6 100644 --- a/src/algorithms/polygon_clipping/sutherland_hodgman.jl +++ b/src/algorithms/polygon_clipping/sutherland_hodgman.jl @@ -16,7 +16,7 @@ The polygons should be defined in counter-clockwise order. # Output - `clipped_polygon`: The coordinates of the clipped polygon, given in counter-clockwise order and `clipped_polygon[begin] == clipped_polygon[end]`. """ -function clip_polygon(vertices, points, clip_vertices, clip_points; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function clip_polygon(vertices, points, clip_vertices, clip_points; predicates::AbstractPredicateKernel = AdaptiveKernel()) return clip_polygon(Polygon(vertices, points), Polygon(clip_vertices, clip_points); predicates) end @@ -55,15 +55,15 @@ function clip_polygon_to_edge(input_list, q, p, predicates::AbstractPredicateKer return output_list end -function clip_polygon(poly::Polygon{T}, clip_poly::Polygon; predicates::AbstractPredicateKernel=AdaptiveKernel()) where {T} +function clip_polygon(poly::Polygon{T}, clip_poly::Polygon; predicates::AbstractPredicateKernel = AdaptiveKernel()) where {T} output_list = poly q = clip_poly[end] for p in clip_poly - input_list = output_list + input_list = output_list isempty(output_list) && break output_list = clip_polygon_to_edge(input_list, q, p, predicates) q = p end !isempty(output_list) && push!(output_list, output_list[begin]) return output_list::Vector{T} -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/add_boundary_information.jl b/src/algorithms/triangulation/basic_operations/add_boundary_information.jl index e63e0fb7b..07a7c83da 100644 --- a/src/algorithms/triangulation/basic_operations/add_boundary_information.jl +++ b/src/algorithms/triangulation/basic_operations/add_boundary_information.jl @@ -5,7 +5,7 @@ Updates `tri` so that the ghost triangle information defined by the boundary nod """ function add_boundary_information!(tri::Triangulation) I = integer_type(tri) - ghost_vertex= I(𝒢) + ghost_vertex = I(𝒢) bn = get_boundary_nodes(tri) if has_multiple_curves(tri) add_boundary_curve_information!(tri, bn, ghost_vertex) diff --git a/src/algorithms/triangulation/basic_operations/add_point.jl b/src/algorithms/triangulation/basic_operations/add_point.jl index 73ed24338..425ba4ca1 100644 --- a/src/algorithms/triangulation/basic_operations/add_point.jl +++ b/src/algorithms/triangulation/basic_operations/add_point.jl @@ -35,29 +35,31 @@ The triangulation is updated in-place, but we do return In cases where `(x, y)` is outside of the triangulation, it will be added successfully but note that the `convex_hull` field of `tri` will no longer be accurate. You can use [`convex_hull!`](@ref) to fix it. """ -function add_point!(tri::Triangulation, new_point; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - point_indices=each_solid_vertex(tri), - m=default_num_samples(length(point_indices)), - try_points=(), - rng::Random.AbstractRNG=Random.default_rng(), - initial_search_point=integer_type(tri)(select_initial_point(tri, new_point; point_indices, m, try_points, rng)), - update_representative_point=false, - store_event_history=Val(false), - event_history=nothing, - concavity_protection=false, - V=find_triangle( - tri, - get_point(tri, new_point); - m=nothing, - point_indices=nothing, - try_points=nothing, - k=initial_search_point, - concavity_protection, - predicates, - rng - ), - peek::P=Val(false)) where {P} +function add_point!( + tri::Triangulation, new_point; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + point_indices = each_solid_vertex(tri), + m = default_num_samples(length(point_indices)), + try_points = (), + rng::Random.AbstractRNG = Random.default_rng(), + initial_search_point = integer_type(tri)(select_initial_point(tri, new_point; point_indices, m, try_points, rng)), + update_representative_point = false, + store_event_history = Val(false), + event_history = nothing, + concavity_protection = false, + V = find_triangle( + tri, + get_point(tri, new_point); + m = nothing, + point_indices = nothing, + try_points = nothing, + k = initial_search_point, + concavity_protection, + predicates, + rng, + ), + peek::P = Val(false), + ) where {P} int_flag = new_point isa Integer if !int_flag && !is_true(peek) push_point!(tri, new_point) @@ -73,44 +75,47 @@ function add_point!(tri::Triangulation, new_point; return V end -function add_point!(tri::Triangulation, new_point_x, new_point_y; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - point_indices=get_vertices(tri), - m=default_num_samples(length(point_indices)), - try_points=(), - rng::Random.AbstractRNG=Random.default_rng(), - initial_search_point=integer_type(tri)(select_initial_point(tri, (new_point_x, new_point_y); point_indices, m, try_points, rng)), - update_representative_point=false, - store_event_history=Val(false), - event_history=nothing, - concavity_protection=false, - V=find_triangle( - tri, - (new_point_x, new_point_y); - m=nothing, - point_indices=nothing, - try_points=nothing, - k=initial_search_point, - concavity_protection, - predicates, - rng - ), - peek::P=Val(false)) where {P} +function add_point!( + tri::Triangulation, new_point_x, new_point_y; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + point_indices = get_vertices(tri), + m = default_num_samples(length(point_indices)), + try_points = (), + rng::Random.AbstractRNG = Random.default_rng(), + initial_search_point = integer_type(tri)(select_initial_point(tri, (new_point_x, new_point_y); point_indices, m, try_points, rng)), + update_representative_point = false, + store_event_history = Val(false), + event_history = nothing, + concavity_protection = false, + V = find_triangle( + tri, + (new_point_x, new_point_y); + m = nothing, + point_indices = nothing, + try_points = nothing, + k = initial_search_point, + concavity_protection, + predicates, + rng, + ), + peek::P = Val(false), + ) where {P} !is_true(peek) && push_point!(tri, new_point_x, new_point_y) VV = add_point!( tri, is_true(peek) ? (new_point_x, new_point_y) : num_points(tri); predicates, - point_indices=point_indices, - m=m, - try_points=try_points, - rng=rng, - initial_search_point=initial_search_point, - update_representative_point=update_representative_point, - store_event_history=store_event_history, - event_history=event_history, + point_indices = point_indices, + m = m, + try_points = try_points, + rng = rng, + initial_search_point = initial_search_point, + update_representative_point = update_representative_point, + store_event_history = store_event_history, + event_history = event_history, V, - peek) + peek, + ) return VV end @@ -123,4 +128,4 @@ is defined on the weights stored in `tri`. The `kwargs` match those from [`add_p function add_point!(tri::Triangulation, x, y, w; kwargs...) add_weight!(tri, w) return add_point!(tri, x, y; kwargs...) -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/add_segment.jl b/src/algorithms/triangulation/basic_operations/add_segment.jl index ed7670d9f..023a2384b 100644 --- a/src/algorithms/triangulation/basic_operations/add_segment.jl +++ b/src/algorithms/triangulation/basic_operations/add_segment.jl @@ -74,7 +74,7 @@ Adds `segment = (i, j)` to `tri`. # Outputs There is no output, but `tri` will be updated so that it now contains `segment`. """ -function add_segment!(tri::Triangulation, segment; predicates::AbstractPredicateKernel=AdaptiveKernel(), rng::Random.AbstractRNG=Random.default_rng()) +function add_segment!(tri::Triangulation, segment; predicates::AbstractPredicateKernel = AdaptiveKernel(), rng::Random.AbstractRNG = Random.default_rng()) e = optimise_edge_order(tri, segment) fix_edge_order_after_rotation!(tri, segment, e) add_segment_to_list!(tri, e) @@ -95,4 +95,4 @@ function add_segment!(tri::Triangulation, segment; predicates::AbstractPredicate end return tri end -add_segment!(tri::Triangulation, i, j; predicates::AbstractPredicateKernel=AdaptiveKernel(), rng=Random.default_rng()) = add_segment!(tri, construct_edge(edge_type(tri), i, j); predicates, rng) \ No newline at end of file +add_segment!(tri::Triangulation, i, j; predicates::AbstractPredicateKernel = AdaptiveKernel(), rng = Random.default_rng()) = add_segment!(tri, construct_edge(edge_type(tri), i, j); predicates, rng) diff --git a/src/algorithms/triangulation/basic_operations/add_triangle.jl b/src/algorithms/triangulation/basic_operations/add_triangle.jl index 3c53bdf65..7c391ccb4 100644 --- a/src/algorithms/triangulation/basic_operations/add_triangle.jl +++ b/src/algorithms/triangulation/basic_operations/add_triangle.jl @@ -16,8 +16,10 @@ so that its existence in the triangulation is known. # Outputs There are no outputs as `tri` is updated in-place. """ -function add_triangle!(tri::Ts, u::Integer, v::Integer, w::Integer; - protect_boundary=false, update_ghost_edges=false) where {Ts<:Triangulation} +function add_triangle!( + tri::Ts, u::Integer, v::Integer, w::Integer; + protect_boundary = false, update_ghost_edges = false, + ) where {Ts <: Triangulation} ## Add the necessary triangles adj = get_adjacent(tri) adj2v = get_adjacent2vertex(tri) @@ -43,13 +45,13 @@ function add_triangle!(tri::Ts, u::Integer, v::Integer, w::Integer; end return tri end -function add_triangle!(tri::Triangulation, T; protect_boundary=false, update_ghost_edges=false) +function add_triangle!(tri::Triangulation, T; protect_boundary = false, update_ghost_edges = false) u, v, w = triangle_vertices(T) add_triangle!(tri, u, v, w; protect_boundary, update_ghost_edges) return tri end -function add_boundary_edges_single!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function add_boundary_edges_single!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) # Here, we are adding two ghost triangles uwg and wvg, where g is the ghost vertex, coming from # the two new boundary edges uw and wv. @@ -79,7 +81,7 @@ function add_boundary_edges_single!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, return nothing end -function add_boundary_edges_double!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function add_boundary_edges_double!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) # Here, we are only adding a single ghost triangle vug, where g is the ghost vertex, # coming from the new boundary edge vu. @@ -109,7 +111,7 @@ function add_boundary_edges_double!(u, v, w, uv_bnd, vw_bnd, wu_bnd, triangles, return nothing end -function add_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function add_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) # Here, we are adding three ghost triangles uwg, wvg, and vug, where g is the ghost vertex. add_adjacent!(adj, v, u, g) @@ -138,4 +140,4 @@ function add_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I,E}, adj2 add_triangle!(triangles, w, v, g) end return nothing -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/delete_holes.jl b/src/algorithms/triangulation/basic_operations/delete_holes.jl index ef6e41bc7..bf2f7d31d 100644 --- a/src/algorithms/triangulation/basic_operations/delete_holes.jl +++ b/src/algorithms/triangulation/basic_operations/delete_holes.jl @@ -30,7 +30,7 @@ Deletes all the triangles in the set `triangles` from the triangulation `tri`. """ function delete_all_exterior_triangles!(tri::Triangulation, triangles) for T in each_triangle(triangles) - delete_triangle!(tri, T; protect_boundary=true) + delete_triangle!(tri, T; protect_boundary = true) end return tri end @@ -181,4 +181,4 @@ function find_all_triangles_to_delete(tri::Triangulation, points_to_process) end end return triangles_to_delete -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/delete_point.jl b/src/algorithms/triangulation/basic_operations/delete_point.jl index 25364cc57..ed8418062 100644 --- a/src/algorithms/triangulation/basic_operations/delete_point.jl +++ b/src/algorithms/triangulation/basic_operations/delete_point.jl @@ -16,11 +16,11 @@ Returns the counter-clockwise sequence of neighbours of `u` in `tri`. the associated boundary curve. If you do not have ghost triangles and you try to get the surrounding polygon of a ghost vertex, then this function may return an invalid polygon. """ -function get_surrounding_polygon(tri::Triangulation, u; skip_ghost_vertices=false) +function get_surrounding_polygon(tri::Triangulation, u; skip_ghost_vertices = false) return copy(get_surrounding_polygon!(tri, u; skip_ghost_vertices)) end -function get_surrounding_polygon!(tri::Triangulation, u; skip_ghost_vertices=false) +function get_surrounding_polygon!(tri::Triangulation, u; skip_ghost_vertices = false) cache = get_cache(tri) S = get_surrounding_polygon(cache) neighbouring_vertices = get_neighbours(tri, u) @@ -96,9 +96,9 @@ end Ensures that the edges in `S` surrounding a deleted vertex of `tri` are correctly updated. """ function fix_edges_after_deletion!(tri, S) - for i in firstindex(S):(lastindex(S)-1) + for i in firstindex(S):(lastindex(S) - 1) u = S[i] - v = S[i+1] + v = S[i + 1] w = get_adjacent(tri, v, u) if edge_exists(w) add_adjacent!(tri, u, w, v) @@ -133,11 +133,13 @@ See also [`check_delete_point_args`](@ref). - `event_history=nothing`: The event history of the triangulation from deleting the point. Only updated if `store_event_history` is true, in which case it needs to be an [`InsertionEventHistory`](@ref) object. - `rng::Random.AbstractRNG=Random.default_rng()`: The random number generator to use for the triangulation. """ -function delete_point!(tri::Triangulation, vertex; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - store_event_history=Val(false), - event_history=nothing, - rng::Random.AbstractRNG=Random.default_rng()) +function delete_point!( + tri::Triangulation, vertex; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + store_event_history = Val(false), + event_history = nothing, + rng::Random.AbstractRNG = Random.default_rng(), + ) cache = get_cache(tri) empty!(cache) convex_tri = get_triangulation(cache) @@ -147,13 +149,13 @@ function delete_point!(tri::Triangulation, vertex; trit = triangle_type(tri) for uv in each_edge(neighbouring_edges) # note that we are mutating this iterator during iteration u, v = edge_vertices(uv) - delete_triangle!(tri, vertex, u, v; protect_boundary=true) + delete_triangle!(tri, vertex, u, v; protect_boundary = true) is_true(store_event_history) && delete_triangle!(event_history, construct_triangle(trit, vertex, u, v)) end triangulate_convex!(convex_tri, S; predicates, rng) # fill in the cavity for T in each_solid_triangle(convex_tri) u, v, w = triangle_vertices(T) - add_triangle!(tri, u, v, w; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, u, v, w; protect_boundary = true, update_ghost_edges = false) is_true(store_event_history) && add_triangle!(event_history, T) end delete_adjacent2vertex!(tri, vertex) diff --git a/src/algorithms/triangulation/basic_operations/delete_triangle.jl b/src/algorithms/triangulation/basic_operations/delete_triangle.jl index 5fb832b43..c5d89bdb2 100644 --- a/src/algorithms/triangulation/basic_operations/delete_triangle.jl +++ b/src/algorithms/triangulation/basic_operations/delete_triangle.jl @@ -16,8 +16,10 @@ so that its non-existence in the triangulation is known. # Outputs There are no outputs as `tri` is updated in-place. """ -function delete_triangle!(tri::Ts, u::Integer, v::Integer, w::Integer; - protect_boundary=false, update_ghost_edges=false) where {Ts<:Triangulation} +function delete_triangle!( + tri::Ts, u::Integer, v::Integer, w::Integer; + protect_boundary = false, update_ghost_edges = false, + ) where {Ts <: Triangulation} adj = get_adjacent(tri) adj2v = get_adjacent2vertex(tri) graph = get_graph(tri) @@ -48,13 +50,13 @@ function delete_triangle!(tri::Ts, u::Integer, v::Integer, w::Integer; end return nothing end -function delete_triangle!(tri::Triangulation, T; protect_boundary=false, update_ghost_edges=false) +function delete_triangle!(tri::Triangulation, T; protect_boundary = false, update_ghost_edges = false) u, v, w = triangle_vertices(T) delete_triangle!(tri, u, v, w; protect_boundary, update_ghost_edges) return nothing end -function delete_boundary_edges_single!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function delete_boundary_edges_single!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) u, v, w = choose_uvw(vu_bnd, wv_bnd, uw_bnd, u, v, w) delete_adjacent!(adj, v, u) @@ -85,7 +87,7 @@ function delete_boundary_edges_single!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangle return nothing end -function delete_boundary_edges_double!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function delete_boundary_edges_double!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) u, v, w = choose_uvw(!vu_bnd, !wv_bnd, !uw_bnd, u, v, w) delete_adjacent!(adj, u, w) @@ -116,7 +118,7 @@ function delete_boundary_edges_double!(u, v, w, vu_bnd, uw_bnd, wv_bnd, triangle return nothing end -function delete_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I,E}, adj2v, graph, update_ghost_edges) where {I,E} +function delete_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I, E}, adj2v, graph, update_ghost_edges) where {I, E} g = I(𝒢) delete_adjacent!(adj, w, v) delete_adjacent!(adj, v, u) @@ -146,4 +148,4 @@ function delete_boundary_edges_triple!(u, v, w, triangles, adj::Adjacent{I,E}, a delete_triangle!(triangles, u, w, g) end return nothing -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/flip_edge.jl b/src/algorithms/triangulation/basic_operations/flip_edge.jl index 5b676ba0e..7a4a4d6b7 100644 --- a/src/algorithms/triangulation/basic_operations/flip_edge.jl +++ b/src/algorithms/triangulation/basic_operations/flip_edge.jl @@ -20,17 +20,17 @@ There is no output, as `tri` is updated in-place. If `(i, j, k, ℓ)`, where `ℓ = get_adjacent(tri, i, j)` and `k = get_adjacent(tri, j, i)`, is not a convex quadrilateral, then this edge flip will make the triangulation non-planar. """ -function flip_edge!(tri::Triangulation, i::I, j::I, store_event_history::Val{B}=Val(false), event_history=nothing) where {I<:Integer,B} +function flip_edge!(tri::Triangulation, i::I, j::I, store_event_history::Val{B} = Val(false), event_history = nothing) where {I <: Integer, B} ℓ = get_adjacent(tri, i, j) k = get_adjacent(tri, j, i) flip_edge!(tri, i, j, k, ℓ, store_event_history, event_history) return tri end -function flip_edge!(tri::Triangulation, i::I, j::I, k::I, ℓ::I, store_event_history::Val{B}=Val(false), event_history=nothing) where {I<:Integer,B} - delete_triangle!(tri, i, k, j; protect_boundary=true, update_ghost_edges=false) - delete_triangle!(tri, i, j, ℓ; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, ℓ, k, j; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, ℓ, i, k; protect_boundary=true, update_ghost_edges=false) +function flip_edge!(tri::Triangulation, i::I, j::I, k::I, ℓ::I, store_event_history::Val{B} = Val(false), event_history = nothing) where {I <: Integer, B} + delete_triangle!(tri, i, k, j; protect_boundary = true, update_ghost_edges = false) + delete_triangle!(tri, i, j, ℓ; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, ℓ, k, j; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, ℓ, i, k; protect_boundary = true, update_ghost_edges = false) is_true(store_event_history) && store_flip_edge_history!(event_history, i, j, k, ℓ) return tri end @@ -51,4 +51,4 @@ function store_flip_edge_history!(event_history, i, j, k, ℓ) delete_triangle!(event_history.deleted_triangles, Tℓkj) delete_triangle!(event_history.deleted_triangles, Tℓik) return event_history -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/legalise_edge.jl b/src/algorithms/triangulation/basic_operations/legalise_edge.jl index 68a3e5e03..8a07f4f0c 100644 --- a/src/algorithms/triangulation/basic_operations/legalise_edge.jl +++ b/src/algorithms/triangulation/basic_operations/legalise_edge.jl @@ -26,13 +26,13 @@ There is no output, as `tri` is updated in-place. To get around this, we only store in these fields the triangles necessary to allow [`undo_insertion!`](@ref) to work, so that at a triangle that might have appeared in both will only appear in one. """ -function legalise_edge!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function legalise_edge!(tri::Triangulation, i, j, r, store_event_history = Val(false), event_history = nothing; predicates::AbstractPredicateKernel = AdaptiveKernel()) cert = is_legal(predicates, tri, i, j) - if is_illegal(cert) + if is_illegal(cert) e = get_adjacent(tri, j, i) flip_edge!(tri, i, j, e, r, store_event_history, event_history) legalise_edge!(tri, i, e, r, store_event_history, event_history; predicates) legalise_edge!(tri, e, j, r, store_event_history, event_history; predicates) end return tri -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/lock_convex_hull.jl b/src/algorithms/triangulation/basic_operations/lock_convex_hull.jl index 729535aeb..f33b8948e 100644 --- a/src/algorithms/triangulation/basic_operations/lock_convex_hull.jl +++ b/src/algorithms/triangulation/basic_operations/lock_convex_hull.jl @@ -13,7 +13,7 @@ and similarly for `predicates`. then this edge will be deleted from `tri.interior_segments`; this will be undone from `unlock_convex_hull!`, possibly splitting the segments in case they were split before unlocking. """ -function lock_convex_hull!(tri::Triangulation; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function lock_convex_hull!(tri::Triangulation; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) if has_boundary_nodes(tri) throw(ArgumentError("Cannot lock the convex hull of a triangulation with boundary nodes.")) end @@ -44,4 +44,4 @@ function lock_convex_hull!(tri::Triangulation; rng::Random.AbstractRNG=Random.de add_segment!(tri, e; rng, predicates) end return tri -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/split_edge.jl b/src/algorithms/triangulation/basic_operations/split_edge.jl index 165f09330..2b326a3f5 100644 --- a/src/algorithms/triangulation/basic_operations/split_edge.jl +++ b/src/algorithms/triangulation/basic_operations/split_edge.jl @@ -37,7 +37,7 @@ There is no output, as `tri` is updated in-place. The triangulation will only be updated as if `(i, j)` has been split rather than also `(j, i)`. You will need to call `split_edge!` again with `(j, i)` if you want to split that edge as well. """ -function split_edge!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing) +function split_edge!(tri::Triangulation, i, j, r, store_event_history = Val(false), event_history = nothing) if is_constrained(tri) && contains_segment(tri, i, j) is_bnd = contains_boundary_edge(tri, i, j) || contains_boundary_edge(tri, j, i) eᵢⱼ, eⱼᵢ, eᵢᵣ, eᵣᵢ, eᵣⱼ, eⱼᵣ = get_edges_for_split_edge(tri, i, j, r) @@ -79,9 +79,9 @@ function split_edge!(tri::Triangulation, i, j, r, store_event_history=Val(false) end end k = get_adjacent(tri, i, j) - delete_triangle!(tri, i, j, k; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, i, r, k; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, r, j, k; protect_boundary=true, update_ghost_edges=false) + delete_triangle!(tri, i, j, k; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, i, r, k; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, r, j, k; protect_boundary = true, update_ghost_edges = false) if is_true(store_event_history) trit = triangle_type(tri) Tᵢⱼₖ = construct_triangle(trit, i, j, k) @@ -116,7 +116,7 @@ See also [`complete_split_edge_and_legalise!`](@ref). # Outputs There is no output, as `tri` is updated in-place. """ -function legalise_split_edge!(tri::Triangulation, i, j, k, r, store_event_history=Val(false), event_history=nothing; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function legalise_split_edge!(tri::Triangulation, i, j, k, r, store_event_history = Val(false), event_history = nothing; predicates::AbstractPredicateKernel = AdaptiveKernel()) legalise_edge!(tri, j, k, r, store_event_history, event_history; predicates) legalise_edge!(tri, k, i, r, store_event_history, event_history; predicates) return tri @@ -141,7 +141,7 @@ Given a triangulation `tri`, an edge `(i, j)`, and a point `r`, splits both `(i, # Outputs There is no output, as `tri` is updated in-place. """ -function complete_split_edge_and_legalise!(tri::Triangulation, i, j, r, store_event_history=Val(false), event_history=nothing; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function complete_split_edge_and_legalise!(tri::Triangulation, i, j, r, store_event_history = Val(false), event_history = nothing; predicates::AbstractPredicateKernel = AdaptiveKernel()) k = get_adjacent(tri, i, j) ℓ = get_adjacent(tri, j, i) split_edge!(tri, i, j, r, store_event_history, event_history) @@ -151,9 +151,11 @@ function complete_split_edge_and_legalise!(tri::Triangulation, i, j, r, store_ev if is_true(store_event_history) # The deleted_triangles in event_history will contain triangles with the vertex r, which didn't actually appear # initially. So, we need to deal any triangles with r as a vertex from event_history.deleted_triangles. - filter!(T -> let r = r - r ∉ triangle_vertices(T) - end, event_history.deleted_triangles) + filter!( + T -> let r = r + r ∉ triangle_vertices(T) + end, event_history.deleted_triangles, + ) end return tri -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/basic_operations/split_triangle.jl b/src/algorithms/triangulation/basic_operations/split_triangle.jl index c8f69e973..edfee8e9f 100644 --- a/src/algorithms/triangulation/basic_operations/split_triangle.jl +++ b/src/algorithms/triangulation/basic_operations/split_triangle.jl @@ -16,10 +16,10 @@ See also [`legalise_split_triangle!`](@ref) and [`complete_split_triangle_and_le There is no output, but `tri` will be updated so that it now contains the triangles `(i, j, r)`, `(j, k, r)`, and `(k, i, r)`. """ function split_triangle!(tri::Triangulation, i, j, k, r) - delete_triangle!(tri, i, j, k; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, i, j, r; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, j, k, r; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, k, i, r; protect_boundary=true, update_ghost_edges=false) + delete_triangle!(tri, i, j, k; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, i, j, r; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, j, k, r; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, k, i, r; protect_boundary = true, update_ghost_edges = false) return tri end @@ -43,7 +43,7 @@ See also [`complete_split_triangle_and_legalise!`](@ref). # Outputs There is no output, as `tri` is updated in-place. """ -function legalise_split_triangle!(tri::Triangulation, i, j, k, r; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function legalise_split_triangle!(tri::Triangulation, i, j, k, r; predicates::AbstractPredicateKernel = AdaptiveKernel()) legalise_edge!(tri, i, j, r; predicates) legalise_edge!(tri, j, k, r; predicates) legalise_edge!(tri, k, i, r; predicates) @@ -65,7 +65,7 @@ Splits the triangle `(i, j, k)` at the vertex `r`, assumed to be inside the tria # Outputs There is no output, as `tri` is updated in-place. """ -function complete_split_triangle_and_legalise!(tri::Triangulation, i, j, k, r; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function complete_split_triangle_and_legalise!(tri::Triangulation, i, j, k, r; predicates::AbstractPredicateKernel = AdaptiveKernel()) split_triangle!(tri, i, j, k, r) legalise_split_triangle!(tri, i, j, k, r; predicates) return tri diff --git a/src/algorithms/triangulation/basic_operations/unlock_convex_hull.jl b/src/algorithms/triangulation/basic_operations/unlock_convex_hull.jl index 356e5541f..a8ec74930 100644 --- a/src/algorithms/triangulation/basic_operations/unlock_convex_hull.jl +++ b/src/algorithms/triangulation/basic_operations/unlock_convex_hull.jl @@ -6,7 +6,7 @@ assuming that it was locked using [`lock_convex_hull!`](@ref). If `reconstruct = convex hull of `tri` will be reconstructed from the boundary nodes of `tri`. This is useful if, for example, you have split some of the boundary edges during mesh refinement. """ -function unlock_convex_hull!(tri::Triangulation; reconstruct=false) +function unlock_convex_hull!(tri::Triangulation; reconstruct = false) if !has_boundary_nodes(tri) throw(ArgumentError("Cannot unlock the convex hull of a triangulation without boundary nodes.")) end @@ -43,7 +43,7 @@ function unlock_convex_hull!(tri::Triangulation; reconstruct=false) chain = get_boundary_chain(tri, u, v, I(𝒢)) ne = length(chain) - 1 for ℓ in 1:ne - i, j = chain[ℓ], chain[ℓ+1] + i, j = chain[ℓ], chain[ℓ + 1] e_int = construct_edge(E, i, j) add_edge!(all_segments, e_int) add_edge!(interior_segments, e_int) @@ -51,4 +51,4 @@ function unlock_convex_hull!(tri::Triangulation; reconstruct=false) end empty!(interior_segments_on_hull) return tri -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/check_args.jl b/src/algorithms/triangulation/check_args.jl index 93ddef49a..f04f8db8d 100644 --- a/src/algorithms/triangulation/check_args.jl +++ b/src/algorithms/triangulation/check_args.jl @@ -37,7 +37,7 @@ end struct InsufficientPointsError{P} <: Exception points::P end -struct InconsistentConnectionError{I,J} <: Exception +struct InconsistentConnectionError{I, J} <: Exception curve_index::I segment_index₁::I segment_index₂::I @@ -71,7 +71,7 @@ function Base.showerror(io::IO, err::InsufficientPointsError) print(io, "InsufficientPointsError: The provided point set has ", num_points(points), " points, but triangulations require at least three points.") return io end -function Base.showerror(io::IO, err::InconsistentConnectionError) +function Base.showerror(io::IO, err::InconsistentConnectionError) print(io, "InconsistentConnectionError: ") if !iszero(err.segment_index₁) && !(isone(err.segment_index₁) && isone(err.segment_index₂)) print(io, "Segment ", err.segment_index₁) @@ -95,11 +95,11 @@ function Base.showerror(io::IO, err::InconsistentOrientationError) # It's hard to detect if the curve is indeed defined by an AbstractParametricCurve since the curve could be defined # by a combination of multiple AbstractParametricCurves and possibly a PiecewiseLinear part. Thus, the above advice # might nto be wrong. - str2 = "\nIf this curve is defined by an AbstractParametricCurve, you may instead need to reverse the order of the control points defining" * - " the sections of the curve; the `positive` keyword may also be of interest for CircularArcs and EllipticalArcs." - str *= str2 + str2 = "\nIf this curve is defined by an AbstractParametricCurve, you may instead need to reverse the order of the control points defining" * + " the sections of the curve; the `positive` keyword may also be of interest for CircularArcs and EllipticalArcs." + str *= str2 end - sign = err.should_be_positive ? "positive" : "negative" + sign = err.should_be_positive ? "positive" : "negative" sign2 = err.should_be_positive ? "negative" : "positive" print(io, "The orientation of the boundary curve with index ", err.index, " should be $sign, but it is $sign2.", str) return io @@ -157,7 +157,7 @@ function has_consistent_connections_multiple_curves(boundary_nodes) end return true end -function has_consistent_connections_multiple_sections(boundary_nodes, curve_index=0) +function has_consistent_connections_multiple_sections(boundary_nodes, curve_index = 0) ns = num_sections(boundary_nodes) segmentⱼ₋₁ = get_boundary_nodes(boundary_nodes, 1) nn = num_boundary_edges(segmentⱼ₋₁) + 1 diff --git a/src/algorithms/triangulation/constrained_triangulation.jl b/src/algorithms/triangulation/constrained_triangulation.jl index bdb27fa47..51f41c7e9 100644 --- a/src/algorithms/triangulation/constrained_triangulation.jl +++ b/src/algorithms/triangulation/constrained_triangulation.jl @@ -52,7 +52,7 @@ function fix_segments!(segments::AbstractVector{E}, bad_indices) where {E} if i == firstindex(segments) # If it starts with a bad index, then no problem, it connects two valid indices. continue else - prev = segments[i-1] + prev = segments[i - 1] cur = segments[i] segments[i] = construct_edge(E, terminal(prev), terminal(cur)) end @@ -86,11 +86,11 @@ function connect_segments!(segments::AbstractVector{E}) where {E} f = firstindex(segments) ℓ = lastindex(segments) I = number_type(E) - insert_idxs = Tuple{Int,I,I}[] + insert_idxs = Tuple{Int, I, I}[] shift_idx = 0 - for i in f:(ℓ-1) + for i in f:(ℓ - 1) eᵢ = segments[i] - eᵢ₊₁ = segments[i+1] + eᵢ₊₁ = segments[i + 1] if terminal(eᵢ) ≠ initial(eᵢ₊₁) push!(insert_idxs, (i + 1 + shift_idx, terminal(eᵢ), initial(eᵢ₊₁))) shift_idx += 1 @@ -221,39 +221,39 @@ into a set of boundary nodes for use in [`triangulate`](@ref). - `points`: The point set, which is the same as `existing_points` but with the boundary points appended to it. """ convert_boundary_points_to_indices -function convert_boundary_points_to_indices(x::AAA, y::AAA; existing_points=NTuple{2,Float64}[], check_args=true, adjust=true) where {F<:Number,A<:AbstractVector{F},AA<:AbstractVector{A},AAA<:AbstractVector{AA}} +function convert_boundary_points_to_indices(x::AAA, y::AAA; existing_points = NTuple{2, Float64}[], check_args = true, adjust = true) where {F <: Number, A <: AbstractVector{F}, AA <: AbstractVector{A}, AAA <: AbstractVector{AA}} check_args && @assert length(x) == length(y) nodes = [[Int[] for _ in eachindex(x[i])] for i in eachindex(x)] for i in eachindex(x) - _nodes, _ = convert_boundary_points_to_indices(x[i], y[i]; existing_points=existing_points, check_args=true) + _nodes, _ = convert_boundary_points_to_indices(x[i], y[i]; existing_points = existing_points, check_args = true) copyto!(nodes[i], _nodes) end return nodes, existing_points end -function convert_boundary_points_to_indices(x::AA, y::AA; existing_points=NTuple{2,Float64}[], check_args=true, adjust=true) where {F<:Number,A<:AbstractVector{F},AA<:AbstractVector{A}} +function convert_boundary_points_to_indices(x::AA, y::AA; existing_points = NTuple{2, Float64}[], check_args = true, adjust = true) where {F <: Number, A <: AbstractVector{F}, AA <: AbstractVector{A}} if check_args @assert length(x) == length(y) @assert all(i -> length(x[i]) == length(y[i]), eachindex(x, y)) @assert x[begin][begin] ≈ x[end][end] @assert y[begin][begin] ≈ y[end][end] - @assert all(i -> x[i][end] ≈ x[i+1][begin], firstindex(x):(lastindex(x)-1)) - @assert all(i -> y[i][end] ≈ y[i+1][begin], firstindex(y):(lastindex(y)-1)) + @assert all(i -> x[i][end] ≈ x[i + 1][begin], firstindex(x):(lastindex(x) - 1)) + @assert all(i -> y[i][end] ≈ y[i + 1][begin], firstindex(y):(lastindex(y) - 1)) end nodes = [Int[] for _ in eachindex(x)] for i in eachindex(x) - _nodes, _ = convert_boundary_points_to_indices(x[i], y[i]; existing_points=existing_points, check_args=false, adjust=false) + _nodes, _ = convert_boundary_points_to_indices(x[i], y[i]; existing_points = existing_points, check_args = false, adjust = false) resize!(nodes[i], length(_nodes)) copyto!(nodes[i], _nodes) end if adjust # needed so that the different segments connect - for i in firstindex(nodes):(lastindex(nodes)-1) - push!(nodes[i], nodes[i+1][begin]) + for i in firstindex(nodes):(lastindex(nodes) - 1) + push!(nodes[i], nodes[i + 1][begin]) end push!(nodes[end], nodes[begin][begin]) end return nodes, existing_points end -function convert_boundary_points_to_indices(x::A, y::A; existing_points=NTuple{2,Float64}[], check_args=true, adjust=true) where {F<:Number,A<:AbstractVector{F}} +function convert_boundary_points_to_indices(x::A, y::A; existing_points = NTuple{2, Float64}[], check_args = true, adjust = true) where {F <: Number, A <: AbstractVector{F}} if check_args @assert length(x) == length(y) @assert x[begin] ≈ x[end] @@ -261,7 +261,7 @@ function convert_boundary_points_to_indices(x::A, y::A; existing_points=NTuple{2 end nodes = Int[] init = num_points(existing_points) + 1 - for i in firstindex(x):(lastindex(x)-1) + for i in firstindex(x):(lastindex(x) - 1) push!(nodes, init) push_point!(existing_points, x[i], y[i]) init += 1 @@ -270,7 +270,7 @@ function convert_boundary_points_to_indices(x::A, y::A; existing_points=NTuple{2 return nodes, existing_points end -function convert_boundary_points_to_indices(xy; existing_points=NTuple{2,Float64}[], check_args=true, adjust=true) +function convert_boundary_points_to_indices(xy; existing_points = NTuple{2, Float64}[], check_args = true, adjust = true) if is_point2(xy[1]) x = [getx(xy[i]) for i in eachindex(xy)] y = [gety(xy[i]) for i in eachindex(xy)] @@ -283,7 +283,7 @@ function convert_boundary_points_to_indices(xy; existing_points=NTuple{2,Float64 else throw(ArgumentError("Invalid boundary coordinates provided. Please provide either a (1) vector of numbers, (2) vector of vector of numbers, or (3) a vector of vector of vector of numbers.")) end - return convert_boundary_points_to_indices(x, y; existing_points=existing_points, check_args=check_args, adjust=adjust) + return convert_boundary_points_to_indices(x, y; existing_points = existing_points, check_args = check_args, adjust = adjust) end """ @@ -327,24 +327,25 @@ function remake_triangulation_with_constraints(tri::Triangulation, segments, bou boundary_enricher = get_boundary_enricher(tri) cache = get_cache(tri) return new_ghost_vertex_map, new_ghost_vertex_ranges, Triangulation( - points, - triangles, - boundary_nodes, - interior_segments, - all_segments, - weights, - adjacent, - adjacent2vertex, - graph, - boundary_curves, - boundary_edge_map, - ghost_vertex_map, # Delay putting these in until we are done with the triangulation - ghost_vertex_ranges, # Delay putting these in until we are done with the triangulation - ch, - representative_point_list, - polygon_hierarchy, - boundary_enricher, - cache) + points, + triangles, + boundary_nodes, + interior_segments, + all_segments, + weights, + adjacent, + adjacent2vertex, + graph, + boundary_curves, + boundary_edge_map, + ghost_vertex_map, # Delay putting these in until we are done with the triangulation + ghost_vertex_ranges, # Delay putting these in until we are done with the triangulation + ch, + representative_point_list, + polygon_hierarchy, + boundary_enricher, + cache, + ) end """ @@ -396,7 +397,8 @@ function replace_ghost_vertex_information(tri::Triangulation, ghost_vertex_map, representative_point_list, polygon_hierarchy, boundary_enricher, - cache) + cache, + ) end """ @@ -475,7 +477,7 @@ function prepare_vertex_linked_list(V::AbstractArray{I}) where {I} next = zeros(I, m) prev = zeros(I, m) shuffled_indices = zeros(I, m) - for i = 2:(m-1) + for i in 2:(m - 1) next[i] = i + 1 prev[i] = i - 1 shuffled_indices[i] = i @@ -500,7 +502,7 @@ There is no output, but `list` is updated in-place. """ function delete_polygon_vertices_in_random_order!(list::ShuffledPolygonLinkedList, tri::Triangulation, u, v, rng::Random.AbstractRNG, predicates::AbstractPredicateKernel) m = list.k - for i in (m-1):-1:3 + for i in (m - 1):-1:3 j = select_random_vertex(tri, list, u, v, 2:i, rng, predicates) delete_vertex!(list, j) swap_permutation!(list, i, j) @@ -526,7 +528,7 @@ See also [`prepare_vertex_linked_list`](@ref) and [`delete_polygon_vertices_in_r # Outputs - `list::ShuffledPolygonLinkedList`: The linked list of polygon vertices representing the cavity. """ -function setup_cavity_cdt(tri::Triangulation, V; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function setup_cavity_cdt(tri::Triangulation, V; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) v = V[begin] u = V[end] list = prepare_vertex_linked_list(V) @@ -553,10 +555,10 @@ Triangulates the cavity `V` left behind when deleting triangles intersected in a # Outputs There is no output, but `tri` is updated in-place. """ -function triangulate_cavity_cdt!(tri::Triangulation, V, tri_fan::Triangulation, marked_vertices, fan_triangles; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function triangulate_cavity_cdt!(tri::Triangulation, V, tri_fan::Triangulation, marked_vertices, fan_triangles; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) list = setup_cavity_cdt(tri, V; rng, predicates) - add_triangle!(tri, V[begin], V[list.shuffled_indices[2]], V[end]; protect_boundary=true, update_ghost_edges=false) - for i in 3:(list.k-1) + add_triangle!(tri, V[begin], V[list.shuffled_indices[2]], V[end]; protect_boundary = true, update_ghost_edges = false) + for i in 3:(list.k - 1) a, b, c = get_triplet(list, i) add_point_cavity_cdt!(tri, a, b, c, marked_vertices, predicates) if !isempty(marked_vertices) && (last(marked_vertices) == a) || (a ∈ marked_vertices) # We try and insert a last, so the first check will sometimes be a nice boost @@ -581,15 +583,15 @@ using `tri_fan` as a temporary triangulation. (This implements Lines 17--19 and The `predicates` argument defines the method for computing predicates. Can be one of [`FastKernel`](@ref), [`ExactKernel`](@ref), and [`AdaptiveKernel`](@ref). See the documentation for a further discussion of these methods. """ -function retriangulate_fan!(tri::Triangulation, tri_fan::Triangulation, fan, fan_triangles; predicates::AbstractPredicateKernel=AdaptiveKernel(), rng::Random.AbstractRNG=Random.default_rng()) +function retriangulate_fan!(tri::Triangulation, tri_fan::Triangulation, fan, fan_triangles; predicates::AbstractPredicateKernel = AdaptiveKernel(), rng::Random.AbstractRNG = Random.default_rng()) for T in each_triangle(fan_triangles) u, v, w = triangle_vertices(T) - delete_triangle!(tri, u, v, w; protect_boundary=true) + delete_triangle!(tri, u, v, w; protect_boundary = true) end triangulate_convex!(tri_fan, fan; predicates, rng) for T in each_solid_triangle(tri_fan) u, v, w = triangle_vertices(T) - add_triangle!(tri, u, v, w; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, u, v, w; protect_boundary = true, update_ghost_edges = false) end return tri end @@ -643,7 +645,7 @@ Adds a point to the cavity `V` left behind when deleting triangles intersected i # Outputs There is no output, but `tri` is updated in-place, as is `marked_vertices` if necessary. """ -function add_point_cavity_cdt!(tri::Triangulation, u, v, w, marked_vertices, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function add_point_cavity_cdt!(tri::Triangulation, u, v, w, marked_vertices, predicates::AbstractPredicateKernel = AdaptiveKernel()) (u == v || v == w || u == w) && return tri # For some pathological cases, the found cavities double back on itself, e.g. a right cavity [6, 22, 124, 96, 135, 96, 124, 26] is possible. (Take i = 2567; rng = StableRNG(i); points, edges, mat_edges = get_random_vertices_and_constrained_edges(40, 200, 20, rng); tri = triangulate(points; segments=edges, rng=StableRNG(i))) x = get_adjacent(tri, w, v) if !edge_exists(x) @@ -655,9 +657,9 @@ function add_point_cavity_cdt!(tri::Triangulation, u, v, w, marked_vertices, pre insert_flag = !is_inside(incircle_test) && is_positively_oriented(orient_test) end if insert_flag - add_triangle!(tri, u, v, w; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, u, v, w; protect_boundary = true, update_ghost_edges = false) else - delete_triangle!(tri, w, v, x; protect_boundary=true, update_ghost_edges=false) + delete_triangle!(tri, w, v, x; protect_boundary = true, update_ghost_edges = false) add_point_cavity_cdt!(tri, u, v, x, marked_vertices, predicates) add_point_cavity_cdt!(tri, u, x, w, marked_vertices, predicates) if !is_inside(incircle_test) @@ -674,7 +676,7 @@ Adds the triangles from `tris` to `tri_original`. """ function add_new_triangles!(tri_original::Triangulation, tris) for tri in each_triangle(tris) - add_triangle!(tri_original, tri; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri_original, tri; protect_boundary = true, update_ghost_edges = false) end return tri_original end @@ -699,16 +701,17 @@ See also [`find_triangle`](@ref). - `left_vertices`: The vertices of the intersected triangles that are left of `e`. - `right_vertices`: The vertices of the intersected triangles that are right of `e`. """ -function locate_intersecting_triangles(tri::Triangulation, e, rotate=Val(true), rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function locate_intersecting_triangles(tri::Triangulation, e, rotate = Val(true), rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) V = triangle_type(tri) E = edge_type(tri) I = integer_type(tri) e = is_true(rotate) ? sort_edge_by_degree(tri, e) : e # faster to start at the minimum degree vertex of the edge - history = PointLocationHistory{V,E,I}() + history = PointLocationHistory{V, E, I}() add_left_vertex!(history, initial(e)) add_right_vertex!(history, initial(e)) - find_triangle(tri, get_point(tri, terminal(e)); predicates, - m=nothing, k=initial(e), store_history=Val(true), history, rng + find_triangle( + tri, get_point(tri, terminal(e)); predicates, + m = nothing, k = initial(e), store_history = Val(true), history, rng, ) add_left_vertex!(history, terminal(e)) add_right_vertex!(history, terminal(e)) @@ -733,7 +736,7 @@ Deletes the triangles in `triangles` from `tri`. """ function delete_intersected_triangles!(tri, triangles) # don't really _need_ this method, but maybe it makes the code a bit clearer? for τ in each_triangle(triangles) - delete_triangle!(tri, τ; protect_boundary=true) + delete_triangle!(tri, τ; protect_boundary = true) end return tri end @@ -749,7 +752,7 @@ The `predicates::AbstractPredicateKernel` argument defines the method for comput See also [`connect_segments!`](@ref), [`extend_segments!`](@ref), [`split_segment!`](@ref) and [`split_boundary_edge_at_collinear_segments!`](@ref). """ -function process_collinear_segments!(tri::Triangulation, e, collinear_segments; predicates::AbstractPredicateKernel=AdaptiveKernel(), rng::Random.AbstractRNG=Random.default_rng()) +function process_collinear_segments!(tri::Triangulation, e, collinear_segments; predicates::AbstractPredicateKernel = AdaptiveKernel(), rng::Random.AbstractRNG = Random.default_rng()) isempty(collinear_segments) && return false all_segments = get_all_segments(tri) # the difference between all_segments and segments is important since we need to be careful about what segments are already in the triangulation delete_edge!(all_segments, e) @@ -819,7 +822,7 @@ to accommodate the changed types. # Outputs - `new_tri`: The new triangulation, now containing `segments` in the `interior_segments` field and `boundary_nodes` in the `boundary_nodes` field, and with the updated [`PolygonHierarchy`](@ref). See also [`remake_triangulation_with_constraints`](@ref) and [`replace_ghost_vertex_information`](@ref). """ -function constrained_triangulation!(tri::Triangulation, segments, boundary_nodes, predicates::AbstractPredicateKernel, full_polygon_hierarchy; rng=Random.default_rng(), delete_holes=true) +function constrained_triangulation!(tri::Triangulation, segments, boundary_nodes, predicates::AbstractPredicateKernel, full_polygon_hierarchy; rng = Random.default_rng(), delete_holes = true) ghost_vertex_map, ghost_vertex_ranges, new_tri = remake_triangulation_with_constraints(tri, segments, boundary_nodes) all_segments = merge_segments(new_tri, ghost_vertex_map) for e in each_edge(all_segments) @@ -835,4 +838,3 @@ function constrained_triangulation!(tri::Triangulation, segments, boundary_nodes end return new_tri_2 end - diff --git a/src/algorithms/triangulation/main.jl b/src/algorithms/triangulation/main.jl index 13be40173..33f21d940 100644 --- a/src/algorithms/triangulation/main.jl +++ b/src/algorithms/triangulation/main.jl @@ -7,7 +7,7 @@ Postprocesses the triangulation `tri` after it has been constructed using [`tria - Clearing empty features using [`clear_empty_features!`](@ref) if `delete_empty_features` is `true`. - Recomputing the representative points using [`compute_representative_points!`](@ref) if `recompute_representative_points` is `true`. """ -function postprocess_triangulate!(tri; delete_ghosts=false, delete_empty_features=true, recompute_representative_points=true) +function postprocess_triangulate!(tri; delete_ghosts = false, delete_empty_features = true, recompute_representative_points = true) delete_ghosts && delete_ghost_triangles!(tri) delete_empty_features && clear_empty_features!(tri) recompute_representative_points && compute_representative_points!(tri) @@ -116,33 +116,35 @@ Here are some warnings to consider for some of the arguments. Weighted triangulations are not yet fully implemented due to certain bugs with the implementation. """ -function triangulate(points::P; - segments=nothing, - boundary_nodes=nothing, - predicates::AbstractPredicateKernel=AdaptiveKernel(), - weights=ZeroWeight(), - IntegerType::Type{I}=Int, - EdgeType::Type{E}=isnothing(segments) ? NTuple{2,IntegerType} : (edge_type ∘ typeof)(segments), - TriangleType::Type{V}=NTuple{3,IntegerType}, - EdgesType::Type{Es}=isnothing(segments) ? Set{EdgeType} : typeof(segments), - TrianglesType::Type{Ts}=Set{TriangleType}, - randomise=true, - delete_ghosts=false, - delete_empty_features=true, - try_last_inserted_point=true, - skip_points=(), - num_sample_rule::M=default_num_samples, - rng::Random.AbstractRNG=Random.default_rng(), - insertion_order::Vector=get_insertion_order(points, randomise, skip_points, IntegerType, rng), - recompute_representative_points=true, - delete_holes=true, - check_arguments=true, - full_polygon_hierarchy::H=nothing, - boundary_enricher=nothing, - boundary_curves=(), - polygonise_n=4096, - coarse_n=0, - enrich=false) where {P,I,E,V,Es,Ts,M,H} +function triangulate( + points::P; + segments = nothing, + boundary_nodes = nothing, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + weights = ZeroWeight(), + IntegerType::Type{I} = Int, + EdgeType::Type{E} = isnothing(segments) ? NTuple{2, IntegerType} : (edge_type ∘ typeof)(segments), + TriangleType::Type{V} = NTuple{3, IntegerType}, + EdgesType::Type{Es} = isnothing(segments) ? Set{EdgeType} : typeof(segments), + TrianglesType::Type{Ts} = Set{TriangleType}, + randomise = true, + delete_ghosts = false, + delete_empty_features = true, + try_last_inserted_point = true, + skip_points = (), + num_sample_rule::M = default_num_samples, + rng::Random.AbstractRNG = Random.default_rng(), + insertion_order::Vector = get_insertion_order(points, randomise, skip_points, IntegerType, rng), + recompute_representative_points = true, + delete_holes = true, + check_arguments = true, + full_polygon_hierarchy::H = nothing, + boundary_enricher = nothing, + boundary_curves = (), + polygonise_n = 4096, + coarse_n = 0, + enrich = false, + ) where {P, I, E, V, Es, Ts, M, H} check_config(points, weights, segments, boundary_nodes, predicates) if enrich || (isempty(boundary_curves) && is_curve_bounded(boundary_nodes)) # If boundary_curves is not empty, then we are coming from triangulate_curve_bounded return triangulate_curve_bounded(points; segments, boundary_nodes, predicates, weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, randomise, delete_ghosts, delete_empty_features, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order, recompute_representative_points, delete_holes, check_arguments, polygonise_n, coarse_n) @@ -152,20 +154,24 @@ function triangulate(points::P; end check_arguments && check_args(points, boundary_nodes, full_polygon_hierarchy, boundary_curves) tri = Triangulation(points; IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, weights, boundary_curves, boundary_enricher, build_cache = Val(true)) - return _triangulate!(tri, segments, boundary_nodes, predicates, randomise, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order, - recompute_representative_points, delete_holes, full_polygon_hierarchy, delete_ghosts, delete_empty_features) + return _triangulate!( + tri, segments, boundary_nodes, predicates, randomise, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order, + recompute_representative_points, delete_holes, full_polygon_hierarchy, delete_ghosts, delete_empty_features, + ) end function check_config(points, weights, segments, boundary_nodes, kernel) - (number_type(points) == Float32 && kernel != AdaptiveKernel()) && @warn "Using non-Float64 coordinates may cause issues. If you run into problems, consider using Float64 coordinates." maxlog=1 + (number_type(points) == Float32 && kernel != AdaptiveKernel()) && @warn "Using non-Float64 coordinates may cause issues. If you run into problems, consider using Float64 coordinates." maxlog = 1 is_weighted(weights) && throw(ArgumentError("Weighted triangulations are not yet fully implemented.")) is_constrained = !(isnothing(segments) || isempty(segments)) || !(isnothing(boundary_nodes) || !has_boundary_nodes(boundary_nodes)) is_weighted(weights) && is_constrained && throw(ArgumentError("You cannot compute a constrained triangulation with weighted points.")) return nothing end -function _triangulate!(tri::Triangulation, segments, boundary_nodes, predicates, randomise, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order, - recompute_representative_points, delete_holes, full_polygon_hierarchy, delete_ghosts, delete_empty_features) +function _triangulate!( + tri::Triangulation, segments, boundary_nodes, predicates, randomise, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order, + recompute_representative_points, delete_holes, full_polygon_hierarchy, delete_ghosts, delete_empty_features, + ) unconstrained_triangulation!(tri; predicates, randomise, try_last_inserted_point, skip_points, num_sample_rule, rng, insertion_order) _tri = if !(isnothing(segments) || isempty(segments)) || !(isnothing(boundary_nodes) || !has_boundary_nodes(boundary_nodes)) constrained_triangulation!(tri, segments, boundary_nodes, predicates, full_polygon_hierarchy; rng, delete_holes) @@ -190,23 +196,25 @@ Retriangulates the triangulation `tri` using the points `points`, returning a ne - `kwargs...`: Extra keyword arguments passed to `triangulate`. Other keyword arguments, like `segments` and `boundary_nodes`, are automatically passed from the fields of `tri`, but may be overridden by passing the corresponding keyword arguments. """ -function retriangulate(tri::T, points=get_points(tri); - segments=get_interior_segments(tri), - boundary_nodes=get_boundary_nodes(tri), - skip_points = Set(filter(i -> !has_vertex(tri, i), each_point_index(tri))), - kwargs...) where {T<:Triangulation} +function retriangulate( + tri::T, points = get_points(tri); + segments = get_interior_segments(tri), + boundary_nodes = get_boundary_nodes(tri), + skip_points = Set(filter(i -> !has_vertex(tri, i), each_point_index(tri))), + kwargs..., + ) where {T <: Triangulation} return triangulate( points; segments, boundary_nodes, - weights=get_weights(tri), - IntegerType=integer_type(tri), - EdgeType=edge_type(tri), - TriangleType=triangle_type(tri), - EdgesType=edges_type(tri), - TrianglesType=triangles_type(tri), - check_arguments=false, + weights = get_weights(tri), + IntegerType = integer_type(tri), + EdgeType = edge_type(tri), + TriangleType = triangle_type(tri), + EdgesType = edges_type(tri), + TrianglesType = triangles_type(tri), + check_arguments = false, skip_points, - kwargs... + kwargs..., )::T -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/mesh_refinement.jl b/src/algorithms/triangulation/mesh_refinement.jl index 5cf599dfe..d27422305 100644 --- a/src/algorithms/triangulation/mesh_refinement.jl +++ b/src/algorithms/triangulation/mesh_refinement.jl @@ -124,7 +124,7 @@ Finalises the triangulation after refinement, e.g. by deleting ghost triangles a """ function finalise!(tri::Triangulation, args::RefinementArguments) !args.had_ghosts && delete_ghost_triangles!(tri) - args.locked_convex_hull && unlock_convex_hull!(tri; reconstruct=true) + args.locked_convex_hull && unlock_convex_hull!(tri; reconstruct = true) return tri end @@ -252,7 +252,7 @@ function locate_steiner_point(tri::Triangulation, args::RefinementArguments, T, flag = point_position_relative_to_triangle(args.predicates, tri, T, c) !is_outside(flag) && return T, flag # T is never a ghost triangle, so don't worry about checking is_on(flag) here init = get_init_for_steiner_point(tri, T) - V, _ = find_triangle(tri, c; predicates=args.predicates, m=nothing, point_indices=nothing, try_points=nothing, k=init, args.rng, args.concavity_protection, use_barriers=Val(true)) + V, _ = find_triangle(tri, c; predicates = args.predicates, m = nothing, point_indices = nothing, try_points = nothing, k = init, args.rng, args.concavity_protection, use_barriers = Val(true)) flag = point_position_relative_to_triangle(args.predicates, tri, V, c) if is_ghost_triangle(V) && is_on(flag) V = replace_ghost_triangle_with_boundary_triangle(tri, V) @@ -342,7 +342,7 @@ function enqueue_newly_encroached_segments!(args::RefinementArguments, tri::Tria return any_encroached end -const MIDPOINT_TOLERANCE = 1e-6 +const MIDPOINT_TOLERANCE = 1.0e-6 """ compute_split_position(tri::Triangulation, args::RefinementArguments, e) -> NTuple{2, Float} @@ -490,7 +490,7 @@ Determines if the vertices of a segment `e` of `tri` adjoin other segments at an - `num_adjoin`: The number of vertices of `e` that adjoin other segments at an acute angle. - `adjoin_vert`: The vertex of `e` that adjoins another segment at an acute angle if `num_adjoin == 1`, and `∅` otherwise. """ -function segment_vertices_adjoin_other_segments_at_acute_angle(tri::Triangulation, e, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function segment_vertices_adjoin_other_segments_at_acute_angle(tri::Triangulation, e, predicates::AbstractPredicateKernel = AdaptiveKernel()) u, v = edge_vertices(e) p, q = get_point(tri, u, v) I = integer_type(tri) @@ -578,7 +578,7 @@ function check_split_subsegment_precision(mx, my, p, q) abs_err_flag_1 = check_absolute_precision(mx, px) && check_absolute_precision(my, py) abs_err_flag_2 = check_absolute_precision(mx, qx) && check_absolute_precision(my, qy) abs_err_flag = abs_err_flag_1 || abs_err_flag_2 - return abs_err_flag + return abs_err_flag end """ @@ -615,7 +615,7 @@ function _split_subsegment_piecewise_linear!(tri::Triangulation, args::Refinemen push_point!(tri, mx, my) I = integer_type(tri) r = I(num_points(tri)) - complete_split_edge_and_legalise!(tri, u, v, r, Val(true), args.events; predicates=args.predicates) + complete_split_edge_and_legalise!(tri, u, v, r, Val(true), args.events; predicates = args.predicates) assess_added_triangles!(args, tri) return tri end @@ -654,8 +654,8 @@ function _split_subsegment_curve_bounded_standard!(tri::Triangulation, args::Ref I = integer_type(tri) r = I(num_points(tri)) is_interior = is_segment(enricher, i, j) - complete_split_edge_and_legalise!(tri, i, j, r, Val(true), args.events; predicates=args.predicates) - split_edge!(enricher, i, j, r, Val(false), Val(false), is_interior) + complete_split_edge_and_legalise!(tri, i, j, r, Val(true), args.events; predicates = args.predicates) + split_edge!(enricher, i, j, r, Val(false), Val(false), is_interior) assess_added_triangles!(args, tri) push!(args.midpoint_split_list, r) return tri @@ -687,7 +687,7 @@ function _split_subsegment_curve_bounded_small_angle!(tri::Triangulation, args:: e′ = construct_edge(E, i, j) delete_free_vertices_around_subsegment!(tri, args, e′) is_interior = is_segment(enricher, i, j) - complete_split_edge_and_legalise!(tri, i, j, r, Val(true), args.events; predicates=args.predicates) + complete_split_edge_and_legalise!(tri, i, j, r, Val(true), args.events; predicates = args.predicates) split_edge!(enricher, i, j, r, Val(false), Val(false), is_interior) replace_next_edge!(enricher, apex, complex_id, member_id, r) assess_added_triangles!(args, tri) @@ -716,7 +716,7 @@ function delete_free_vertices_around_subsegment!(tri::Triangulation, args::Refin w = get_adjacent(tri, e′) r = get_point(tri, w) while is_free(args, w) && !is_outside(point_position_relative_to_diametral_circle(args.predicates, p, q, r)) - delete_point!(tri, w; store_event_history=Val(true), event_history=args.events, rng=args.rng, predicates=args.predicates) + delete_point!(tri, w; store_event_history = Val(true), event_history = args.events, rng = args.rng, predicates = args.predicates) w = get_adjacent(tri, e′) r = get_point(tri, w) end @@ -899,4 +899,4 @@ function assess_added_triangles!(args::RefinementArguments, tri::Triangulation) end end return args -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/triangulate_convex.jl b/src/algorithms/triangulation/triangulate_convex.jl index dd131730a..54a33bf5b 100644 --- a/src/algorithms/triangulation/triangulate_convex.jl +++ b/src/algorithms/triangulation/triangulate_convex.jl @@ -22,12 +22,14 @@ Triangulates the convex polygon `S`. # Output - `tri::Triangulation`: The triangulated polygon. """ -function triangulate_convex(points, S; - rng::Random.AbstractRNG=Random.default_rng(), - delete_ghosts=false, - delete_empty_features=true, - predicates::AbstractPredicateKernel=AdaptiveKernel(), - kwargs...) +function triangulate_convex( + points, S; + rng::Random.AbstractRNG = Random.default_rng(), + delete_ghosts = false, + delete_empty_features = true, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + kwargs..., + ) tri = Triangulation(points; kwargs...) triangulate_convex!(tri, S; predicates, rng) postprocess_triangulate_convex!(tri, S; delete_ghosts, delete_empty_features) @@ -51,11 +53,11 @@ Triangulates the convex polygon `S` in-place into `tri`. There is no output, as `tri` is updated in-place. This function does not do any post-processing, e.g. deleting any ghost triangles. This is done by [`triangulate_convex`](@ref) or [`postprocess_triangulate_convex!`](@ref). """ -function triangulate_convex!(tri::Triangulation, S; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function triangulate_convex!(tri::Triangulation, S; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) list = ShuffledPolygonLinkedList(S; rng) delete_vertices_in_random_order!(list, tri, rng, predicates) u, v, w = get_triplet(list, 1) - add_triangle!(tri, u, v, w; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, u, v, w; protect_boundary = true, update_ghost_edges = false) for i in 4:list.k u, v, w = get_triplet(list, i) add_point_convex_triangulation!(tri, u, v, w, S, predicates) @@ -122,16 +124,16 @@ to make. 2. For this method to be efficient, the set `x ∈ S` must be `O(1)` time. This is why we use a `Set` type for `S`. 3. The algorithm is recursive, recursively digging further through the polygon to find non-Delaunay edges to adjoins with `u`. """ -function add_point_convex_triangulation!(tri::Triangulation, u, v, w, S, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function add_point_convex_triangulation!(tri::Triangulation, u, v, w, S, predicates::AbstractPredicateKernel = AdaptiveKernel()) x = get_adjacent(tri, w, v) if edge_exists(x) && is_inside(point_position_relative_to_circumcircle(predicates, tri, u, v, w, x)) # uvw and wvx are not Delaunay - delete_triangle!(tri, w, v, x; protect_boundary=true, update_ghost_edges=false) + delete_triangle!(tri, w, v, x; protect_boundary = true, update_ghost_edges = false) add_point_convex_triangulation!(tri, u, v, x, S, predicates) add_point_convex_triangulation!(tri, u, x, w, S, predicates) else # vw is a Delaunay edge - add_triangle!(tri, u, v, w; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, u, v, w; protect_boundary = true, update_ghost_edges = false) end return tri end @@ -162,9 +164,9 @@ function postprocess_triangulate_convex!(tri::Triangulation, S; delete_ghosts, d append!(hull, S) push!(hull, S[begin]) I = integer_type(tri) - for i in firstindex(S):(lastindex(S)-1) + for i in firstindex(S):(lastindex(S) - 1) u = S[i] - v = S[i+1] + v = S[i + 1] if !delete_ghosts add_triangle!(tri, v, u, I(𝒢)) else @@ -189,4 +191,4 @@ function postprocess_triangulate_convex!(tri::Triangulation, S; delete_ghosts, d representative_point_list = get_representative_point_list(tri) representative_point_list[1] = RepresentativeCoordinates(cx, cy, length(S)) return tri -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/triangulate_curve_bounded.jl b/src/algorithms/triangulation/triangulate_curve_bounded.jl index 16d22b8a2..acc26b96a 100644 --- a/src/algorithms/triangulation/triangulate_curve_bounded.jl +++ b/src/algorithms/triangulation/triangulate_curve_bounded.jl @@ -33,22 +33,25 @@ See also [`BoundaryEnricher`](@ref) and [`enrich_boundary!`](@ref). To refine the mesh further beyond its initial coarse discretisation, as produced from this function, please see [`refine!`](@ref). """ -function triangulate_curve_bounded(points::P; - segments=nothing, - boundary_nodes=nothing, - predicates::AbstractPredicateKernel=AdaptiveKernel(), - IntegerType::Type{I}=Int, - polygonise_n=4096, - coarse_n=0, - check_arguments=true, - delete_ghosts=false, - delete_empty_features=true, - recompute_representative_points=true, - rng::Random.AbstractRNG=Random.default_rng(), - insertion_order=nothing, # use this so that it gets ignored by the kwargs - kwargs...) where {P,I} - enricher = BoundaryEnricher(points, boundary_nodes, segments; IntegerType, n=polygonise_n, coarse_n) - return _triangulate_curve_bounded(points, enricher; +function triangulate_curve_bounded( + points::P; + segments = nothing, + boundary_nodes = nothing, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + IntegerType::Type{I} = Int, + polygonise_n = 4096, + coarse_n = 0, + check_arguments = true, + delete_ghosts = false, + delete_empty_features = true, + recompute_representative_points = true, + rng::Random.AbstractRNG = Random.default_rng(), + insertion_order = nothing, # use this so that it gets ignored by the kwargs + kwargs..., + ) where {P, I} + enricher = BoundaryEnricher(points, boundary_nodes, segments; IntegerType, n = polygonise_n, coarse_n) + return _triangulate_curve_bounded( + points, enricher; predicates, IntegerType, check_arguments, @@ -57,36 +60,41 @@ function triangulate_curve_bounded(points::P; recompute_representative_points, rng, insertion_order, - kwargs...) + kwargs..., + ) end -function _triangulate_curve_bounded(points::P, enricher; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - IntegerType::Type{I}=Int, - check_arguments=true, - delete_ghosts=false, - delete_empty_features=true, - recompute_representative_points=true, - rng::Random.AbstractRNG=Random.default_rng(), - insertion_order=nothing, # use this so that it gets ignored by the kwargs - kwargs...) where {P,I} +function _triangulate_curve_bounded( + points::P, enricher; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + IntegerType::Type{I} = Int, + check_arguments = true, + delete_ghosts = false, + delete_empty_features = true, + recompute_representative_points = true, + rng::Random.AbstractRNG = Random.default_rng(), + insertion_order = nothing, # use this so that it gets ignored by the kwargs + kwargs..., + ) where {P, I} check_arguments && check_args(enricher) enrich_boundary!(enricher; predicates) new_boundary_nodes = get_boundary_nodes(enricher) new_segments = get_segments(enricher) full_polygon_hierarchy = get_polygon_hierarchy(enricher) boundary_curves = get_boundary_curves(enricher) - tri = triangulate(points; + tri = triangulate( + points; IntegerType, - segments=new_segments, - boundary_nodes=new_boundary_nodes, + segments = new_segments, + boundary_nodes = new_boundary_nodes, predicates, full_polygon_hierarchy, boundary_curves, - boundary_enricher=enricher, - check_arguments=false, - delete_ghosts=false, + boundary_enricher = enricher, + check_arguments = false, + delete_ghosts = false, rng, - kwargs...) + kwargs..., + ) postprocess_triangulate!(tri; delete_ghosts, delete_empty_features, recompute_representative_points) return tri end @@ -101,7 +109,7 @@ come from [`convert_boundary_curves!`](@ref). The argument `n` is the amount of If non-zero, this should be a power of two (otherwise it will be rounded up to the next power of two). If it is zero, then the splitting will continue until the maximum total variation over any subcurve is less than π/2. """ -function coarse_discretisation!(points, boundary_nodes, boundary_curves; n::I=0) where {I} +function coarse_discretisation!(points, boundary_nodes, boundary_curves; n::I = 0) where {I} !is_curve_bounded(boundary_curves) && return points, boundary_nodes if n > 0 n = max(n, I(4)) @@ -181,7 +189,7 @@ The `predicates` argument determines how predicates are computed, and should be one of [`ExactKernel`](@ref), [`FastKernel`](@ref), and [`AdaptiveKernel`](@ref) (the default). See the documentation for more information about these choices. """ -function enrich_boundary!(enricher::BoundaryEnricher; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function enrich_boundary!(enricher::BoundaryEnricher; predicates::AbstractPredicateKernel = AdaptiveKernel()) queue = get_queue(enricher) points = get_points(enricher) enqueue_all!(queue, each_point_index(points)) @@ -190,13 +198,13 @@ function enrich_boundary!(enricher::BoundaryEnricher; predicates::AbstractPredic end return enricher end -function _enrich_boundary_itr!(enricher::BoundaryEnricher, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function _enrich_boundary_itr!(enricher::BoundaryEnricher, predicates::AbstractPredicateKernel = AdaptiveKernel()) queue = get_queue(enricher) points = get_points(enricher) spatial_tree = get_spatial_tree(enricher) v = popfirst!(queue) r = get_point(points, v) - intersections = get_intersections(spatial_tree, v; cache_id=1) + intersections = get_intersections(spatial_tree, v; cache_id = 1) requeued = false for bbox in intersections i, j = get_edge(bbox) @@ -227,7 +235,7 @@ The `predicate` argument determines how predicates are computed, and should be one of [`ExactKernel`](@ref), [`FastKernel`](@ref), and [`AdaptiveKernel`](@ref) (the default). See the documentation for more information about these choices. """ -function split_subcurve!(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function split_subcurve!(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel = AdaptiveKernel()) flag, apex, complex_id, _ = is_small_angle_complex_member(enricher, i, j) if !flag return _split_subcurve_standard!(enricher, i, j, predicates) @@ -235,7 +243,7 @@ function split_subcurve!(enricher::BoundaryEnricher, i, j, predicates::AbstractP return _split_subcurve_complex!(enricher, apex, complex_id) end end -function _split_subcurve_standard!(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function _split_subcurve_standard!(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel = AdaptiveKernel()) points = get_points(enricher) t, Δθ, ct = compute_split_position(enricher, i, j, predicates) if isnan(Δθ) @@ -292,7 +300,7 @@ Gets the point to split the edge `(i, j)` at. - `Δθ`: The total variation of the subcurve `(i, t)`. If a split was created due to a small angle, this will be set to zero. - `ct`: The point to split the edge at. """ -function compute_split_position(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function compute_split_position(enricher::BoundaryEnricher, i, j, predicates::AbstractPredicateKernel = AdaptiveKernel()) num_adjoin, adjoin_vert = has_acute_neighbouring_angles(predicates, enricher, i, j) if num_adjoin == 0 t, Δθ, ct = _compute_split_position_standard(enricher, i, j) @@ -410,7 +418,7 @@ returned vertex is `$∅`. (The purpose of this function is similar to [`segment_vertices_adjoin_other_segments_at_acute_angle`](@ref).) """ -function has_acute_neighbouring_angles(predicates::AbstractPredicateKernel, enricher::BoundaryEnricher{P,B,C,I}, i, j) where {P,B,C,I} +function has_acute_neighbouring_angles(predicates::AbstractPredicateKernel, enricher::BoundaryEnricher{P, B, C, I}, i, j) where {P, B, C, I} is_segment(enricher, i, j) && return 0, I(∅) points = get_points(enricher) p, q = get_point(points, i, j) @@ -504,7 +512,7 @@ function test_visibility(predicates::AbstractPredicateKernel, points, boundary_n end int₁ = false int₂ = false - intersections = get_intersections(spatial_tree, i, j, k; cache_id=2) + intersections = get_intersections(spatial_tree, i, j, k; cache_id = 2) for box in intersections u, v = get_edge(box) !edges_are_disjoint((i, j), (u, v)) && continue @@ -520,4 +528,4 @@ function test_visibility(predicates::AbstractPredicateKernel, points, boundary_n int₁ && int₂ && return Cert.Invisible end return Cert.Visible -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/triangulate_rectangle.jl b/src/algorithms/triangulation/triangulate_rectangle.jl index dfe21550a..90f5c4908 100644 --- a/src/algorithms/triangulation/triangulate_rectangle.jl +++ b/src/algorithms/triangulation/triangulate_rectangle.jl @@ -25,24 +25,28 @@ Triangulates the rectangle `[a, b] × [c, d]`. # Outputs - `tri`: The triangulation of the rectangle. """ -@inline function triangulate_rectangle(a, b, c, d, nx, ny; - single_boundary=false, - delete_ghosts=false, - IntegerType::Type{I}=Int, - EdgeType::Type{E}=NTuple{2,IntegerType}, - TriangleType::Type{V}=NTuple{3,IntegerType}, - EdgesType::Type{Es}=Set{EdgeType}, - TrianglesType::Type{Ts}=Set{TriangleType}, - predicates::AbstractPredicateKernel=AdaptiveKernel()) where {I,E,V,Es,Ts} +@inline function triangulate_rectangle( + a, b, c, d, nx, ny; + single_boundary = false, + delete_ghosts = false, + IntegerType::Type{I} = Int, + EdgeType::Type{E} = NTuple{2, IntegerType}, + TriangleType::Type{V} = NTuple{3, IntegerType}, + EdgesType::Type{Es} = Set{EdgeType}, + TrianglesType::Type{Ts} = Set{TriangleType}, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) where {I, E, V, Es, Ts} return _triangulate_rectangle(a, b, c, d, nx, ny, I, E, V, Es, Ts, single_boundary, delete_ghosts, predicates) end -@inline function _triangulate_rectangle(a, b, c, d, nx, ny, - ::Type{I}, ::Type{E}, ::Type{V}, ::Type{Es}, ::Type{Ts}, - single_boundary, delete_ghosts, predicates::AbstractPredicateKernel=AdaptiveKernel()) where {I,E,V,Es,Ts} +@inline function _triangulate_rectangle( + a, b, c, d, nx, ny, + ::Type{I}, ::Type{E}, ::Type{V}, ::Type{Es}, ::Type{Ts}, + single_boundary, delete_ghosts, predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) where {I, E, V, Es, Ts} T, sub2ind = get_lattice_triangles(nx, ny, Ts, V) points = get_lattice_points(a, b, c, d, nx, ny, sub2ind) boundary_nodes = get_lattice_boundary(nx, ny, sub2ind, Val(single_boundary), I) - tri = Triangulation(points, T, boundary_nodes; predicates, IntegerType=I, EdgeType=E, TriangleType=V, EdgesType=Es, TrianglesType=Ts, delete_ghosts) + tri = Triangulation(points, T, boundary_nodes; predicates, IntegerType = I, EdgeType = E, TriangleType = V, EdgesType = Es, TrianglesType = Ts, delete_ghosts) compute_representative_points!(tri) return tri end @@ -65,11 +69,11 @@ See [`triangulate_rectangle`](@ref). - `T`: The collection of triangles. - `sub2ind`: A map that takes cartesian indices `(i, j)` into the associated linear index along the lattice. See `LinearIndices`. """ -@inline function get_lattice_triangles(nx, ny, ::Type{Ts}, ::Type{V}) where {Ts,V} +@inline function get_lattice_triangles(nx, ny, ::Type{Ts}, ::Type{V}) where {Ts, V} T = Ts() sub2ind = LinearIndices((1:nx, 1:ny)) - for j in 1:(ny-1) - for i in 1:(nx-1) + for j in 1:(ny - 1) + for i in 1:(nx - 1) u = sub2ind[CartesianIndex(i, j)] v = sub2ind[CartesianIndex(i + 1, j)] w = sub2ind[CartesianIndex(i, j + 1)] @@ -105,7 +109,7 @@ See [`triangulate_rectangle`](@ref). - `points`: The points on the lattice, where `points[sub2ind[CartesianIndex(i, j)]]` is the point at the `i`th `x` point and the `j`th `y` point, """ @inline function get_lattice_points(a, b, c, d, nx, ny, sub2ind) - points = Vector{NTuple{2,Float64}}(undef, nx * ny) + points = Vector{NTuple{2, Float64}}(undef, nx * ny) Δx = (b - a) / (nx - 1) Δy = (d - c) / (ny - 1) for j in 1:ny @@ -137,7 +141,7 @@ See [`triangulate_rectangle`](@ref). # Outputs - `boundary_nodes`: The boundary nodes, returned according to `single_boundary` as described above. """ -@inline function get_lattice_boundary(nx, ny, sub2ind, single_boundary::Val{B}, ::Type{I}) where {B,I} +@inline function get_lattice_boundary(nx, ny, sub2ind, single_boundary::Val{B}, ::Type{I}) where {B, I} b1 = Vector{I}(undef, nx) b2 = Vector{I}(undef, ny) b3 = Vector{I}(undef, nx) @@ -149,10 +153,10 @@ See [`triangulate_rectangle`](@ref). b2[j] = sub2ind[CartesianIndex(nx, j)] end for i in nx:-1:1 - b3[nx-i+1] = sub2ind[CartesianIndex(i, ny)] + b3[nx - i + 1] = sub2ind[CartesianIndex(i, ny)] end for j in ny:-1:1 - b4[ny-j+1] = sub2ind[CartesianIndex(1, j)] + b4[ny - j + 1] = sub2ind[CartesianIndex(1, j)] end if is_true(single_boundary) popfirst!(b2) @@ -163,4 +167,4 @@ See [`triangulate_rectangle`](@ref). boundary_nodes = [b1, b2, b3, b4] end return boundary_nodes -end \ No newline at end of file +end diff --git a/src/algorithms/triangulation/unconstrained_triangulation.jl b/src/algorithms/triangulation/unconstrained_triangulation.jl index 5dbbff1e7..e89162295 100644 --- a/src/algorithms/triangulation/unconstrained_triangulation.jl +++ b/src/algorithms/triangulation/unconstrained_triangulation.jl @@ -43,7 +43,7 @@ Gets the initial triangle for the Bowyer-Watson algorithm. # Output - `initial_triangle`: The initial triangle. """ -function get_initial_triangle(tri::Triangulation, insertion_order, predicates::AbstractPredicateKernel=AdaptiveKernel(), itr=0) +function get_initial_triangle(tri::Triangulation, insertion_order, predicates::AbstractPredicateKernel = AdaptiveKernel(), itr = 0) i, j, k = @view insertion_order[1:3] # insertion_order got converted into a Vector, so indexing is safe initial_triangle = construct_positively_oriented_triangle(tri, i, j, k, predicates) i, j, k = triangle_vertices(initial_triangle) @@ -74,10 +74,10 @@ Initialises the Bowyer-Watson algorithm. # Output `tri` is updated in place to contain the initial triangle from which the Bowyer-Watson algorithm starts. """ -function initialise_bowyer_watson!(tri::Triangulation, insertion_order, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function initialise_bowyer_watson!(tri::Triangulation, insertion_order, predicates::AbstractPredicateKernel = AdaptiveKernel()) I = integer_type(tri) initial_triangle = get_initial_triangle(tri, insertion_order, predicates) - add_triangle!(tri, initial_triangle; update_ghost_edges=true) + add_triangle!(tri, initial_triangle; update_ghost_edges = true) new_representative_point!(tri, I(1)) for i in triangle_vertices(initial_triangle) p = get_point(tri, i) @@ -109,7 +109,7 @@ function get_initial_search_point(tri::Triangulation, num_points, new_point, ins currently_inserted_points = @view insertion_order[begin:num_currently_inserted] m = num_sample_rule(num_currently_inserted) try_points = try_last_inserted_point ? (last_inserted_point_index,) : (∅,) - initial_search_point = select_initial_point(tri, new_point; m, point_indices=currently_inserted_points, rng, try_points) + initial_search_point = select_initial_point(tri, new_point; m, point_indices = currently_inserted_points, rng, try_points) return initial_search_point end @@ -143,10 +143,10 @@ This function works as follows: The function [`add_point_bowyer_watson_dig_cavities!`](@ref) is the main workhorse of this function from `add_point_bowyer_watson_after_found_triangle`. See its docstring for the details. """ -function add_point_bowyer_watson!(tri::Triangulation, new_point, initial_search_point::I, rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel(), update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::P=Val(false)) where {I,P} +function add_point_bowyer_watson!(tri::Triangulation, new_point, initial_search_point::I, rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel(), update_representative_point = true, store_event_history = Val(false), event_history = nothing, peek::P = Val(false)) where {I, P} _new_point = is_true(peek) ? new_point : I(new_point) q = get_point(tri, _new_point) - V = find_triangle(tri, q; predicates, m=nothing, point_indices=nothing, try_points=nothing, k=initial_search_point, rng) + V = find_triangle(tri, q; predicates, m = nothing, point_indices = nothing, try_points = nothing, k = initial_search_point, rng) if is_weighted(tri) #= This part here is why the Bowyer-Watson algorithm is not implemented for weighted triangulations yet. I don't understand why it sometimes @@ -160,7 +160,7 @@ function add_point_bowyer_watson!(tri::Triangulation, new_point, initial_search_ return V end -function add_point_bowyer_watson_and_process_after_found_triangle!(tri::Triangulation, new_point, V, q, flag, update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::P=Val(false), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P} +function add_point_bowyer_watson_and_process_after_found_triangle!(tri::Triangulation, new_point, V, q, flag, update_representative_point = true, store_event_history = Val(false), event_history = nothing, peek::P = Val(false), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {P} I = integer_type(tri) _new_point = is_true(peek) ? new_point : I(new_point) add_point_bowyer_watson_after_found_triangle!(tri, _new_point, V, q, flag, update_representative_point, store_event_history, event_history, peek, predicates) @@ -168,7 +168,7 @@ function add_point_bowyer_watson_and_process_after_found_triangle!(tri::Triangul return V end -function add_point_bowyer_watson_after_found_triangle!(tri::Triangulation, new_point, V, q, flag, update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::P=Val(false), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P} +function add_point_bowyer_watson_after_found_triangle!(tri::Triangulation, new_point, V, q, flag, update_representative_point = true, store_event_history = Val(false), event_history = nothing, peek::P = Val(false), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {P} if is_ghost_triangle(V) && is_constrained(tri) # When we have a constrained boundary edge, we don't want to walk into its interior. So let's just check this case now. V = sort_triangle(V) @@ -214,13 +214,13 @@ This function works as follows: will fix this case. The need for `is_ghost_triangle(V) && !is_boundary_node(tri, new_point)[1]` is in case the ghost edges were already correctly added. Nothing happens if the edge of `V` that `new_point` is on is not the boundary edge. """ -function add_point_bowyer_watson_dig_cavities!(tri::Triangulation, new_point::N, V, q, flag, update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::F=Val(false), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {N,F} +function add_point_bowyer_watson_dig_cavities!(tri::Triangulation, new_point::N, V, q, flag, update_representative_point = true, store_event_history = Val(false), event_history = nothing, peek::F = Val(false), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {N, F} _new_point = is_true(peek) ? num_points(tri) + 1 : new_point # If we are peeking, then we need to use the number of points in the triangulation as the index for the new point since we don't actually insert the point i, j, k = triangle_vertices(V) ℓ₁ = get_adjacent(tri, j, i) ℓ₂ = get_adjacent(tri, k, j) ℓ₃ = get_adjacent(tri, i, k) - !is_true(peek) && delete_triangle!(tri, V; protect_boundary=true, update_ghost_edges=false) + !is_true(peek) && delete_triangle!(tri, V; protect_boundary = true, update_ghost_edges = false) is_true(store_event_history) && delete_triangle!(event_history, V) dig_cavity!(tri, new_point, i, j, ℓ₁, flag, V, store_event_history, event_history, peek, predicates) dig_cavity!(tri, new_point, j, k, ℓ₂, flag, V, store_event_history, event_history, peek, predicates) @@ -238,10 +238,10 @@ function add_point_bowyer_watson_dig_cavities!(tri::Triangulation, new_point::N, end g = get_adjacent(tri, u, v) if !is_true(peek) - delete_triangle!(tri, v, u, new_point; protect_boundary=true, update_ghost_edges=false) - delete_triangle!(tri, u, v, g; protect_boundary=true, update_ghost_edges=false) - add_triangle!(tri, new_point, v, g; update_ghost_edges=false) - add_triangle!(tri, u, new_point, g; update_ghost_edges=false) + delete_triangle!(tri, v, u, new_point; protect_boundary = true, update_ghost_edges = false) + delete_triangle!(tri, u, v, g; protect_boundary = true, update_ghost_edges = false) + add_triangle!(tri, new_point, v, g; update_ghost_edges = false) + add_triangle!(tri, u, new_point, g; update_ghost_edges = false) end if is_true(store_event_history) trit = triangle_type(tri) @@ -311,7 +311,7 @@ This function works as follows: `(i, j)` is a segment, then the situation is more complicated. In particular, `r` being on an edge of `V` might imply that we are going to add a degenerate triangle `(r, i, j)` into `tri`, and so this needs to be avoided. So, we check if `is_on(flag) && contains_segment(tri, i, j)` and, if the edge that `r` is on is `(i, j)`, we add the triangle `(r, i, j)`. Otherwise, we do nothing. """ -function dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_history=Val(false), event_history=nothing, peek::F=Val(false), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {F} +function dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_history = Val(false), event_history = nothing, peek::F = Val(false), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {F} if !edge_exists(ℓ) # The triangle has already been deleted in this case. return tri @@ -320,7 +320,7 @@ function dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_hist if !contains_segment(tri, i, j) && !is_ghost_vertex(ℓ) && is_inside(point_position_relative_to_circumcircle(predicates, tri, r, i, j, ℓ)) ℓ₁ = get_adjacent(tri, ℓ, i) ℓ₂ = get_adjacent(tri, j, ℓ) - !is_true(peek) && delete_triangle!(tri, j, i, ℓ; protect_boundary=true, update_ghost_edges=false) + !is_true(peek) && delete_triangle!(tri, j, i, ℓ; protect_boundary = true, update_ghost_edges = false) dig_cavity!(tri, r, i, ℓ, ℓ₁, flag, V, store_event_history, event_history, peek, predicates) dig_cavity!(tri, r, ℓ, j, ℓ₂, flag, V, store_event_history, event_history, peek, predicates) if is_true(store_event_history) @@ -340,14 +340,14 @@ function dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_hist if u == i && v == j return tri else - !is_true(peek) && add_triangle!(tri, r, i, j; update_ghost_edges=false) + !is_true(peek) && add_triangle!(tri, r, i, j; update_ghost_edges = false) if is_true(store_event_history) trit = triangle_type(tri) add_triangle!(event_history, construct_triangle(trit, _r, i, j)) end end else - !is_true(peek) && add_triangle!(tri, r, i, j; update_ghost_edges=false) + !is_true(peek) && add_triangle!(tri, r, i, j; update_ghost_edges = false) if is_true(store_event_history) trit = triangle_type(tri) add_triangle!(event_history, construct_triangle(trit, _r, i, j)) @@ -357,7 +357,7 @@ function dig_cavity!(tri::Triangulation, r, i, j, ℓ, flag, V, store_event_hist return tri end -function add_point_bowyer_watson_onto_segment!(tri::Triangulation, new_point, V, q, flag, update_representative_point=true, store_event_history=Val(false), event_history=nothing, peek::P=Val(false), predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P} +function add_point_bowyer_watson_onto_segment!(tri::Triangulation, new_point, V, q, flag, update_representative_point = true, store_event_history = Val(false), event_history = nothing, peek::P = Val(false), predicates::AbstractPredicateKernel = AdaptiveKernel()) where {P} _new_point = is_true(peek) ? num_points(tri) + 1 : new_point # If we are peeking, then we need to use the number of points in the triangulation as the index for the new point since we don't actually insert the point if is_on(flag) && is_constrained(tri) # If the point we are adding appears on a segment, then we perform the depth-first search @@ -418,20 +418,22 @@ Computes the unconstrained Delaunay triangulation of the points in `tri`. # Outputs There is no output, but `tri` is updated in-place. """ -function unconstrained_triangulation!(tri::Triangulation; - predicates::AbstractPredicateKernel=AdaptiveKernel(), - randomise=true, - try_last_inserted_point=true, - skip_points=(), - num_sample_rule::M=default_num_samples, - rng::Random.AbstractRNG=Random.default_rng(), - insertion_order=get_insertion_order(tri, randomise, skip_points, rng)) where {M} +function unconstrained_triangulation!( + tri::Triangulation; + predicates::AbstractPredicateKernel = AdaptiveKernel(), + randomise = true, + try_last_inserted_point = true, + skip_points = (), + num_sample_rule::M = default_num_samples, + rng::Random.AbstractRNG = Random.default_rng(), + insertion_order = get_insertion_order(tri, randomise, skip_points, rng), + ) where {M} initialise_bowyer_watson!(tri, insertion_order, predicates) - remaining_points = @view insertion_order[(begin+3):end] + remaining_points = @view insertion_order[(begin + 3):end] for (num_points, new_point) in enumerate(remaining_points) initial_search_point = get_initial_search_point(tri, num_points, new_point, insertion_order, num_sample_rule, rng, try_last_inserted_point) add_point_bowyer_watson!(tri, new_point, initial_search_point, rng, predicates) end - convex_hull!(tri; predicates, reconstruct=false) + convex_hull!(tri; predicates, reconstruct = false) return tri end diff --git a/src/algorithms/voronoi/centroidal.jl b/src/algorithms/voronoi/centroidal.jl index 035241063..4cfab5f81 100644 --- a/src/algorithms/voronoi/centroidal.jl +++ b/src/algorithms/voronoi/centroidal.jl @@ -36,7 +36,7 @@ of the bounding box of the underlying point set. function default_displacement_tolerance(vorn::VoronoiTessellation) xmin, xmax, ymin, ymax = polygon_bounds(vorn) max_extent = max(xmax - xmin, ymax - ymin) - return oftype(max_extent, max_extent / 1e4) + return oftype(max_extent, max_extent / 1.0e4) end """ @@ -58,7 +58,7 @@ Performs a single iteration of the centroidal smoothing algorithm. - `vorn`: The updated [`VoronoiTessellation`](@ref). - `max_dist`: The maximum distance moved by any generator. """ -function _centroidal_smooth_itr(vorn::VoronoiTessellation, set_of_boundary_nodes, points, rng, predicates::AbstractPredicateKernel=AdaptiveKernel(); kwargs...) +function _centroidal_smooth_itr(vorn::VoronoiTessellation, set_of_boundary_nodes, points, rng, predicates::AbstractPredicateKernel = AdaptiveKernel(); kwargs...) F = number_type(vorn) max_dist = zero(F) for i in each_generator(vorn) @@ -68,7 +68,7 @@ function _centroidal_smooth_itr(vorn::VoronoiTessellation, set_of_boundary_nodes end end _tri = retriangulate(get_triangulation(vorn), points; rng, predicates, kwargs...) - vorn = voronoi(_tri, clip=true; rng, predicates) + vorn = voronoi(_tri, clip = true; rng, predicates) return vorn, max_dist end @@ -94,7 +94,7 @@ Smooths `vorn` into a centroidal tessellation so that the new tessellation is of The algorithm is simple. We iteratively smooth the generators, moving them to the centroid of their associated Voronoi polygon for the current tessellation, continuing until the maximum distance moved of any generator is less than `tol`. Boundary generators are not moved. """ -function centroidal_smooth(vorn::VoronoiTessellation; maxiters=1000, tol=default_displacement_tolerance(vorn), rng=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel(), kwargs...) +function centroidal_smooth(vorn::VoronoiTessellation; maxiters = 1000, tol = default_displacement_tolerance(vorn), rng = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel(), kwargs...) iter = 0 F = number_type(vorn) max_dist = typemax(F) @@ -112,4 +112,4 @@ function centroidal_smooth(vorn::VoronoiTessellation; maxiters=1000, tol=default !has_bnds && unlock_convex_hull!(tri) !has_ghost && delete_ghost_triangles!(tri) return vorn -end \ No newline at end of file +end diff --git a/src/algorithms/voronoi/clipped.jl b/src/algorithms/voronoi/clipped.jl index 9f71cc08a..a83f5b107 100644 --- a/src/algorithms/voronoi/clipped.jl +++ b/src/algorithms/voronoi/clipped.jl @@ -126,7 +126,7 @@ Add the edge `uv` to the list of intersected edges. # Outputs There are no outputs, as `intersected_edge_cache` is modified in-place. """ -function add_to_intersected_edge_cache!(intersected_edge_cache::AbstractVector{V}, u, v, a, b) where {E,V<:Pair{E,E}} +function add_to_intersected_edge_cache!(intersected_edge_cache::AbstractVector{V}, u, v, a, b) where {E, V <: Pair{E, E}} uv = construct_edge(E, u, v) ab = construct_edge(E, a, b) push!(intersected_edge_cache, uv => ab) @@ -166,16 +166,17 @@ Process the intersection of the Voronoi polygon of the site `u` with the ray ema In addition to the point `p`, [`add_segment_intersection!`](@ref) is also updated to incorporate the new intersection point, as is [`add_to_intersected_edge_cache!`](@ref). """ function process_ray_intersection!( - vorn::VoronoiTessellation, - u, - v, - incident_polygon, - intersected_edge_cache, - segment_intersections, - boundary_sites, - exterior_circumcenters, - equal_circumcenter_mapping, - predicates::AbstractPredicateKernel=AdaptiveKernel()) + vorn::VoronoiTessellation, + u, + v, + incident_polygon, + intersected_edge_cache, + segment_intersections, + boundary_sites, + exterior_circumcenters, + equal_circumcenter_mapping, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) u_tri = get_circumcenter_to_triangle(vorn, u) a = geti(u_tri) b = getj(u_tri) @@ -227,17 +228,18 @@ Process the intersection of the Voronoi polygon's edge `(u, v)` with the edge `e In addition to the point `p`, [`add_segment_intersection!`](@ref) is also updated to incorporate the new intersection point, as is [`add_to_intersected_edge_cache!`](@ref). """ function process_segment_intersection!( - vorn::VoronoiTessellation, - u, - v, - e, - incident_polygon, - intersected_edge_cache, - segment_intersections, - boundary_sites, - exterior_circumcenters, - equal_circumcenter_mapping, - predicates::AbstractPredicateKernel=AdaptiveKernel()) + vorn::VoronoiTessellation, + u, + v, + e, + incident_polygon, + intersected_edge_cache, + segment_intersections, + boundary_sites, + exterior_circumcenters, + equal_circumcenter_mapping, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) e = convert_to_edge_adjoining_ghost_vertex(vorn, e) a, b = edge_vertices(e) p, q = get_generator(vorn, a, b) @@ -290,20 +292,20 @@ function initialise_clipping_arrays(vorn::VoronoiTessellation) foreach(boundary_edges) do e push!(edges_to_process, e) end - polygon_edge_queue = Queue{Tuple{E,I}}() - boundary_sites = Dict{I,Set{I}}() + polygon_edge_queue = Queue{Tuple{E, I}}() + boundary_sites = Dict{I, Set{I}}() F = number_type(vorn) - segment_intersections = NTuple{2,F}[] - processed_pairs = Set{Tuple{E,I}}() - intersected_edge_cache = Pair{E,E}[] + segment_intersections = NTuple{2, F}[] + processed_pairs = Set{Tuple{E, I}}() + intersected_edge_cache = Pair{E, E}[] sizehint!(intersected_edge_cache, 2^3) exterior_circumcenters = Set{I}() left_edge_intersectors = Set{E}() right_edge_intersectors = Set{E}() current_edge_intersectors = Set{E}() - equal_circumcenter_mapping = Dict{I,I}() + equal_circumcenter_mapping = Dict{I, I}() return edges_to_process, polygon_edge_queue, boundary_sites, segment_intersections, processed_pairs, intersected_edge_cache, exterior_circumcenters, - left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, equal_circumcenter_mapping + left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, equal_circumcenter_mapping end """ @@ -321,11 +323,11 @@ Enqueue the edge `e` of the boundary to be processed. # Outputs There are no outputs, as `polygon_edge_queue` is modified in-place. """ -function enqueue_new_edge!(polygon_edge_queue, vorn::VoronoiTessellation, e, rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function enqueue_new_edge!(polygon_edge_queue, vorn::VoronoiTessellation, e, rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) u, v = edge_vertices(e) p, q = get_generator(vorn, u, v) m = midpoint(p, q) - incident_polygon = get_nearest_neighbour(vorn, m; rng, predicates,k=u) + incident_polygon = get_nearest_neighbour(vorn, m; rng, predicates, k = u) push!(polygon_edge_queue, (e, incident_polygon)) return polygon_edge_queue end @@ -393,19 +395,21 @@ Process the intersection of the ray from the ghost site `u` to the site `v` with # Outputs There are no outputs, but [`add_segment_intersection!`](@ref) and [`add_to_intersected_edge_cache!`](@ref) are used to update the intersection objects. """ -function process_ray_intersection_with_other_edges!(vorn::VoronoiTessellation, - u, - v, - e, - left_edge, - right_edge, - r, - segment_intersections, - boundary_sites, - incident_polygon, - equal_circumcenter_mapping, - intersected_edge_cache, - predicates::AbstractPredicateKernel=AdaptiveKernel()) +function process_ray_intersection_with_other_edges!( + vorn::VoronoiTessellation, + u, + v, + e, + left_edge, + right_edge, + r, + segment_intersections, + boundary_sites, + incident_polygon, + equal_circumcenter_mapping, + intersected_edge_cache, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) if !any(isnan, r) E = edge_type(vorn) u_tri = get_circumcenter_to_triangle(vorn, u) @@ -464,7 +468,7 @@ This function works as follows: the intersection. We apply this function with each of `e`, `left_edge`, and `right_edge` to check for all intersections. 3. The function is done once each of the polygon edges has been considered. """ -function process_polygon!(vorn, e, incident_polygon, boundary_sites, segment_intersections, intersected_edge_cache, exterior_circumcenters, equal_circumcenter_mapping, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function process_polygon!(vorn, e, incident_polygon, boundary_sites, segment_intersections, intersected_edge_cache, exterior_circumcenters, equal_circumcenter_mapping, predicates::AbstractPredicateKernel = AdaptiveKernel()) left_edge, right_edge = get_neighbouring_boundary_edges(vorn, e) polygon_vertices = get_polygon(vorn, incident_polygon) nedges = num_boundary_edges(polygon_vertices) @@ -568,12 +572,16 @@ This function works as follows: we need to get the polygon adjacent to that edge. Then, if `(current_edge, adjacent_incident_polygon)` or `(reverse_edge(current_edge), adjacent_incident_polygon)` have not been processed, we enqueue `(current_edge, adjacent_incident_polygon)`. 5. Once the edges have all been processed as above, we return. """ -function process_intersection_points!(polygon_edge_queue, vorn, current_incident_polygon, - left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, - left_edge, right_edge, current_edge, processed_pairs, segment_intersections, boundary_sites) - all_indices = (initial(left_edge), terminal(left_edge), +function process_intersection_points!( + polygon_edge_queue, vorn, current_incident_polygon, + left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, + left_edge, right_edge, current_edge, processed_pairs, segment_intersections, boundary_sites, + ) + all_indices = ( + initial(left_edge), terminal(left_edge), initial(right_edge), terminal(right_edge), - initial(current_edge), terminal(current_edge)) + initial(current_edge), terminal(current_edge), + ) if num_polygon_vertices(vorn) > 1 # A single triangle is a special case that we add the corners into manually for (e, intersectors) in zip((left_edge, right_edge), (left_edge_intersectors, right_edge_intersectors)) if (length(intersectors) > 0 && length(current_edge_intersectors) > 0) && ((e, current_incident_polygon) ∉ processed_pairs && (reverse_edge(e), current_incident_polygon) ∉ processed_pairs) @@ -643,10 +651,12 @@ This function works as follows: 5. Then, [`process_intersection_points!`](@ref) is used to process the intersection points, enqueueing new edges when needed. 6. We then delete the edge from `edges_to_process` if it is in there and return. """ -function dequeue_and_process!(vorn, polygon_edge_queue, edges_to_process, - intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, - processed_pairs, boundary_sites, segment_intersections, exterior_circumcenters, equal_circumcenter_mapping, - rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function dequeue_and_process!( + vorn, polygon_edge_queue, edges_to_process, + intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, + processed_pairs, boundary_sites, segment_intersections, exterior_circumcenters, equal_circumcenter_mapping, + rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) if isempty(polygon_edge_queue) e = convert_to_edge_adjoining_ghost_vertex(vorn, first(edges_to_process)) enqueue_new_edge!(polygon_edge_queue, vorn, e, rng, predicates) @@ -661,9 +671,11 @@ function dequeue_and_process!(vorn, polygon_edge_queue, edges_to_process, end left_edge, right_edge, e = process_polygon!(vorn, e, incident_polygon, boundary_sites, segment_intersections, intersected_edge_cache, exterior_circumcenters, equal_circumcenter_mapping, predicates) classify_intersections!(intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, left_edge, right_edge, e) - process_intersection_points!(polygon_edge_queue, vorn, incident_polygon, + process_intersection_points!( + polygon_edge_queue, vorn, incident_polygon, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, - left_edge, right_edge, e, processed_pairs, segment_intersections, boundary_sites) + left_edge, right_edge, e, processed_pairs, segment_intersections, boundary_sites, + ) if contains_edge(e, edges_to_process) delete!(edges_to_process, e) elseif contains_edge(reverse_edge(e), edges_to_process) @@ -699,25 +711,27 @@ This algorithm works as follows: 4. In the special case that there is just a single triangle in the underlying triangulation, we process the intersections using [`add_segment_intersection!`](@ref) directly. 5. We then return. """ -function find_all_intersections(vorn::VoronoiTessellation; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function find_all_intersections(vorn::VoronoiTessellation; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) edges_to_process, - polygon_edge_queue, - boundary_sites, - segment_intersections, - processed_pairs, - intersected_edge_cache, - exterior_circumcenters, - left_edge_intersectors, - right_edge_intersectors, - current_edge_intersectors, - equal_circumcenter_mapping = initialise_clipping_arrays(vorn) + polygon_edge_queue, + boundary_sites, + segment_intersections, + processed_pairs, + intersected_edge_cache, + exterior_circumcenters, + left_edge_intersectors, + right_edge_intersectors, + current_edge_intersectors, + equal_circumcenter_mapping = initialise_clipping_arrays(vorn) e = convert_to_edge_adjoining_ghost_vertex(vorn, first(edges_to_process)) enqueue_new_edge!(polygon_edge_queue, vorn, e, rng, predicates) while !isempty(edges_to_process) || !isempty(polygon_edge_queue) - dequeue_and_process!(vorn, polygon_edge_queue, edges_to_process, + dequeue_and_process!( + vorn, polygon_edge_queue, edges_to_process, intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, processed_pairs, boundary_sites, segment_intersections, exterior_circumcenters, equal_circumcenter_mapping, - rng, predicates) + rng, predicates, + ) end if num_polygon_vertices(vorn) == 1 # 1 triangle for i in each_generator(vorn) @@ -842,10 +856,10 @@ Clip the Voronoi tessellation `vorn` to the convex hull of the generators in `vo # Outputs There are no outputs, but the Voronoi tessellation is clipped in-place. """ -function clip_voronoi_tessellation!(vorn::VoronoiTessellation, is_convex=true; rng::Random.AbstractRNG=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function clip_voronoi_tessellation!(vorn::VoronoiTessellation, is_convex = true; rng::Random.AbstractRNG = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel()) boundary_sites, segment_intersections, exterior_circumcenters, equal_circumcenter_mapping = find_all_intersections(vorn; rng, predicates) n = add_intersection_points!(vorn, segment_intersections) clip_all_polygons!(vorn, n, boundary_sites, exterior_circumcenters, equal_circumcenter_mapping, is_convex) add_all_boundary_polygons!(vorn, boundary_sites) return vorn -end \ No newline at end of file +end diff --git a/src/algorithms/voronoi/clipped_coordinates.jl b/src/algorithms/voronoi/clipped_coordinates.jl index f8f3dc20f..7fba96ebc 100644 --- a/src/algorithms/voronoi/clipped_coordinates.jl +++ b/src/algorithms/voronoi/clipped_coordinates.jl @@ -54,7 +54,7 @@ See also [`get_unbounded_polygon_coordinates`](@ref) and [`get_bounded_polygon_c # Outputs - `coords`: The coordinates of the polygon. This is a circular vector. """ -function get_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box=nothing; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function get_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box = nothing; predicates::AbstractPredicateKernel = AdaptiveKernel()) if !isnothing(bounding_box) a, b, c, d = bounding_box @assert a < b && c < d "The bounding box must be of the form (xmin, xmax, ymin, ymax) with xmin < xmax and ymin < ymax." @@ -110,7 +110,7 @@ See also [`clip_polygon`](@ref). # Outputs - `coords`: The coordinates of the clipped polygon. This is a circular vector. """ -function clip_bounded_polygon_to_bounding_box(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function clip_bounded_polygon_to_bounding_box(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel = AdaptiveKernel()) poly, clip_poly = get_clipping_poly_structs(vorn, i, bounding_box) return clip_polygon(poly, clip_poly; predicates) end @@ -131,7 +131,7 @@ here means that `get_polygon(vorn, i)[ghost_vertex]` is a ghost vertex. - `p`: The first point of the ray. - `q`: A second point of the ray, so that `pq` gives the direction of the ray (which extends to infinity). """ -function _get_ray(vorn::VoronoiTessellation, i, ghost_vertex, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function _get_ray(vorn::VoronoiTessellation, i, ghost_vertex, predicates::AbstractPredicateKernel = AdaptiveKernel()) C = get_polygon(vorn, i) ghost_tri = get_circumcenter_to_triangle(vorn, C[ghost_vertex]) u, v, _ = triangle_vertices(ghost_tri) # w is the ghost vertex @@ -216,7 +216,7 @@ Truncates the unbounded edges of the `i`th polygon of `vorn` so that the line co - `new_vertices`: The new vertices of the polygon. This is not a circular vector. - `new_points`: The new points of the polygon. This is not a circular vector. """ -function grow_polygon_outside_of_box(vorn::VoronoiTessellation, i, bounding_box, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function grow_polygon_outside_of_box(vorn::VoronoiTessellation, i, bounding_box, predicates::AbstractPredicateKernel = AdaptiveKernel()) a, b, c, d = bounding_box vertices = get_polygon(vorn, i) new_vertices, new_points, ghost_vertices = get_new_polygon_indices(vorn, vertices) @@ -272,11 +272,11 @@ Returns the new vertices and points of the polygon, as well as the indices of th - `ghost_vertices`: The indices of the ghost vertices in `new_vertices`. """ function get_new_polygon_indices(vorn, vertices) - new_points = NTuple{2,Float64}[] + new_points = NTuple{2, Float64}[] sizehint!(new_points, length(vertices)) new_vertices = similar(vertices, length(vertices) - 1) ghost_vertices = (0, 0) - for i in firstindex(vertices):(lastindex(vertices)-1) + for i in firstindex(vertices):(lastindex(vertices) - 1) v = vertices[i] if is_ghost_vertex(v) is_first = is_first_ghost_vertex(vertices, i) @@ -303,11 +303,11 @@ Returns the coordinates of the `i`th polygon of `vorn`, clipped to `bounding_box Use the keyword arguments `predicates` to determine how predicates are computed. Should be one of [`ExactKernel`](@ref), [`AdaptiveKernel`](@ref), and [`FastKernel`](@ref). See the documentation for more information about these choices. """ -function get_bounded_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function get_bounded_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel = AdaptiveKernel()) if isnothing(bounding_box) C = get_polygon(vorn, i) F = number_type(vorn) - coords = Vector{NTuple{2,F}}(undef, length(C)) + coords = Vector{NTuple{2, F}}(undef, length(C)) for j in eachindex(C) coords[j] = get_polygon_point(vorn, C[j]) end @@ -325,7 +325,7 @@ Returns the coordinates of the `i`th polygon of `vorn`, clipped to `bounding_box Use the keyword arguments `predicates` to determine how predicates are computed. Should be one of [`ExactKernel`](@ref), [`AdaptiveKernel`](@ref), and [`FastKernel`](@ref). See the documentation for more information about these choices. """ -function get_unbounded_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function get_unbounded_polygon_coordinates(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel = AdaptiveKernel()) return clip_unbounded_polygon_to_bounding_box(vorn, i, bounding_box; predicates) end @@ -337,10 +337,10 @@ Clips the `i`th polygon of `vorn` to `bounding_box`. The polygon is assumed to b Use the keyword arguments `predicates` to determine how predicates are computed. Should be one of [`ExactKernel`](@ref), [`AdaptiveKernel`](@ref), and [`FastKernel`](@ref). See the documentation for more information about these choices. """ -function clip_unbounded_polygon_to_bounding_box(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel=AdaptiveKernel()) +function clip_unbounded_polygon_to_bounding_box(vorn::VoronoiTessellation, i, bounding_box; predicates::AbstractPredicateKernel = AdaptiveKernel()) new_vertices, new_points = grow_polygon_outside_of_box(vorn, i, bounding_box, predicates) clip_vertices = (1, 2, 3, 4) a, b, c, d = bounding_box clip_points = ((a, c), (b, c), (b, d), (a, d)) return clip_polygon(new_vertices, new_points, clip_vertices, clip_points; predicates) -end \ No newline at end of file +end diff --git a/src/algorithms/voronoi/main.jl b/src/algorithms/voronoi/main.jl index db287821c..1f56eedaa 100644 --- a/src/algorithms/voronoi/main.jl +++ b/src/algorithms/voronoi/main.jl @@ -15,7 +15,7 @@ Computes the Voronoi tessellation dual to a triangulation. # Output - `vorn`: The [`VoronoiTessellation`](@ref). """ -function voronoi(tri::Triangulation; clip=false, smooth=false, rng=Random.default_rng(), predicates::AbstractPredicateKernel=AdaptiveKernel(), kwargs...) +function voronoi(tri::Triangulation; clip = false, smooth = false, rng = Random.default_rng(), predicates::AbstractPredicateKernel = AdaptiveKernel(), kwargs...) if smooth @assert clip "Smoothing requires clipping." end diff --git a/src/algorithms/voronoi/unbounded.jl b/src/algorithms/voronoi/unbounded.jl index 137d2f20c..187091b9f 100644 --- a/src/algorithms/voronoi/unbounded.jl +++ b/src/algorithms/voronoi/unbounded.jl @@ -9,20 +9,20 @@ Initialise a `VoronoiTessellation` from the triangulation `tri`. # Output - `vorn`: The [`VoronoiTessellation`](@ref). This tessellation is not yet filled in, as all the polygons and other fields need to be properly defined. This simply defines all the initial objects that will be pushed into. """ -function initialise_voronoi_tessellation(tri::Tr) where {Tr<:Triangulation} +function initialise_voronoi_tessellation(tri::Tr) where {Tr <: Triangulation} I = integer_type(tri) T = triangle_type(tri) F = number_type(tri) - P = NTuple{2,F} + P = NTuple{2, F} polygon_points = Vector{P}() - circumcenter_to_triangle = Dict{I,T}() - triangle_to_circumcenter = Dict{T,I}() + circumcenter_to_triangle = Dict{I, T}() + triangle_to_circumcenter = Dict{T, I}() sizehint!(polygon_points, num_triangles(tri)) sizehint!(circumcenter_to_triangle, num_triangles(tri)) sizehint!(triangle_to_circumcenter, num_triangles(tri)) cur_ghost_idx = I(0) - cocircular_dict = Dict{P,I}() - encountered_circumcenters = Dict{P,I}() + cocircular_dict = Dict{P, I}() + encountered_circumcenters = Dict{P, I}() cocircular_circumcenters = Set{I}() for V in each_triangle(tri) V = sort_triangle(V) @@ -50,24 +50,24 @@ function initialise_voronoi_tessellation(tri::Tr) where {Tr<:Triangulation} cocircular_dict[(cx, cy)] = num_points(polygon_points) end else - circumcenter_to_triangle[I(𝒢)-cur_ghost_idx] = V + circumcenter_to_triangle[I(𝒢) - cur_ghost_idx] = V triangle_to_circumcenter[V] = I(𝒢) - cur_ghost_idx cur_ghost_idx += I(1) end end - polygons = Dict{I,Vector{I}}() + polygons = Dict{I, Vector{I}}() sizehint!(polygons, num_solid_vertices(tri)) unbounded_polygons = Set{I}() sizehint!(unbounded_polygons, num_ghost_edges(tri)) - generators = Dict{I,P}() + generators = Dict{I, P}() sizehint!(generators, num_solid_vertices(tri)) for i in each_solid_vertex(tri) generators[i] = get_point(tri, i) end E = edge_type(tri) - adj = Adjacent{I,E}() + adj = Adjacent{I, E}() boundary_polygons = Set{I}() - return VoronoiTessellation{Tr,P,I,T,typeof(cocircular_circumcenters),E}(tri, generators, polygon_points, polygons, circumcenter_to_triangle, triangle_to_circumcenter, unbounded_polygons, cocircular_circumcenters, adj, boundary_polygons) + return VoronoiTessellation{Tr, P, I, T, typeof(cocircular_circumcenters), E}(tri, generators, polygon_points, polygons, circumcenter_to_triangle, triangle_to_circumcenter, unbounded_polygons, cocircular_circumcenters, adj, boundary_polygons) end """ @@ -194,11 +194,11 @@ function add_voronoi_polygon!(vorn::VoronoiTessellation, i) k = S[begin] encountered_duplicate_circumcenter = false prev_ci, encountered_duplicate_circumcenter, k = add_edge_to_voronoi_polygon!(B, vorn, i, k, S, m, encountered_duplicate_circumcenter) - for m in (firstindex(S)+2):lastindex(S) + for m in (firstindex(S) + 2):lastindex(S) ci, encountered_duplicate_circumcenter, k = add_edge_to_voronoi_polygon!(B, vorn, i, k, S, m, encountered_duplicate_circumcenter) add_adjacent!(vorn, prev_ci, ci, i) prev_ci = ci end close_voronoi_polygon!(vorn, B, i, encountered_duplicate_circumcenter, prev_ci) return B -end \ No newline at end of file +end diff --git a/src/data_structures.jl b/src/data_structures.jl index 76b1bd127..c1fb869e9 100644 --- a/src/data_structures.jl +++ b/src/data_structures.jl @@ -40,4 +40,4 @@ include("data_structures/mesh_refinement/refinement_queue.jl") include("data_structures/mesh_refinement/refinement_arguments.jl") include("data_structures/voronoi.jl") include("data_structures/polygon.jl") -include("data_structures/shuffled_polygon_linked_list.jl") \ No newline at end of file +include("data_structures/shuffled_polygon_linked_list.jl") diff --git a/src/data_structures/convex_hull.jl b/src/data_structures/convex_hull.jl index 26ac82691..2f7692529 100644 --- a/src/data_structures/convex_hull.jl +++ b/src/data_structures/convex_hull.jl @@ -11,7 +11,7 @@ Struct for representing a convex hull. See also [`convex_hull`](@ref). ConvexHull(points, vertices) convex_hull(points; IntegerType=Int) """ -struct ConvexHull{P,I} +struct ConvexHull{P, I} points::P vertices::Vector{I} end @@ -51,4 +51,4 @@ function Base.empty!(ch::ConvexHull) vertices = get_vertices(ch) empty!(vertices) return ch -end \ No newline at end of file +end diff --git a/src/data_structures/mesh_refinement/boundary_enricher.jl b/src/data_structures/mesh_refinement/boundary_enricher.jl index 3c03f4c45..33dc5f0fd 100644 --- a/src/data_structures/mesh_refinement/boundary_enricher.jl +++ b/src/data_structures/mesh_refinement/boundary_enricher.jl @@ -105,8 +105,8 @@ get_members(complex::SmallAngleComplex) = complex.members Returns a map from an apex vertex to a list of all curves that define a small angle complex associated with that apex vertex. """ -function get_small_angle_complexes(points, boundary_nodes, boundary_curves, segments=nothing; IntegerType=Int) - d = Dict{IntegerType,Vector{SmallAngleComplex{IntegerType}}}() +function get_small_angle_complexes(points, boundary_nodes, boundary_curves, segments = nothing; IntegerType = Int) + d = Dict{IntegerType, Vector{SmallAngleComplex{IntegerType}}}() if has_multiple_curves(boundary_nodes) _get_small_angle_complexes_multiple_curves!(d, boundary_nodes, boundary_curves, IntegerType) elseif has_multiple_sections(boundary_nodes) @@ -208,7 +208,7 @@ Segments are stored twice. The vertices associated with a vertex are sorted coun to define the coordinates. """ function construct_segment_map(segments, points, ::Type{I}) where {I} - segment_map = Dict{I,Vector{I}}() + segment_map = Dict{I, Vector{I}}() for e in each_edge(segments) i, j = edge_vertices(e) iset = get!(Vector{I}, segment_map, i) @@ -224,12 +224,14 @@ function construct_segment_map(segments, points, ::Type{I}) where {I} px, py = getxy(p) qx, qy = getxy(q) base = (qx - px, qy - py) - sort!(vertices, by=_vertex -> begin + sort!( + vertices, by = _vertex -> begin _q = get_point(points, _vertex) _qx, _qy = getxy(_q) next_base = (_qx - px, _qy - py) return angle_between(base, next_base) - end, rev=false) + end, rev = false, + ) end return segment_map end @@ -248,12 +250,14 @@ function sort_members!(complex::SmallAngleComplex, points) px, py = getxy(p) qx, qy = getxy(q) base = (qx - px, qy - py) - sort!(members, by=member -> begin + sort!( + members, by = member -> begin _q = get_point(points, get_next_edge(member)) _qx, _qy = getxy(_q) next_base = (_qx - px, _qy - py) return angle_between(base, next_base) - end, rev=false) + end, rev = false, + ) return complex end @@ -363,34 +367,34 @@ field will no longer aliased with the input `boundary_nodes`, although `points` The argument `n` is used in [`polygonise`](@ref) for filling out the boundary temporarily in order to construct the [`PolygonHierarchy`](@ref). The argument `coarse_n` defines the initial coarse discretisation through [`coarse_discretisation!`](@ref); the default `n=0` means that the coarse discretisation will be performed until the maximum total variation of a subcurve is less than π/2. """ -struct BoundaryEnricher{P,B,C,I,BM,S} +struct BoundaryEnricher{P, B, C, I, BM, S} points::P boundary_nodes::B segments::S boundary_curves::C polygon_hierarchy::PolygonHierarchy{I} - parent_map::Dict{NTuple{2,I},I} - curve_index_map::Dict{I,I} + parent_map::Dict{NTuple{2, I}, I} + curve_index_map::Dict{I, I} boundary_edge_map::BM spatial_tree::BoundaryRTree{P} queue::Queue{I} - small_angle_complexes::Dict{I,Vector{SmallAngleComplex{I}}} + small_angle_complexes::Dict{I, Vector{SmallAngleComplex{I}}} end -function BoundaryEnricher(points::P, boundary_nodes::B, segments=nothing; IntegerType=Int, n=4096, coarse_n=0) where {P,B} +function BoundaryEnricher(points::P, boundary_nodes::B, segments = nothing; IntegerType = Int, n = 4096, coarse_n = 0) where {P, B} boundary_curves, new_boundary_nodes = convert_boundary_curves!(points, boundary_nodes, IntegerType) polygon_hierarchy = construct_polygon_hierarchy(points, new_boundary_nodes, boundary_curves; IntegerType, n) - return _construct_boundary_enricher(points, new_boundary_nodes, boundary_curves, polygon_hierarchy, segments, n, coarse_n, IntegerType) + return _construct_boundary_enricher(points, new_boundary_nodes, boundary_curves, polygon_hierarchy, segments, n, coarse_n, IntegerType) end function _construct_boundary_enricher(points, boundary_nodes, boundary_curves, polygon_hierarchy, segments, n, coarse_n, ::Type{I}) where {I} expand_bounds!(polygon_hierarchy, ε(number_type(points))) - coarse_discretisation!(points, boundary_nodes, boundary_curves; n=coarse_n) + coarse_discretisation!(points, boundary_nodes, boundary_curves; n = coarse_n) boundary_edge_map = construct_boundary_edge_map(boundary_nodes, I) - parent_map = Dict{NTuple{2,I},I}() - curve_index_map = Dict{I,I}() + parent_map = Dict{NTuple{2, I}, I}() + curve_index_map = Dict{I, I}() spatial_tree = BoundaryRTree(points) queue = Queue{I}() - small_angle_complexes = get_small_angle_complexes(points, boundary_nodes, boundary_curves, segments; IntegerType=I) - _segments = isnothing(segments) ? Set{NTuple{2,I}}() : segments + small_angle_complexes = get_small_angle_complexes(points, boundary_nodes, boundary_curves, segments; IntegerType = I) + _segments = isnothing(segments) ? Set{NTuple{2, I}}() : segments enricher = BoundaryEnricher(points, boundary_nodes, _segments, boundary_curves, polygon_hierarchy, parent_map, curve_index_map, boundary_edge_map, spatial_tree, queue, small_angle_complexes) construct_parent_map!(enricher) construct_curve_index_map!(enricher) @@ -570,7 +574,7 @@ end Returns the parent of the edge `(i, j)` in `boundary_enricher`. If the edge is not in the parent map, then `$∅` is returned. """ -get_parent(boundary_enricher::BoundaryEnricher{P,B,C,I}, i, j) where {P,B,C,I} = get(get_parent_map(boundary_enricher), (i, j), I(∅)) +get_parent(boundary_enricher::BoundaryEnricher{P, B, C, I}, i, j) where {P, B, C, I} = get(get_parent_map(boundary_enricher), (i, j), I(∅)) """ set_parent!(boundary_enricher::BoundaryEnricher, i, j, k) @@ -645,7 +649,7 @@ function _construct_parent_map_multiple_curves!(enricher::BoundaryEnricher) end return enricher end -function _construct_parent_map_multiple_sections!(enricher::BoundaryEnricher, boundary_nodes=get_boundary_nodes(enricher), ctr=1) +function _construct_parent_map_multiple_sections!(enricher::BoundaryEnricher, boundary_nodes = get_boundary_nodes(enricher), ctr = 1) ns = num_sections(boundary_nodes) for i in 1:ns section_nodes = get_boundary_nodes(boundary_nodes, i) @@ -654,7 +658,7 @@ function _construct_parent_map_multiple_sections!(enricher::BoundaryEnricher, bo end return enricher end -function _construct_parent_map_contiguous!(enricher::BoundaryEnricher, boundary_nodes=get_boundary_nodes(enricher), ctr=1) +function _construct_parent_map_contiguous!(enricher::BoundaryEnricher, boundary_nodes = get_boundary_nodes(enricher), ctr = 1) n = num_boundary_edges(boundary_nodes) for i in 1:n u = get_boundary_nodes(boundary_nodes, i) @@ -716,7 +720,7 @@ Returns `true` if the `curve_index`th curve in `enricher` is piecewise linear, a boundary_curves = get_boundary_curves(enricher) return is_piecewise_linear(boundary_curves, curve_index) end -@inline function is_piecewise_linear(boundary_curves::C, curve_index) where {C<:Tuple} +@inline function is_piecewise_linear(boundary_curves::C, curve_index) where {C <: Tuple} isempty(boundary_curves) && return true return eval_fnc_at_het_tuple_element(is_piecewise_linear, boundary_curves, curve_index) end @@ -730,7 +734,7 @@ Returns the inverse of the `curve_index`th curve at `q`. boundary_curves = get_boundary_curves(enricher) return get_inverse(boundary_curves, curve_index, q) end -@inline function get_inverse(boundary_curves::C, curve_index, q) where {C<:Tuple} +@inline function get_inverse(boundary_curves::C, curve_index, q) where {C <: Tuple} return eval_fnc_at_het_tuple_element_with_arg(get_inverse, boundary_curves, (q,), curve_index) end @@ -743,7 +747,7 @@ Returns the equivariation split of the `curve_index`th curve between `t₁` and boundary_curves = get_boundary_curves(enricher) return get_equivariation_split(boundary_curves, curve_index, t₁, t₂) end -@inline function get_equivariation_split(boundary_curves::C, curve_index, t₁, t₂) where {C<:Tuple} +@inline function get_equivariation_split(boundary_curves::C, curve_index, t₁, t₂) where {C <: Tuple} return eval_fnc_at_het_tuple_element_with_arg(get_equivariation_split, boundary_curves, (t₁, t₂), curve_index) end @@ -756,7 +760,7 @@ Returns the equidistant split of the `curve_index`th curve between `t₁` and `t boundary_curves = get_boundary_curves(enricher) return get_equidistant_split(boundary_curves, curve_index, t₁, t₂) end -@inline function get_equidistant_split(boundary_curves::C, curve_index, t₁, t₂) where {C<:Tuple} +@inline function get_equidistant_split(boundary_curves::C, curve_index, t₁, t₂) where {C <: Tuple} return eval_fnc_at_het_tuple_element_with_arg(get_equidistant_split, boundary_curves, (t₁, t₂), curve_index) end @@ -770,7 +774,7 @@ Returns the `curve_index`th boundary curve at `t`. boundary_curves = get_boundary_curves(enricher) return eval_boundary_curve(boundary_curves, curve_index, t) end -@inline function eval_boundary_curve(boundary_curves::C, curve_index, t) where {C<:Tuple} +@inline function eval_boundary_curve(boundary_curves::C, curve_index, t) where {C <: Tuple} return eval_fnc_in_het_tuple(boundary_curves, t, curve_index) end @@ -792,10 +796,10 @@ See the documentation for more information about these choices. return point_position_relative_to_curve(kernel, boundary_curves, curve_index, p) end @inline point_position_relative_to_curve(enricher::BoundaryEnricher, curve_index, p) = point_position_relative_to_curve(AdaptiveKernel(), enricher, curve_index, p) -@inline function point_position_relative_to_curve(kernel::AbstractPredicateKernel, boundary_curves::C, curve_index, p) where {C<:Tuple} +@inline function point_position_relative_to_curve(kernel::AbstractPredicateKernel, boundary_curves::C, curve_index, p) where {C <: Tuple} return eval_fnc_at_het_tuple_element_with_arg_and_prearg(point_position_relative_to_curve, boundary_curves, kernel, (p,), curve_index) end -@inline point_position_relative_to_curve(boundary_curves::C, curve_index, p) where {C<:Tuple} = point_position_relative_to_curve(AdaptiveKernel(),boundary_curves,curve_index,p) +@inline point_position_relative_to_curve(boundary_curves::C, curve_index, p) where {C <: Tuple} = point_position_relative_to_curve(AdaptiveKernel(), boundary_curves, curve_index, p) """ angle_between(enricher::BoundaryEnricher, curve_index1, curve_index2) -> Float64 @@ -851,7 +855,7 @@ Fills out a set of points for a curve-bounded domain for use with [`PolygonHiera If the boundary is not curve bounded, then `new_points` and `new_boundary_nodes` remain aliased with the input `points` and `boundary_nodes`. """ -function polygonise(points, boundary_nodes, boundary_curves; n=4096) +function polygonise(points, boundary_nodes, boundary_curves; n = 4096) new_points = deepcopy(points) new_boundary_nodes = deepcopy(boundary_nodes) coarse_discretisation!(new_points, new_boundary_nodes, boundary_curves; n) @@ -902,7 +906,7 @@ Updates the fields of `enricher` after splitting a boundary edge `(i, j)` at the can be used to avoid inserting an additional boundary node when `boundary_nodes` was already updated somewhere else (e.g., we need this for mesh refinement which already updates the `boundary_nodes` which is aliased with the same field in the enricher). """ -function split_boundary_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes=Val(true)) +function split_boundary_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes = Val(true)) boundary_nodes = get_boundary_nodes(enricher) boundary_edge_map = get_boundary_edge_map(enricher) spatial_tree = get_spatial_tree(enricher) @@ -922,7 +926,7 @@ Updates the fields of `enricher` after splitting an interior segment `(i, j)` at The `update_segments` argument can be used to avoid inserting an additional segment when `segments` was already updated somewhere else (e.g., we need this for mesh refinement which already updates the `interior_segments` which is aliased with the `segments` field in the enricher). """ -function split_interior_segment!(enricher::BoundaryEnricher, i, j, r, update_segments=Val(true)) +function split_interior_segment!(enricher::BoundaryEnricher, i, j, r, update_segments = Val(true)) segments = get_segments(enricher) spatial_tree = get_spatial_tree(enricher) E = edge_type(segments) @@ -948,7 +952,7 @@ The `is_interior` argument can be used to specify whether the edge is an interio See also [`split_boundary_edge!`](@ref) and [`split_interior_segment!`](@ref). """ -function split_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes=Val(true), update_segments=Val(true), is_interior=is_segment(enricher, i, j)) +function split_edge!(enricher::BoundaryEnricher, i, j, r, update_boundary_nodes = Val(true), update_segments = Val(true), is_interior = is_segment(enricher, i, j)) if is_interior split_interior_segment!(enricher, i, j, r, update_segments) else @@ -997,4 +1001,4 @@ function replace_next_edge!(enricher::BoundaryEnricher, apex, complex_id, member complex = complexes[complex_id] replace_next_edge!(complex, member_id, next_edge) return enricher -end \ No newline at end of file +end diff --git a/src/data_structures/mesh_refinement/curves.jl b/src/data_structures/mesh_refinement/curves.jl index b906264bc..879bd151c 100644 --- a/src/data_structures/mesh_refinement/curves.jl +++ b/src/data_structures/mesh_refinement/curves.jl @@ -1,255 +1,257 @@ -const GL_NW = permutedims([ - -0.999953919435642 0.00011825670068171721 - -0.9997572122115891 0.00027526103865831744 - -0.9994033532930161 0.00043245460060038196 - -0.9988923197258543 0.0005896003421932499 - -0.998224182256913 0.0007466574055662421 - -0.9973990436722557 0.0009035982480626941 - -0.9964170329848294 0.0010603974326420873 - -0.9952783043339365 0.0012170300415936897 - -0.9939830366739069 0.0013734713364273322 - -0.992531433650476 0.0015296966649272486 - -0.9909237235316215 0.0016856814323170032 - -0.9891601591554368 0.0018414010924821323 - -0.9872410178826077 0.0019968311464057843 - -0.9851666015488034 0.002151947143493035 - -0.9829372364150317 0.002306724684154767 - -0.9805532731150799 0.0024611394229790977 - -0.9780150865996246 0.002615167072191434 - -0.9753230760767991 0.0027687834052614944 - -0.9724776649491127 0.002921964260586262 - -0.9694793007466641 0.00307468554521151 - -0.9663284550566241 0.0032269232385712526 - -0.963025623448975 0.0033786533962332863 - -0.959571325398504 0.0035298521536436056 - -0.9559661042030546 0.0036804957298652166 - -0.9522105268980449 0.003830560431308329 - -0.9483051841672582 0.003980022655449804 - -0.944250690249923 0.0041288588945403645 - -0.94004768284409 0.004277045739298241 - -0.9356968230063247 0.004424559882588365 - -0.931198795047727 0.004571378123086171 - -0.9265543064262952 0.004717477368925247 - -0.9217640876356519 0.0048628346413281485 - -0.9168288920901461 0.005007427078219678 - -0.911749496006352 0.0051512319378220145 - -0.9065266982809823 0.005294226602231066 - -0.901161320365234 0.005436388580973459 - -0.8956542061355872 0.0055776955145435516 - -0.890006221761078 0.0057181251779199384 - -0.8842182555670642 0.00585765548406083 - -0.8782912178955077 0.005996264487377793 - -0.8722260409617927 0.006133930387187249 - -0.866023678708105 0.006270631531139229 - -0.8596851066533939 0.006406346418622805 - -0.85321132173994 0.00654105370414767 - -0.8466033421765535 0.006674732200701343 - -0.8398622072784298 0.006807360883081451 - -0.8329889773036814 0.006938918891202568 - -0.8259847332865807 0.007069385533377089 - -0.818850576867531 0.007198740289569644 - -0.8115876301197994 0.007326962814624488 - -0.804197035373034 0.007454032941465406 - -0.796679955033597 0.007579930684267617 - -0.7890375714017384 0.007704636241601166 - -0.7812710864856423 0.007828129999545307 - -0.7733817218123715 0.007950392534773417 - -0.7653707182357452 0.00807140461760791 - -0.7572393357411735 0.008191147215044737 - -0.7489888532474854 0.008309601493746885 - -0.740620568405778 0.008426748823006541 - -0.732135797395319 0.008542570777675352 - -0.7235358747165359 0.008657049141062358 - -0.7148221529811238 0.008770165907799143 - -0.705996002699303 0.008881903286671764 - -0.6970588120642633 0.008992243703418954 - -0.6880119867338267 0.009101169803496257 - -0.6788569496093618 0.00920866445480557 - -0.6695951406119885 0.00931471075038971 - -0.6602280164561035 0.009419292011091571 - -0.6507570504202663 0.009522391788177445 - -0.641183732115479 0.00962399386592412 - -0.6315095672508971 0.0097240822641693 - -0.6217360773970098 0.009822641240825014 - -0.6118647997463229 0.009919655294353544 - -0.6018972868715882 0.010015109166205537 - -0.5918351064816105 0.010108987843219902 - -0.5816798411746766 0.010201276559985107 - -0.5714330881896406 0.010291960801161504 - -0.5610964591547072 0.010381026303764331 - -0.550671579833952 0.010468459059407015 - -0.5401600898716189 0.010554245316504453 - -0.529563642534233 0.010638371582435857 - -0.5188839044505712 0.010720824625666934 - -0.5081225553495348 0.01080159147783093 - -0.49728128779595404 0.010880659435768353 - -0.48636180692438263 0.01095801606352491 - -0.4753658301709075 0.011033649194307498 - -0.4642950870030309 0.011107546932397785 - -0.4531513186476536 0.011179697655023212 - -0.4419362778172123 0.011250090014185036 - -0.43065172843401034 0.011318712938443162 - -0.4192994453527847 0.011385555634657481 - -0.4078812140815536 0.011450607589685441 - -0.39639883050078745 0.011513858572035563 - -0.38485410058095026 0.011575298633476675 - -0.37324884009845394 0.011634918110602589 - -0.3615848743500686 0.01169270762635197 - -0.34986403786583664 0.011748658091483198 - -0.33808817412053493 0.011802760706003907 - -0.32625913524372974 0.011855006960555099 - -0.3143787817284691 0.011905388637749498 - -0.30244898213866317 0.011953897813463982 - -0.29047161281519085 0.012000526858085933 - -0.27844855758078807 0.012045268437713197 - -0.2663817074437531 0.012088115515307618 - -0.2542729603005287 0.012129061351801793 - -0.24212422063719571 0.012168099507159044 - -0.2299373992299318 0.012205223841386304 - -0.21771441284448234 0.012240428515499802 - -0.20545718393468665 0.012273707992443457 - -0.19316764034011163 0.012305057037959772 - -0.1808477149828374 0.012334470721413042 - -0.16849934556344323 0.012361944416564878 - -0.15612447425624337 0.012387473802301837 - -0.14372504740381872 0.012411054863315053 - -0.1313030152108904 0.01243268389073175 - -0.11886033143758944 0.01245235748269861 - -0.10639895309216538 0.012470072544916794 - -0.09392084012318516 0.01248582629112865 - -0.08142795511126816 0.01249961624355592 - -0.0689222629604074 0.012511440233289444 - -0.05640573058892591 0.012521296400630325 - -0.043880326620117996 0.01252918319538237 - -0.031348021072617915 0.01253509937709596 - -0.01881078505055355 0.012539044015263127 - -0.0062705904335270835 0.012541016489463895 - 0.0062705904335270835 0.012541016489463895 - 0.01881078505055355 0.012539044015263127 - 0.031348021072617915 0.01253509937709596 - 0.043880326620117996 0.01252918319538237 - 0.05640573058892591 0.012521296400630325 - 0.0689222629604074 0.012511440233289444 - 0.08142795511126816 0.01249961624355592 - 0.09392084012318516 0.01248582629112865 - 0.10639895309216538 0.012470072544916794 - 0.11886033143758944 0.01245235748269861 - 0.1313030152108904 0.01243268389073175 - 0.14372504740381872 0.012411054863315053 - 0.15612447425624337 0.012387473802301837 - 0.16849934556344323 0.012361944416564878 - 0.1808477149828374 0.012334470721413042 - 0.19316764034011163 0.012305057037959772 - 0.20545718393468665 0.012273707992443457 - 0.21771441284448234 0.012240428515499802 - 0.2299373992299318 0.012205223841386304 - 0.24212422063719571 0.012168099507159044 - 0.2542729603005287 0.012129061351801793 - 0.2663817074437531 0.012088115515307618 - 0.27844855758078807 0.012045268437713197 - 0.29047161281519085 0.012000526858085933 - 0.30244898213866317 0.011953897813463982 - 0.3143787817284691 0.011905388637749498 - 0.32625913524372974 0.011855006960555099 - 0.33808817412053493 0.011802760706003907 - 0.34986403786583664 0.011748658091483198 - 0.3615848743500686 0.01169270762635197 - 0.37324884009845394 0.011634918110602589 - 0.38485410058095026 0.011575298633476675 - 0.39639883050078745 0.011513858572035563 - 0.4078812140815536 0.011450607589685441 - 0.4192994453527847 0.011385555634657481 - 0.43065172843401034 0.011318712938443162 - 0.4419362778172123 0.011250090014185036 - 0.4531513186476536 0.011179697655023212 - 0.4642950870030309 0.011107546932397785 - 0.4753658301709075 0.011033649194307498 - 0.48636180692438263 0.01095801606352491 - 0.49728128779595404 0.010880659435768353 - 0.5081225553495348 0.01080159147783093 - 0.5188839044505712 0.010720824625666934 - 0.529563642534233 0.010638371582435857 - 0.5401600898716189 0.010554245316504453 - 0.550671579833952 0.010468459059407015 - 0.5610964591547072 0.010381026303764331 - 0.5714330881896406 0.010291960801161504 - 0.5816798411746766 0.010201276559985107 - 0.5918351064816105 0.010108987843219902 - 0.6018972868715882 0.010015109166205537 - 0.6118647997463229 0.009919655294353544 - 0.6217360773970098 0.009822641240825014 - 0.6315095672508971 0.0097240822641693 - 0.641183732115479 0.00962399386592412 - 0.6507570504202663 0.009522391788177445 - 0.6602280164561035 0.009419292011091571 - 0.6695951406119885 0.00931471075038971 - 0.6788569496093618 0.00920866445480557 - 0.6880119867338267 0.009101169803496257 - 0.6970588120642633 0.008992243703418954 - 0.705996002699303 0.008881903286671764 - 0.7148221529811238 0.008770165907799143 - 0.7235358747165359 0.008657049141062358 - 0.732135797395319 0.008542570777675352 - 0.740620568405778 0.008426748823006541 - 0.7489888532474854 0.008309601493746885 - 0.7572393357411735 0.008191147215044737 - 0.7653707182357452 0.00807140461760791 - 0.7733817218123715 0.007950392534773417 - 0.7812710864856423 0.007828129999545307 - 0.7890375714017384 0.007704636241601166 - 0.796679955033597 0.007579930684267617 - 0.804197035373034 0.007454032941465406 - 0.8115876301197994 0.007326962814624488 - 0.818850576867531 0.007198740289569644 - 0.8259847332865807 0.007069385533377089 - 0.8329889773036814 0.006938918891202568 - 0.8398622072784298 0.006807360883081451 - 0.8466033421765535 0.006674732200701343 - 0.85321132173994 0.00654105370414767 - 0.8596851066533939 0.006406346418622805 - 0.866023678708105 0.006270631531139229 - 0.8722260409617927 0.006133930387187249 - 0.8782912178955077 0.005996264487377793 - 0.8842182555670642 0.00585765548406083 - 0.890006221761078 0.0057181251779199384 - 0.8956542061355872 0.0055776955145435516 - 0.901161320365234 0.005436388580973459 - 0.9065266982809823 0.005294226602231066 - 0.911749496006352 0.0051512319378220145 - 0.9168288920901461 0.005007427078219678 - 0.9217640876356519 0.0048628346413281485 - 0.9265543064262952 0.004717477368925247 - 0.931198795047727 0.004571378123086171 - 0.9356968230063247 0.004424559882588365 - 0.94004768284409 0.004277045739298241 - 0.944250690249923 0.0041288588945403645 - 0.9483051841672582 0.003980022655449804 - 0.9522105268980449 0.003830560431308329 - 0.9559661042030546 0.0036804957298652166 - 0.959571325398504 0.0035298521536436056 - 0.963025623448975 0.0033786533962332863 - 0.9663284550566241 0.0032269232385712526 - 0.9694793007466641 0.00307468554521151 - 0.9724776649491127 0.002921964260586262 - 0.9753230760767991 0.0027687834052614944 - 0.9780150865996246 0.002615167072191434 - 0.9805532731150799 0.0024611394229790977 - 0.9829372364150317 0.002306724684154767 - 0.9851666015488034 0.002151947143493035 - 0.9872410178826077 0.0019968311464057843 - 0.9891601591554368 0.0018414010924821323 - 0.9909237235316215 0.0016856814323170032 - 0.992531433650476 0.0015296966649272486 - 0.9939830366739069 0.0013734713364273322 - 0.9952783043339365 0.0012170300415936897 - 0.9964170329848294 0.0010603974326420873 - 0.9973990436722557 0.0009035982480626941 - 0.998224182256913 0.0007466574055662421 - 0.9988923197258543 0.0005896003421932499 - 0.9994033532930161 0.00043245460060038196 - 0.9997572122115891 0.00027526103865831744 - 0.999953919435642 0.00011825670068171721 -]) +const GL_NW = permutedims( + [ + -0.999953919435642 0.00011825670068171721 + -0.9997572122115891 0.00027526103865831744 + -0.9994033532930161 0.00043245460060038196 + -0.9988923197258543 0.0005896003421932499 + -0.998224182256913 0.0007466574055662421 + -0.9973990436722557 0.0009035982480626941 + -0.9964170329848294 0.0010603974326420873 + -0.9952783043339365 0.0012170300415936897 + -0.9939830366739069 0.0013734713364273322 + -0.992531433650476 0.0015296966649272486 + -0.9909237235316215 0.0016856814323170032 + -0.9891601591554368 0.0018414010924821323 + -0.9872410178826077 0.0019968311464057843 + -0.9851666015488034 0.002151947143493035 + -0.9829372364150317 0.002306724684154767 + -0.9805532731150799 0.0024611394229790977 + -0.9780150865996246 0.002615167072191434 + -0.9753230760767991 0.0027687834052614944 + -0.9724776649491127 0.002921964260586262 + -0.9694793007466641 0.00307468554521151 + -0.9663284550566241 0.0032269232385712526 + -0.963025623448975 0.0033786533962332863 + -0.959571325398504 0.0035298521536436056 + -0.9559661042030546 0.0036804957298652166 + -0.9522105268980449 0.003830560431308329 + -0.9483051841672582 0.003980022655449804 + -0.944250690249923 0.0041288588945403645 + -0.94004768284409 0.004277045739298241 + -0.9356968230063247 0.004424559882588365 + -0.931198795047727 0.004571378123086171 + -0.9265543064262952 0.004717477368925247 + -0.9217640876356519 0.0048628346413281485 + -0.9168288920901461 0.005007427078219678 + -0.911749496006352 0.0051512319378220145 + -0.9065266982809823 0.005294226602231066 + -0.901161320365234 0.005436388580973459 + -0.8956542061355872 0.0055776955145435516 + -0.890006221761078 0.0057181251779199384 + -0.8842182555670642 0.00585765548406083 + -0.8782912178955077 0.005996264487377793 + -0.8722260409617927 0.006133930387187249 + -0.866023678708105 0.006270631531139229 + -0.8596851066533939 0.006406346418622805 + -0.85321132173994 0.00654105370414767 + -0.8466033421765535 0.006674732200701343 + -0.8398622072784298 0.006807360883081451 + -0.8329889773036814 0.006938918891202568 + -0.8259847332865807 0.007069385533377089 + -0.818850576867531 0.007198740289569644 + -0.8115876301197994 0.007326962814624488 + -0.804197035373034 0.007454032941465406 + -0.796679955033597 0.007579930684267617 + -0.7890375714017384 0.007704636241601166 + -0.7812710864856423 0.007828129999545307 + -0.7733817218123715 0.007950392534773417 + -0.7653707182357452 0.00807140461760791 + -0.7572393357411735 0.008191147215044737 + -0.7489888532474854 0.008309601493746885 + -0.740620568405778 0.008426748823006541 + -0.732135797395319 0.008542570777675352 + -0.7235358747165359 0.008657049141062358 + -0.7148221529811238 0.008770165907799143 + -0.705996002699303 0.008881903286671764 + -0.6970588120642633 0.008992243703418954 + -0.6880119867338267 0.009101169803496257 + -0.6788569496093618 0.00920866445480557 + -0.6695951406119885 0.00931471075038971 + -0.6602280164561035 0.009419292011091571 + -0.6507570504202663 0.009522391788177445 + -0.641183732115479 0.00962399386592412 + -0.6315095672508971 0.0097240822641693 + -0.6217360773970098 0.009822641240825014 + -0.6118647997463229 0.009919655294353544 + -0.6018972868715882 0.010015109166205537 + -0.5918351064816105 0.010108987843219902 + -0.5816798411746766 0.010201276559985107 + -0.5714330881896406 0.010291960801161504 + -0.5610964591547072 0.010381026303764331 + -0.550671579833952 0.010468459059407015 + -0.5401600898716189 0.010554245316504453 + -0.529563642534233 0.010638371582435857 + -0.5188839044505712 0.010720824625666934 + -0.5081225553495348 0.01080159147783093 + -0.49728128779595404 0.010880659435768353 + -0.48636180692438263 0.01095801606352491 + -0.4753658301709075 0.011033649194307498 + -0.4642950870030309 0.011107546932397785 + -0.4531513186476536 0.011179697655023212 + -0.4419362778172123 0.011250090014185036 + -0.43065172843401034 0.011318712938443162 + -0.4192994453527847 0.011385555634657481 + -0.4078812140815536 0.011450607589685441 + -0.39639883050078745 0.011513858572035563 + -0.38485410058095026 0.011575298633476675 + -0.37324884009845394 0.011634918110602589 + -0.3615848743500686 0.01169270762635197 + -0.34986403786583664 0.011748658091483198 + -0.33808817412053493 0.011802760706003907 + -0.32625913524372974 0.011855006960555099 + -0.3143787817284691 0.011905388637749498 + -0.30244898213866317 0.011953897813463982 + -0.29047161281519085 0.012000526858085933 + -0.27844855758078807 0.012045268437713197 + -0.2663817074437531 0.012088115515307618 + -0.2542729603005287 0.012129061351801793 + -0.24212422063719571 0.012168099507159044 + -0.2299373992299318 0.012205223841386304 + -0.21771441284448234 0.012240428515499802 + -0.20545718393468665 0.012273707992443457 + -0.19316764034011163 0.012305057037959772 + -0.1808477149828374 0.012334470721413042 + -0.16849934556344323 0.012361944416564878 + -0.15612447425624337 0.012387473802301837 + -0.14372504740381872 0.012411054863315053 + -0.1313030152108904 0.01243268389073175 + -0.11886033143758944 0.01245235748269861 + -0.10639895309216538 0.012470072544916794 + -0.09392084012318516 0.01248582629112865 + -0.08142795511126816 0.01249961624355592 + -0.0689222629604074 0.012511440233289444 + -0.05640573058892591 0.012521296400630325 + -0.043880326620117996 0.01252918319538237 + -0.031348021072617915 0.01253509937709596 + -0.01881078505055355 0.012539044015263127 + -0.0062705904335270835 0.012541016489463895 + 0.0062705904335270835 0.012541016489463895 + 0.01881078505055355 0.012539044015263127 + 0.031348021072617915 0.01253509937709596 + 0.043880326620117996 0.01252918319538237 + 0.05640573058892591 0.012521296400630325 + 0.0689222629604074 0.012511440233289444 + 0.08142795511126816 0.01249961624355592 + 0.09392084012318516 0.01248582629112865 + 0.10639895309216538 0.012470072544916794 + 0.11886033143758944 0.01245235748269861 + 0.1313030152108904 0.01243268389073175 + 0.14372504740381872 0.012411054863315053 + 0.15612447425624337 0.012387473802301837 + 0.16849934556344323 0.012361944416564878 + 0.1808477149828374 0.012334470721413042 + 0.19316764034011163 0.012305057037959772 + 0.20545718393468665 0.012273707992443457 + 0.21771441284448234 0.012240428515499802 + 0.2299373992299318 0.012205223841386304 + 0.24212422063719571 0.012168099507159044 + 0.2542729603005287 0.012129061351801793 + 0.2663817074437531 0.012088115515307618 + 0.27844855758078807 0.012045268437713197 + 0.29047161281519085 0.012000526858085933 + 0.30244898213866317 0.011953897813463982 + 0.3143787817284691 0.011905388637749498 + 0.32625913524372974 0.011855006960555099 + 0.33808817412053493 0.011802760706003907 + 0.34986403786583664 0.011748658091483198 + 0.3615848743500686 0.01169270762635197 + 0.37324884009845394 0.011634918110602589 + 0.38485410058095026 0.011575298633476675 + 0.39639883050078745 0.011513858572035563 + 0.4078812140815536 0.011450607589685441 + 0.4192994453527847 0.011385555634657481 + 0.43065172843401034 0.011318712938443162 + 0.4419362778172123 0.011250090014185036 + 0.4531513186476536 0.011179697655023212 + 0.4642950870030309 0.011107546932397785 + 0.4753658301709075 0.011033649194307498 + 0.48636180692438263 0.01095801606352491 + 0.49728128779595404 0.010880659435768353 + 0.5081225553495348 0.01080159147783093 + 0.5188839044505712 0.010720824625666934 + 0.529563642534233 0.010638371582435857 + 0.5401600898716189 0.010554245316504453 + 0.550671579833952 0.010468459059407015 + 0.5610964591547072 0.010381026303764331 + 0.5714330881896406 0.010291960801161504 + 0.5816798411746766 0.010201276559985107 + 0.5918351064816105 0.010108987843219902 + 0.6018972868715882 0.010015109166205537 + 0.6118647997463229 0.009919655294353544 + 0.6217360773970098 0.009822641240825014 + 0.6315095672508971 0.0097240822641693 + 0.641183732115479 0.00962399386592412 + 0.6507570504202663 0.009522391788177445 + 0.6602280164561035 0.009419292011091571 + 0.6695951406119885 0.00931471075038971 + 0.6788569496093618 0.00920866445480557 + 0.6880119867338267 0.009101169803496257 + 0.6970588120642633 0.008992243703418954 + 0.705996002699303 0.008881903286671764 + 0.7148221529811238 0.008770165907799143 + 0.7235358747165359 0.008657049141062358 + 0.732135797395319 0.008542570777675352 + 0.740620568405778 0.008426748823006541 + 0.7489888532474854 0.008309601493746885 + 0.7572393357411735 0.008191147215044737 + 0.7653707182357452 0.00807140461760791 + 0.7733817218123715 0.007950392534773417 + 0.7812710864856423 0.007828129999545307 + 0.7890375714017384 0.007704636241601166 + 0.796679955033597 0.007579930684267617 + 0.804197035373034 0.007454032941465406 + 0.8115876301197994 0.007326962814624488 + 0.818850576867531 0.007198740289569644 + 0.8259847332865807 0.007069385533377089 + 0.8329889773036814 0.006938918891202568 + 0.8398622072784298 0.006807360883081451 + 0.8466033421765535 0.006674732200701343 + 0.85321132173994 0.00654105370414767 + 0.8596851066533939 0.006406346418622805 + 0.866023678708105 0.006270631531139229 + 0.8722260409617927 0.006133930387187249 + 0.8782912178955077 0.005996264487377793 + 0.8842182555670642 0.00585765548406083 + 0.890006221761078 0.0057181251779199384 + 0.8956542061355872 0.0055776955145435516 + 0.901161320365234 0.005436388580973459 + 0.9065266982809823 0.005294226602231066 + 0.911749496006352 0.0051512319378220145 + 0.9168288920901461 0.005007427078219678 + 0.9217640876356519 0.0048628346413281485 + 0.9265543064262952 0.004717477368925247 + 0.931198795047727 0.004571378123086171 + 0.9356968230063247 0.004424559882588365 + 0.94004768284409 0.004277045739298241 + 0.944250690249923 0.0041288588945403645 + 0.9483051841672582 0.003980022655449804 + 0.9522105268980449 0.003830560431308329 + 0.9559661042030546 0.0036804957298652166 + 0.959571325398504 0.0035298521536436056 + 0.963025623448975 0.0033786533962332863 + 0.9663284550566241 0.0032269232385712526 + 0.9694793007466641 0.00307468554521151 + 0.9724776649491127 0.002921964260586262 + 0.9753230760767991 0.0027687834052614944 + 0.9780150865996246 0.002615167072191434 + 0.9805532731150799 0.0024611394229790977 + 0.9829372364150317 0.002306724684154767 + 0.9851666015488034 0.002151947143493035 + 0.9872410178826077 0.0019968311464057843 + 0.9891601591554368 0.0018414010924821323 + 0.9909237235316215 0.0016856814323170032 + 0.992531433650476 0.0015296966649272486 + 0.9939830366739069 0.0013734713364273322 + 0.9952783043339365 0.0012170300415936897 + 0.9964170329848294 0.0010603974326420873 + 0.9973990436722557 0.0009035982480626941 + 0.998224182256913 0.0007466574055662421 + 0.9988923197258543 0.0005896003421932499 + 0.9994033532930161 0.00043245460060038196 + 0.9997572122115891 0.00027526103865831744 + 0.999953919435642 0.00011825670068171721 + ], +) """ abstract type AbstractParametricCurve <: Function end @@ -280,7 +282,7 @@ Functions that are defined for all [`AbstractParametricCurve`](@ref) subtypes ar """ abstract type AbstractParametricCurve <: Function end # defined in t ∈ [0, 1] -Base.show(io::IO, c::C) where C <: AbstractParametricCurve = print(io, string(C)) +Base.show(io::IO, c::C) where {C <: AbstractParametricCurve} = print(io, string(C)) """ is_curve_bounded(c::AbstractParametricCurve) -> Bool @@ -413,13 +415,13 @@ function marked_total_variation(b::AbstractParametricCurve, t₁, t₂) return θ₁ + θ₂ else T₁ = differentiate(b, t₁) - T₂ = differentiate(b, b.orientation_markers[i₁+1]) + T₂ = differentiate(b, b.orientation_markers[i₁ + 1]) θ = angle_between(T₁, T₂) θ > π && (θ = 2π - θ) Δθ = θ - for i in (i₁+1):(i₂-1) + for i in (i₁ + 1):(i₂ - 1) T₁ = T₂ - T₂ = differentiate(b, b.orientation_markers[i+1]) + T₂ = differentiate(b, b.orientation_markers[i + 1]) θ = angle_between(T₁, T₂) θ > π && (θ = 2π - θ) Δθ += θ @@ -466,7 +468,7 @@ function convert_lookup_idx(b::AbstractParametricCurve, i) return (i - 1) / (n - 1) end -const PROJECTION_INTERVAL_TOL = 1e-12 +const PROJECTION_INTERVAL_TOL = 1.0e-12 """ get_closest_point(b::AbstractParametricCurve p) -> (Float64, NTuple{2,Float64}) @@ -494,8 +496,8 @@ function get_closest_point(b::AbstractParametricCurve, p) t, q = _get_closest_point_right_search(b, p, δ) else tmid, pmid = convert_lookup_idx(b, i), b.lookup_table[i] - tleft, pleft = convert_lookup_idx(b, i - 1), b.lookup_table[i-1] - tright, pright = convert_lookup_idx(b, i + 1), b.lookup_table[i+1] + tleft, pleft = convert_lookup_idx(b, i - 1), b.lookup_table[i - 1] + tright, pright = convert_lookup_idx(b, i + 1), b.lookup_table[i + 1] t, q = _get_closest_point_interior_search(b, p, tmid, pmid, tleft, pleft, tright, pright, δ) end return t, q @@ -556,7 +558,7 @@ function _get_closest_point_left_search(b::AbstractParametricCurve, p, δ) end end function _get_closest_point_right_search(b::AbstractParametricCurve, p, δ) - tleft, pleft = convert_lookup_idx(b, length(b.lookup_table) - 1), b.lookup_table[end-1] + tleft, pleft = convert_lookup_idx(b, length(b.lookup_table) - 1), b.lookup_table[end - 1] tright, pright = 1.0, b.lookup_table[end] δleft, δright = dist_sqr(p, pleft), δ tmid = midpoint(tleft, tright) @@ -605,7 +607,7 @@ end Protects against bad division in root-finding algorithms. This function checks if `val` is close to `0` or if `roots[i]` is outside of `[0, 1]`. If either of these conditions are true, then `roots[i]` and `residuals[i]` are set to `NaN` and `true` is returned. Otherwise, `false` is returned. """ function protect_against_bad_division!(roots, residuals, val, i) - if abs(val) < 1e-8 || roots[i] < 0 || roots[i] > 1 + if abs(val) < 1.0e-8 || roots[i] < 0 || roots[i] > 1 roots[i] = NaN residuals[i] = NaN return true @@ -634,7 +636,7 @@ Returns points `t` such that `x'(t) = 0` and `0 ≤ t ≤ 1`, where `x'` is the # Output - `t`: All turning points, given in sorted order. """ -function horizontal_turning_points(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) +function horizontal_turning_points(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) roots = collect(LinRange(0, 1, steps)) residuals = fill(Inf, steps) for i in eachindex(roots) @@ -674,7 +676,7 @@ Returns points `t` such that `y'(t) = 0` and `0 ≤ t ≤ 1`, where `y'` is the # Output - `t`: All turning points, given in sorted order. """ -function vertical_turning_points(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) +function vertical_turning_points(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) roots = collect(LinRange(0, 1, steps)) residuals = fill(Inf, steps) for i in eachindex(roots) @@ -715,7 +717,7 @@ Note that these are only technically inflection points if `x'''(t) ≠ 0` at the # Output - `t`: All inflection points, given in sorted order. """ -function horizontal_inflection_points(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) +function horizontal_inflection_points(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) roots = collect(LinRange(0, 1, steps)) residuals = fill(Inf, steps) for i in eachindex(roots) @@ -756,7 +758,7 @@ Note that these are only technically inflection points if `y'''(t) ≠ 0` at the # Output - `t`: All inflection points, given in sorted order. """ -function vertical_inflection_points(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) +function vertical_inflection_points(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) roots = collect(LinRange(0, 1, steps)) residuals = fill(Inf, steps) for i in eachindex(roots) @@ -793,7 +795,7 @@ Returns points `t` such that `κ(t) = 0` and `0 ≤ t ≤ 1`, where `κ` is the - `iters=50`: The number of iterations to run Newton's method for. - `tol=1e-5`: The tolerance to use for [`uniquetol`](@ref). Also used for deciding whether a root is a valid root, i.e. if `abs(κ(t)) > tol` for a found root `t`, then `t` is not a valid root and is rejected. """ -function inflection_points(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) +function inflection_points(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) roots = collect(LinRange(0, 1, steps)) residuals = fill(Inf, steps) for i in eachindex(roots) @@ -853,12 +855,12 @@ See also [`horizontal_turning_points`](@ref), [`vertical_turning_points`](@ref), of any `t` is not considered (so the `t`-values in the returned vector are unique). These values can be used to split the curve into monotone pieces, meaning the orientation is monotone. These markers also guarantee that, over any monotone piece, the orientation changes by an angle of at most `π/2`. """ -function orientation_markers(c::AbstractParametricCurve; steps=200, iters=50, tol=1e-5) - t₁ = horizontal_turning_points(c, steps=steps, iters=iters, tol=tol) - t₂ = vertical_turning_points(c, steps=steps, iters=iters, tol=tol) - t₃ = horizontal_inflection_points(c, steps=steps, iters=iters, tol=tol) - t₄ = vertical_inflection_points(c, steps=steps, iters=iters, tol=tol) - t₅ = inflection_points(c, steps=steps, iters=iters, tol=tol) +function orientation_markers(c::AbstractParametricCurve; steps = 200, iters = 50, tol = 1.0e-5) + t₁ = horizontal_turning_points(c, steps = steps, iters = iters, tol = tol) + t₂ = vertical_turning_points(c, steps = steps, iters = iters, tol = tol) + t₃ = horizontal_inflection_points(c, steps = steps, iters = iters, tol = tol) + t₄ = vertical_inflection_points(c, steps = steps, iters = iters, tol = tol) + t₅ = inflection_points(c, steps = steps, iters = iters, tol = tol) all_t = vcat(t₁, t₂, t₃, t₄, t₅) isempty(all_t) && return [0.0, 1.0] sort!(all_t) @@ -881,7 +883,7 @@ function get_equidistant_split(c::AbstractParametricCurve, t₁, t₂) t = midpoint(a, t₂) for _ in 1:100 # limit iterations to 100 s₁t = arc_length(c, a, t) - if abs(s₁t - s) < 1e-3 || abs(t₁ - t₂) < 2e-8 + if abs(s₁t - s) < 1.0e-3 || abs(t₁ - t₂) < 2.0e-8 return t end s₁t > s ? (t₂ = t) : (t₁ = t) @@ -904,7 +906,7 @@ function get_equivariation_split(c::AbstractParametricCurve, t₁, t₂) t = get_equidistant_split(c, a, t₂) for _ in 1:100 # limit iterations to 100 Δθ₁t = total_variation(c, a, t) - if abs(Δθ₁t - Δθ) < 1e-4 || abs(t₁ - t₂) < 2e-8 + if abs(Δθ₁t - Δθ) < 1.0e-4 || abs(t₁ - t₂) < 2.0e-8 return t, Δθ₁t end Δθ₁t > Δθ ? (t₂ = t) : (t₁ = t) @@ -953,7 +955,7 @@ function get_circle_intersection(c::AbstractParametricCurve, t₁, t₂, r) for _ in 1:100 q = c(t) δ = dist(p, q) - if abs(δ - r) < 1e-3 || abs(tᵢ - tⱼ) < 2e-8 + if abs(δ - r) < 1.0e-3 || abs(tᵢ - tⱼ) < 2.0e-8 return t, q end (δ > r) ? (tⱼ = t) : (tᵢ = t) @@ -1028,8 +1030,8 @@ You can construct a `LineSegment` using LineSegment(first, last) """ struct LineSegment <: AbstractParametricCurve # line segment - first::NTuple{2,Float64} - last::NTuple{2,Float64} + first::NTuple{2, Float64} + last::NTuple{2, Float64} length::Float64 end Base.:(==)(L₁::LineSegment, L₂::LineSegment) = L₁.first == L₂.first && L₁.last == L₂.last @@ -1150,7 +1152,7 @@ know that its `boundary_nodes` field should be used instead. on the curve, and the last point otherwise (meaning `L(h)` is constant for `h > 0`), and similarly for differentiation. Do NOT rely on the implementation of these methods. """ -struct PiecewiseLinear{P,V} <: AbstractParametricCurve +struct PiecewiseLinear{P, V} <: AbstractParametricCurve points::P boundary_nodes::V end @@ -1233,13 +1235,13 @@ distance between `center` and `first`. The `positive` keyword argument is used t arc is positively oriented or negatively oriented. """ struct CircularArc <: AbstractParametricCurve - center::NTuple{2,Float64} + center::NTuple{2, Float64} radius::Float64 start_angle::Float64 sector_angle::Float64 - first::NTuple{2,Float64} - last::NTuple{2,Float64} - pqr::NTuple{3,NTuple{2,Float64}} + first::NTuple{2, Float64} + last::NTuple{2, Float64} + pqr::NTuple{3, NTuple{2, Float64}} end function Base.:(==)(c₁::CircularArc, c₂::CircularArc) c₁.center ≠ c₂.center && return false @@ -1249,7 +1251,7 @@ function Base.:(==)(c₁::CircularArc, c₂::CircularArc) return true end -function CircularArc(p, q, c; positive=true) +function CircularArc(p, q, c; positive = true) px, py = getxy(p) qx, qy = getxy(q) cx, cy = getxy(c) @@ -1332,8 +1334,8 @@ end get_equidistant_split(c::CircularArc, t₁, t₂) = midpoint(t₁, t₂) get_equivariation_split(c::CircularArc, t₁, t₂) = let t = midpoint(t₁, t₂) - (t, total_variation(c, t₁, t)) - end + (t, total_variation(c, t₁, t)) +end function get_inverse(c::CircularArc, p) if p == c.first @@ -1383,14 +1385,14 @@ where `rotation` is the angle of rotation of the ellipse, in degrees. The `posit arc is positively oriented or negatively oriented. """ struct EllipticalArc <: AbstractParametricCurve - center::NTuple{2,Float64} + center::NTuple{2, Float64} horz_radius::Float64 vert_radius::Float64 - rotation_scales::NTuple{2,Float64} + rotation_scales::NTuple{2, Float64} start_angle::Float64 sector_angle::Float64 - first::NTuple{2,Float64} - last::NTuple{2,Float64} + first::NTuple{2, Float64} + last::NTuple{2, Float64} end function Base.:(==)(e₁::EllipticalArc, e₂::EllipticalArc) e₁.center ≠ e₂.center && return false @@ -1402,7 +1404,7 @@ function Base.:(==)(e₁::EllipticalArc, e₂::EllipticalArc) return true end -function EllipticalArc(p, q, c, α, β, θ°; positive=true) +function EllipticalArc(p, q, c, α, β, θ°; positive = true) px, py = getxy(p) qx, qy = getxy(q) cx, cy = getxy(c) @@ -1564,9 +1566,9 @@ You can construct a `BezierCurve` using The keyword argument `lookup_steps=100` controls how many time points in `[0, 1]` are used for the lookup table. The `kwargs...` are keyword arguments passed to [`orientation_markers`](@ref). """ struct BezierCurve <: AbstractParametricCurve - control_points::Vector{NTuple{2,Float64}} - cache::Vector{NTuple{2,Float64}} - lookup_table::Vector{NTuple{2,Float64}} + control_points::Vector{NTuple{2, Float64}} + cache::Vector{NTuple{2, Float64}} + lookup_table::Vector{NTuple{2, Float64}} orientation_markers::Vector{Float64} end function Base.:(==)(b₁::BezierCurve, b₂::BezierCurve) @@ -1574,7 +1576,7 @@ function Base.:(==)(b₁::BezierCurve, b₂::BezierCurve) return true end -function BezierCurve(control_points::Vector{NTuple{2,Float64}}; lookup_steps=5000, kwargs...) +function BezierCurve(control_points::Vector{NTuple{2, Float64}}; lookup_steps = 5000, kwargs...) cache = similar(control_points) # will be copyto! later lookup_table = similar(control_points, lookup_steps) markers = Float64[] @@ -1589,7 +1591,7 @@ function BezierCurve(control_points::Vector{NTuple{2,Float64}}; lookup_steps=500 return spl end -function (b::BezierCurve)(t)::NTuple{2,Float64} +function (b::BezierCurve)(t)::NTuple{2, Float64} return _eval_bezier_curve(b.control_points, b.cache, t) end function de_casteljau!(control_points, t) @@ -1600,9 +1602,9 @@ function de_casteljau!(control_points, t) else n = length(control_points) - 1 for j in 1:n - for k in 1:n-j+1 + for k in 1:(n - j + 1) xₖ, yₖ = getxy(control_points[k]) - xₖ₊₁, yₖ₊₁ = getxy(control_points[k+1]) + xₖ₊₁, yₖ₊₁ = getxy(control_points[k + 1]) x = (one(t) - t) * xₖ + t * xₖ₊₁ y = (one(t) - t) * yₖ + t * yₖ₊₁ control_points[k] = (x, y) @@ -1621,10 +1623,10 @@ function differentiate(b::BezierCurve, t) n = length(b.control_points) - 1 for i in 1:n xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) b.cache[i] = (n * (xᵢ₊₁ - xᵢ), n * (yᵢ₊₁ - yᵢ)) end - return @views de_casteljau!(b.cache[begin:end-1], t) + return @views de_casteljau!(b.cache[begin:(end - 1)], t) end function twice_differentiate(b::BezierCurve, t) @@ -1633,10 +1635,10 @@ function twice_differentiate(b::BezierCurve, t) if n == 1 return (0.0, 0.0) end - for i in 1:(n-1) + for i in 1:(n - 1) xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) - xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i+2]) + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) + xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i + 2]) # To compute the second derivative control points, we note that e.g. # for points [A, B, C, D], the first derivative gives [3(B - A), 3(C - B), 3(D - C)]. # Let these new points be [A', B', C']. Thus, differentiating again, we obtain @@ -1649,7 +1651,7 @@ function twice_differentiate(b::BezierCurve, t) scale = n * (n - 1) b.cache[i] = (scale * (xᵢ₊₂ - 2xᵢ₊₁ + xᵢ), scale * (yᵢ₊₂ - 2yᵢ₊₁ + yᵢ)) end - return @views de_casteljau!(b.cache[begin:end-2], t) + return @views de_casteljau!(b.cache[begin:(end - 2)], t) end function thrice_differentiate(b::BezierCurve, t) @@ -1658,11 +1660,11 @@ function thrice_differentiate(b::BezierCurve, t) if n ≤ 2 return (0.0, 0.0) end - for i in 1:(n-2) + for i in 1:(n - 2) xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) - xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i+2]) - xᵢ₊₃, yᵢ₊₃ = getxy(b.control_points[i+3]) + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) + xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i + 2]) + xᵢ₊₃, yᵢ₊₃ = getxy(b.control_points[i + 3]) # We know that Qᵢ′ = p(Pᵢ₊₁ - Pᵢ), where Qᵢ′ is the ith control point for the first derivative, # p is the degree of b, and Pᵢ is the ith control point of b. Thus, # Qᵢ′′ = (p-1)(Qᵢ₊₁′ - Qᵢ′) = p(p-1)(Pᵢ₊₂ - 2Pᵢ₊₁ + Pᵢ), and then @@ -1670,7 +1672,7 @@ function thrice_differentiate(b::BezierCurve, t) scale = n * (n - 1) * (n - 2) b.cache[i] = (scale * (xᵢ₊₃ - 3xᵢ₊₂ + 3xᵢ₊₁ - xᵢ), scale * (yᵢ₊₃ - 3yᵢ₊₂ + 3yᵢ₊₁ - yᵢ)) end - return @views de_casteljau!(b.cache[begin:end-3], t) + return @views de_casteljau!(b.cache[begin:(end - 3)], t) end total_variation(b::BezierCurve, t₁, t₂) = marked_total_variation(b, t₁, t₂) @@ -1712,10 +1714,10 @@ The keyword argument `lookup_steps` is used to build the lookup table for the cu `degree=3` corresponds to a cubic B-spline curve. The `kwargs...` are keyword arguments passed to [`orientation_markers`](@ref). """ struct BSpline <: AbstractParametricCurve - control_points::Vector{NTuple{2,Float64}} + control_points::Vector{NTuple{2, Float64}} knots::Vector{Int} - cache::Vector{NTuple{2,Float64}} - lookup_table::Vector{NTuple{2,Float64}} + cache::Vector{NTuple{2, Float64}} + lookup_table::Vector{NTuple{2, Float64}} orientation_markers::Vector{Float64} end function Base.:(==)(b₁::BSpline, b₂::BSpline) @@ -1724,7 +1726,7 @@ function Base.:(==)(b₁::BSpline, b₂::BSpline) return true end -function BSpline(control_points::Vector{NTuple{2,Float64}}; degree=3, lookup_steps=5000, kwargs...) +function BSpline(control_points::Vector{NTuple{2, Float64}}; degree = 3, lookup_steps = 5000, kwargs...) nc = length(control_points) @assert degree ≥ 1 "Degree must be at least 1, got $degree." @assert degree ≤ nc - 1 "Degree must be at most n - 1 = $(nc - 1), where n is the number of control points, got $degree." @@ -1735,7 +1737,7 @@ function BSpline(control_points::Vector{NTuple{2,Float64}}; degree=3, lookup_ste if i ≤ order knots[i] = 0 elseif i < nc + 1 - knots[i] = knots[i-1] + 1 + knots[i] = knots[i - 1] + 1 else knots[i] = knots[nc] + 1 end @@ -1753,7 +1755,7 @@ function BSpline(control_points::Vector{NTuple{2,Float64}}; degree=3, lookup_ste return spl end -function (b::BSpline)(t)::NTuple{2,Float64} +function (b::BSpline)(t)::NTuple{2, Float64} return _eval_bspline(b.control_points, b.knots, b.cache, t) end @@ -1771,12 +1773,12 @@ function de_boor!(control_points, knots, t) t = a + t * (b - a) s = @views searchsortedfirst(knots[domain[1]:domain[2]], t) + domain[1] - 2 for L in 1:order - for i in s:-1:(s-order+L+1) + for i in s:-1:(s - order + L + 1) numerator = t - knots[i] - denominator = knots[i+order-L] - knots[i] + denominator = knots[i + order - L] - knots[i] α = numerator / denominator α′ = 1 - α - xᵢ₋₁, yᵢ₋₁ = getxy(control_points[i-1]) + xᵢ₋₁, yᵢ₋₁ = getxy(control_points[i - 1]) xᵢ, yᵢ = getxy(control_points[i]) control_points[i] = (α′ * xᵢ₋₁ + α * xᵢ, α′ * yᵢ₋₁ + α * yᵢ) end @@ -1798,13 +1800,13 @@ function differentiate(b::BSpline, t) nc = length(b.control_points) nk = length(b.knots) degree = nk - nc - 1 - for i in 1:(nc-1) + for i in 1:(nc - 1) xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) - scale = degree / (b.knots[i+degree+1] - b.knots[i+1]) + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) + scale = degree / (b.knots[i + degree + 1] - b.knots[i + 1]) b.cache[i] = (scale * (xᵢ₊₁ - xᵢ), scale * (yᵢ₊₁ - yᵢ)) end - deriv = @views de_boor!(b.cache[begin:(end-1)], b.knots[(begin+1):(end-1)], t) + deriv = @views de_boor!(b.cache[begin:(end - 1)], b.knots[(begin + 1):(end - 1)], t) # Need to scale, since the formula used assumes that the knots are all in [0, 1] range = b.knots[end] - b.knots[begin] return (deriv[1] * range, deriv[2] * range) @@ -1818,18 +1820,18 @@ function twice_differentiate(b::BSpline, t) if degree == 1 return (0.0, 0.0) end - for i in 1:(nc-2) + for i in 1:(nc - 2) xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) - xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i+2]) - scale1 = degree / (b.knots[i+degree+1] - b.knots[i+1]) - scale2 = degree / (b.knots[i+degree+2] - b.knots[i+2]) - scale3 = (degree - 1) / (b.knots[i+degree+1] - b.knots[i+2]) # different shifts between the knots are knots[begin+1:end-1] + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) + xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i + 2]) + scale1 = degree / (b.knots[i + degree + 1] - b.knots[i + 1]) + scale2 = degree / (b.knots[i + degree + 2] - b.knots[i + 2]) + scale3 = (degree - 1) / (b.knots[i + degree + 1] - b.knots[i + 2]) # different shifts between the knots are knots[begin+1:end-1] Qᵢ′x, Qᵢ′y = (scale1 * (xᵢ₊₁ - xᵢ), scale1 * (yᵢ₊₁ - yᵢ)) Qᵢ₊₁′x, Qᵢ₊₁′y = (scale2 * (xᵢ₊₂ - xᵢ₊₁), scale2 * (yᵢ₊₂ - yᵢ₊₁)) b.cache[i] = (scale3 * (Qᵢ₊₁′x - Qᵢ′x), scale3 * (Qᵢ₊₁′y - Qᵢ′y)) end - deriv = @views de_boor!(b.cache[begin:(end-2)], b.knots[(begin+2):(end-2)], t) + deriv = @views de_boor!(b.cache[begin:(end - 2)], b.knots[(begin + 2):(end - 2)], t) range = (b.knots[end] - b.knots[begin])^2 return (deriv[1] * range, deriv[2] * range) end @@ -1842,17 +1844,17 @@ function thrice_differentiate(b::BSpline, t) # yes there is a way to evaluate (B if degree ≤ 2 return (0.0, 0.0) end - for i in 1:(nc-3) + for i in 1:(nc - 3) xᵢ, yᵢ = getxy(b.control_points[i]) - xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i+1]) - xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i+2]) - xᵢ₊₃, yᵢ₊₃ = getxy(b.control_points[i+3]) - scale1 = degree / (b.knots[i+degree+1] - b.knots[i+1]) - scale2 = degree / (b.knots[i+degree+2] - b.knots[i+2]) - scale3 = degree / (b.knots[i+degree+3] - b.knots[i+3]) - scale4 = (degree - 1) / (b.knots[i+degree+1] - b.knots[i+2]) - scale5 = (degree - 1) / (b.knots[i+degree+2] - b.knots[i+3]) - scale6 = (degree - 2) / (b.knots[i+degree+1] - b.knots[i+3]) + xᵢ₊₁, yᵢ₊₁ = getxy(b.control_points[i + 1]) + xᵢ₊₂, yᵢ₊₂ = getxy(b.control_points[i + 2]) + xᵢ₊₃, yᵢ₊₃ = getxy(b.control_points[i + 3]) + scale1 = degree / (b.knots[i + degree + 1] - b.knots[i + 1]) + scale2 = degree / (b.knots[i + degree + 2] - b.knots[i + 2]) + scale3 = degree / (b.knots[i + degree + 3] - b.knots[i + 3]) + scale4 = (degree - 1) / (b.knots[i + degree + 1] - b.knots[i + 2]) + scale5 = (degree - 1) / (b.knots[i + degree + 2] - b.knots[i + 3]) + scale6 = (degree - 2) / (b.knots[i + degree + 1] - b.knots[i + 3]) Qᵢ′x, Qᵢ′y = (scale1 * (xᵢ₊₁ - xᵢ), scale1 * (yᵢ₊₁ - yᵢ)) Qᵢ₊₁′x, Qᵢ₊₁′y = (scale2 * (xᵢ₊₂ - xᵢ₊₁), scale2 * (yᵢ₊₂ - yᵢ₊₁)) Qᵢ₊₂′x, Qᵢ₊₂′y = (scale3 * (xᵢ₊₃ - xᵢ₊₂), scale3 * (yᵢ₊₃ - yᵢ₊₂)) @@ -1860,7 +1862,7 @@ function thrice_differentiate(b::BSpline, t) # yes there is a way to evaluate (B Qᵢ₊₁′′x, Qᵢ₊₁′′y = (scale5 * (Qᵢ₊₂′x - Qᵢ₊₁′x), scale5 * (Qᵢ₊₂′y - Qᵢ₊₁′y)) b.cache[i] = (scale6 * (Qᵢ₊₁′′x - Qᵢ′′x), scale6 * (Qᵢ₊₁′′y - Qᵢ′′y)) end - deriv = @views de_boor!(b.cache[begin:(end-3)], b.knots[(begin+3):(end-3)], t) + deriv = @views de_boor!(b.cache[begin:(end - 3)], b.knots[(begin + 3):(end - 3)], t) range = (b.knots[end] - b.knots[begin])^3 return (deriv[1] * range, deriv[2] * range) end @@ -1909,12 +1911,12 @@ The parameter `τ` is the tension, and controls the tightness of the segment. ` control points. Both `α` and `τ` must be in `[0, 1]`. """ struct CatmullRomSplineSegment <: AbstractParametricCurve - a::NTuple{2,Float64} - b::NTuple{2,Float64} - c::NTuple{2,Float64} - d::NTuple{2,Float64} - p₁::NTuple{2,Float64} - p₂::NTuple{2,Float64} + a::NTuple{2, Float64} + b::NTuple{2, Float64} + c::NTuple{2, Float64} + d::NTuple{2, Float64} + p₁::NTuple{2, Float64} + p₂::NTuple{2, Float64} end function (c::CatmullRomSplineSegment)(t) if iszero(t) @@ -2040,13 +2042,13 @@ The keyword argument `lookup_steps` is used to build the lookup table for the cu The `kwargs...` are keyword arguments passed to [`orientation_markers`](@ref). """ struct CatmullRomSpline <: AbstractParametricCurve - control_points::Vector{NTuple{2,Float64}} + control_points::Vector{NTuple{2, Float64}} knots::Vector{Float64} - lookup_table::Vector{NTuple{2,Float64}} + lookup_table::Vector{NTuple{2, Float64}} alpha::Float64 tension::Float64 - left::NTuple{2,Float64} - right::NTuple{2,Float64} + left::NTuple{2, Float64} + right::NTuple{2, Float64} lengths::Vector{Float64} segments::Vector{CatmullRomSplineSegment} orientation_markers::Vector{Float64} @@ -2061,7 +2063,7 @@ end is_interpolating(spl::CatmullRomSpline) = true -function CatmullRomSpline(control_points; _alpha=1 / 2, _tension=0.0, lookup_steps=5000, kwargs...) +function CatmullRomSpline(control_points; _alpha = 1 / 2, _tension = 0.0, lookup_steps = 5000, kwargs...) alpha = _alpha tension = _tension @assert length(control_points) ≥ 4 "Catmull-Rom splines require at least 4 control points, got $(length(control_points))." @@ -2070,7 +2072,7 @@ function CatmullRomSpline(control_points; _alpha=1 / 2, _tension=0.0, lookup_ste @assert 0 ≤ tension ≤ 1 "Tension must be in [0, 1], got $tension." knots = zeros(nc) for i in 2:nc - knots[i] = knots[i-1] + dist(control_points[i-1], control_points[i])^alpha + knots[i] = knots[i - 1] + dist(control_points[i - 1], control_points[i])^alpha end left = extend_left_control_point(control_points) right = extend_right_control_point(control_points) @@ -2082,14 +2084,14 @@ function CatmullRomSpline(control_points; _alpha=1 / 2, _tension=0.0, lookup_ste markers = Float64[] segments = Vector{CatmullRomSplineSegment}(undef, nc - 1) spl = CatmullRomSpline(control_points, knots, lookup_table, alpha, tension, left, right, lengths, segments, markers) - for i in 1:(nc-1) + for i in 1:(nc - 1) spl.segments[i] = _get_segment(spl, i) end for i in 1:lookup_steps t = (i - 1) / (lookup_steps - 1) spl.lookup_table[i] = spl(t) end - for i in 1:(nc-1) + for i in 1:(nc - 1) segment = get_segment(spl, i) spl.lengths[i] = arc_length(segment, 0.0, 1.0) end @@ -2102,9 +2104,9 @@ end function extend_left_control_point(control_points) is_closed = control_points[begin] == control_points[end] if is_closed - return control_points[end-1] + return control_points[end - 1] else - c₁, c₂, c₃, c₄ = control_points[begin], control_points[begin+1], control_points[begin+2], control_points[begin+3] + c₁, c₂, c₃, c₄ = control_points[begin], control_points[begin + 1], control_points[begin + 2], control_points[begin + 3] x₁, x₂ = getx(c₁), getx(c₂) reverse_flag = x₁ == x₂ if reverse_flag @@ -2123,9 +2125,9 @@ end function extend_right_control_point(control_points) is_closed = control_points[begin] == control_points[end] if is_closed - return control_points[begin+1] + return control_points[begin + 1] else - cₙ₋₃, cₙ₋₂, cₙ₋₁, cₙ = control_points[end-3], control_points[end-2], control_points[end-1], control_points[end] + cₙ₋₃, cₙ₋₂, cₙ₋₁, cₙ = control_points[end - 3], control_points[end - 2], control_points[end - 1], control_points[end] xₙ₋₁, xₙ = getx(cₙ₋₁), getx(cₙ) reverse_flag = xₙ₋₁ == xₙ if reverse_flag @@ -2230,14 +2232,14 @@ function (c::CatmullRomSpline)(t) end function map_t_to_segment(c::CatmullRomSpline, i, t) - tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i+1] + tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i + 1] t′ = (t - tᵢ) / (tᵢ₊₁ - tᵢ) return t′ end function differentiate(c::CatmullRomSpline, t) segment, i = get_segment(c, t) - tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i+1] + tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i + 1] t′ = map_t_to_segment(c, i, t) ∂x, ∂y = getxy(differentiate(segment, t′)) scale = inv(tᵢ₊₁ - tᵢ) @@ -2246,7 +2248,7 @@ end function twice_differentiate(c::CatmullRomSpline, t) segment, i = get_segment(c, t) - tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i+1] + tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i + 1] t′ = map_t_to_segment(c, i, t) ∂x, ∂y = getxy(twice_differentiate(segment, t′)) scale = inv(tᵢ₊₁ - tᵢ) @@ -2255,7 +2257,7 @@ end function thrice_differentiate(c::CatmullRomSpline, t) segment, i = get_segment(c, t) - tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i+1] + tᵢ, tᵢ₊₁ = c.knots[i], c.knots[i + 1] t′ = map_t_to_segment(c, i, t) ∂x, ∂y = getxy(thrice_differentiate(segment, t′)) scale = inv(tᵢ₊₁ - tᵢ) @@ -2276,14 +2278,14 @@ function _get_segment(c::CatmullRomSpline, i::Int) if i == firstindex(c.control_points) pᵢ₋₁ = c.left else - pᵢ₋₁ = c.control_points[i-1] + pᵢ₋₁ = c.control_points[i - 1] end if i == lastindex(c.control_points) - 1 pᵢ₊₂ = c.right else - pᵢ₊₂ = c.control_points[i+2] + pᵢ₊₂ = c.control_points[i + 2] end - pᵢ, pᵢ₊₁ = c.control_points[i], c.control_points[i+1] + pᵢ, pᵢ₊₁ = c.control_points[i], c.control_points[i + 1] segment = catmull_rom_spline_segment(pᵢ₋₁, pᵢ, pᵢ₊₁, pᵢ₊₂, c.alpha, c.tension) return segment end @@ -2309,7 +2311,7 @@ function arc_length(c::CatmullRomSpline, t₁, t₂) return s₁ + s₂ else # at least one complete segment separates the outer segments s = 0.0 - for i in (i₁+1):(i₂-1) + for i in (i₁ + 1):(i₂ - 1) s += c.lengths[i] end t₁′ = map_t_to_segment(c, i₁, t₁) @@ -2327,4 +2329,4 @@ has_lookup_table(c::CatmullRomSpline) = true #function is_piecewise_linear(c::CatmullRomSpline) # tension = c.tension # return isone(tension) -#end \ No newline at end of file +#end diff --git a/src/data_structures/mesh_refinement/insertion_event_history.jl b/src/data_structures/mesh_refinement/insertion_event_history.jl index daa381828..dc42aa04e 100644 --- a/src/data_structures/mesh_refinement/insertion_event_history.jl +++ b/src/data_structures/mesh_refinement/insertion_event_history.jl @@ -18,7 +18,7 @@ The default constructor is available, but we also provide which will initialise this struct with empty, appropriately `sizehint!`ed, sets. """ -struct InsertionEventHistory{T,E} +struct InsertionEventHistory{T, E} added_triangles::Set{T} deleted_triangles::Set{T} added_segments::Set{E} @@ -56,7 +56,7 @@ function InsertionEventHistory(tri::Triangulation) sizehint!(delete_edge_set, 8) sizehint!(add_bnd_set, 8) sizehint!(delete_bnd_set, 8) - return InsertionEventHistory{T,E}(add_set, delete_set, add_edge_set, delete_edge_set, add_bnd_set, delete_bnd_set) + return InsertionEventHistory{T, E}(add_set, delete_set, add_edge_set, delete_edge_set, add_bnd_set, delete_bnd_set) end """ @@ -92,7 +92,7 @@ delete_edge!(events::InsertionEventHistory, e) = push!(events.deleted_segments, Add the edge `(u, v)` to the `deleted_boundary_segments` of `events` and add the edges `(u, new_point)` and `(new_point, v)` to the `added_boundary_segments` of `events`. """ -function split_boundary_edge!(events::InsertionEventHistory{T,E}, u, v, new_point) where {T,E} +function split_boundary_edge!(events::InsertionEventHistory{T, E}, u, v, new_point) where {T, E} !contains_edge(construct_edge(E, v, u), events.deleted_boundary_segments) && push!(events.deleted_boundary_segments, construct_edge(E, u, v)) !contains_edge(construct_edge(E, new_point, u), events.added_boundary_segments) && push!(events.added_boundary_segments, construct_edge(E, u, new_point)) !contains_edge(construct_edge(E, v, new_point), events.added_boundary_segments) && push!(events.added_boundary_segments, construct_edge(E, new_point, v)) @@ -105,8 +105,12 @@ end Returns `true` if there are any changes to the segments in `events`, and `false` otherwise. """ function has_segment_changes(events::InsertionEventHistory) - return any(!isempty, (events.added_segments, events.deleted_segments, - events.added_boundary_segments, events.deleted_boundary_segments)) + return any( + !isempty, ( + events.added_segments, events.deleted_segments, + events.added_boundary_segments, events.deleted_boundary_segments, + ), + ) end """ @@ -160,13 +164,13 @@ recorded into `events` and the vertex is `num_points(tri)`. If you do not want to delete the latest vertex from the triangulation, set `pop` to `Val(false)`. """ -function undo_insertion!(tri::Triangulation, events::InsertionEventHistory, pop=Val(true)) +function undo_insertion!(tri::Triangulation, events::InsertionEventHistory, pop = Val(true)) vertex = num_points(tri) for T in events.added_triangles - delete_triangle!(tri, T; protect_boundary=true, update_ghost_edges=false) + delete_triangle!(tri, T; protect_boundary = true, update_ghost_edges = false) end for T in events.deleted_triangles - add_triangle!(tri, T; protect_boundary=true, update_ghost_edges=false) + add_triangle!(tri, T; protect_boundary = true, update_ghost_edges = false) end undo_segment_changes!(tri, events) undo_boundary_segment_changes!(tri, events) @@ -218,4 +222,4 @@ function undo_boundary_segment_changes!(tri::Triangulation, events::InsertionEve e = pop!(deleted_boundary_segments) merge_boundary_edge!(tri, e, vertex) return tri -end \ No newline at end of file +end diff --git a/src/data_structures/mesh_refinement/refinement_arguments.jl b/src/data_structures/mesh_refinement/refinement_arguments.jl index 5bd27cfbc..18768a2f0 100644 --- a/src/data_structures/mesh_refinement/refinement_arguments.jl +++ b/src/data_structures/mesh_refinement/refinement_arguments.jl @@ -29,7 +29,7 @@ In addition to the default constructor, we provide for constructing this struct. This constructor will lock the convex hull and add ghost triangles to `tri` if needed ([`refine!`](@ref) will undo these changes once the refinement is finished)) """ -struct RefinementArguments{Q,C,H,I,E,R,T,P<:AbstractPredicateKernel} +struct RefinementArguments{Q, C, H, I, E, R, T, P <: AbstractPredicateKernel} queue::Q constraints::C events::H @@ -60,20 +60,22 @@ match those from [`refine!`](@ref). has no constrained boundary, then the convex hull will be locked so that it is treated as a constrained boundary. These changes will be undone in [`refine!`](@ref) once the refinement is finished. """ -function RefinementArguments(tri::Triangulation; - min_angle=30.0, - max_angle=180.0, - min_area=number_type(tri)(get_area(tri) / 1e9), - max_area=typemax(number_type(tri)), - max_points=max(1_000, num_solid_vertices(tri))^2, - seditious_angle=20.0, - custom_constraint=(_tri, T) -> false, - use_circumcenter=true, # TODO: When we implement generalised Steiner points, change this default to FALSE. - use_lens=true, - steiner_scale=0.999, - rng=Random.default_rng(), - concavity_protection=false, - predicates::AbstractPredicateKernel=AdaptiveKernel()) +function RefinementArguments( + tri::Triangulation; + min_angle = 30.0, + max_angle = 180.0, + min_area = number_type(tri)(get_area(tri) / 1.0e9), + max_area = typemax(number_type(tri)), + max_points = max(1_000, num_solid_vertices(tri))^2, + seditious_angle = 20.0, + custom_constraint = (_tri, T) -> false, + use_circumcenter = true, # TODO: When we implement generalised Steiner points, change this default to FALSE. + use_lens = true, + steiner_scale = 0.999, + rng = Random.default_rng(), + concavity_protection = false, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) if !use_circumcenter throw(ArgumentError("Generalised Steiner points are not yet implemented.")) end @@ -88,7 +90,7 @@ function RefinementArguments(tri::Triangulation; max_area, max_points, seditious_angle, - custom_constraint + custom_constraint, ) queue = RefinementQueue(tri) events = InsertionEventHistory(tri) @@ -123,7 +125,7 @@ function RefinementArguments(tri::Triangulation; has_ghosts, rng, concavity_protection, - predicates + predicates, ) end diff --git a/src/data_structures/mesh_refinement/refinement_constraints.jl b/src/data_structures/mesh_refinement/refinement_constraints.jl index d953fb7fe..77d2ed562 100644 --- a/src/data_structures/mesh_refinement/refinement_constraints.jl +++ b/src/data_structures/mesh_refinement/refinement_constraints.jl @@ -23,13 +23,14 @@ struct RefinementConstraints{F} seditious_angle::Float64 custom_constraint::F function RefinementConstraints(; - min_angle=0.0, - max_angle=180.0, - min_area=0.0, - max_area=Inf, - max_points=typemax(Int), - seditious_angle=20.0, - custom_constraint=(tri, triangle) -> false) + min_angle = 0.0, + max_angle = 180.0, + min_area = 0.0, + max_area = Inf, + max_points = typemax(Int), + seditious_angle = 20.0, + custom_constraint = (tri, triangle) -> false, + ) max_radius_edge_ratio = cscd(min_angle) / 2 min_angle, max_angle, min_area, max_area, max_radius_edge_ratio, seditious_angle = convert.(Float64, (min_angle, max_angle, min_area, max_area, max_radius_edge_ratio, seditious_angle)) F = typeof(custom_constraint) diff --git a/src/data_structures/mesh_refinement/refinement_queue.jl b/src/data_structures/mesh_refinement/refinement_queue.jl index b6968a011..bc48de5ce 100644 --- a/src/data_structures/mesh_refinement/refinement_queue.jl +++ b/src/data_structures/mesh_refinement/refinement_queue.jl @@ -14,11 +14,11 @@ The default constructor is available, but we also provide which will initialise this struct with empty queues with the appropriate types. """ -struct RefinementQueue{T,E,F} - segments::MaxPriorityQueue{E,F} - triangles::MaxPriorityQueue{T,F} - function RefinementQueue{T,E,F}() where {T,E,F} - return new{T,E,F}(MaxPriorityQueue{E,F}(), MaxPriorityQueue{T,F}()) +struct RefinementQueue{T, E, F} + segments::MaxPriorityQueue{E, F} + triangles::MaxPriorityQueue{T, F} + function RefinementQueue{T, E, F}() where {T, E, F} + return new{T, E, F}(MaxPriorityQueue{E, F}(), MaxPriorityQueue{T, F}()) end end function Base.show(io::IO, ::MIME"text/plain", queue::RefinementQueue) @@ -31,7 +31,7 @@ function RefinementQueue(tri::Triangulation) T = triangle_type(tri) E = edge_type(tri) F = number_type(tri) - return RefinementQueue{T,E,F}() + return RefinementQueue{T, E, F}() end """ @@ -39,7 +39,7 @@ end Return `true` if `queue` has `segment` or its reverse, and `false` otherwise. """ -function Base.haskey(queue::RefinementQueue{T,E,F}, segment::E) where {T,E,F} +function Base.haskey(queue::RefinementQueue{T, E, F}, segment::E) where {T, E, F} return haskey(queue.segments, segment) || haskey(queue.segments, reverse_edge(segment)) end @@ -48,10 +48,10 @@ end Return `true` if `queue` has `triangle` or any of its counter-clockwise rotations, and `false` otherwise. """ -function Base.haskey(queue::RefinementQueue{T,E,F}, triangle::T) where {T,E,F} +function Base.haskey(queue::RefinementQueue{T, E, F}, triangle::T) where {T, E, F} return haskey(queue.triangles, triangle) || - haskey(queue.triangles, rotate_triangle(triangle, Val(1))) || - haskey(queue.triangles, rotate_triangle(triangle, Val(2))) + haskey(queue.triangles, rotate_triangle(triangle, Val(1))) || + haskey(queue.triangles, rotate_triangle(triangle, Val(2))) end """ @@ -60,7 +60,7 @@ end Return the radius-edge ratio of `triangle` in `queue`. """ -function Base.getindex(queue::RefinementQueue{T,E,F}, triangle::T) where {T,E,F} +function Base.getindex(queue::RefinementQueue{T, E, F}, triangle::T) where {T, E, F} if haskey(queue.triangles, triangle) return queue.triangles[triangle] elseif haskey(queue.triangles, rotate_triangle(triangle, Val(1))) @@ -77,7 +77,7 @@ end Add a `segment` to `queue` whose squared length is `ℓ²`. If the `segment` is already in the `queue`, its priority is updated to `ℓ`. """ -function Base.setindex!(queue::RefinementQueue{T,E,F}, ℓ²::F, segment::E) where {T,E,F} +function Base.setindex!(queue::RefinementQueue{T, E, F}, ℓ²::F, segment::E) where {T, E, F} segments = queue.segments if haskey(segments, reverse_edge(segment)) segments[reverse_edge(segment)] = ℓ² @@ -93,7 +93,7 @@ end Add a `triangle` to `queue` whose radius-edge ratio is `ρ`. If the `triangle` is already in the `queue`, its priority is updated to `ρ`. """ -function Base.setindex!(queue::RefinementQueue{T,E,F}, ρ, triangle::T) where {T,E,F} +function Base.setindex!(queue::RefinementQueue{T, E, F}, ρ, triangle::T) where {T, E, F} triangles = queue.triangles if haskey(triangles, triangle) triangles[triangle] = ρ @@ -140,4 +140,4 @@ has_triangles(queue::RefinementQueue) = !isempty(queue.triangles) Return `true` if `queue` has no segments or triangles, `false` otherwise. """ -Base.isempty(queue::RefinementQueue) = !has_segments(queue) && !has_triangles(queue) \ No newline at end of file +Base.isempty(queue::RefinementQueue) = !has_segments(queue) && !has_triangles(queue) diff --git a/src/data_structures/point_location_history.jl b/src/data_structures/point_location_history.jl index f1de77cc0..45d726c6c 100644 --- a/src/data_structures/point_location_history.jl +++ b/src/data_structures/point_location_history.jl @@ -10,13 +10,13 @@ History from using [`find_triangle`](@ref). - `left_vertices::Vector{I}`: Vertices from the visited triangles to the left of `pq`. - `right_verices::Vector{I}`: Vertices from the visited triangles to the right of `pq`. """ -struct PointLocationHistory{T,E,I} +struct PointLocationHistory{T, E, I} triangles::Vector{T} collinear_segments::Vector{E} collinear_point_indices::Vector{I} left_vertices::Vector{I} right_vertices::Vector{I} - PointLocationHistory{T,E,I}() where {T,E,I} = new{T,E,I}(T[], E[], I[], I[], I[]) + PointLocationHistory{T, E, I}() where {T, E, I} = new{T, E, I}(T[], E[], I[], I[], I[]) end """ @@ -24,20 +24,20 @@ end Adds the triangle `(i, j, k)` to the `triangles` field of `history`. """ -add_triangle!(history::Ts, i::I, j::I, k::I) where {Ts<:PointLocationHistory,I<:Integer} = add_triangle!(history.triangles, i, j, k) +add_triangle!(history::Ts, i::I, j::I, k::I) where {Ts <: PointLocationHistory, I <: Integer} = add_triangle!(history.triangles, i, j, k) """ add_edge!(history::PointLocationHistory{T,E}, i, j) Adds the edge `(i, j)` to the `collinear_segments` field of `history`. """ -add_edge!(history::PointLocationHistory{T,E}, i, j) where {T,E} = add_edge!(history.collinear_segments, construct_edge(E, i, j)) +add_edge!(history::PointLocationHistory{T, E}, i, j) where {T, E} = add_edge!(history.collinear_segments, construct_edge(E, i, j)) """ add_left_vertex!(history::PointLocationHistory, i) Adds the vertex `i` to the `left_vertices` field of `history`. -""" +""" add_left_vertex!(history::PointLocationHistory, i) = push!(history.left_vertices, i) """ @@ -59,4 +59,4 @@ add_index!(history::PointLocationHistory, i) = push!(history.collinear_point_ind Returns the number of edges in `history.collinear_segments`. """ -num_edges(history::PointLocationHistory) = num_edges(history.collinear_segments) \ No newline at end of file +num_edges(history::PointLocationHistory) = num_edges(history.collinear_segments) diff --git a/src/data_structures/polygon.jl b/src/data_structures/polygon.jl index 7468344ee..9dd7e82c5 100644 --- a/src/data_structures/polygon.jl +++ b/src/data_structures/polygon.jl @@ -13,20 +13,20 @@ the integers themselves refer to points in `points`. In the case where `vertices[begin] ≠ vertices[end]`, the `vertices` field is exactly the same as the input `vertices`. Where `vertices[begin] = vertices[end]`, the `vertices` field is a view of `vertices` that excludes the last element. """ -struct Polygon{T,V,P} <: AbstractVector{T} +struct Polygon{T, V, P} <: AbstractVector{T} vertices::V points::P is_circular::Bool - @inline function Polygon(vertices::V, points::P) where {V,P} + @inline function Polygon(vertices::V, points::P) where {V, P} p = get_point(points, vertices[begin]) T = typeof(p) - return new{T,V,P}(vertices, points, is_circular(vertices)) + return new{T, V, P}(vertices, points, is_circular(vertices)) end end Base.length(P::Polygon) = length(P.vertices) - P.is_circular Base.size(P::Polygon) = (length(P),) Base.getindex(P::Polygon, i::Int) = get_point(P.points, P.vertices[i]) -Base.getindex(P::Polygon, i::Vararg{Int,N}) where {N} = +Base.getindex(P::Polygon, i::Vararg{Int, N}) where {N} = map(i) do j - P[j] - end \ No newline at end of file + P[j] +end diff --git a/src/data_structures/queue/max_priority_queue.jl b/src/data_structures/queue/max_priority_queue.jl index f60520e4c..ba257a1c1 100644 --- a/src/data_structures/queue/max_priority_queue.jl +++ b/src/data_structures/queue/max_priority_queue.jl @@ -10,15 +10,15 @@ Struct for a max priority queue. - `data::Vector{Pair{K, V}}`: The data of the queue, stored in a vector of key-value pairs mapping elements to their priority. - `map::Dict{K, Int}`: A dictionary mapping elements to their index in the data vector. """ -struct MaxPriorityQueue{K,V} <: AbstractDict{K,V} - data::Vector{Pair{K,V}} - map::Dict{K,Int} +struct MaxPriorityQueue{K, V} <: AbstractDict{K, V} + data::Vector{Pair{K, V}} + map::Dict{K, Int} end -function MaxPriorityQueue{K,V}() where {K,V} - return MaxPriorityQueue{K,V}(Pair{K,V}[], Dict{K,Int}()) +function MaxPriorityQueue{K, V}() where {K, V} + return MaxPriorityQueue{K, V}(Pair{K, V}[], Dict{K, Int}()) end -function MaxPriorityQueue(data::Dict{K,V}) where {K,V} - queue = MaxPriorityQueue{K,V}() +function MaxPriorityQueue(data::Dict{K, V}) where {K, V} + queue = MaxPriorityQueue{K, V}() for pair in data push!(queue, pair) end @@ -163,8 +163,8 @@ end Sets the priority of the element with key `key` in a `queue` to `priority`, or adds the element to the `queue` if it is not already present. """ -function Base.setindex!(queue::MaxPriorityQueue{K,V}, priority, key) where {K,V} - new_pair = Pair{K,V}(key, priority) +function Base.setindex!(queue::MaxPriorityQueue{K, V}, priority, key) where {K, V} + new_pair = Pair{K, V}(key, priority) if haskey(queue, key) idx = queue.map[key] orig_priority = queue.data[idx].second @@ -231,4 +231,4 @@ end function Base.iterate(queue::MaxPriorityQueue, state::MaxPriorityQueue) isempty(state) && return nothing return popfirst!(state), state -end \ No newline at end of file +end diff --git a/src/data_structures/queue/queue.jl b/src/data_structures/queue/queue.jl index 4b3b3203e..1961f5c6f 100644 --- a/src/data_structures/queue/queue.jl +++ b/src/data_structures/queue/queue.jl @@ -7,11 +7,11 @@ Struct for a first-in first-out queue. Under the hood, `Queue` simply uses a `Vector`. This may not be as optimised compared to other implementations, e.g. DataStructure.jl's block-based approach with a `Dequeue`. -""" +""" struct Queue{T} data::Vector{T} end -Queue{T}() where T = Queue{T}(T[]) +Queue{T}() where {T} = Queue{T}(T[]) Base.:(==)(q1::Queue, q2::Queue) = q1.data == q2.data """ @@ -55,4 +55,3 @@ Base.popfirst!(queue::Queue) = popfirst!(queue.data) Adds all `data` to the end of the `queue`. """ enqueue_all!(queue::Queue, data) = append!(queue.data, data) - diff --git a/src/data_structures/representative_coordinates/cell.jl b/src/data_structures/representative_coordinates/cell.jl index 83ff6b1ce..e0798ac98 100644 --- a/src/data_structures/representative_coordinates/cell.jl +++ b/src/data_structures/representative_coordinates/cell.jl @@ -58,4 +58,4 @@ getx(c::Cell) = c.x Returns the y-coordinate of `c`. """ -gety(c::Cell) = c.y \ No newline at end of file +gety(c::Cell) = c.y diff --git a/src/data_structures/representative_coordinates/cell_queue.jl b/src/data_structures/representative_coordinates/cell_queue.jl index 64cec7149..cebc67f54 100644 --- a/src/data_structures/representative_coordinates/cell_queue.jl +++ b/src/data_structures/representative_coordinates/cell_queue.jl @@ -12,10 +12,10 @@ according to their maximum distance. Constructs a new `CellQueue` with elements of type `Cell{T}`. """ -struct CellQueue{T} - queue::MaxPriorityQueue{Cell{T},T} +struct CellQueue{T} + queue::MaxPriorityQueue{Cell{T}, T} function CellQueue{T}() where {T} - return new{T}(MaxPriorityQueue{Cell{T},T}()) + return new{T}(MaxPriorityQueue{Cell{T}, T}()) end end @@ -43,4 +43,4 @@ get_next_cell!(queue::CellQueue) = popfirst!(queue.queue).first Returns `true` if the `queue` is empty, and `false` otherwise. """ -Base.isempty(queue::CellQueue) = Base.isempty(queue.queue) \ No newline at end of file +Base.isempty(queue::CellQueue) = Base.isempty(queue.queue) diff --git a/src/data_structures/representative_coordinates/representative_coordinates.jl b/src/data_structures/representative_coordinates/representative_coordinates.jl index 834407b34..c3f34e6ac 100644 --- a/src/data_structures/representative_coordinates/representative_coordinates.jl +++ b/src/data_structures/representative_coordinates/representative_coordinates.jl @@ -8,13 +8,13 @@ A mutable struct for representing the coordinates of a representative point of p - `y::NumberType`: The y-coordinate of the representative point. - `n::IntegerType`: The number of points represented by the representative point. """ -mutable struct RepresentativeCoordinates{I,T} +mutable struct RepresentativeCoordinates{I, T} x::T y::T n::I end -function RepresentativeCoordinates{I,T}() where {I,T} - return RepresentativeCoordinates{I,T}(zero(T), zero(T), zero(I)) +function RepresentativeCoordinates{I, T}() where {I, T} + return RepresentativeCoordinates{I, T}(zero(T), zero(T), zero(I)) end function Base.:(==)(p::RepresentativeCoordinates, q::RepresentativeCoordinates) getx(p) ≠ getx(q) && return false @@ -22,13 +22,13 @@ function Base.:(==)(p::RepresentativeCoordinates, q::RepresentativeCoordinates) getn(p) ≠ getn(q) && return false return true end -function Base.convert(::Type{RepresentativeCoordinates{I,T}}, c::RepresentativeCoordinates) where {I,T} +function Base.convert(::Type{RepresentativeCoordinates{I, T}}, c::RepresentativeCoordinates) where {I, T} x = getx(c) y = gety(c) n = getn(c) return RepresentativeCoordinates(T(x), T(y), I(n)) end -function Base.convert(::Type{RepresentativeCoordinates{I,T}}, c::RepresentativeCoordinates{I,T}) where {I,T} +function Base.convert(::Type{RepresentativeCoordinates{I, T}}, c::RepresentativeCoordinates{I, T}) where {I, T} return c end @@ -58,7 +58,7 @@ getn(c::RepresentativeCoordinates) = c.n Resets the coordinates of `c` to zero. """ -function reset!(c::RepresentativeCoordinates{I,T}) where {I,T} +function reset!(c::RepresentativeCoordinates{I, T}) where {I, T} c.x = zero(T) c.y = zero(T) c.n = zero(I) @@ -102,4 +102,4 @@ function compute_centroid!(c::RepresentativeCoordinates, points) add_point!(c, p) end return c -end \ No newline at end of file +end diff --git a/src/data_structures/shuffled_polygon_linked_list.jl b/src/data_structures/shuffled_polygon_linked_list.jl index 06b4af7af..3e6c2f62a 100644 --- a/src/data_structures/shuffled_polygon_linked_list.jl +++ b/src/data_structures/shuffled_polygon_linked_list.jl @@ -19,20 +19,20 @@ To construct this, use The argument `rng` is used for shuffling the `shuffled_indices` vector. """ -struct ShuffledPolygonLinkedList{I,T} +struct ShuffledPolygonLinkedList{I, T} next::Vector{I} prev::Vector{I} shuffled_indices::Vector{I} k::I S::T - function ShuffledPolygonLinkedList(next::Vector{I}, prev::Vector{I}, shuffled_indices::Vector{I}, k::I, S::T) where {I,T} + function ShuffledPolygonLinkedList(next::Vector{I}, prev::Vector{I}, shuffled_indices::Vector{I}, k::I, S::T) where {I, T} Base.require_one_based_indexing(S) @assert !is_circular(S) "S must not be circular." @assert length(next) == length(prev) == length(shuffled_indices) == k == length(S) "The lengths of next, prev, shuffled_indices, and S must be equal." new{I, T}(next, prev, shuffled_indices, k, S) end end -function ShuffledPolygonLinkedList(S::AbstractVector{I}; rng::Random.AbstractRNG=Random.default_rng()) where {I} +function ShuffledPolygonLinkedList(S::AbstractVector{I}; rng::Random.AbstractRNG = Random.default_rng()) where {I} k = I(length(S)) shuffled_indices = collect(I, eachindex(S)) next = zeros(I, k) @@ -48,10 +48,10 @@ end Resets the linked `list`, so that `list.next[i] = mod1(i+1, list.k)` and `list.prev[i] = mod1(i-1, list.k)`, and also reshuffles the `list.shuffled_indices` vector. """ -function reset!(list::ShuffledPolygonLinkedList; rng::Random.AbstractRNG=Random.default_rng()) - for i in 1:list.k - list.next[i] = mod1(i+1, list.k) - list.prev[i] = mod1(i-1, list.k) +function reset!(list::ShuffledPolygonLinkedList; rng::Random.AbstractRNG = Random.default_rng()) + for i in 1:list.k + list.next[i] = mod1(i + 1, list.k) + list.prev[i] = mod1(i - 1, list.k) end Random.shuffle!(rng, list.shuffled_indices) return list @@ -83,7 +83,7 @@ we perform which is the same as removing `S[πᵢ]` from the linked `list`. """ function delete_vertex!(list::ShuffledPolygonLinkedList, i) - πᵢ = list.shuffled_indices[i] + πᵢ = list.shuffled_indices[i] list.next[list.prev[πᵢ]] = list.next[πᵢ] list.prev[list.next[πᵢ]] = list.prev[πᵢ] return list @@ -98,4 +98,4 @@ Reorders the permutation `list.shuffled_indices` of the linked `list`, swapping function swap_permutation!(list::ShuffledPolygonLinkedList, i, j) list.shuffled_indices[i], list.shuffled_indices[j] = list.shuffled_indices[j], list.shuffled_indices[i] return list -end \ No newline at end of file +end diff --git a/src/data_structures/statistics/individual_triangle_statistics.jl b/src/data_structures/statistics/individual_triangle_statistics.jl index 824f4c52c..84942805c 100644 --- a/src/data_structures/statistics/individual_triangle_statistics.jl +++ b/src/data_structures/statistics/individual_triangle_statistics.jl @@ -49,20 +49,20 @@ The relevant functions used for computing these statistics are """ struct IndividualTriangleStatistics{T} area::T - lengths::NTuple{3,T} - circumcenter::NTuple{2,T} + lengths::NTuple{3, T} + circumcenter::NTuple{2, T} circumradius::T - angles::NTuple{3,T} + angles::NTuple{3, T} radius_edge_ratio::T - edge_midpoints::NTuple{3,NTuple{2,T}} + edge_midpoints::NTuple{3, NTuple{2, T}} aspect_ratio::T inradius::T perimeter::T - centroid::NTuple{2,T} - offcenter::NTuple{2,T} - sink::NTuple{2,T} + centroid::NTuple{2, T} + offcenter::NTuple{2, T} + sink::NTuple{2, T} end -function IndividualTriangleStatistics(p, q, r, sink=(NaN, NaN)) +function IndividualTriangleStatistics(p, q, r, sink = (NaN, NaN)) F = number_type(p) ℓmin², ℓmed², ℓmax² = squared_triangle_lengths(p, q, r) ℓmin, ℓmed, ℓmax = sqrt(ℓmin²), sqrt(ℓmed²), sqrt(ℓmax²) @@ -190,7 +190,7 @@ Computes the centroid of a triangle with vertices `p`, `q`, and `r`, given by c = \dfrac{p + q + r}{3}. ``` """ -function triangle_centroid(p, q, r) +function triangle_centroid(p, q, r) px, py = getxy(p) qx, qy = getxy(q) rx, ry = getxy(r) @@ -319,7 +319,7 @@ c_x = r_x + \dfrac{d_{11}d_{22} - d_{12}d_{21}}{4A}, \quad c_y = r_y + \dfrac{e_ where ``d_{11} = \|p - r\|_2^2``, ``d_{12} = p_y - r_y``, ``d_{21} = \|q - r\|_2^2``, ``d_{22} = q_y - r_y``, ``e_{11} = p_x - r_x`` ``e_{12} = d_{11}``, ``e_{21} = q_x - r_x``, and ``e_{22} = d_{21}``. """ -function triangle_circumcenter(p, q, r, A=triangle_area(p, q, r)) +function triangle_circumcenter(p, q, r, A = triangle_area(p, q, r)) px, py = getxy(p) qx, qy = getxy(q) rx, ry = getxy(r) @@ -378,7 +378,7 @@ Computes the off-center of the triangle `(p, q, r)`. be the circumcenter if it the triangle `pqc₁` has radius-edge ratio less than `β`. Here, we just let the off-center be the point `c` so that `pqc` has radius-edge ratio of exactly `β`. """ -function triangle_offcenter(p, q, r, c₁=triangle_circumcenter(p, q, r), β=1.0) +function triangle_offcenter(p, q, r, c₁ = triangle_circumcenter(p, q, r), β = 1.0) ℓ₁², ℓ₂², _, idx = squared_triangle_lengths_and_smallest_index(p, q, r) ℓ₁ = sqrt(ℓ₁²) p, q, r = make_shortest_edge_first(p, q, r, idx) @@ -596,7 +596,7 @@ Sinks were introduced in [this paper](https://doi.org/10.1145/378583.378644). Fo In cases where the triangulation has holes, this definition can lead to loops. In such a case, we just pick one of the triangles in the loop as the sink triangle. """ -function triangle_sink(tri::Triangulation, T, prev_T=construct_triangle(triangle_type(tri), integer_type(tri)(∅), integer_type(tri)(∅), integer_type(tri)(∅)); predicates::AbstractPredicateKernel=AdaptiveKernel()) +function triangle_sink(tri::Triangulation, T, prev_T = construct_triangle(triangle_type(tri), integer_type(tri)(∅), integer_type(tri)(∅), integer_type(tri)(∅)); predicates::AbstractPredicateKernel = AdaptiveKernel()) # TODO: This function would be faster if we just always search away from the largest angle. T = sort_triangle(T) c = triangle_circumcenter(tri, T) @@ -632,4 +632,4 @@ function triangle_sink(tri::Triangulation, T, prev_T=construct_triangle(triangle end sort_triangle(next_T) == prev_T && return c return triangle_sink(tri, next_T, T; predicates) -end \ No newline at end of file +end diff --git a/src/data_structures/statistics/triangulation_statistics.jl b/src/data_structures/statistics/triangulation_statistics.jl index 951b2393b..a980ed7fe 100644 --- a/src/data_structures/statistics/triangulation_statistics.jl +++ b/src/data_structures/statistics/triangulation_statistics.jl @@ -29,7 +29,7 @@ A struct containing statistics about a triangulation. # Constructors To construct these statistics, use [`statistics`](@ref), which you call as `statistics(tri::Triangulation)`. """ -struct TriangulationStatistics{T,V,I} +struct TriangulationStatistics{T, V, I} num_vertices::I num_solid_vertices::I num_ghost_vertices::I @@ -50,7 +50,7 @@ struct TriangulationStatistics{T,V,I} smallest_radius_edge_ratio::V largest_radius_edge_ratio::V area::V - individual_statistics::Dict{T,IndividualTriangleStatistics{V}} + individual_statistics::Dict{T, IndividualTriangleStatistics{V}} end function Base.show(io::IO, ::MIME"text/plain", stats::TriangulationStatistics) println(io, "Delaunay Triangulation Statistics.") @@ -102,7 +102,7 @@ function statistics(tri::Triangulation) nsegments = num_edges(segments) convex_hull_vertices = get_convex_hull_vertices(tri) nconvex_hull_vertices = max(0, length(convex_hull_vertices) - 1) # -1 because the last index is the same as the first - individual_statistics = Dict{V,IndividualTriangleStatistics{F}}() + individual_statistics = Dict{V, IndividualTriangleStatistics{F}}() sizehint!(individual_statistics, nsolid_tris) smallest_angle = typemax(F) largest_angle = typemin(F) @@ -144,7 +144,7 @@ function statistics(tri::Triangulation) smallest_radius_edge_ratio, largest_radius_edge_ratio, total_area, - individual_statistics + individual_statistics, ) end for n in fieldnames(TriangulationStatistics) @@ -176,10 +176,10 @@ for n in fieldnames(IndividualTriangleStatistics) Returns the $($name) field from the individual triangle statistics for the triangle `T` in the [`TriangulationStatistics`](@ref) `stats`. """ ($(Symbol("get_$n")))(stats::TriangulationStatistics, T) = let indiv_stats = get_individual_statistics(stats) - T = contains_triangle(T, keys(indiv_stats)) - !T[2] && throw(BoundsError(indiv_stats, T)) - return indiv_stats[T[1]].$n - end + T = contains_triangle(T, keys(indiv_stats)) + !T[2] && throw(BoundsError(indiv_stats, T)) + return indiv_stats[T[1]].$n + end end end @@ -221,4 +221,4 @@ function get_all_stat!(stats::Vector{F}, indiv_stats::Dict, stat::Symbol) where stats[i] = getfield(indiv_stats[T], stat)::F end return stats -end \ No newline at end of file +end diff --git a/src/data_structures/trees/bst.jl b/src/data_structures/trees/bst.jl index 12211520c..6687ebcb3 100644 --- a/src/data_structures/trees/bst.jl +++ b/src/data_structures/trees/bst.jl @@ -24,9 +24,9 @@ mutable struct BalancedBSTNode{K} key::K height::Int8 count::Int32 - parent::Union{Nothing,BalancedBSTNode{K}} - left::Union{Nothing,BalancedBSTNode{K}} - right::Union{Nothing,BalancedBSTNode{K}} + parent::Union{Nothing, BalancedBSTNode{K}} + left::Union{Nothing, BalancedBSTNode{K}} + right::Union{Nothing, BalancedBSTNode{K}} function BalancedBSTNode(key::K) where {K} new{K}(key, 1, 1, nothing, nothing, nothing) end @@ -170,7 +170,7 @@ Struct representing a balanced binary search tree. Nodes with duplicate keys are not supported. If a duplicate key is inserted, the tree will not be modified. """ mutable struct BalancedBST{K} - root::Union{Nothing,BalancedBSTNode{K}} + root::Union{Nothing, BalancedBSTNode{K}} count::Int32 BalancedBST(root::BalancedBSTNode{K}, count) where {K} = new{K}(root, count) BalancedBST{K}(root::BalancedBSTNode{K}, count) where {K} = new{K}(root, count) @@ -299,7 +299,7 @@ end Computes the count of the subtree rooted at `node`, i.e. the number of nodes in the subtree rooted at `node`, including `node`. """ -function compute_count(node::Union{Nothing,BalancedBSTNode}) +function compute_count(node::Union{Nothing, BalancedBSTNode}) if isnothing(node) return Int32(0) else @@ -316,7 +316,7 @@ end Computes the height of the subtree rooted at `node`. """ -function compute_height(node::Union{Nothing,BalancedBSTNode}) +function compute_height(node::Union{Nothing, BalancedBSTNode}) if isnothing(node) return Int8(0) else @@ -333,7 +333,7 @@ end Computes the balance of the subtree rooted at `node`. This is the difference between the left and right heights. """ -function compute_balance(node::Union{Nothing,BalancedBSTNode}) +function compute_balance(node::Union{Nothing, BalancedBSTNode}) if isnothing(node) return Int8(0) else @@ -488,9 +488,9 @@ end Returns the node with the minimum key in the subtree rooted at `node`. If `node` is `nothing`, returns `nothing`. """ -function _minimum(node::Union{BalancedBSTNode,Nothing}) +function _minimum(node::Union{BalancedBSTNode, Nothing}) while !isnothing(node) && has_left(node) node = get_left(node) end return node -end \ No newline at end of file +end diff --git a/src/data_structures/trees/polygon_hierarchy.jl b/src/data_structures/trees/polygon_hierarchy.jl index 909685d86..b67baa616 100644 --- a/src/data_structures/trees/polygon_hierarchy.jl +++ b/src/data_structures/trees/polygon_hierarchy.jl @@ -16,19 +16,19 @@ A tree structure used to define a polygon hierarchy. Constructs a [`PolygonTree`](@ref) with `parent`, `index`, and `height`, and no children. """ mutable struct PolygonTree{I} - parent::Union{Nothing,PolygonTree{I}} - @const children::Set{PolygonTree{I}} + parent::Union{Nothing, PolygonTree{I}} + @const children::Set{PolygonTree{I}} @const index::I height::Int end -PolygonTree{I}(parent::Union{Nothing,PolygonTree{I}}, index, height) where {I} = PolygonTree{I}(parent, Set{PolygonTree{I}}(), index, height) +PolygonTree{I}(parent::Union{Nothing, PolygonTree{I}}, index, height) where {I} = PolygonTree{I}(parent, Set{PolygonTree{I}}(), index, height) function hash_tree(tree::PolygonTree) height = get_height(tree) index = get_index(tree) parent_index = has_parent(tree) ? get_index(get_parent(tree)) : 0 h = hash((parent_index, index, height)) children = collect(get_children(tree)) - sort!(children, by=get_index) + sort!(children, by = get_index) for child in children h = hash((h, hash_tree(child))) end @@ -174,10 +174,10 @@ Constructs a [`PolygonHierarchy`](@ref) with no polygons. struct PolygonHierarchy{I} polygon_orientations::BitVector bounding_boxes::Vector{BoundingBox} - trees::Dict{I,PolygonTree{I}} + trees::Dict{I, PolygonTree{I}} reorder_cache::Vector{PolygonTree{I}} end -PolygonHierarchy{I}() where {I} = PolygonHierarchy{I}(BitVector(), BoundingBox[], Dict{I,PolygonTree{I}}(), PolygonTree{I}[]) +PolygonHierarchy{I}() where {I} = PolygonHierarchy{I}(BitVector(), BoundingBox[], Dict{I, PolygonTree{I}}(), PolygonTree{I}[]) @static if VERSION ≥ v"1.10" function Base.deepcopy(hierarchy::PolygonHierarchy{I}) where {I} # without this definition, deepcopy would occassionally segfault polygon_orientations = get_polygon_orientations(hierarchy) @@ -186,7 +186,7 @@ PolygonHierarchy{I}() where {I} = PolygonHierarchy{I}(BitVector(), BoundingBox[] reorder_cache = get_reorder_cache(hierarchy) new_polygon_orientations = copy(polygon_orientations) new_bounding_boxes = copy(bounding_boxes) - new_trees = Dict{I,PolygonTree{I}}() + new_trees = Dict{I, PolygonTree{I}}() for (index, tree) in trees new_trees[index] = deepcopy(tree) end @@ -354,7 +354,7 @@ end Returns a [`PolygonHierarchy`](@ref) defining the polygon hierarchy for a given set of `points`. This defines a hierarchy with a single polygon. """ -function construct_polygon_hierarchy(points; IntegerType=Int) +function construct_polygon_hierarchy(points; IntegerType = Int) hierarchy = PolygonHierarchy{IntegerType}() return construct_polygon_hierarchy!(hierarchy, points) end @@ -374,11 +374,11 @@ end Returns a [`PolygonHierarchy`](@ref) defining the polygon hierarchy for a given set of `boundary_nodes` that define a set of piecewise linear curves. """ -function construct_polygon_hierarchy(points, boundary_nodes; IntegerType=Int) +function construct_polygon_hierarchy(points, boundary_nodes; IntegerType = Int) hierarchy = PolygonHierarchy{IntegerType}() return construct_polygon_hierarchy!(hierarchy, points, boundary_nodes) end -construct_polygon_hierarchy(points, ::Nothing; IntegerType=Int) = construct_polygon_hierarchy(points; IntegerType) +construct_polygon_hierarchy(points, ::Nothing; IntegerType = Int) = construct_polygon_hierarchy(points; IntegerType) function construct_polygon_hierarchy!(hierarchy::PolygonHierarchy{I}, points, boundary_nodes) where {I} if !has_boundary_nodes(boundary_nodes) return construct_polygon_hierarchy!(hierarchy, points) @@ -600,7 +600,7 @@ end Expands the bounding boxes of `hierarchy` by a factor of `perc` in each direction. """ -function expand_bounds!(hierarchy::PolygonHierarchy, perc=0.10) +function expand_bounds!(hierarchy::PolygonHierarchy, perc = 0.1) bboxes = get_bounding_boxes(hierarchy) for (i, bbox) in enumerate(bboxes) bboxes[i] = expand(bbox, perc) @@ -623,9 +623,9 @@ from the curves in `boundary_curves`. Uses [`polygonise`](@ref) to fill in the b - `IntegerType=Int`: The integer type to use for indexing the polygons. - `n=4096`: The number of points to use for filling in the boundary curves in [`polygonise`](@ref). """ -function construct_polygon_hierarchy(points, boundary_nodes, boundary_curves; IntegerType=Int, n=4096) +function construct_polygon_hierarchy(points, boundary_nodes, boundary_curves; IntegerType = Int, n = 4096) new_points, new_boundary_nodes = polygonise(points, boundary_nodes, boundary_curves; n) hierarchy = PolygonHierarchy{IntegerType}() return construct_polygon_hierarchy!(hierarchy, new_points, new_boundary_nodes) end -construct_polygon_hierarchy(points, boundary_nodes, ::Tuple{}; IntegerType=Int, n=4096) = construct_polygon_hierarchy(points, boundary_nodes; IntegerType) \ No newline at end of file +construct_polygon_hierarchy(points, boundary_nodes, ::Tuple{}; IntegerType = Int, n = 4096) = construct_polygon_hierarchy(points, boundary_nodes; IntegerType) diff --git a/src/data_structures/trees/rtree.jl b/src/data_structures/trees/rtree.jl index f89c14df6..fc0e09019 100644 --- a/src/data_structures/trees/rtree.jl +++ b/src/data_structures/trees/rtree.jl @@ -145,7 +145,7 @@ A constant for representing an invalid rectangle, i.e. a rectangle with `NaN` en """ const InvalidBoundingBox = BoundingBox(InvalidBoundingInterval, InvalidBoundingInterval) BoundingBox(a, b, c, d) = BoundingBox(BoundingInterval(a, b), BoundingInterval(c, d)) -BoundingBox(p::NTuple{2,<:Number}) = BoundingBox(getx(p), getx(p), gety(p), gety(p)) +BoundingBox(p::NTuple{2, <:Number}) = BoundingBox(getx(p), getx(p), gety(p), gety(p)) """ hspan(r::BoundingBox) -> Float64 @@ -224,7 +224,7 @@ Base.in(r1::BoundingBox, r2::BoundingBox) = (r1.x ∈ r2.x) && (r1.y ∈ r2.y) Tests whether `p` is in `r`. """ -Base.in(p::NTuple{2,<:Number}, r::BoundingBox) = BoundingBox(p) ∈ r +Base.in(p::NTuple{2, <:Number}, r::BoundingBox) = BoundingBox(p) ∈ r """ is_touching(r1::BoundingBox, r2::BoundingBox) -> Bool @@ -263,7 +263,7 @@ end Returns the bounding box of the circle `(center, radius)`. """ -function bounding_box(center::NTuple{2,<:Number}, radius::Number) +function bounding_box(center::NTuple{2, <:Number}, radius::Number) cx, cy = getxy(center) return BoundingBox(cx - radius, cx + radius, cy - radius, cy + radius) end @@ -293,7 +293,7 @@ end Expands the bounding box `box` by a factor `perc` in each direction. """ -function expand(box::BoundingBox, perc=0.10) +function expand(box::BoundingBox, perc = 0.1) x = box.x y = box.y a, b = x.a, x.b @@ -328,7 +328,7 @@ Type for representing a bounding box generated from an edge's diametral circle. """ struct DiametralBoundingBox bounding_box::BoundingBox - edge::NTuple{2,Int} + edge::NTuple{2, Int} end """ @@ -493,7 +493,7 @@ Type for representing a leaf node in an R-tree. Leaf(parent::Union{Branch,Nothing}=nothing) = Leaf{Branch}(parent, InvalidBoundingBox, DiametralBoundingBox[]) """ mutable struct Leaf{Branch} <: AbstractNode - parent::Union{Branch,Nothing} + parent::Union{Branch, Nothing} bounding_box::BoundingBox @const children::Vector{DiametralBoundingBox} Leaf(parent::Branch, bounding_box, children) where {Branch} = new{Branch}(parent, bounding_box, children) @@ -524,13 +524,13 @@ Type for representing a branch node in an R-tree. Branch(parent::Union{Branch,Nothing}=nothing, ::Type{C}=Branch) where {C<:AbstractNode} = new(parent, InvalidBoundingBox, C[], 1) """ mutable struct Branch <: AbstractNode - parent::Union{Branch,Nothing} + parent::Union{Branch, Nothing} bounding_box::BoundingBox - @const children::Union{Vector{Branch},Vector{Leaf{Branch}}} # if we do e.g. Branch{C}, it makes resolving some of the other types a bit difficult, especially Leaf{Branch}. + @const children::Union{Vector{Branch}, Vector{Leaf{Branch}}} # if we do e.g. Branch{C}, it makes resolving some of the other types a bit difficult, especially Leaf{Branch}. level::Int end -Branch(parent::Union{Branch,Nothing}=nothing, ::Type{C}=Branch) where {C<:AbstractNode} = Branch(parent, InvalidBoundingBox, C[], 1) -Leaf(parent::Union{Branch,Nothing}=nothing) = Leaf{Branch}(parent, InvalidBoundingBox, DiametralBoundingBox[]) +Branch(parent::Union{Branch, Nothing} = nothing, ::Type{C} = Branch) where {C <: AbstractNode} = Branch(parent, InvalidBoundingBox, C[], 1) +Leaf(parent::Union{Branch, Nothing} = nothing) = Leaf{Branch}(parent, InvalidBoundingBox, DiametralBoundingBox[]) function Base.:(==)(branch1::Branch, branch2::Branch) xor(isnothing(branch1), isnothing(branch1)) && return false # if we test get_parent(branch1) ≠ get_parent(branch2), then we get a StackOverflowError @@ -605,13 +605,13 @@ Type for representing a cache of nodes whose children are of type `Child`. This NodeCache{Node,Child}(size_limit::Int) where {Node,Child} = new{Node,Child}(Node[], size_limit) """ -struct NodeCache{Node,Child} # similar to why we use TriangulationCache. Think of it like implementing some CapacityVector that fails to push if it's full. +struct NodeCache{Node, Child} # similar to why we use TriangulationCache. Think of it like implementing some CapacityVector that fails to push if it's full. cache::Vector{Node} size_limit::Int - function NodeCache{Node,Child}(size_limit::Int) where {Node,Child} + function NodeCache{Node, Child}(size_limit::Int) where {Node, Child} cache = Node[] sizehint!(cache, size_limit) - return new{Node,Child}(cache, size_limit) + return new{Node, Child}(cache, size_limit) end end @@ -620,21 +620,21 @@ end Type for representing a cache of branch nodes. """ -const BranchCache = NodeCache{Branch,Branch} +const BranchCache = NodeCache{Branch, Branch} """ TwigCache Type for representing a cache of twig nodes, i.e. branch nodes at level 2. """ -const TwigCache = NodeCache{Branch,Leaf{Branch}} +const TwigCache = NodeCache{Branch, Leaf{Branch}} """ LeafCache Type for representing a cache of leaf nodes. """ -const LeafCache = NodeCache{Leaf{Branch},DiametralBoundingBox} +const LeafCache = NodeCache{Leaf{Branch}, DiametralBoundingBox} """ length(cache::NodeCache) -> Int @@ -752,16 +752,16 @@ Type for representing an R-tree with linear splitting. The `size_limit` is the node capacity. All node types have the same capacity. """ mutable struct RTree # linear - root::Union{Branch,Leaf{Branch}} + root::Union{Branch, Leaf{Branch}} num_elements::Int - @const branch_cache::BranchCache - @const twig_cache::TwigCache - @const leaf_cache::LeafCache - @const fill_factor::Float64 - @const free_cache::BitVector - @const detached_cache::Vector{Union{Branch,Leaf{Branch}}} - @const intersection_cache::NTuple{2,RTreeIntersectionCache} - function RTree(; size_limit=100, fill_factor=0.7) # https://en.wikipedia.org/wiki/R-tree: "however best performance has been experienced with a minimum fill of 30%–40%) + @const branch_cache::BranchCache + @const twig_cache::TwigCache + @const leaf_cache::LeafCache + @const fill_factor::Float64 + @const free_cache::BitVector + @const detached_cache::Vector{Union{Branch, Leaf{Branch}}} + @const intersection_cache::NTuple{2, RTreeIntersectionCache} + function RTree(; size_limit = 100, fill_factor = 0.7) # https://en.wikipedia.org/wiki/R-tree: "however best performance has been experienced with a minimum fill of 30%–40%) branch_cache = BranchCache(size_limit) twig_cache = TwigCache(size_limit) leaf_cache = LeafCache(size_limit) @@ -769,7 +769,7 @@ mutable struct RTree # linear num_elements = 0 free_cache = BitVector() sizehint!(free_cache, size_limit) - detached_cache = Vector{Union{Branch,Leaf{Branch}}}() + detached_cache = Vector{Union{Branch, Leaf{Branch}}}() sizehint!(detached_cache, size_limit) cache1, cache2 = RTreeIntersectionCache(), RTreeIntersectionCache() sizehint!(cache1, ceil(Int, log2(size_limit))) @@ -783,7 +783,7 @@ mutable struct RTree # linear fill_factor, free_cache, detached_cache, - (cache1, cache2) + (cache1, cache2), ) end end @@ -1127,7 +1127,7 @@ end Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that intersect with the diametral circle of the edge between `i` and `j`. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::BoundaryRTree, i, j; cache_id=1) +function get_intersections(tree::BoundaryRTree, i, j; cache_id = 1) bbox = bounding_box(tree, i, j) return get_intersections(tree.tree, get_bounding_box(bbox); cache_id) end @@ -1138,7 +1138,7 @@ end Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that intersect with the bounding box of the triangle `(i, j, k)`. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::BoundaryRTree, i, j, k; cache_id=1) +function get_intersections(tree::BoundaryRTree, i, j, k; cache_id = 1) points = tree.points p, q, r = get_point(points, i, j, k) bbox = bounding_box(p, q, r) @@ -1151,7 +1151,7 @@ end Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that intersect with the `i`th vertex. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::BoundaryRTree, i; cache_id=1) +function get_intersections(tree::BoundaryRTree, i; cache_id = 1) p = get_point(tree.points, i) return get_intersections(tree.tree, p; cache_id) end @@ -1162,6 +1162,6 @@ end Returns an [`RTreeIntersectionIterator`](@ref) over the elements in `tree` that intersect with `bbox`. `cache_id` must be `1` or `2`, and determines what cache to use for the intersection query. """ -function get_intersections(tree::BoundaryRTree, bbox::BoundingBox; cache_id=1) +function get_intersections(tree::BoundaryRTree, bbox::BoundingBox; cache_id = 1) return get_intersections(tree.tree, bbox; cache_id) -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/adjacent.jl b/src/data_structures/triangulation/adjacent.jl index 019278853..f66c4031d 100644 --- a/src/data_structures/triangulation/adjacent.jl +++ b/src/data_structures/triangulation/adjacent.jl @@ -12,14 +12,14 @@ The map taking edges `(u, v)` to `w` such that `(u, v, w)` is a positively orien Adjacent{IntegerType, EdgeType}() Adjacent(adjacent::Dict{EdgeType, IntegerType}) """ -struct Adjacent{I,E} - adjacent::Dict{E,I} +struct Adjacent{I, E} + adjacent::Dict{E, I} end -Adjacent{I,E}() where {I,E} = Adjacent{I,E}(Dict{E,I}()) +Adjacent{I, E}() where {I, E} = Adjacent{I, E}(Dict{E, I}()) Base.:(==)(adj::Adjacent, adj2::Adjacent) = get_adjacent(adj) == get_adjacent(adj2) -function Base.show(io::IO, m::MIME"text/plain", adj::Adjacent{I,E}) where {I,E} - println(io, "Adjacent{$I, $E}, with map:") - show(io, m, get_adjacent(adj)) +function Base.show(io::IO, m::MIME"text/plain", adj::Adjacent{I, E}) where {I, E} + println(io, "Adjacent{$I, $E}, with map:") + show(io, m, get_adjacent(adj)) end Base.sizehint!(adj::Adjacent, n) = sizehint!(get_adjacent(adj), n) @@ -89,13 +89,13 @@ julia> get_adjacent(adj, (1, 6)) 0 ``` """ -function get_adjacent(adj::Adjacent{I,E}, uv::E) where {I,E} - dict = get_adjacent(adj) - return get(dict, uv, I(∅)) +function get_adjacent(adj::Adjacent{I, E}, uv::E) where {I, E} + dict = get_adjacent(adj) + return get(dict, uv, I(∅)) end -function get_adjacent(adj::Adjacent{I,E}, u, v) where {I,E} - e = construct_edge(E, u, v) - return get_adjacent(adj, e) +function get_adjacent(adj::Adjacent{I, E}, u, v) where {I, E} + e = construct_edge(E, u, v) + return get_adjacent(adj, e) end @@ -131,13 +131,13 @@ Dict{Tuple{Int64, Int64}, Int64} with 3 entries: ``` """ function add_adjacent!(adj::Adjacent, uv, w) - dict = get_adjacent(adj) - dict[uv] = w - return adj + dict = get_adjacent(adj) + dict[uv] = w + return adj end -function add_adjacent!(adj::Adjacent{I,E}, u, v, w) where {I,E} - e = construct_edge(E, u, v) - return add_adjacent!(adj, e, w) +function add_adjacent!(adj::Adjacent{I, E}, u, v, w) where {I, E} + e = construct_edge(E, u, v) + return add_adjacent!(adj, e, w) end """ @@ -178,13 +178,13 @@ Dict{Tuple{Int64, Int64}, Int64} with 3 entries: ``` """ function delete_adjacent!(adj::Adjacent, uv) - dict = get_adjacent(adj) - delete!(dict, uv) - return adj + dict = get_adjacent(adj) + delete!(dict, uv) + return adj end -function delete_adjacent!(adj::Adjacent{I,E}, u, v) where {I,E} - e = construct_edge(E, u, v) - return delete_adjacent!(adj, e) +function delete_adjacent!(adj::Adjacent{I, E}, u, v) where {I, E} + e = construct_edge(E, u, v) + return delete_adjacent!(adj, e) end """ @@ -218,10 +218,10 @@ Dict{Tuple{Int32, Int32}, Int32} with 6 entries: ``` """ function add_triangle!(adj::Adjacent, u::Integer, v::Integer, w::Integer) # method ambiguity - add_adjacent!(adj, u, v, w) - add_adjacent!(adj, v, w, u) - add_adjacent!(adj, w, u, v) - return adj + add_adjacent!(adj, u, v, w) + add_adjacent!(adj, v, w, u) + add_adjacent!(adj, w, u, v) + return adj end add_triangle!(adj::Adjacent, T) = add_triangle!(adj, geti(T), getj(T), getk(T)) @@ -264,15 +264,15 @@ Dict{Tuple{Int32, Int32}, Int32}() ``` """ function delete_triangle!(adj::Adjacent, u::Integer, v::Integer, w::Integer) # method ambiguity - for (i, j) in triangle_edges(u, v, w) - delete_adjacent!(adj, i, j) - end - return adj + for (i, j) in triangle_edges(u, v, w) + delete_adjacent!(adj, i, j) + end + return adj end delete_triangle!(adj::Adjacent, T) = delete_triangle!(adj, geti(T), getj(T), getk(T)) function Base.empty!(adj::Adjacent) - dict = get_adjacent(adj) - empty!(dict) - return adj -end \ No newline at end of file + dict = get_adjacent(adj) + empty!(dict) + return adj +end diff --git a/src/data_structures/triangulation/adjacent2vertex.jl b/src/data_structures/triangulation/adjacent2vertex.jl index 768907dd3..c29610c25 100644 --- a/src/data_structures/triangulation/adjacent2vertex.jl +++ b/src/data_structures/triangulation/adjacent2vertex.jl @@ -12,13 +12,13 @@ The map taking `w` to the set of all `(u, v)` such that `(u, v, w)` is a positiv Adjacent2Vertex{IntegerType, EdgesType}() Adjacent2Vertex(adj2v::Dict{IntegerType, EdgesType}) """ -struct Adjacent2Vertex{I,Es} - adjacent2vertex::Dict{I,Es} - Adjacent2Vertex(adj2v::Dict{I,Es}) where {I,Es} = new{I,Es}(adj2v) +struct Adjacent2Vertex{I, Es} + adjacent2vertex::Dict{I, Es} + Adjacent2Vertex(adj2v::Dict{I, Es}) where {I, Es} = new{I, Es}(adj2v) end -Adjacent2Vertex{I,Es}() where {I,Es} = Adjacent2Vertex(Dict{I,Es}()) +Adjacent2Vertex{I, Es}() where {I, Es} = Adjacent2Vertex(Dict{I, Es}()) Base.:(==)(adj2v::Adjacent2Vertex, adj2v2::Adjacent2Vertex) = get_adjacent2vertex(adj2v) == get_adjacent2vertex(adj2v2) -function Base.show(io::IO, m::MIME"text/plain", adj2v::Adjacent2Vertex{I,Es}) where {I,Es} +function Base.show(io::IO, m::MIME"text/plain", adj2v::Adjacent2Vertex{I, Es}) where {I, Es} println(io, "Adjacent2Vertex{", I, ", ", Es, "} with map:") show(io, m, get_adjacent2vertex(adj2v)) end @@ -122,13 +122,13 @@ Dict{Int64, Set{Tuple{Int64, Int64}}} with 2 entries: 1 => Set([(5, 7), (2, 3)]) ``` """ -function add_adjacent2vertex!(adj2v::Adjacent2Vertex{I,Es}, w, uv) where {I,Es} +function add_adjacent2vertex!(adj2v::Adjacent2Vertex{I, Es}, w, uv) where {I, Es} dict = get_adjacent2vertex(adj2v) existing_edges = get!(Es, dict, w) add_edge!(existing_edges, uv) return adj2v end -function add_adjacent2vertex!(adj2v::Adjacent2Vertex{I,Es}, w, u, v) where {I,Es} +function add_adjacent2vertex!(adj2v::Adjacent2Vertex{I, Es}, w, u, v) where {I, Es} E = edge_type(Es) uv = construct_edge(E, u, v) return add_adjacent2vertex!(adj2v, w, uv) @@ -169,7 +169,7 @@ function delete_adjacent2vertex!(adj2v::Adjacent2Vertex, w, uv) delete_edge!(existing_edges, uv) return adj2v end -function delete_adjacent2vertex!(adj2v::Adjacent2Vertex{I,Es}, w, u, v) where {I,Es} +function delete_adjacent2vertex!(adj2v::Adjacent2Vertex{I, Es}, w, u, v) where {I, Es} E = edge_type(Es) uv = construct_edge(E, u, v) return delete_adjacent2vertex!(adj2v, w, uv) @@ -346,4 +346,4 @@ function Base.empty!(adj2v::Adjacent2Vertex) dict = get_adjacent2vertex(adj2v) empty!(dict) return adj2v -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/graph.jl b/src/data_structures/triangulation/graph.jl index ef36d7b2a..d9363fbe6 100644 --- a/src/data_structures/triangulation/graph.jl +++ b/src/data_structures/triangulation/graph.jl @@ -20,10 +20,10 @@ The map taking vertices `u` to the set of all `v` such that `(u, v)` is an edge """ struct Graph{I} vertices::Set{I} - edges::Set{NTuple{2,I}} - neighbours::Dict{I,Set{I}} + edges::Set{NTuple{2, I}} + neighbours::Dict{I, Set{I}} end -Graph{I}() where {I} = Graph(Set{I}(), Set{NTuple{2,I}}(), Dict{I,Set{I}}()) +Graph{I}() where {I} = Graph(Set{I}(), Set{NTuple{2, I}}(), Dict{I, Set{I}}()) function Base.show(io::IO, ::MIME"text/plain", graph::Graph) println(io, "Graph") println(io, " Number of edges: ", num_edges(graph)) @@ -117,17 +117,17 @@ has_vertex(G::Graph, u) = u ∈ get_vertices(G) Adds the vertices `u...` to `G`. """ function add_vertex!(G::Graph{I}, v) where {I} - has_vertex(G, v) && return G + has_vertex(G, v) && return G V = get_vertices(G) - push!(V, v) + push!(V, v) N = get_neighbours(G) - get!(N, v) do + get!(N, v) do Set{I}() # in case N is empty, let's add it here end return G end function add_vertex!(G::Graph{I}, u...) where {I} - foreach(u) do v + foreach(u) do v add_vertex!(G, v) end return G diff --git a/src/data_structures/triangulation/methods/adjacent.jl b/src/data_structures/triangulation/methods/adjacent.jl index 4d2c5e51a..f606a509e 100644 --- a/src/data_structures/triangulation/methods/adjacent.jl +++ b/src/data_structures/triangulation/methods/adjacent.jl @@ -60,4 +60,4 @@ add_adjacent!(tri::Triangulation, u, v, w) = add_adjacent!(get_adjacent(tri), u, Deletes the key `(u, v)` from the adjacency map of `tri`. """ delete_adjacent!(tri::Triangulation, uv) = delete_adjacent!(get_adjacent(tri), uv) -delete_adjacent!(tri::Triangulation, u, v) = delete_adjacent!(get_adjacent(tri), u, v) \ No newline at end of file +delete_adjacent!(tri::Triangulation, u, v) = delete_adjacent!(get_adjacent(tri), u, v) diff --git a/src/data_structures/triangulation/methods/adjacent2vertex.jl b/src/data_structures/triangulation/methods/adjacent2vertex.jl index aa9c950c2..22f399f94 100644 --- a/src/data_structures/triangulation/methods/adjacent2vertex.jl +++ b/src/data_structures/triangulation/methods/adjacent2vertex.jl @@ -28,4 +28,4 @@ delete_adjacent2vertex!(tri::Triangulation, w, u, v) = delete_adjacent2vertex!(g Deletes the key `w` from the [`Adjacent2Vertex`](@ref) map of `tri`. """ -delete_adjacent2vertex!(tri::Triangulation, w) = delete_adjacent2vertex!(get_adjacent2vertex(tri), w) \ No newline at end of file +delete_adjacent2vertex!(tri::Triangulation, w) = delete_adjacent2vertex!(get_adjacent2vertex(tri), w) diff --git a/src/data_structures/triangulation/methods/boundary_curves.jl b/src/data_structures/triangulation/methods/boundary_curves.jl index 60e90b21d..859fc79f4 100644 --- a/src/data_structures/triangulation/methods/boundary_curves.jl +++ b/src/data_structures/triangulation/methods/boundary_curves.jl @@ -51,7 +51,7 @@ end return (PiecewiseLinear(points, boundary_nodes),) end end -@inline function _to_boundary_curves_multiple_sections(points, boundary_nodes, section=1, boundary_curves=()) +@inline function _to_boundary_curves_multiple_sections(points, boundary_nodes, section = 1, boundary_curves = ()) if section > num_sections(boundary_nodes) return boundary_curves else @@ -60,7 +60,7 @@ end return _to_boundary_curves_multiple_sections(points, boundary_nodes, section + 1, (boundary_curves..., new_boundary_curves...)) end end -@inline function _to_boundary_curves_multiple_curves(points, boundary_nodes, curve=1, boundary_curves=()) +@inline function _to_boundary_curves_multiple_curves(points, boundary_nodes, curve = 1, boundary_curves = ()) if curve > num_curves(boundary_nodes) return boundary_curves else @@ -90,7 +90,7 @@ triangulation. In particular: - `boundary_curves`: The boundary curves associated with `boundary_nodes`. - `boundary_nodes`: The modified boundary nodes. """ -@inline function convert_boundary_curves!(points, boundary_nodes, ::Type{I}) where {I<:Integer} +@inline function convert_boundary_curves!(points, boundary_nodes, ::Type{I}) where {I <: Integer} boundary_curves = to_boundary_curves(points, boundary_nodes) !is_curve_bounded(boundary_curves) && return boundary_curves, boundary_nodes new_boundary_nodes = get_skeleton(boundary_nodes, I) @@ -106,7 +106,7 @@ end @inline function _convert_boundary_curves_multiple_curves!(points, boundary_nodes, boundary_curves, new_boundary_nodes) ctr = 1 for curve_index in 1:num_curves(boundary_nodes) - curve_nodes =get_boundary_nodes(boundary_nodes, curve_index) + curve_nodes = get_boundary_nodes(boundary_nodes, curve_index) new_curve_nodes = get_boundary_nodes(new_boundary_nodes, curve_index) for section_index in 1:num_sections(curve_nodes) section_nodes = get_boundary_nodes(curve_nodes, section_index) @@ -128,7 +128,7 @@ end @inline function _convert_boundary_curves_contiguous!(points, boundary_nodes, boundary_curves, curve_index, new_boundary_nodes) if is_piecewise_linear(boundary_curves, curve_index) n = num_boundary_edges(boundary_nodes) - for i in 1:(n+1) + for i in 1:(n + 1) v = get_boundary_nodes(boundary_nodes, i) insert_boundary_node!(new_boundary_nodes, (new_boundary_nodes, i), v) end @@ -147,4 +147,3 @@ end end return nothing end - diff --git a/src/data_structures/triangulation/methods/boundary_edge_map.jl b/src/data_structures/triangulation/methods/boundary_edge_map.jl index fbbc4b7e6..c3ae92fd0 100644 --- a/src/data_structures/triangulation/methods/boundary_edge_map.jl +++ b/src/data_structures/triangulation/methods/boundary_edge_map.jl @@ -23,7 +23,7 @@ each_boundary_edge(tri::Triangulation) = keys(get_boundary_edge_map(tri)) After splitting an edge starting at `pos` on the boundary, updates the `boundary_edge_map` to reflect the new boundary edges. See [`split_boundary_edge!`](@ref). """ -function split_boundary_edge_map!(boundary_edge_map::Dict{E,T}, boundary_nodes, pos, i, j) where {E,T} +function split_boundary_edge_map!(boundary_edge_map::Dict{E, T}, boundary_nodes, pos, i, j) where {E, T} e = construct_edge(E, i, j) delete!(boundary_edge_map, e) nodes = get_boundary_nodes(boundary_nodes, pos[1]) @@ -35,4 +35,4 @@ function split_boundary_edge_map!(boundary_edge_map::Dict{E,T}, boundary_nodes, boundary_edge_map[e] = (pos[1], k) end return boundary_edge_map -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/boundary_nodes.jl b/src/data_structures/triangulation/methods/boundary_nodes.jl index d4ceaf51e..fc9301a79 100644 --- a/src/data_structures/triangulation/methods/boundary_nodes.jl +++ b/src/data_structures/triangulation/methods/boundary_nodes.jl @@ -25,9 +25,9 @@ There are several forms for the methods: """ @inline get_boundary_nodes(tri::Triangulation, mnℓ...) = get_boundary_nodes(get_boundary_nodes(tri), mnℓ...) @inline get_boundary_nodes(tri::Triangulation, m::Integer) = get_boundary_nodes(get_boundary_nodes(tri), m) # method ambiguity -@inline get_boundary_nodes(tri::Triangulation, (m, n)::NTuple{2,Integer}) = get_boundary_nodes(get_boundary_nodes(tri), (m, n)) # method ambiguity +@inline get_boundary_nodes(tri::Triangulation, (m, n)::NTuple{2, Integer}) = get_boundary_nodes(get_boundary_nodes(tri), (m, n)) # method ambiguity @inline get_boundary_nodes(tri::Triangulation, m::Integer, n::Integer) = get_boundary_nodes(get_boundary_nodes(tri), m, n) # method ambiguity -@inline get_boundary_nodes(tri::A, ::A) where {A<:Triangulation} = get_boundary_nodes(tri) # ambiguity. method doesn't really make sense +@inline get_boundary_nodes(tri::A, ::A) where {A <: Triangulation} = get_boundary_nodes(tri) # ambiguity. method doesn't really make sense """ get_right_boundary_node(tri::Triangulation, k, ghost_vertex) -> Vertex @@ -191,7 +191,7 @@ function split_boundary_edge_at_collinear_segments!(tri::Triangulation, collinea # u -- r₁ -- r₂ -- r₃ -- r₄ -------- v -> split(r₃, v, r₄) # u -- r₁ -- r₂ -- r₃ -- r₄ -- r₅ -- v -> split(r₄, v, r₅) v = terminal(last(collinear_segments)) - for k in (firstindex(collinear_segments)):(lastindex(collinear_segments)-1) + for k in (firstindex(collinear_segments)):(lastindex(collinear_segments) - 1) segment = collinear_segments[k] rₖ₋₁, rₖ = edge_vertices(segment) split_boundary_edge!(tri, rₖ₋₁, v, rₖ) @@ -216,7 +216,7 @@ function get_all_boundary_nodes(tri::Triangulation) for section_index in boundary_sections bn_nodes = get_boundary_nodes(tri, section_index) nedges = num_boundary_edges(bn_nodes) - for node_idx in 1:(nedges+1) + for node_idx in 1:(nedges + 1) vᵢ = get_boundary_nodes(bn_nodes, node_idx) push!(all_nodes, vᵢ) end @@ -257,4 +257,4 @@ function contains_boundary_edge(tri::Triangulation, i, j) E = edge_type(tri) e = construct_edge(E, i, j) return contains_boundary_edge(tri, e) -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/checks.jl b/src/data_structures/triangulation/methods/checks.jl index e6be9c0de..f36116455 100644 --- a/src/data_structures/triangulation/methods/checks.jl +++ b/src/data_structures/triangulation/methods/checks.jl @@ -6,9 +6,9 @@ Tests if the edge `(i, j)` is in `tri`, returning `true` if so and `false` other See also [`unoriented_edge_exists`](@ref). """ -edge_exists(i::I) where {I<:Integer} = i ≠ I(∅) -edge_exists(tri::Triangulation, ij) = edge_exists(get_adjacent(tri,ij)) -edge_exists(tri::Triangulation, i, j) = edge_exists(get_adjacent(tri,i,j)) +edge_exists(i::I) where {I <: Integer} = i ≠ I(∅) +edge_exists(tri::Triangulation, ij) = edge_exists(get_adjacent(tri, ij)) +edge_exists(tri::Triangulation, i, j) = edge_exists(get_adjacent(tri, i, j)) """ unoriented_edge_exists(tri::Triangulation, ij) -> Bool @@ -59,9 +59,9 @@ has_multiple_sections(tri::Triangulation) = has_multiple_sections(get_boundary_n Returns `true` if `tri` has boundary nodes, and `false` otherwise. """ -function has_boundary_nodes(boundary_nodes) +function has_boundary_nodes(boundary_nodes) return has_multiple_sections(boundary_nodes) || num_boundary_edges(boundary_nodes) ≠ 0 || eltype(boundary_nodes) <: AbstractParametricCurve -end +end has_boundary_nodes(tri::Triangulation) = has_boundary_nodes(get_boundary_nodes(tri)) has_boundary_nodes(::Nothing) = false @@ -70,4 +70,4 @@ has_boundary_nodes(::Nothing) = false Returns `true` if `tri` is weighted, and `false` otherwise. """ -is_weighted(tri::Triangulation) = is_weighted(get_weights(tri)) \ No newline at end of file +is_weighted(tri::Triangulation) = is_weighted(get_weights(tri)) diff --git a/src/data_structures/triangulation/methods/convex_hull.jl b/src/data_structures/triangulation/methods/convex_hull.jl index 3bc2e0ddf..dd69d44be 100644 --- a/src/data_structures/triangulation/methods/convex_hull.jl +++ b/src/data_structures/triangulation/methods/convex_hull.jl @@ -20,7 +20,7 @@ Updates the `convex_hull` field of `tri` to match the current triangulation. computes the convex hull using the ghost triangles of `tri`. If there are no ghost triangles but `reconstruct=true`, then the convex hull is reconstructed from scratch. - `predicates::AbstractPredicateKernel=AdaptiveKernel()`: Method to use for computing predicates. Can be one of [`FastKernel`](@ref), [`ExactKernel`](@ref), and [`AdaptiveKernel`](@ref). See the documentation for a further discussion of these methods. """ -function convex_hull!(tri::Triangulation; reconstruct=has_boundary_nodes(tri), predicates::AbstractPredicateKernel=AdaptiveKernel()) +function convex_hull!(tri::Triangulation; reconstruct = has_boundary_nodes(tri), predicates::AbstractPredicateKernel = AdaptiveKernel()) I = integer_type(tri) if reconstruct convex_hull!(get_convex_hull(tri); predicates) @@ -43,8 +43,8 @@ function convex_hull!(tri::Triangulation; reconstruct=has_boundary_nodes(tri), p return tri else add_ghost_triangles!(tri) - convex_hull!(tri; predicates, reconstruct=false) + convex_hull!(tri; predicates, reconstruct = false) delete_ghost_triangles!(tri) end return tri -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/exterior_curve_indices.jl b/src/data_structures/triangulation/methods/exterior_curve_indices.jl index 618bc34dc..5d7de0b3c 100644 --- a/src/data_structures/triangulation/methods/exterior_curve_indices.jl +++ b/src/data_structures/triangulation/methods/exterior_curve_indices.jl @@ -24,4 +24,4 @@ num_exterior_curves(tri::Triangulation) = (length ∘ get_exterior_curve_indices Returns `true` if `tri` has disjoint exterior boundary curves, and `false` otherwise. """ -is_disjoint(tri::Triangulation) = num_exterior_curves(tri) > 1 \ No newline at end of file +is_disjoint(tri::Triangulation) = num_exterior_curves(tri) > 1 diff --git a/src/data_structures/triangulation/methods/ghost_vertex_map.jl b/src/data_structures/triangulation/methods/ghost_vertex_map.jl index a96a1fade..6e2c47944 100644 --- a/src/data_structures/triangulation/methods/ghost_vertex_map.jl +++ b/src/data_structures/triangulation/methods/ghost_vertex_map.jl @@ -46,4 +46,4 @@ get_section_index(tri::Triangulation, ℓ) = get_section_index(ghost_vertex_map( Given a ghost vertex `ℓ` in `tri`, returns the corresponding section in the `boundary_nodes` of `tri`. See also [`get_ghost_vertex_map`](@ref). """ -map_ghost_vertex(tri::Triangulation, ℓ) = get_ghost_vertex_map(tri)[ℓ] \ No newline at end of file +map_ghost_vertex(tri::Triangulation, ℓ) = get_ghost_vertex_map(tri)[ℓ] diff --git a/src/data_structures/triangulation/methods/ghost_vertex_ranges.jl b/src/data_structures/triangulation/methods/ghost_vertex_ranges.jl index c31e19c53..4f1b1324f 100644 --- a/src/data_structures/triangulation/methods/ghost_vertex_ranges.jl +++ b/src/data_structures/triangulation/methods/ghost_vertex_ranges.jl @@ -11,4 +11,4 @@ get_ghost_vertex_range(tri::Triangulation, ℓ) = get_ghost_vertex_ranges(tri)[ Returns the set of all ghost vertices in `tri`. """ -all_ghost_vertices(tri::Triangulation) = keys(get_ghost_vertex_ranges(tri)) \ No newline at end of file +all_ghost_vertices(tri::Triangulation) = keys(get_ghost_vertex_ranges(tri)) diff --git a/src/data_structures/triangulation/methods/graph.jl b/src/data_structures/triangulation/methods/graph.jl index a8f89c39d..aa9f439a0 100644 --- a/src/data_structures/triangulation/methods/graph.jl +++ b/src/data_structures/triangulation/methods/graph.jl @@ -68,7 +68,7 @@ add_neighbour!(tri::Triangulation, u, v...) = add_neighbour!(get_graph(tri), u, delete_neighbour!(tri::Triangulation, u, v...) Deletes the neighbours `v...` from `u` in the graph of `tri`. -""" +""" delete_neighbour!(tri::Triangulation, u, v...) = delete_neighbour!(get_graph(tri), u, v...) """ diff --git a/src/data_structures/triangulation/methods/iterators.jl b/src/data_structures/triangulation/methods/iterators.jl index 86a029ba8..19436943c 100644 --- a/src/data_structures/triangulation/methods/iterators.jl +++ b/src/data_structures/triangulation/methods/iterators.jl @@ -52,7 +52,7 @@ An iterator over all solid vertices in a triangulation. - `vertices::V`: The iterator over all vertices in the triangulation. - `tri::T`: The triangulation. """ -struct EachSolidVertex{V,T} <: AbstractEachVertex{V} +struct EachSolidVertex{V, T} <: AbstractEachVertex{V} vertices::V tri::T end @@ -66,7 +66,7 @@ An iterator over all ghost vertices in a triangulation. - `vertices::V`: The iterator over all vertices in the triangulation. - `tri::T`: The triangulation. """ -struct EachGhostVertex{V,T} <: AbstractEachVertex{V} +struct EachGhostVertex{V, T} <: AbstractEachVertex{V} vertices::V tri::T end @@ -157,7 +157,7 @@ An iterator over all solid triangles in a triangulation. - `triangles::V`: The iterator over all triangles in the triangulation. - `tri::T`: The triangulation. """ -struct EachSolidTriangle{V,T} <: AbstractEachTriangle{V} +struct EachSolidTriangle{V, T} <: AbstractEachTriangle{V} triangles::V tri::T end @@ -171,7 +171,7 @@ An iterator over all ghost triangles in a triangulation. - `triangles::V`: The iterator over all triangles in the triangulation. - `tri::T`: The triangulation. """ -struct EachGhostTriangle{V,T} <: AbstractEachTriangle{V} +struct EachGhostTriangle{V, T} <: AbstractEachTriangle{V} triangles::V tri::T end @@ -273,7 +273,7 @@ An iterator over all solid edges in a triangulation. - `edges::E`: The iterator over all edges in the triangulation. - `tri::T`: The triangulation. """ -struct EachSolidEdge{E,T} <: AbstractEachEdge{E} +struct EachSolidEdge{E, T} <: AbstractEachEdge{E} edges::E tri::T end @@ -287,7 +287,7 @@ An iterator over all ghost edges in a triangulation. - `edges::E`: The iterator over all edges in the triangulation. - `tri::T`: The triangulation. """ -struct EachGhostEdge{E,T} <: AbstractEachEdge{E} +struct EachGhostEdge{E, T} <: AbstractEachEdge{E} edges::E tri::T end @@ -361,4 +361,4 @@ function Random.rand(rng::Random.AbstractRNG, v::Random.SamplerTrivial{<:EachGho e = rand(rng, edges) end return e -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/points.jl b/src/data_structures/triangulation/methods/points.jl index af916ec82..d21616c9e 100644 --- a/src/data_structures/triangulation/methods/points.jl +++ b/src/data_structures/triangulation/methods/points.jl @@ -17,7 +17,7 @@ function get_point(tri::Triangulation, i) return c end end -get_point(tri::Triangulation, i::Vararg{Any,N}) where {N} = ntuple(j -> get_point(tri, i[j]), Val(N)) +get_point(tri::Triangulation, i::Vararg{Any, N}) where {N} = ntuple(j -> get_point(tri, i[j]), Val(N)) """ num_points(tri::Triangulation) -> Integer @@ -56,4 +56,4 @@ pop_point!(tri::Triangulation) = pop_point!(get_points(tri)) Sets the `i`th point of `tri` to `p = (x, y)`. """ set_point!(tri::Triangulation, i, x, y) = set_point!(get_points(tri), i, x, y) -set_point!(tri::Triangulation, i, p) = set_point!(get_points(tri), i, p) \ No newline at end of file +set_point!(tri::Triangulation, i, p) = set_point!(get_points(tri), i, p) diff --git a/src/data_structures/triangulation/methods/representative_point_list.jl b/src/data_structures/triangulation/methods/representative_point_list.jl index f570214e7..3ef65f0a3 100644 --- a/src/data_structures/triangulation/methods/representative_point_list.jl +++ b/src/data_structures/triangulation/methods/representative_point_list.jl @@ -26,12 +26,12 @@ end update_centroid_after_addition!(tri::Triangulation, curve_index, p) Updates the centroid of the `curve_index`th curve in `tri` after the addition of the point `p`. -""" +""" function update_centroid_after_addition!(tri::Triangulation, curve_index, p) I = integer_type(tri) F = number_type(tri) representative_point_list = get_representative_point_list(tri) - centroid = get!(RepresentativeCoordinates{I,F}, representative_point_list, curve_index) + centroid = get!(RepresentativeCoordinates{I, F}, representative_point_list, curve_index) add_point!(centroid, p) return representative_point_list end @@ -45,7 +45,7 @@ function update_centroid_after_deletion!(tri::Triangulation, curve_index, p) I = integer_type(tri) F = number_type(tri) representative_point_list = get_representative_point_list(tri) - centroid = get!(RepresentativeCoordinates{I,F}, representative_point_list, curve_index) + centroid = get!(RepresentativeCoordinates{I, F}, representative_point_list, curve_index) delete_point!(centroid, p) return representative_point_list end @@ -98,7 +98,7 @@ There are no outputs as `tri` is updated in-place, but for each curve the repres might have representative points that are in a hole of one of their interior holes. This isn't much of a problem, indeed it wouldn't be a significant problem even if we had the representative point in a hole of the first curve, but it is something to be aware of. """ -function compute_representative_points!(tri::Triangulation; use_convex_hull=!has_boundary_nodes(tri), precision=one(number_type(tri))) +function compute_representative_points!(tri::Triangulation; use_convex_hull = !has_boundary_nodes(tri), precision = one(number_type(tri))) reset_representative_points!(tri) if use_convex_hull return _compute_representative_points!(tri, get_convex_hull_vertices(tri); precision) @@ -106,7 +106,7 @@ function compute_representative_points!(tri::Triangulation; use_convex_hull=!has return _compute_representative_points!(tri, get_boundary_nodes(tri); precision) end end -function _compute_representative_points!(tri::Triangulation, boundary_nodes; precision=one(number_type(tri))) # need this to be separate for type stability. +function _compute_representative_points!(tri::Triangulation, boundary_nodes; precision = one(number_type(tri))) # need this to be separate for type stability. points = get_points(tri) representative_point_list = get_representative_point_list(tri) I = integer_type(tri) @@ -124,4 +124,4 @@ function _compute_representative_points!(tri::Triangulation, boundary_nodes; pre representative_point_list[1] = RepresentativeCoordinates(x, y, zero(I)) end return representative_point_list -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/segments.jl b/src/data_structures/triangulation/methods/segments.jl index 4865624ee..0fec60681 100644 --- a/src/data_structures/triangulation/methods/segments.jl +++ b/src/data_structures/triangulation/methods/segments.jl @@ -20,4 +20,4 @@ function contains_segment(tri::Triangulation, i, j) E = edge_type(tri) e = construct_edge(E, i, j) return contains_segment(tri, e) -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/methods/triangles.jl b/src/data_structures/triangulation/methods/triangles.jl index 90de82c7d..f8eae4463 100644 --- a/src/data_structures/triangulation/methods/triangles.jl +++ b/src/data_structures/triangulation/methods/triangles.jl @@ -27,7 +27,7 @@ You can use the `predicates` argument to determine how the orientation predicate [`FastKernel`](@ref), [`ExactKernel`](@ref), and [`AdaptiveKernel`](@ref). See the documentation for more discussion on these choices. """ -function construct_positively_oriented_triangle(tri::Triangulation, i, j, k, predicates::AbstractPredicateKernel=AdaptiveKernel()) +function construct_positively_oriented_triangle(tri::Triangulation, i, j, k, predicates::AbstractPredicateKernel = AdaptiveKernel()) return construct_positively_oriented_triangle(triangle_type(tri), i, j, k, get_points(tri), predicates) end @@ -56,4 +56,4 @@ end Returns the number of solid triangles in `tri`. """ -num_solid_triangles(tri::Triangulation) = num_triangles(tri) - num_ghost_triangles(tri) \ No newline at end of file +num_solid_triangles(tri::Triangulation) = num_triangles(tri) - num_ghost_triangles(tri) diff --git a/src/data_structures/triangulation/methods/weights.jl b/src/data_structures/triangulation/methods/weights.jl index 66a864003..1096f16be 100644 --- a/src/data_structures/triangulation/methods/weights.jl +++ b/src/data_structures/triangulation/methods/weights.jl @@ -127,7 +127,7 @@ Using a greedy search, finds the closest vertex in `tri` to the vertex `i` (whic measuring distance in lifted space (i.e., using the power distance - see [`get_power_distance`](@ref)). The search starts from the vertex `j` which should be in `tri`. """ -function get_weighted_nearest_neighbour(tri::Triangulation, i, j=rand(each_solid_vertex(tri))) +function get_weighted_nearest_neighbour(tri::Triangulation, i, j = rand(each_solid_vertex(tri))) if has_vertex(tri, i) return i else @@ -170,8 +170,8 @@ function is_submerged(tri::Triangulation, i) V = find_triangle(tri, q) return is_submerged(tri, i, V) end -function is_submerged(tri::Triangulation, i, V) +function is_submerged(tri::Triangulation, i, V) is_ghost_vertex(i) && return false cert = point_position_relative_to_circumcircle(tri, V, i) return is_outside(cert) -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/triangulation.jl b/src/data_structures/triangulation/triangulation.jl index da5b11e37..703b55ed3 100644 --- a/src/data_structures/triangulation/triangulation.jl +++ b/src/data_structures/triangulation/triangulation.jl @@ -76,7 +76,7 @@ The [`BoundaryEnricher`](@ref) used for triangulating a curve-bounded domain. If A [`TriangulationCache`](@ref) used as a cache for [`add_segment!`](@ref) which requires a separate `Triangulation` structure for use. This will not contain any segments or boundary nodes. Also stores segments useful for [`lock_convex_hull!`](@ref) and [`unlock_convex_hull!`](@ref). """ -struct Triangulation{P,T,BN,W,I,E,Es,BC,BEM,GVM,GVR,BPL,C,BE} +struct Triangulation{P, T, BN, W, I, E, Es, BC, BEM, GVM, GVR, BPL, C, BE} # Geometry points::P triangles::T @@ -85,8 +85,8 @@ struct Triangulation{P,T,BN,W,I,E,Es,BC,BEM,GVM,GVR,BPL,C,BE} all_segments::Es weights::W # Topology - adjacent::Adjacent{I,E} - adjacent2vertex::Adjacent2Vertex{I,Es} + adjacent::Adjacent{I, E} + adjacent2vertex::Adjacent2Vertex{I, Es} graph::Graph{I} # Boundary handling boundary_curves::BC @@ -94,7 +94,7 @@ struct Triangulation{P,T,BN,W,I,E,Es,BC,BEM,GVM,GVR,BPL,C,BE} ghost_vertex_map::GVM ghost_vertex_ranges::GVR # Other - convex_hull::ConvexHull{P,I} + convex_hull::ConvexHull{P, I} representative_point_list::BPL polygon_hierarchy::PolygonHierarchy{I} boundary_enricher::BE @@ -325,28 +325,28 @@ number_type(::Triangulation{P}) where {P} = number_type(P) Returns the type used for representing vertices in `tri`. """ -integer_type(::Triangulation{P,T,BN,W,I}) where {P,T,BN,W,I} = I +integer_type(::Triangulation{P, T, BN, W, I}) where {P, T, BN, W, I} = I """ edges_type(tri::Triangulation) -> DataType Returns the type used for representing collections of edges in `tri`. """ -edges_type(::Triangulation{P,T,BN,W,I,E,Es}) where {P,T,BN,W,I,E,Es} = Es +edges_type(::Triangulation{P, T, BN, W, I, E, Es}) where {P, T, BN, W, I, E, Es} = Es """ edge_type(tri::Triangulation) -> DataType Returns the type used for representing individual edges in `tri`. """ -edge_type(::Triangulation{P,T,BN,W,I,E}) where {P,T,BN,W,I,E} = E +edge_type(::Triangulation{P, T, BN, W, I, E}) where {P, T, BN, W, I, E} = E """ triangle_type(tri::Triangulation) -> DataType Returns the type used for representing collections of triangles in `tri`. """ -triangles_type(::Triangulation{P,T}) where {P,T} = T +triangles_type(::Triangulation{P, T}) where {P, T} = T """ triangle_type(tri::Triangulation) -> DataType @@ -355,11 +355,13 @@ Returns the type used for representing individual triangles in `tri`. """ triangle_type(tri::Triangulation) = triangle_type(triangles_type(tri)) -@inline function __Triangulation(points::P, boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}, - TriangleType::Type{V}, EdgesType::Type{Es}, TrianglesType::Type{Ts}) where {P,I,E,V,Es,Ts} +@inline function __Triangulation( + points::P, boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}, + TriangleType::Type{V}, EdgesType::Type{Es}, TrianglesType::Type{Ts}, + ) where {P, I, E, V, Es, Ts} T = TrianglesType() - adj = Adjacent{IntegerType,EdgeType}() - adj2v = Adjacent2Vertex{IntegerType,EdgesType}() + adj = Adjacent{IntegerType, EdgeType}() + adj2v = Adjacent2Vertex{IntegerType, EdgesType}() graph = Graph{IntegerType}() all_segments = EdgesType() boundary_edge_map = construct_boundary_edge_map(boundary_nodes, IntegerType, EdgeType) @@ -376,24 +378,27 @@ triangle_type(tri::Triangulation) = triangle_type(triangles_type(tri)) return T, adj, adj2v, graph, all_segments, boundary_edge_map, ghost_vertex_map, ghost_vertex_ranges, ch, polygon_hierarchy end -@inline function _build_cache(points::P, IntegerType::Type{I}, EdgeType::Type{E}, - TriangleType::Type{V}, EdgesType::Type{Es}, TrianglesType::Type{T}, weights::W, build_cache::Val{B}) where {P,I,E,V,Es,T,W,B} +@inline function _build_cache( + points::P, IntegerType::Type{I}, EdgeType::Type{E}, + TriangleType::Type{V}, EdgesType::Type{Es}, TrianglesType::Type{T}, weights::W, build_cache::Val{B}, + ) where {P, I, E, V, Es, T, W, B} if B BN = Vector{IntegerType} BC = Tuple{} - BEM = Dict{EdgeType,Tuple{Vector{IntegerType},IntegerType}} - GVM = Dict{IntegerType,Vector{IntegerType}} - GVR = Dict{IntegerType,UnitRange{IntegerType}} - BPL = Dict{IntegerType,RepresentativeCoordinates{IntegerType,number_type(points)}} - C = TriangulationCache{Nothing,Nothing,Nothing,Nothing,Nothing} + BEM = Dict{EdgeType, Tuple{Vector{IntegerType}, IntegerType}} + GVM = Dict{IntegerType, Vector{IntegerType}} + GVR = Dict{IntegerType, UnitRange{IntegerType}} + BPL = Dict{IntegerType, RepresentativeCoordinates{IntegerType, number_type(points)}} + C = TriangulationCache{Nothing, Nothing, Nothing, Nothing, Nothing} cache = TriangulationCache( - Triangulation(points; weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, build_cache=Val(false)), - Triangulation(points; weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, build_cache=Val(false)), - I[], Es(), I[], T())::TriangulationCache{ - Triangulation{P,T,BN,W,I,E,Es,BC,BEM,GVM,GVR,BPL,C,Nothing},Vector{I},Es,Vector{I},T + Triangulation(points; weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, build_cache = Val(false)), + Triangulation(points; weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, build_cache = Val(false)), + I[], Es(), I[], T(), + )::TriangulationCache{ + Triangulation{P, T, BN, W, I, E, Es, BC, BEM, GVM, GVR, BPL, C, Nothing}, Vector{I}, Es, Vector{I}, T, } else - cache = TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing)::TriangulationCache{Nothing,Nothing,Nothing,Nothing,Nothing} + cache = TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing)::TriangulationCache{Nothing, Nothing, Nothing, Nothing, Nothing} end return cache end @@ -404,32 +409,40 @@ end Initialises an empty `Triangulation` for triangulating `points`. The keyword arguments `kwargs...` match those of [`triangulate`](@ref). """ -@inline function Triangulation(points::P; - IntegerType::Type{I}=Int, - EdgeType::Type{E}=NTuple{2,IntegerType}, - TriangleType::Type{T}=NTuple{3,IntegerType}, - EdgesType::Type{Es}=Set{EdgeType}, - TrianglesType::Type{Vs}=Set{TriangleType}, - boundary_nodes=IntegerType[], - segments=EdgesType(), - weights=ZeroWeight(), - representative_point_list=Dict{IntegerType,RepresentativeCoordinates{IntegerType,number_type(points)}}(), - boundary_curves=(), - build_cache=true, - boundary_enricher=nothing) where {P,I,E,T,Es,Vs} - return _Triangulation(points, +@inline function Triangulation( + points::P; + IntegerType::Type{I} = Int, + EdgeType::Type{E} = NTuple{2, IntegerType}, + TriangleType::Type{T} = NTuple{3, IntegerType}, + EdgesType::Type{Es} = Set{EdgeType}, + TrianglesType::Type{Vs} = Set{TriangleType}, + boundary_nodes = IntegerType[], + segments = EdgesType(), + weights = ZeroWeight(), + representative_point_list = Dict{IntegerType, RepresentativeCoordinates{IntegerType, number_type(points)}}(), + boundary_curves = (), + build_cache = true, + boundary_enricher = nothing, + ) where {P, I, E, T, Es, Vs} + return _Triangulation( + points, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType, boundary_nodes, segments, weights, representative_point_list, - boundary_curves, _to_val(build_cache), boundary_enricher) + boundary_curves, _to_val(build_cache), boundary_enricher, + ) end -@inline function _Triangulation(points, ::Type{I}, ::Type{E}, ::Type{V}, ::Type{Es}, ::Type{Ts}, - boundary_nodes, segments, weights, representative_point_list, - boundary_curves, build_cache::Val{B}, boundary_enricher) where {I,E,V,Es,Ts,B} +@inline function _Triangulation( + points, ::Type{I}, ::Type{E}, ::Type{V}, ::Type{Es}, ::Type{Ts}, + boundary_nodes, segments, weights, representative_point_list, + boundary_curves, build_cache::Val{B}, boundary_enricher, + ) where {I, E, V, Es, Ts, B} T, adj, adj2v, graph, all_segments, boundary_edge_map, ghost_vertex_map, ghost_vertex_ranges, ch, polygon_hierarchy = __Triangulation(points, boundary_nodes, I, E, V, Es, Ts) cache = _build_cache(points, I, E, V, Es, Ts, weights, build_cache) - tri = Triangulation(points, T, boundary_nodes, segments, all_segments, weights, + tri = Triangulation( + points, T, boundary_nodes, segments, all_segments, weights, adj, adj2v, graph, boundary_curves, boundary_edge_map, - ghost_vertex_map, ghost_vertex_ranges, ch, representative_point_list, polygon_hierarchy, boundary_enricher, cache) + ghost_vertex_map, ghost_vertex_ranges, ch, representative_point_list, polygon_hierarchy, boundary_enricher, cache, + ) return tri end @@ -456,17 +469,19 @@ Returns the `Triangulation` corresponding to the triangulation of `points` with # Output - `tri`: The [`Triangulation`](@ref). """ -@inline function Triangulation(points::P, triangles::T, boundary_nodes::BN; - IntegerType::Type{I}=Int, - EdgeType::Type{E}=NTuple{2,IntegerType}, - TriangleType::Type{V}=NTuple{3,IntegerType}, - EdgesType::Type{Es}=Set{EdgeType}, - TrianglesType::Type{Ts}=Set{TriangleType}, - weights=ZeroWeight(), - delete_ghosts=false, - predicates::AbstractPredicateKernel=AdaptiveKernel()) where {P,T,BN,I,E,V,Es,Ts} +@inline function Triangulation( + points::P, triangles::T, boundary_nodes::BN; + IntegerType::Type{I} = Int, + EdgeType::Type{E} = NTuple{2, IntegerType}, + TriangleType::Type{V} = NTuple{3, IntegerType}, + EdgesType::Type{Es} = Set{EdgeType}, + TrianglesType::Type{Ts} = Set{TriangleType}, + weights = ZeroWeight(), + delete_ghosts = false, + predicates::AbstractPredicateKernel = AdaptiveKernel(), + ) where {P, T, BN, I, E, V, Es, Ts} _bn = copy(boundary_nodes) - tri = Triangulation(points; boundary_nodes=_bn, weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType) + tri = Triangulation(points; boundary_nodes = _bn, weights, IntegerType, EdgeType, TriangleType, EdgesType, TrianglesType) return build_triangulation_from_data!(tri, triangles, _bn, delete_ghosts, predicates) end @@ -480,7 +495,7 @@ The `kernel` argument determines how predicates are computed, and should be one of [`ExactKernel`](@ref), [`FastKernel`](@ref), and [`AdaptiveKernel`](@ref) (the default). See the documentation for more information about these choices. """ -@inline function build_triangulation_from_data!(tri::Triangulation, triangles, boundary_nodes, delete_ghosts, predicates::AbstractPredicateKernel=AdaptiveKernel()) +@inline function build_triangulation_from_data!(tri::Triangulation, triangles, boundary_nodes, delete_ghosts, predicates::AbstractPredicateKernel = AdaptiveKernel()) Es = edges_type(tri) points = get_points(tri) polygon_hierarchy = get_polygon_hierarchy(tri) @@ -497,7 +512,7 @@ See the documentation for more information about these choices. end add_boundary_information!(tri) add_ghost_triangles!(tri) - convex_hull!(tri; predicates, reconstruct=true) + convex_hull!(tri; predicates, reconstruct = true) segments = get_all_segments(tri) ghost_vertex_map = get_ghost_vertex_map(tri) all_segments = merge_segments(ghost_vertex_map, boundary_nodes, Es()) @@ -506,4 +521,4 @@ See the documentation for more information about these choices. end postprocess_triangulate!(tri; delete_ghosts) return tri -end \ No newline at end of file +end diff --git a/src/data_structures/triangulation/triangulation_cache.jl b/src/data_structures/triangulation/triangulation_cache.jl index ad8ed2dac..3917d2a07 100644 --- a/src/data_structures/triangulation/triangulation_cache.jl +++ b/src/data_structures/triangulation/triangulation_cache.jl @@ -24,7 +24,7 @@ A cache to be used as a field in [`Triangulation`](@ref). The `points` of the cache's `triangulation` will be aliased to the `points` of the parent triangulation. """ -struct TriangulationCache{T,M,I,S,F} +struct TriangulationCache{T, M, I, S, F} triangulation::T triangulation_2::T marked_vertices::M @@ -122,4 +122,4 @@ function empty_unconstrained_triangulation!(tri::Triangulation) empty!(convex_hull) empty!(representative_points) return tri -end \ No newline at end of file +end diff --git a/src/data_structures/voronoi.jl b/src/data_structures/voronoi.jl index c9bd4415d..dcad078d8 100644 --- a/src/data_structures/voronoi.jl +++ b/src/data_structures/voronoi.jl @@ -24,16 +24,16 @@ See also [`voronoi`](@ref). - `boundary_polygons::Set{I}`: A `Set` of indices of the polygons that are on the boundary of the tessellation. Only relevant for clipped tessellations, otherwise see `unbounded_polygons`. """ -struct VoronoiTessellation{Tr<:Triangulation,P,I,T,S,E} +struct VoronoiTessellation{Tr <: Triangulation, P, I, T, S, E} triangulation::Tr - generators::Dict{I,P} + generators::Dict{I, P} polygon_points::Vector{P} # not guaranteed to be unique if a circumcenter appears on the boundary, but the vertices (below) do handle this automatically - polygons::Dict{I,Vector{I}} - circumcenter_to_triangle::Dict{I,T} - triangle_to_circumcenter::Dict{T,I} + polygons::Dict{I, Vector{I}} + circumcenter_to_triangle::Dict{I, T} + triangle_to_circumcenter::Dict{T, I} unbounded_polygons::Set{I} cocircular_circumcenters::S - adjacent::Adjacent{I,E} + adjacent::Adjacent{I, E} boundary_polygons::Set{I} end @@ -127,28 +127,28 @@ end Type used for representing individual edges in the Voronoi tessellation. """ -edge_type(::VoronoiTessellation{Tr,P,I,T,S,E}) where {Tr,P,I,T,S,E} = E +edge_type(::VoronoiTessellation{Tr, P, I, T, S, E}) where {Tr, P, I, T, S, E} = E """ number_type(vorn::VoronoiTessellation) -> DataType Type used for representing individual coordinates in the Voronoi tessellation. """ -number_type(::VoronoiTessellation{Tr,P}) where {Tr,P} = number_type(P) +number_type(::VoronoiTessellation{Tr, P}) where {Tr, P} = number_type(P) """ integer_type(vorn::VoronoiTessellation) -> DataType Type used for representing indices in the Voronoi tessellation. """ -integer_type(::VoronoiTessellation{Tr,P,I}) where {Tr,P,I} = I +integer_type(::VoronoiTessellation{Tr, P, I}) where {Tr, P, I} = I """ triangle_type(vorn::VoronoiTessellation) -> DataType Type used for representing individual triangles in the Voronoi tessellation. """ -triangle_type(::VoronoiTessellation{Tr,P,I,T}) where {Tr,P,I,T} = T +triangle_type(::VoronoiTessellation{Tr, P, I, T}) where {Tr, P, I, T} = T """ get_generator(vor::VoronoiTessellation, i) -> NTuple{2, Number} @@ -410,7 +410,7 @@ Gets the bounding box for the Voronoi tessellation `vorn`. - `ymin`: Given by `ymin′ - unbounded_extension_factor * (ymin′ - ymin′)`, where `ymin′` is the original minimum `y`-coordinate of the computed bounding box and similarly for `ymax′`. - `ymax`: Given by `ymax′ + unbounded_extension_factor * (ymax′ - ymax′)`, where `ymax′` is the original maximum `y`-coordinate of the computed bounding box and similarly for `ymin′`. """ -function polygon_bounds(vorn::VoronoiTessellation, unbounded_extension_factor=0.0; include_polygon_vertices=true) +function polygon_bounds(vorn::VoronoiTessellation, unbounded_extension_factor = 0.0; include_polygon_vertices = true) F = number_type(vorn) xmin = typemax(F) xmax = typemin(F) diff --git a/src/exports.jl b/src/exports.jl index b791f43c6..b8089a6f5 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -103,4 +103,4 @@ export num_neighbours, FastKernel, AdaptiveKernel, - ExactKernel \ No newline at end of file + ExactKernel diff --git a/src/geometric_primitives.jl b/src/geometric_primitives.jl index 706734cb9..7b1b2c26c 100644 --- a/src/geometric_primitives.jl +++ b/src/geometric_primitives.jl @@ -1,4 +1,4 @@ include("geometric_primitives/boundary_nodes.jl") include("geometric_primitives/edges.jl") include("geometric_primitives/points.jl") -include("geometric_primitives/triangles.jl") \ No newline at end of file +include("geometric_primitives/triangles.jl") diff --git a/src/geometric_primitives/boundary_nodes.jl b/src/geometric_primitives/boundary_nodes.jl index 6772f7535..16389a6ad 100644 --- a/src/geometric_primitives/boundary_nodes.jl +++ b/src/geometric_primitives/boundary_nodes.jl @@ -19,9 +19,9 @@ true ``` """ has_multiple_curves -has_multiple_curves(::AAA) where {F<:Number,A<:AV{F},AA<:AV{A},AAA<:AV{AA}} = true -has_multiple_curves(::AA) where {F<:Number,A<:AV{F},AA<:AV{A}} = false -has_multiple_curves(::A) where {F<:Number,A<:AV{F}} = false +has_multiple_curves(::AAA) where {F <: Number, A <: AV{F}, AA <: AV{A}, AAA <: AV{AA}} = true +has_multiple_curves(::AA) where {F <: Number, A <: AV{F}, AA <: AV{A}} = false +has_multiple_curves(::A) where {F <: Number, A <: AV{F}} = false function has_multiple_curves(boundary_nodes::AV) #= Need this since, e.g. @@ -62,9 +62,9 @@ true ``` """ has_multiple_sections -has_multiple_sections(::AAA) where {F<:Number,A<:AV{F},AA<:AV{A},AAA<:AV{AA}} = true -has_multiple_sections(::AA) where {F<:Number,A<:AV{F},AA<:AV{A}} = true -has_multiple_sections(::A) where {F<:Number,A<:AV{F}} = false +has_multiple_sections(::AAA) where {F <: Number, A <: AV{F}, AA <: AV{A}, AAA <: AV{AA}} = true +has_multiple_sections(::AA) where {F <: Number, A <: AV{F}, AA <: AV{A}} = true +has_multiple_sections(::A) where {F <: Number, A <: AV{F}} = false function has_multiple_sections(boundary_nodes::AV) #= Need this since, e.g. @@ -193,10 +193,10 @@ julia> get_boundary_nodes([1, 2, 3, 4, 5, 1], [1, 2, 3, 4, 5, 1]) get_boundary_nodes @inline get_boundary_nodes(boundary_nodes, m::Integer) = boundary_nodes[m] @inline get_boundary_nodes(boundary_nodes, m::Integer, n::Integer) = get_boundary_nodes(get_boundary_nodes(boundary_nodes, m), n) -@inline get_boundary_nodes(boundary_nodes, (m, n)::NTuple{2,Integer}) = get_boundary_nodes(boundary_nodes, m, n) # for indexing from a boundary map +@inline get_boundary_nodes(boundary_nodes, (m, n)::NTuple{2, Integer}) = get_boundary_nodes(boundary_nodes, m, n) # for indexing from a boundary map @inline get_boundary_nodes(boundary_nodes::A, ::A) where {A} = boundary_nodes # for indexing from a boundary map -@inline get_boundary_nodes(boundary_nodes::A, ::A) where {A<:Tuple{Integer,Integer}} = boundary_nodes # ambiguity -@inline get_boundary_nodes(boundary_nodes::A, ::A) where {A<:Integer} = boundary_nodes # ambiguity +@inline get_boundary_nodes(boundary_nodes::A, ::A) where {A <: Tuple{Integer, Integer}} = boundary_nodes # ambiguity +@inline get_boundary_nodes(boundary_nodes::A, ::A) where {A <: Integer} = boundary_nodes # ambiguity """ each_boundary_node(boundary_nodes) -> Iterator @@ -286,7 +286,7 @@ end This works for any form of `boundary_nodes`. """ -@inline function construct_ghost_vertex_map(boundary_nodes, IntegerType::Type{I}=number_type(boundary_nodes)) where {I} +@inline function construct_ghost_vertex_map(boundary_nodes, IntegerType::Type{I} = number_type(boundary_nodes)) where {I} if has_multiple_curves(boundary_nodes) return _construct_ghost_vertex_map_multiple_curves(boundary_nodes, IntegerType) elseif has_multiple_sections(boundary_nodes) @@ -296,7 +296,7 @@ This works for any form of `boundary_nodes`. end end function _construct_ghost_vertex_map_multiple_curves(boundary_nodes, IntegerType::Type{I}) where {I} - dict = Dict{I,NTuple{2,I}}() + dict = Dict{I, NTuple{2, I}}() nc = num_curves(boundary_nodes) current_idx = I(𝒢) for m in 1:nc @@ -310,7 +310,7 @@ function _construct_ghost_vertex_map_multiple_curves(boundary_nodes, IntegerType return dict end function _construct_ghost_vertex_map_multiple_sections(boundary_nodes, IntegerType::Type{I}) where {I} - dict = Dict{I,I}() + dict = Dict{I, I}() ns = num_sections(boundary_nodes) current_idx = I(𝒢) for n in 1:ns @@ -372,9 +372,11 @@ Dict{Tuple{Int64, Int64}, Tuple{Tuple{Int64, Int64}, Int64}} with 12 entries: (85, 91) => ((2, 2), 3) ``` """ -@inline function construct_boundary_edge_map(boundary_nodes::A, - IntegerType::Type{I}=number_type(boundary_nodes), - EdgeType::Type{E}=NTuple{2,IntegerType}) where {A,I,E} +@inline function construct_boundary_edge_map( + boundary_nodes::A, + IntegerType::Type{I} = number_type(boundary_nodes), + EdgeType::Type{E} = NTuple{2, IntegerType}, + ) where {A, I, E} if has_multiple_curves(boundary_nodes) return _construct_boundary_edge_map_multiple_curves(boundary_nodes, IntegerType, EdgeType) elseif has_multiple_sections(boundary_nodes) @@ -383,8 +385,8 @@ Dict{Tuple{Int64, Int64}, Tuple{Tuple{Int64, Int64}, Int64}} with 12 entries: return _construct_boundary_edge_map_contiguous(boundary_nodes, IntegerType, EdgeType) end end -function _construct_boundary_edge_map_multiple_curves(boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}) where {I,E} - dict = Dict{E,Tuple{NTuple{2,I},I}}() +function _construct_boundary_edge_map_multiple_curves(boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}) where {I, E} + dict = Dict{E, Tuple{NTuple{2, I}, I}}() nc = num_curves(boundary_nodes) for m in 1:nc bn_m = get_boundary_nodes(boundary_nodes, m) @@ -402,8 +404,8 @@ function _construct_boundary_edge_map_multiple_curves(boundary_nodes, IntegerTyp end return dict end -function _construct_boundary_edge_map_multiple_sections(boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}) where {I,E} - dict = Dict{E,NTuple{2,I}}() +function _construct_boundary_edge_map_multiple_sections(boundary_nodes, IntegerType::Type{I}, EdgeType::Type{E}) where {I, E} + dict = Dict{E, NTuple{2, I}}() ns = num_sections(boundary_nodes) for n in 1:ns bn_n = get_boundary_nodes(boundary_nodes, n) @@ -417,8 +419,8 @@ function _construct_boundary_edge_map_multiple_sections(boundary_nodes, IntegerT end return dict end -function _construct_boundary_edge_map_contiguous(boundary_nodes::A, IntegerType::Type{I}, EdgeType::Type{E}) where {A,I,E} - dict = Dict{E,Tuple{A,I}}() +function _construct_boundary_edge_map_contiguous(boundary_nodes::A, IntegerType::Type{I}, EdgeType::Type{E}) where {A, I, E} + dict = Dict{E, Tuple{A, I}}() ne = num_boundary_edges(boundary_nodes) for ℓ in 1:ne u = get_boundary_nodes(boundary_nodes, ℓ) @@ -656,7 +658,7 @@ Dict{Int64, UnitRange{Int64}} with 7 entries: -6 => -7:-4 ``` """ -@inline function construct_ghost_vertex_ranges(boundary_nodes, IntegerType::Type{I}=number_type(boundary_nodes)) where {I} +@inline function construct_ghost_vertex_ranges(boundary_nodes, IntegerType::Type{I} = number_type(boundary_nodes)) where {I} if has_multiple_curves(boundary_nodes) return _construct_ghost_vertex_ranges_multiple_curves(boundary_nodes, IntegerType) elseif has_multiple_sections(boundary_nodes) @@ -668,7 +670,7 @@ end function _construct_ghost_vertex_ranges_multiple_curves(boundary_nodes, IntegerType::Type{I}) where {I} start = I(𝒢) current_ghost_vertex = I(𝒢) - dict = Dict{I,UnitRange{I}}() + dict = Dict{I, UnitRange{I}}() nc = num_curves(boundary_nodes) for i in 1:nc bn = get_boundary_nodes(boundary_nodes, i) @@ -684,9 +686,9 @@ function _construct_ghost_vertex_ranges_multiple_curves(boundary_nodes, IntegerT end function _construct_ghost_vertex_ranges_multiple_sections(boundary_nodes, IntegerType::Type{I}) where {I} current_ghost_vertex = I(𝒢) - dict = Dict{I,UnitRange{I}}() + dict = Dict{I, UnitRange{I}}() ns = num_sections(boundary_nodes) - range = (current_ghost_vertex-ns+1):current_ghost_vertex + range = (current_ghost_vertex - ns + 1):current_ghost_vertex for _ in 1:ns dict[current_ghost_vertex] = range current_ghost_vertex -= 1 @@ -695,7 +697,7 @@ function _construct_ghost_vertex_ranges_multiple_sections(boundary_nodes, Intege end function _construct_ghost_vertex_ranges_contiguous(IntegerType::Type{I}) where {I} current_ghost_vertex = I(𝒢) - dict = Dict{I,UnitRange{I}}() + dict = Dict{I, UnitRange{I}}() dict[current_ghost_vertex] = current_ghost_vertex:current_ghost_vertex return dict end @@ -734,4 +736,4 @@ end end @inline function _get_skeleton_contiguous(boundary_nodes, ::Type{I}) where {I} return I[] -end \ No newline at end of file +end diff --git a/src/geometric_primitives/edges.jl b/src/geometric_primitives/edges.jl index 3f1c0363b..3adbdec50 100644 --- a/src/geometric_primitives/edges.jl +++ b/src/geometric_primitives/edges.jl @@ -17,9 +17,9 @@ julia> DelaunayTriangulation.construct_edge(Vector{Int32}, 5, 15) ``` """ construct_edge -construct_edge(::Type{NTuple{2,I}}, i, j) where {I} = (I(i), I(j)) +construct_edge(::Type{NTuple{2, I}}, i, j) where {I} = (I(i), I(j)) construct_edge(::Type{Vector{I}}, i, j) where {I} = I[i, j] -construct_edge(::Type{A}, i, j) where {I,A<:AbstractVector{I}} = A(I[i, j]) +construct_edge(::Type{A}, i, j) where {I, A <: AbstractVector{I}} = A(I[i, j]) """ initial(e) -> Vertex @@ -140,9 +140,9 @@ true ``` """ function compare_unoriented_edges(u, v) - i, j = edge_vertices(u) - k, ℓ = edge_vertices(v) - return (i, j) == (k, ℓ) || (i, j) == (ℓ, k) + i, j = edge_vertices(u) + k, ℓ = edge_vertices(v) + return (i, j) == (k, ℓ) || (i, j) == (ℓ, k) end """ @@ -299,9 +299,9 @@ Set{Tuple{Int64, Int64}} with 7 elements: ``` """ function add_edge!(E, e...) - for v in e - add_to_edges!(E, v) - end + for v in e + add_to_edges!(E, v) + end end """ @@ -364,9 +364,9 @@ Set{Vector{Int64}} with 2 elements: ``` """ function delete_edge!(E, e...) - for v in e - delete_from_edges!(E, v) - end + for v in e + delete_from_edges!(E, v) + end end """ @@ -443,11 +443,11 @@ random_edge(rng, E) = rand(rng, E) Tests if the edge collections `E` and `F` are equal, ignoring edge orientation. """ function compare_unoriented_edge_collections(E, F) - num_edges(E) ≠ num_edges(F) && return false - for e in each_edge(E) - contains_unoriented_edge(e, F) || return false - end - return true + num_edges(E) ≠ num_edges(F) && return false + for e in each_edge(E) + contains_unoriented_edge(e, F) || return false + end + return true end """ @@ -458,4 +458,4 @@ Returns `true` if `e` and `e′` have any shared vertex, and `false` otherwise. function edges_are_disjoint(e, e′) w = get_shared_vertex(e, e′) return w == ∅ -end \ No newline at end of file +end diff --git a/src/geometric_primitives/points.jl b/src/geometric_primitives/points.jl index ecbd4f35b..b60ddea09 100644 --- a/src/geometric_primitives/points.jl +++ b/src/geometric_primitives/points.jl @@ -150,7 +150,7 @@ Tests if `p` represents a point in the plane. By default, this returns the resul eltype(p) <: Number && length(p) == 2 """ -is_point2(p) = eltype(p) <: Number && length(p) == 2 +is_point2(p) = eltype(p) <: Number && length(p) == 2 """ is_point3(p) -> Bool @@ -220,8 +220,8 @@ NTuple{4, Tuple{Float64, Float64}} ``` """ get_point -get_point(points, i) = getpoint(points, i) -get_point(points, i::Vararg{Any,N}) where {N} = ntuple(j -> get_point(points, i[j]), Val(N)) +get_point(points, i) = getpoint(points, i) +get_point(points, i::Vararg{Any, N}) where {N} = ntuple(j -> get_point(points, i[j]), Val(N)) @doc """ each_point_index(points) -> Iterator @@ -326,9 +326,9 @@ false function points_are_unique(points) n = num_points(points) T = number_type(points) - seen = Set{NTuple{2,T}}() + seen = Set{NTuple{2, T}}() sizehint!(seen, n) - for i in each_point_index(points) + for i in each_point_index(points) p = get_point(points, i) p ∈ seen && return false push!(seen, p) @@ -406,9 +406,9 @@ julia> DelaunayTriangulation.push_point!(points, (17.3, 5.0)) ``` """ push_point! -push_point!(points::AbstractVector{T}, x, y) where {F,T<:NTuple{2,F}} = push!(points, (F(x), F(y))) -push_point!(points::AbstractVector{T}, x, y) where {F<:Number,T<:AbstractVector{F}} = push!(points, F[x, y]) -push_point!(points::AbstractMatrix{T}, x, y) where {T<:Number} = append!(points, (x, y)) # ElasticArrays +push_point!(points::AbstractVector{T}, x, y) where {F, T <: NTuple{2, F}} = push!(points, (F(x), F(y))) +push_point!(points::AbstractVector{T}, x, y) where {F <: Number, T <: AbstractVector{F}} = push!(points, F[x, y]) +push_point!(points::AbstractMatrix{T}, x, y) where {T <: Number} = append!(points, (x, y)) # ElasticArrays push_point!(points, p) = push_point!(points, getx(p), gety(p)) @doc """ @@ -474,7 +474,7 @@ julia> (1.0 + 17.3)/2, (2.0 + 5.3)/2 (9.15, 3.65) ``` """ -function mean_points(points, vertices=each_point_index(points)) +function mean_points(points, vertices = each_point_index(points)) F = number_type(points) x = zero(F) y = zero(F) @@ -558,7 +558,7 @@ Returns a `Dict` of `points` that maps each duplicate point to a `Vector` of the function find_duplicate_points(points) T = number_type(points) n = num_points(points) - dup_seen = Dict{NTuple{2,T},Vector{Int}}() + dup_seen = Dict{NTuple{2, T}, Vector{Int}}() sizehint!(dup_seen, n) for i in each_point_index(points) p = get_point(points, i) @@ -569,4 +569,4 @@ function find_duplicate_points(points) length(ivec) > 1 end return dup_seen -end \ No newline at end of file +end diff --git a/src/geometric_primitives/triangles.jl b/src/geometric_primitives/triangles.jl index a9333b336..78833b191 100644 --- a/src/geometric_primitives/triangles.jl +++ b/src/geometric_primitives/triangles.jl @@ -18,9 +18,9 @@ julia> DelaunayTriangulation.construct_triangle(Vector{Int32}, 1, 2, 3) ``` """ construct_triangle -construct_triangle(::Type{NTuple{3,I}}, i, j, k) where {I} = (I(i), I(j), I(k)) +construct_triangle(::Type{NTuple{3, I}}, i, j, k) where {I} = (I(i), I(j), I(k)) construct_triangle(::Type{Vector{I}}, i, j, k) where {I} = I[i, j, k] -construct_triangle(::Type{A}, i, j, k) where {I,A<:AbstractVector{I}} = A(I[i, j, k]) +construct_triangle(::Type{A}, i, j, k) where {I, A <: AbstractVector{I}} = A(I[i, j, k]) """ geti(T) -> Vertex @@ -190,7 +190,7 @@ julia> DelaunayTriangulation.rotate_triangle(T, 3) (1, 2, 3) ``` """ -function rotate_triangle(T::V, ::Val{N}) where {N,V} +function rotate_triangle(T::V, ::Val{N}) where {N, V} i, j, k = triangle_vertices(T) N < 0 && throw(ArgumentError("Cannot rotate triangle $T by a negative amount.")) if N == 0 @@ -256,7 +256,7 @@ julia> DelaunayTriangulation.construct_positively_oriented_triangle(Vector{Int}, 3 ``` """ -function construct_positively_oriented_triangle(::Type{V}, i, j, k, points, predicates::AbstractPredicateKernel=AdaptiveKernel()) where {V} +function construct_positively_oriented_triangle(::Type{V}, i, j, k, points, predicates::AbstractPredicateKernel = AdaptiveKernel()) where {V} p, q, r = get_point(points, i, j, k) orientation = triangle_orientation(predicates, p, q, r) if is_negatively_oriented(orientation) @@ -302,8 +302,8 @@ function compare_triangles(T, V) i, j, k = triangle_vertices(T) u, v, w = triangle_vertices(V) return (i, j, k) == (u, v, w) || - (i, j, k) == (v, w, u) || - (i, j, k) == (w, u, v) + (i, j, k) == (v, w, u) || + (i, j, k) == (w, u, v) end @doc """ @@ -338,7 +338,7 @@ julia> DelaunayTriangulation.contains_triangle(9, 7, 8, V) ``` """ contains_triangle -function contains_triangle(T::F, V::S) where {F,S} +function contains_triangle(T::F, V::S) where {F, S} if F ≠ triangle_type(S) i, j, k = triangle_vertices(T) Tfix = construct_triangle(triangle_type(S), i, j, k) @@ -433,7 +433,7 @@ Set{Tuple{Int64, Int64, Int64}} with 4 elements: (-1, 3, 6) ``` """ -function add_to_triangles!(T::Ts, V::VT) where {Ts,VT} +function add_to_triangles!(T::Ts, V::VT) where {Ts, VT} if VT ≠ triangle_type(Ts) i, j, k = triangle_vertices(V) U = construct_triangle(triangle_type(Ts), i, j, k) @@ -672,4 +672,4 @@ function sort_triangles(T::Ts) where {Ts} add_to_triangles!(V, σ) end return V -end \ No newline at end of file +end diff --git a/src/predicates.jl b/src/predicates.jl index 5b17437a9..f8a469722 100644 --- a/src/predicates.jl +++ b/src/predicates.jl @@ -19,7 +19,7 @@ should be used, avoiding adaptivity and exact arithmetic. See also [`ExactKernel`](@ref) and [`AdaptiveKernel`](@ref). """ -struct FastKernel <: AbstractPredicateKernel end +struct FastKernel <: AbstractPredicateKernel end """ ExactKernel() @@ -28,7 +28,7 @@ Pass this to predicates to use ExactPredicates.jl for computing predicates. See also [`FastKernel`](@ref) and [`AdaptiveKernel`](@ref). """ -struct ExactKernel <: AbstractPredicateKernel end +struct ExactKernel <: AbstractPredicateKernel end """ AdaptiveKernel() @@ -37,9 +37,9 @@ Pass this to predicates to use AdaptivePredicates.jl for computing predicates. See also [`FastKernel`](@ref) and [`ExactKernel`](@ref). """ -struct AdaptiveKernel <: AbstractPredicateKernel end +struct AdaptiveKernel <: AbstractPredicateKernel end include("predicates/certificate.jl") include("predicates/predicate_definitions.jl") include("predicates/predicates.jl") -include("predicates/boundaries_and_ghosts.jl") \ No newline at end of file +include("predicates/boundaries_and_ghosts.jl") diff --git a/src/predicates/boundaries_and_ghosts.jl b/src/predicates/boundaries_and_ghosts.jl index c42eb81a8..182736533 100644 --- a/src/predicates/boundaries_and_ghosts.jl +++ b/src/predicates/boundaries_and_ghosts.jl @@ -3,7 +3,7 @@ Tests if `i` is a ghost vertex, meaning `i ≤ $𝒢`. """ -is_ghost_vertex(i::I) where {I<:Integer} = i ≤ I(𝒢) +is_ghost_vertex(i::I) where {I <: Integer} = i ≤ I(𝒢) is_ghost_vertex(i) = false # in case we provide a point instead of an integer """ @@ -121,4 +121,4 @@ function is_boundary_node(tri::Triangulation, i) end I = integer_type(tri) return (false, I(∅)) -end \ No newline at end of file +end diff --git a/src/predicates/certificate.jl b/src/predicates/certificate.jl index 349b675dd..448cd808f 100644 --- a/src/predicates/certificate.jl +++ b/src/predicates/certificate.jl @@ -71,7 +71,7 @@ for inst in instances(Certificate.T) Returns `true` if `cert` is `$($name)`, and `false` otherwise. """ ($(Symbol("is_$(lowercase(name))")))(cert::Certificate.T) = cert == $inst - end + end end """ is_positively_oriented(cert::Certificate) -> Bool @@ -128,4 +128,4 @@ Given `cert ∈ (-1, 0, 1)`, return `Cert1`, `Cert2` or `Cert3` depending on if end end -const Cert = Certificate \ No newline at end of file +const Cert = Certificate diff --git a/src/predicates/predicate_definitions.jl b/src/predicates/predicate_definitions.jl index c957e906b..0e97343ec 100644 --- a/src/predicates/predicate_definitions.jl +++ b/src/predicates/predicate_definitions.jl @@ -276,9 +276,9 @@ See the documentation for more information about these choices. return -1 elseif pqa == 0 && pqb == 0 if sameside_predicate(a, b, p) == 1 && - sameside_predicate(a, b, q) == 1 && - sameside_predicate(p, q, a) == 1 && - sameside_predicate(p, q, b) == 1 + sameside_predicate(a, b, q) == 1 && + sameside_predicate(p, q, a) == 1 && + sameside_predicate(p, q, b) == 1 return -1 else return 0 @@ -287,4 +287,4 @@ See the documentation for more information about these choices. return 0 end end -@inline meet_predicate(p, q, a, b) = meet_predicate(AdaptiveKernel(), p, q, a, b) \ No newline at end of file +@inline meet_predicate(p, q, a, b) = meet_predicate(AdaptiveKernel(), p, q, a, b) diff --git a/src/predicates/predicates.jl b/src/predicates/predicates.jl index 9c0381202..4cfc2f7d1 100644 --- a/src/predicates/predicates.jl +++ b/src/predicates/predicates.jl @@ -16,8 +16,10 @@ See the documentation for more information about these choices. triangle_orientation function triangle_orientation(kernel::AbstractPredicateKernel, p, q, r) cert = orient_predicate(kernel, p, q, r) - return convert_certificate(cert, Cert.NegativelyOriented, Cert.Degenerate, - Cert.PositivelyOriented) + return convert_certificate( + cert, Cert.NegativelyOriented, Cert.Degenerate, + Cert.PositivelyOriented, + ) end triangle_orientation(p, q, r) = triangle_orientation(AdaptiveKernel(), p, q, r) function triangle_orientation(kernel::AbstractPredicateKernel, tri::Triangulation, i, j, k) @@ -334,9 +336,9 @@ is_legal(p, q, r, s) = is_legal(AdaptiveKernel(), p, q, r, s) function is_legal(kernel::AbstractPredicateKernel, tri::Triangulation, i, j) if contains_segment(tri, i, j) || - is_boundary_edge(tri, j, i) || is_boundary_edge(tri, i, j) || - !edge_exists(tri, i, j) || !edge_exists(tri, j, i) || - is_ghost_edge(i, j) + is_boundary_edge(tri, j, i) || is_boundary_edge(tri, i, j) || + !edge_exists(tri, i, j) || !edge_exists(tri, j, i) || + is_ghost_edge(i, j) return Cert.Legal else k = get_adjacent(tri, i, j) @@ -573,8 +575,8 @@ function point_position_relative_to_circumcircle(kernel::AbstractPredicateKernel else cert = point_position_relative_to_witness_plane(kernel, tri, i, j, k, ℓ) return is_above(cert) ? Cert.Outside : - is_below(cert) ? Cert.Inside : - Cert.On + is_below(cert) ? Cert.Inside : + Cert.On end end point_position_relative_to_circumcircle(tri::Triangulation, i, j, k, ℓ) = point_position_relative_to_circumcircle(AdaptiveKernel(), tri, i, j, k, ℓ) @@ -698,7 +700,7 @@ To test if a point `r` is inside the diametral lens with lens angle `θ°`, we s at that point, i.e. the angle at `r` in the triangle `pqr`. If this angle is greater than `180° - 2θ°`, then `r` is inside of the lens. This result comes from [Shewchuk (2002)](https://doi.org/10.1016/S0925-7721(01)00047-5). Note that this is the same as a diametral circle in the case `θ° = 45°`. """ -function point_position_relative_to_diametral_lens(p, q, r, lens_angle=30.0) +function point_position_relative_to_diametral_lens(p, q, r, lens_angle = 30.0) px, py = getxy(p) qx, qy = getxy(q) rx, ry = getxy(r) @@ -737,7 +739,7 @@ the two does not intersect any segments. - `cert`: A [`Certificate`](@ref). This will be `Visible` if `i` is visible from `q`, and `Invisible` otherwise. """ function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, q, i) - V, invisible_flag = find_triangle(tri, q; use_barriers=Val(true), k=i, concavity_protection=true, predicates=kernel) + V, invisible_flag = find_triangle(tri, q; use_barriers = Val(true), k = i, concavity_protection = true, predicates = kernel) if invisible_flag return Certificate.Invisible else @@ -767,7 +769,7 @@ of `(u, v)` can see `i`. To test this, we only check `10` points equally spaced # Outputs - `cert`: A [`Certificate`](@ref). This will be `Visible` if `i` is visible from `(u, v)`, and `Invisible` otherwise. """ -function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, u, v, i; shift=0.0, attractor=get_point(tri, i)) +function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, u, v, i; shift = 0.0, attractor = get_point(tri, i)) pu, pv = get_point(tri, u, v) pux, puy = getxy(pu) pvx, pvy = getxy(pv) @@ -781,4 +783,4 @@ function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, u, end return Cert.Invisible end -test_visibility(tri::Triangulation, u, v, i; shift=0.0, attractor=get_point(tri, i)) = test_visibility(AdaptiveKernel(), tri, u, v, i; shift, attractor) \ No newline at end of file +test_visibility(tri::Triangulation, u, v, i; shift = 0.0, attractor = get_point(tri, i)) = test_visibility(AdaptiveKernel(), tri, u, v, i; shift, attractor) diff --git a/src/public.jl b/src/public.jl index f040859b6..7ec594871 100644 --- a/src/public.jl +++ b/src/public.jl @@ -1,6 +1,7 @@ @static if VERSION >= v"1.11.0-DEV.469" - eval(Meta.parse( - """ + eval( + Meta.parse( + """ public Adjacent, Adjacent2Vertex, ConvexHull, @@ -276,5 +277,7 @@ angle_is_acute_predicate, sameside_predicate, meet_predicate - """)) -end \ No newline at end of file + """, + ), + ) +end diff --git a/src/setup.jl b/src/setup.jl index 646b8f777..c3acdc3c0 100644 --- a/src/setup.jl +++ b/src/setup.jl @@ -37,7 +37,7 @@ for mesh refinement when using [`check_precision`](@ref) to avoid degenerate circumcenters. """ ε(::Type{T}) where {T} = sqrt(eps(T)) -ε(x) = ε(number_type(x)) +ε(x) = ε(number_type(x)) const INF_WARN = Ref(true) """ @@ -54,4 +54,4 @@ toggle_inf_warn!() = (INF_WARN[] = !INF_WARN[]) else return esc(field) end -end \ No newline at end of file +end diff --git a/src/utils.jl b/src/utils.jl index bd2257ebd..146a8041b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,2 +1,2 @@ include("utils/geometry_utils.jl") -include("utils/utils.jl") \ No newline at end of file +include("utils/utils.jl") diff --git a/src/utils/geometry_utils.jl b/src/utils/geometry_utils.jl index 1c610436d..d376bc300 100644 --- a/src/utils/geometry_utils.jl +++ b/src/utils/geometry_utils.jl @@ -129,7 +129,7 @@ function polygon_features(points, boundary_nodes) return polygon_features_single_segment(points, boundary_nodes) end end -function polygon_features_single_segment(points, boundary_nodes; scale=Val(true)) +function polygon_features_single_segment(points, boundary_nodes; scale = Val(true)) F = number_type(points) cx = zero(F) cy = zero(F) @@ -138,7 +138,7 @@ function polygon_features_single_segment(points, boundary_nodes; scale=Val(true) vᵢ = get_boundary_nodes(boundary_nodes, 1) pᵢ = get_point(points, vᵢ) xᵢ, yᵢ = getxy(pᵢ) - for j in 2:(n_edge+1) + for j in 2:(n_edge + 1) vᵢ₊₁ = get_boundary_nodes(boundary_nodes, j) pᵢ₊₁ = get_point(points, vᵢ₊₁) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) @@ -162,8 +162,10 @@ function polygon_features_multiple_segments(points, boundary_nodes) ns = num_sections(boundary_nodes) for i in 1:ns bn = get_boundary_nodes(boundary_nodes, i) - sub_a, (sub_cx, sub_cy) = polygon_features_single_segment(points, bn; - scale=Val(false)) + sub_a, (sub_cx, sub_cy) = polygon_features_single_segment( + points, bn; + scale = Val(false), + ) a += sub_a cx += sub_cx cy += sub_cy @@ -223,7 +225,7 @@ function distance_to_polygon(q, points, boundary_nodes) return distance_to_polygon_single_segment(q, points, boundary_nodes) end end -function distance_to_polygon_single_segment(q, points, boundary_nodes, is_in_outer=false; return_sqrt=Val(true)) +function distance_to_polygon_single_segment(q, points, boundary_nodes, is_in_outer = false; return_sqrt = Val(true)) x, y = getxy(q) F = number_type(points) dist = typemax(F) @@ -231,7 +233,7 @@ function distance_to_polygon_single_segment(q, points, boundary_nodes, is_in_out vᵢ = get_boundary_nodes(boundary_nodes, 1) pᵢ = get_point(points, vᵢ) xᵢ, yᵢ = getxy(pᵢ) - for j in 2:(n_edge+1) + for j in 2:(n_edge + 1) vᵢ₊₁ = get_boundary_nodes(boundary_nodes, j) pᵢ₊₁ = get_point(points, vᵢ₊₁) xᵢ₊₁, yᵢ₊₁ = getxy(pᵢ₊₁) @@ -248,13 +250,13 @@ function distance_to_polygon_single_segment(q, points, boundary_nodes, is_in_out dist = is_true(return_sqrt) ? sqrt(dist) : dist return is_in_outer ? dist : -dist end -function distance_to_polygon_multiple_segments(q, points, boundary_nodes, is_in_outer=-one(number_type(points)); return_sqrt=Val(true)) +function distance_to_polygon_multiple_segments(q, points, boundary_nodes, is_in_outer = -one(number_type(points)); return_sqrt = Val(true)) F = number_type(points) dist = typemax(F) ns = num_sections(boundary_nodes) for i in 1:ns bn = get_boundary_nodes(boundary_nodes, i) - new_dist = distance_to_polygon_single_segment(q, points, bn, is_in_outer == one(F); return_sqrt=Val(false)) + new_dist = distance_to_polygon_single_segment(q, points, bn, is_in_outer == one(F); return_sqrt = Val(false)) is_in_outer = sign(new_dist) new_dist = abs(new_dist) dist = new_dist < dist ? new_dist : dist @@ -269,8 +271,10 @@ function distance_to_polygon_multiple_curves(q, points, boundary_nodes) nc = num_curves(boundary_nodes) for i in 1:nc bn = get_boundary_nodes(boundary_nodes, i) - new_dist = distance_to_polygon_multiple_segments(q, points, bn, is_in_outer == one(F); - return_sqrt=Val(false)) + new_dist = distance_to_polygon_multiple_segments( + q, points, bn, is_in_outer == one(F); + return_sqrt = Val(false), + ) is_in_outer = sign(new_dist) new_dist = abs(new_dist) dist = new_dist < dist ? new_dist : dist @@ -284,7 +288,7 @@ end Computes the bounding box of the polygon defined by `(points, boundary_nodes)`. The `boundary_nodes` must match the specification in the documentation and in [`check_args`](@ref). If `check_all_curves` is `true`, then the bounding box of the union of all curves of the `polygon` is computed instead of just the first curve. """ -function polygon_bounds(points, boundary_nodes, check_all_curves=Val(false)) +function polygon_bounds(points, boundary_nodes, check_all_curves = Val(false)) if has_multiple_curves(boundary_nodes) if !is_true(check_all_curves) return polygon_bounds_multiple_segments(points, get_boundary_nodes(boundary_nodes, 1)) # 1 is the outermost boundary, unless you have a multiple polygon. PolygonHierarchy would be better for this but too bad @@ -349,7 +353,7 @@ function sort_convex_polygon!(vertices, points) cx, cy = mean_points(points, vertices) to_angle = p -> atan(gety(p) - cy, getx(p) - cx) vert_to_angle = v -> to_angle(get_point(points, v)) - sort!(vertices, by=vert_to_angle) + sort!(vertices, by = vert_to_angle) return vertices end @@ -453,4 +457,4 @@ function angle_between(p, q) a = px * qx + py * qy b = px * -qy + py * qx return mod(atan(b, a), 2π) -end \ No newline at end of file +end diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 9fd35e458..1dbff9803 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -34,7 +34,7 @@ Float64 """ number_type number_type(x) = number_type(typeof(x)) -number_type(::Type{T}) where {T<:AbstractArray} = number_type(eltype(T)) +number_type(::Type{T}) where {T <: AbstractArray} = number_type(eltype(T)) number_type(x::Type{<:NTuple{N}}) where {N} = eltype(x) number_type(::Type{Tuple{}}) = Any number_type(::Type{T}) where {T} = T @@ -133,12 +133,12 @@ is_circular(A) = isempty(A) || (A[begin] == A[end]) Compares the two circular vectors `A` and `B` for equality up to circular rotation, using `by` to compare individual elements. """ -function circular_equality(A, B, by=isequal) +function circular_equality(A, B, by = isequal) @assert is_circular(A) && is_circular(B) "A and B must be circular" length(A) ≠ length(B) && return false isempty(A) && return true # isempty(B) is true as well because of the previous assertion - _A = @views A[begin:(end-1)] - _B = @views B[begin:(end-1)] + _A = @views A[begin:(end - 1)] + _B = @views B[begin:(end - 1)] same_idx = findfirst(by(_A[begin]), _B) same_idx === nothing && return false n = length(_A) @@ -505,7 +505,7 @@ end Returns the unique elements of `A` up to tolerance `tol`. We say that two values `x` and `y` are within tolerance if `abs(u - v) ≤ M*tol`, where `M = maximum(abs.(A))`. It is assumed that `A` is sorted - this is NOT checked. """ -function uniquetol(A::Vector{Float64}; tol=1e-12) +function uniquetol(A::Vector{Float64}; tol = 1.0e-12) isempty(A) && return Float64[] M = max(abs(A[begin]), abs(A[end])) # assuming A is sorted intol = (x, y) -> abs(x - y) ≤ M * tol @@ -524,14 +524,14 @@ end Evaluates `f(tup[idx])` in a type-stable way. If `idx > length(tup)`, then `f` is evaluated on the last element of `tup`. """ -@inline function eval_fnc_at_het_tuple_element(f::F, tup::T, idx) where {F,T} +@inline function eval_fnc_at_het_tuple_element(f::F, tup::T, idx) where {F, T} return _eval_fnc_at_het_tuple_element(f, idx, tup...) end -@inline function _eval_fnc_at_het_tuple_element(f::F, idx, el::E, tup...) where {F,E} +@inline function _eval_fnc_at_het_tuple_element(f::F, idx, el::E, tup...) where {F, E} idx == 1 && return _eval_fnc_at_het_tuple_element(f, 1, el) return _eval_fnc_at_het_tuple_element(f, idx - 1, tup...) end -@inline function _eval_fnc_at_het_tuple_element(f::F, idx, el::E) where {F,E} +@inline function _eval_fnc_at_het_tuple_element(f::F, idx, el::E) where {F, E} return f(el) end @@ -540,21 +540,21 @@ end Evaluates `f(tup[idx1], tup[idx2])` in a type-stable way. """ -@inline function eval_fnc_at_het_tuple_two_elements(f::F, tup::T, idx1, idx2) where {F,T<:Tuple} +@inline function eval_fnc_at_het_tuple_two_elements(f::F, tup::T, idx1, idx2) where {F, T <: Tuple} return _eval_fnc_at_het_tuple_two_elements(f, idx2, tup, idx1, tup...) end -@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, next_tup::T, idx1, el::E, tup...) where {F,E,T<:Tuple} +@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, next_tup::T, idx1, el::E, tup...) where {F, E, T <: Tuple} idx1 == 1 && return _eval_fnc_at_het_tuple_two_elements(f, idx2, next_tup, 1, el) return _eval_fnc_at_het_tuple_two_elements(f, idx2, next_tup, idx1 - 1, tup...) end -@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, next_tup::T, idx1, el::E) where {F,E,T<:Tuple} +@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, next_tup::T, idx1, el::E) where {F, E, T <: Tuple} return _eval_fnc_at_het_tuple_two_elements(f, idx2, el, next_tup...) end -@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, el::E, el2::V, tup...) where {F,E,V} +@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, el::E, el2::V, tup...) where {F, E, V} idx2 == 1 && return _eval_fnc_at_het_tuple_two_elements(f, 1, el, el2) return _eval_fnc_at_het_tuple_two_elements(f, idx2 - 1, el, tup...) end -@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, el::E, el2::V) where {F,E,V} +@inline function _eval_fnc_at_het_tuple_two_elements(f::F, idx2, el::E, el2::V) where {F, E, V} return f(el, el2) end @@ -563,14 +563,14 @@ end Evaluates `f(tup[idx], arg...)` in a type-stable way. If `idx > length(tup)`, then `f` is evaluated on the last element of `tup`. """ -@inline function eval_fnc_at_het_tuple_element_with_arg(f::F, tup::T, arg, idx) where {F,T} +@inline function eval_fnc_at_het_tuple_element_with_arg(f::F, tup::T, arg, idx) where {F, T} return _eval_fnc_at_het_tuple_element_with_arg(f, idx, arg, tup...) end -@inline function _eval_fnc_at_het_tuple_element_with_arg(f::F, idx, arg, el::E, tup...) where {F,E} +@inline function _eval_fnc_at_het_tuple_element_with_arg(f::F, idx, arg, el::E, tup...) where {F, E} idx == 1 && return _eval_fnc_at_het_tuple_element_with_arg(f, 1, arg, el) return _eval_fnc_at_het_tuple_element_with_arg(f, idx - 1, arg, tup...) end -@inline function _eval_fnc_at_het_tuple_element_with_arg(f::F, idx, arg, el::E) where {F,E} +@inline function _eval_fnc_at_het_tuple_element_with_arg(f::F, idx, arg, el::E) where {F, E} return f(el, arg...) end @@ -579,14 +579,14 @@ end Evaluates `f(prearg, tup[idx], arg...)` in a type-stable way. If `idx > length(tup)`, then `f` is evaluated on the last element of `tup`. """ -@inline function eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, tup::T, prearg, arg, idx) where {F,T} +@inline function eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, tup::T, prearg, arg, idx) where {F, T} return _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f, idx, prearg, arg, tup...) end -@inline function _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, idx, prearg, arg, el::E, tup...) where {F,E} - idx == 1 && return _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f, 1, prearg, arg, el) +@inline function _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, idx, prearg, arg, el::E, tup...) where {F, E} + idx == 1 && return _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f, 1, prearg, arg, el) return _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f, idx - 1, prearg, arg, tup...) end -@inline function _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, idx, prearg, arg, el::E) where {F,E} +@inline function _eval_fnc_at_het_tuple_element_with_arg_and_prearg(f::F, idx, prearg, arg, el::E) where {F, E} return f(prearg, el, arg...) end @@ -595,7 +595,7 @@ end Evaluates `tup[idx](arg...)` in a type-stable way. If `idx > length(tup)`, then `tup[end](arg...)` is evaluated. """ -@inline function eval_fnc_in_het_tuple(tup::T, arg::A, idx) where {T,A} +@inline function eval_fnc_in_het_tuple(tup::T, arg::A, idx) where {T, A} return eval_fnc_at_het_tuple_element_with_arg(self_eval, tup, arg, idx) end diff --git a/src/validation.jl b/src/validation.jl index 1b274bb4f..9443af630 100644 --- a/src/validation.jl +++ b/src/validation.jl @@ -35,10 +35,10 @@ end struct TriangleOrientationState <: AbstractTriangulationState flag::Bool - bad_triangle::NTuple{3,Int} + bad_triangle::NTuple{3, Int} triangle_orientation::Symbol end -TriangleOrientationState(tri; predicates::AbstractPredicateKernel=ExactKernel()) = test_triangle_orientation(tri; predicates) +TriangleOrientationState(tri; predicates::AbstractPredicateKernel = ExactKernel()) = test_triangle_orientation(tri; predicates) function Base.summary(state::TriangleOrientationState) if test_state(state) return "All the triangles have positive orientation." @@ -46,7 +46,7 @@ function Base.summary(state::TriangleOrientationState) return "The triangle $(state.bad_triangle) is $(state.triangle_orientation) oriented." end end -function test_triangle_orientation(tri; predicates::AbstractPredicateKernel=ExactKernel()) +function test_triangle_orientation(tri; predicates::AbstractPredicateKernel = ExactKernel()) for T in each_solid_triangle(tri) cert = triangle_orientation(predicates, tri, T) flag = is_positively_oriented(cert) @@ -58,10 +58,10 @@ end struct DelaunayCriterionState <: AbstractTriangulationState flag::Bool - bad_triangle::NTuple{3,Int} + bad_triangle::NTuple{3, Int} bad_vertex::Int end -DelaunayCriterionState(tri; predicates::AbstractPredicateKernel=ExactKernel()) = test_delaunay_criterion(tri; predicates) +DelaunayCriterionState(tri; predicates::AbstractPredicateKernel = ExactKernel()) = test_delaunay_criterion(tri; predicates) function Base.summary(state::DelaunayCriterionState) if test_state(state) return "All the triangles are Delaunay." @@ -73,12 +73,12 @@ function Base.summary(state::DelaunayCriterionState) end end end -function test_delaunay_criterion(tri; predicates::AbstractPredicateKernel=ExactKernel()) +function test_delaunay_criterion(tri; predicates::AbstractPredicateKernel = ExactKernel()) try points = get_points(tri) triangle_tree = BoundaryRTree(points) segment_tree = BoundaryRTree(points) - failures = Tuple{triangle_type(tri),integer_type(tri)}[] + failures = Tuple{triangle_type(tri), integer_type(tri)}[] for T in each_solid_triangle(tri) i, j, k = triangle_vertices(T) p, q, r = get_point(tri, i, j, k) @@ -106,7 +106,7 @@ function test_delaunay_criterion(tri; predicates::AbstractPredicateKernel=ExactK end for r in Random.shuffle(collect(each_solid_vertex(tri))) !isempty(failures) && break - intersects = get_intersections(triangle_tree, r, cache_id=1) # can't use multithreading here + intersects = get_intersections(triangle_tree, r, cache_id = 1) # can't use multithreading here for box in intersects i, j = get_edge(box) k = get_adjacent(tri, i, j) @@ -123,7 +123,7 @@ function test_delaunay_criterion(tri; predicates::AbstractPredicateKernel=ExactK for (i, j) in triangle_edges(i, j, k) contains_segment(tri, i, j) && continue # visibility is defined according to the relative interior of the simplex, which means that it's fine if a segment can see the vertex if rand() < 1 / 2 # just testing both - cert = test_visibility(predicates, tri, i, j, r, shift=0.01, attractor=c) + cert = test_visibility(predicates, tri, i, j, r, shift = 0.01, attractor = c) else cert = test_visibility(predicates, tri, segment_tree, i, j, r, c) end @@ -144,7 +144,7 @@ function test_delaunay_criterion(tri; predicates::AbstractPredicateKernel=ExactK rethrow(e) end end -function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, segment_tree, i, j, k, centroid=nothing) +function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, segment_tree, i, j, k, centroid = nothing) if is_boundary_edge(tri, j, i) i, j = j, i end @@ -180,7 +180,7 @@ function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, se ax, ay = getxy(a) xmin, ymin, xmax, ymax = min(mx, ax), min(my, ay), max(mx, ax), max(my, ay) bbox = BoundingBox(xmin, xmax, ymin, ymax) - intersections = get_intersections(segment_tree, bbox; cache_id=2) + intersections = get_intersections(segment_tree, bbox; cache_id = 2) for box in intersections u, v = get_edge(box) p′, q′ = get_point(tri, u, v) @@ -191,11 +191,11 @@ function test_visibility(kernel::AbstractPredicateKernel, tri::Triangulation, se end return all(flags) ? Cert.Invisible : Cert.Visible end -test_visibility(tri::Triangulation, segment_tree, i, j, k, centroid=nothing) = test_visibility(ExactKernel(), tri, segment_tree, i, j, k, centroid) +test_visibility(tri::Triangulation, segment_tree, i, j, k, centroid = nothing) = test_visibility(ExactKernel(), tri, segment_tree, i, j, k, centroid) struct EdgesHaveTwoIncidentTrianglesState <: AbstractTriangulationState flag::Bool - bad_edge::NTuple{2,Int} + bad_edge::NTuple{2, Int} end EdgesHaveTwoIncidentTrianglesState(tri) = test_each_edge_has_two_incident_triangles(tri) function Base.summary(state::EdgesHaveTwoIncidentTrianglesState) @@ -227,8 +227,8 @@ end struct AdjacentMapState <: AbstractTriangulationState flag::Bool - bad_triangle::NTuple{3,Int} - bad_edge::NTuple{2,Int} + bad_triangle::NTuple{3, Int} + bad_edge::NTuple{2, Int} bad_vertex::Int end AdjacentMapState(tri) = test_adjacent_map_matches_triangles(tri) @@ -255,10 +255,10 @@ end struct Adjacent2VertexMapState <: AbstractTriangulationState flag::Bool - bad_triangle::NTuple{3,Int} - bad_edge::NTuple{2,Int} + bad_triangle::NTuple{3, Int} + bad_edge::NTuple{2, Int} bad_vertex::Int - bad_edge_set::Set{NTuple{2,Int}} + bad_edge_set::Set{NTuple{2, Int}} end Adjacent2VertexMapState(tri) = test_adjacent2vertex_map_matches_triangles(tri) function Base.summary(state::Adjacent2VertexMapState) @@ -277,20 +277,20 @@ function test_adjacent2vertex_map_matches_triangles(tri) Su = get_adjacent2vertex(tri, u) flag = contains_edge(vw, Su) if !flag - _Su = Set{NTuple{2,Int}}(Int.(edge_vertices(e)) for e in each_edge(Su)) + _Su = Set{NTuple{2, Int}}(Int.(edge_vertices(e)) for e in each_edge(Su)) return Adjacent2VertexMapState(flag, Int.(triangle_vertices(T)), Int.((v, w)), Int(u), _Su) end end end - return Adjacent2VertexMapState(true, (∅, ∅, ∅), (∅, ∅), ∅, Set{NTuple{2,Int}}()) + return Adjacent2VertexMapState(true, (∅, ∅, ∅), (∅, ∅), ∅, Set{NTuple{2, Int}}()) end struct AdjacentMapAdjacent2VertexMapState <: AbstractTriangulationState flag::Bool bad_vertex::Int bad_vertex2::Int - bad_edge_set::Set{NTuple{2,Int}} - bad_edge::NTuple{2,Int} + bad_edge_set::Set{NTuple{2, Int}} + bad_edge::NTuple{2, Int} end AdjacentMapAdjacent2VertexMapState(tri) = test_adjacent_map_matches_adjacent2vertex_map(tri) function Base.summary(state::AdjacentMapAdjacent2VertexMapState) @@ -302,20 +302,20 @@ function Base.summary(state::AdjacentMapAdjacent2VertexMapState) end function test_adjacent_map_matches_adjacent2vertex_map(tri) for (k, S) in get_adjacent2vertex(get_adjacent2vertex(tri)) - _S = Set{NTuple{2,Int}}(Int.(edge_vertices(e)) for e in each_edge(S)) + _S = Set{NTuple{2, Int}}(Int.(edge_vertices(e)) for e in each_edge(S)) for e in each_edge(S) flag = get_adjacent(tri, e) == k !flag && return AdjacentMapAdjacent2VertexMapState(flag, Int(k), get_adjacent(tri, e), _S, Int.(edge_vertices(e))) end end clear_empty_features!(tri) - return AdjacentMapAdjacent2VertexMapState(true, ∅, ∅, Set{NTuple{2,Int}}(), (∅, ∅)) + return AdjacentMapAdjacent2VertexMapState(true, ∅, ∅, Set{NTuple{2, Int}}(), (∅, ∅)) end struct Adjacent2VertexMapAdjacentMapState <: AbstractTriangulationState flag::Bool bad_vertex::Int - bad_edge::NTuple{2,Int} + bad_edge::NTuple{2, Int} in_adjacent2vertex::Bool end Adjacent2VertexMapAdjacentMapState(tri) = test_adjacent2vertex_map_matches_adjacent_map(tri) @@ -373,7 +373,7 @@ end struct GraphAdjacentMapState <: AbstractTriangulationState flag::Bool - bad_edge::NTuple{2,Int} + bad_edge::NTuple{2, Int} end GraphAdjacentMapState(tri) = test_graph_matches_adjacent_map(tri) function Base.summary(state::GraphAdjacentMapState) @@ -406,8 +406,8 @@ end struct AdjacentMapGraphState <: AbstractTriangulationState flag::Bool bad_vertex::Int - bad_edge::NTuple{2,Int} - bad_edge_2::NTuple{2,Int} + bad_edge::NTuple{2, Int} + bad_edge_2::NTuple{2, Int} is_k::Bool adjacent_vertex::Int end @@ -438,8 +438,8 @@ end struct GraphTrianglesState <: AbstractTriangulationState flag::Bool - bad_triangle::NTuple{3,Int} - bad_edge::NTuple{2,Int} + bad_triangle::NTuple{3, Int} + bad_edge::NTuple{2, Int} bad_vertex::Int end GraphTrianglesState(tri) = test_graph_matches_triangles(tri) @@ -474,7 +474,7 @@ end struct SegmentState <: AbstractTriangulationState flag::Bool - segment::NTuple{2,Int} + segment::NTuple{2, Int} type::Int end SegmentState(tri) = test_segments(tri) @@ -505,8 +505,8 @@ function test_segments(tri) flag = edge_exists(tri, e) || edge_exists(tri, reverse_edge(e)) !flag && return SegmentState(flag, Int.(edge_vertices(e)), 0) end - int_segs = Set{NTuple{2,Int}}() - all_segs = Set{NTuple{2,Int}}() + int_segs = Set{NTuple{2, Int}}() + all_segs = Set{NTuple{2, Int}}() for e in get_interior_segments(tri) u, v = edge_vertices(e) push!(int_segs, minmax(u, v)) @@ -522,8 +522,8 @@ end struct BoundaryEdgeMapBoundaryNodesState <: AbstractTriangulationState flag::Bool - bad_edge::NTuple{2,Int} - bad_edge_2::NTuple{2,Int} + bad_edge::NTuple{2, Int} + bad_edge_2::NTuple{2, Int} bad_pos::Tuple end BoundaryEdgeMapBoundaryNodesState(tri) = test_boundary_edge_map_matches_boundary_nodes(tri) @@ -547,7 +547,7 @@ end struct BoundaryNodesBoundaryEdgeMapState <: AbstractTriangulationState flag::Bool - bad_edge::NTuple{2,Int} + bad_edge::NTuple{2, Int} bad_pos::Tuple bad_pos_2::Tuple end @@ -663,17 +663,17 @@ function Base.summary(state::IteratorState) return summary(state.output_state) # !test_state(state.output_state) end function IteratorState( - unique_flag, length_flag, output_flag, - iterator_length, correct_length, - iterator_name, primitive_name, iterator_function_name -) + unique_flag, length_flag, output_flag, + iterator_length, correct_length, + iterator_name, primitive_name, iterator_function_name, + ) flag = unique_flag && length_flag && output_flag return IteratorState( flag, UniqueIteratorOutputState(unique_flag, iterator_name, primitive_name), IteratorLengthState(length_flag, iterator_name, primitive_name, iterator_function_name, iterator_length, correct_length), IteratorOutputState(output_flag, iterator_name, primitive_name, iterator_function_name), - iterator_name + iterator_name, ) end function VertexIteratorState(length_flag, output_flag, iterator_length, correct_length) @@ -705,8 +705,8 @@ function GhostEdgeIteratorState(unique_flag, length_flag, output_flag, iterator_ end function test_iterators(tri::Triangulation) I = integer_type(tri) - T = NTuple{3,I} - E = NTuple{2,I} + T = NTuple{3, I} + E = NTuple{2, I} solid_triangles = T[] ghost_triangles = T[] all_triangles = T[] @@ -804,14 +804,14 @@ function test_iterators(tri::Triangulation) GhostTriangleIteratorState(unique_ghost_triangle_flag, ghost_triangle_length_flag, ghost_triangle_output_flag, ghost_triangle_iterator_length, ghost_triangle_correct_length), EdgeIteratorState(unique_edge_flag, edge_length_flag, edge_output_flag, edge_iterator_length, edge_correct_length), SolidEdgeIteratorState(unique_solid_edge_flag, solid_edge_length_flag, solid_edge_output_flag, solid_edge_iterator_length, solid_edge_correct_length), - GhostEdgeIteratorState(unique_ghost_edge_flag, ghost_edge_length_flag, ghost_edge_output_flag, ghost_edge_iterator_length, ghost_edge_correct_length) + GhostEdgeIteratorState(unique_ghost_edge_flag, ghost_edge_length_flag, ghost_edge_output_flag, ghost_edge_iterator_length, ghost_edge_correct_length), ) end struct DuplicateSegmentsState <: AbstractTriangulationState flag::Bool interior::Bool - bad_edge::NTuple{2,Int} + bad_edge::NTuple{2, Int} end DuplicateSegmentsState(tri) = test_no_duplicate_segments(tri) function Base.summary(state::DuplicateSegmentsState) @@ -866,7 +866,7 @@ struct TriangulationState <: AbstractTriangulationState ghost_edge_iterator_state::IteratorState end -function TriangulationState(tri::Triangulation; predicates::AbstractPredicateKernel=ExactKernel()) +function TriangulationState(tri::Triangulation; predicates::AbstractPredicateKernel = ExactKernel()) has_ghosts = has_ghost_triangles(tri) delete_ghost_triangles!(tri) add_ghost_triangles!(tri) @@ -887,7 +887,7 @@ function TriangulationState(tri::Triangulation; predicates::AbstractPredicateKer GraphTrianglesState(tri), SegmentState(tri), TriangleOrientationState(tri; predicates), - test_iterators(tri)... + test_iterators(tri)..., ) !has_ghosts && delete_ghost_triangles!(tri) return state @@ -925,7 +925,7 @@ Use the `predicates` keyword argument to control the method used for computing p Can be one of [`FastKernel`](@ref), [`ExactKernel`](@ref), and [`AdaptiveKernel`](@ref). See the documentation for a further discussion of these methods. """ -function validate_triangulation(tri::Triangulation; print_result=true, predicates::AbstractPredicateKernel=ExactKernel()) +function validate_triangulation(tri::Triangulation; print_result = true, predicates::AbstractPredicateKernel = ExactKernel()) state = TriangulationState(tri; predicates) print_result && !test_state(state) && println(state) return test_state(state) diff --git a/test/constrained_triangulation/segment_insertion.jl b/test/constrained_triangulation/segment_insertion.jl index fa82df167..1292f915f 100644 --- a/test/constrained_triangulation/segment_insertion.jl +++ b/test/constrained_triangulation/segment_insertion.jl @@ -63,14 +63,15 @@ end DT.delete_intersected_triangles!(tri, T) points = get_points(tri) _tri_1 = tri.cache - DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) - DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) - true_tri = ([ - ## two triangles to account for the cocircular points (2, 9, 3, 10) + true_tri = ( + [ + ## two triangles to account for the cocircular points (2, 9, 3, 10) (1, 4, 2) (8, 11, 10) (8, 7, 11) @@ -113,7 +114,7 @@ end (5, 4, DT.𝒢) (4, 1, DT.𝒢) (1, 2, DT.𝒢) - ] + ], ) @test any(T -> DT.compare_triangle_collections(get_triangles(tri), T), true_tri) push!(get_all_segments(tri), e) @@ -125,10 +126,10 @@ end DT.delete_intersected_triangles!(tri, T) points = get_points(tri) _tri_1 = tri.cache - DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) - DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) true_tri = [ @@ -162,10 +163,10 @@ end T, C, L, R = DT.locate_intersecting_triangles(tri, e) DT.delete_intersected_triangles!(tri, T) _tri_1 = tri.cache - DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) - DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) true_tri = [ @@ -205,10 +206,10 @@ end DT.delete_intersected_triangles!(tri, T) points = get_points(tri) _tri_1 = tri.cache - DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, L, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) - DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices,_tri_1.fan_triangles) + DT.triangulate_cavity_cdt!(_tri_1.triangulation, R, _tri_1.triangulation_2, _tri_1.marked_vertices, _tri_1.fan_triangles) DT.add_new_triangles!(tri, _tri_1.triangulation) empty!(_tri_1) end @@ -253,4 +254,4 @@ end ] @test DT.compare_triangle_collections(get_triangles(tri), true_tri) @test validate_triangulation(tri) -end \ No newline at end of file +end diff --git a/test/constrained_triangulation/segment_location.jl b/test/constrained_triangulation/segment_location.jl index d97584412..30276e365 100644 --- a/test/constrained_triangulation/segment_location.jl +++ b/test/constrained_triangulation/segment_location.jl @@ -14,7 +14,7 @@ using CairoMakie [(1, 4, 2), (4, 5, 9), (5, 6, 8)], [(3, 4, 10), (10, 8, 11)], [(3, 2, 4), (2, 1, 4)], - [(3, 4, 10), (10, 4, 9), (10, 9, 5), (8, 5, 6), (5, 8, 10)] + [(3, 4, 10), (10, 4, 9), (10, 9, 5), (8, 5, 6), (5, 8, 10)], ] collinear = [ [], @@ -23,7 +23,7 @@ using CairoMakie [(1, 4), (4, 5), (5, 6)], ([(11, 10), (10, 3)], [(3, 10), (10, 11)]), [(1, 2), (2, 3)], - [] + [], ] for _ in 1:250 for (edge, tris, edges) in zip(e, allT, collinear) @@ -38,7 +38,7 @@ using CairoMakie (Set(((1, 4), (4, 5), (5, 6))),), (Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3))),), (Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (3, 10), (10, 11))), Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (11, 10), (10, 3)))), - (Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (3, 10), (10, 11), (11, 7), (7, 6))), Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (11, 10), (10, 3), (11, 7), (7, 6)))) + (Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (3, 10), (10, 11), (11, 7), (7, 6))), Set(((1, 4), (4, 5), (5, 6), (1, 2), (2, 3), (11, 10), (10, 3), (11, 7), (7, 6)))), ] for _ in 1:250 tri = shewchuk_example_constrained() @@ -82,36 +82,36 @@ end e[1] = (7, 28) _T1 = [(7, 8, 12), (12, 8, 13), (17, 12, 13), (17, 13, 18), (22, 17, 18), (22, 18, 23), (27, 22, 23), (27, 23, 28)] crossed_triangles[1] = (_T1, reverse(_T1)) - constrained_edges[1] = Set{NTuple{2,Int}}((e[1],)) - collinear_segments[1] = NTuple{2,Int}[] + constrained_edges[1] = Set{NTuple{2, Int}}((e[1],)) + collinear_segments[1] = NTuple{2, Int}[] e[2] = (44, 21) crossed_triangles[2] = [(21, 22, 26), (26, 22, 27), (31, 26, 27), (31, 27, 32), (32, 27, 28), (32, 28, 33), (37, 32, 33), (37, 33, 38), (38, 33, 34), (38, 34, 39), (43, 38, 39), (43, 39, 44)] - constrained_edges[2] = Set{NTuple{2,Int}}((e[1], e[2])) - collinear_segments[2] = NTuple{2,Int}[] + constrained_edges[2] = Set{NTuple{2, Int}}((e[1], e[2])) + collinear_segments[2] = NTuple{2, Int}[] e[3] = (8, 14) crossed_triangles[3] = ([(13, 8, 9), (13, 9, 14)], [(13, 9, 14), (13, 8, 9)]) - constrained_edges[3] = Set{NTuple{2,Int}}((e[1], e[2], e[3])) - collinear_segments[3] = NTuple{2,Int}[] + constrained_edges[3] = Set{NTuple{2, Int}}((e[1], e[2], e[3])) + collinear_segments[3] = NTuple{2, Int}[] e[4] = (1, 50) _T4 = [(6, 1, 2), (6, 2, 7), (11, 6, 7), (11, 7, 12), (16, 11, 12), (16, 12, 17), (17, 12, 13), (17, 13, 18), (22, 17, 18), (22, 18, 23), (27, 22, 23), (27, 23, 28), (28, 23, 24), (28, 24, 29), (33, 28, 29), (33, 29, 34), (38, 33, 34), (38, 34, 39), (39, 34, 35), (39, 35, 40), (44, 39, 40), (44, 40, 45), (49, 44, 45), (49, 45, 50)] crossed_triangles[4] = (_T4, reverse(_T4)) - constrained_edges[4] = Set{NTuple{2,Int}}((e[1], e[2], e[3], e[4])) - collinear_segments[4] = NTuple{2,Int}[] + constrained_edges[4] = Set{NTuple{2, Int}}((e[1], e[2], e[3], e[4])) + collinear_segments[4] = NTuple{2, Int}[] e[5] = (47, 4) _T5 = [(47, 42, 43), (42, 38, 43), (42, 37, 38), (38, 37, 33), (37, 32, 33), (32, 28, 33), (32, 27, 28), (27, 23, 28), (28, 23, 24), (23, 19, 24), (23, 18, 19), (18, 14, 19), (18, 13, 14), (13, 9, 14), (13, 8, 9), (8, 4, 9)] crossed_triangles[5] = (_T5, reverse(_T5)) - constrained_edges[5] = Set{NTuple{2,Int}}((e[1], e[2], e[3], e[4], e[5])) - collinear_segments[5] = NTuple{2,Int}[] + constrained_edges[5] = Set{NTuple{2, Int}}((e[1], e[2], e[3], e[4], e[5])) + collinear_segments[5] = NTuple{2, Int}[] e[6] = (17, 24) _T6 = [(22, 17, 18), (22, 18, 23), (23, 18, 19), (23, 19, 24)] crossed_triangles[6] = (_T6, reverse(_T6)) - constrained_edges[6] = Set{NTuple{2,Int}}((e[1], e[2], e[3], e[4], e[5], e[6])) - collinear_segments[6] = NTuple{2,Int}[] + constrained_edges[6] = Set{NTuple{2, Int}}((e[1], e[2], e[3], e[4], e[5], e[6])) + collinear_segments[6] = NTuple{2, Int}[] e[7] = (17, 27) _T7a = [(22, 21, 17), (21, 22, 26), (26, 22, 27)] @@ -119,7 +119,7 @@ end _T7c = [(22, 23, 27), (23, 22, 18), (18, 22, 17)] _T7d = [(26, 22, 27), (22, 26, 21), (22, 21, 17)] crossed_triangles[7] = (_T7a, _T7b, _T7c, _T7d) - constrained_edges[7] = Set{NTuple{2,Int}}((e[1], e[2], e[3], e[4], e[5], e[6], (27, 22), (22, 17))) + constrained_edges[7] = Set{NTuple{2, Int}}((e[1], e[2], e[3], e[4], e[5], e[6], (27, 22), (22, 17))) collinear_segments[7] = ([(27, 22), (22, 17)], [(17, 22), (22, 27)]) e[8] = (32, 24) @@ -288,17 +288,19 @@ end d = 0.01 nx = 25 ny = 25 - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - tri = triangulate(get_points(tri), predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + tri = triangulate(get_points(tri), predicates = PT()) for i in 2:24 - add_segment!(tri, i, 600 + i, predicates=PT()) + add_segment!(tri, i, 600 + i, predicates = PT()) end - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - tri = triangulate(get_points(tri), predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + tri = triangulate(get_points(tri), predicates = PT()) e = (23, 71) - history = DT.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}() - find_triangle(tri, get_point(tri, 71); - m=nothing, k=23, store_history=true, history=history, predicates=PT()) + history = DT.PointLocationHistory{NTuple{3, Int}, NTuple{2, Int}, Int}() + find_triangle( + tri, get_point(tri, 71); + m = nothing, k = 23, store_history = true, history = history, predicates = PT(), + ) collinear_segments = history.collinear_segments DT.connect_segments!(collinear_segments) DT.extend_segments!(collinear_segments, e) @@ -309,11 +311,13 @@ end @testset "Some other previously broken examples, dealing with segments going through points without passing through segments" begin for PT in subtypes(DT.AbstractPredicateKernel) - tri = triangulate_rectangle(0, 5, 0, 10, 6, 11; delete_ghosts=false, predicates=PT()) + tri = triangulate_rectangle(0, 5, 0, 10, 6, 11; delete_ghosts = false, predicates = PT()) e = (14, 40) - history = DT.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}() - find_triangle(tri, get_point(tri, 40); - m=nothing, k=14, store_history=true, history=history, predicates=PT()) + history = DT.PointLocationHistory{NTuple{3, Int}, NTuple{2, Int}, Int}() + find_triangle( + tri, get_point(tri, 40); + m = nothing, k = 14, store_history = true, history = history, predicates = PT(), + ) collinear_segments = history.collinear_segments DT.fix_segments!(collinear_segments, history.collinear_point_indices) DT.connect_segments!(collinear_segments) @@ -321,9 +325,11 @@ end @test collinear_segments == [(14, 27), (27, 40)] e = (2, 54) - history = DT.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}() - find_triangle(tri, get_point(tri, 54); - m=nothing, k=2, store_history=true, history=history, predicates=PT()) + history = DT.PointLocationHistory{NTuple{3, Int}, NTuple{2, Int}, Int}() + find_triangle( + tri, get_point(tri, 54); + m = nothing, k = 2, store_history = true, history = history, predicates = PT(), + ) collinear_segments = history.collinear_segments bad_indices = history.collinear_point_indices DT.fix_segments!(collinear_segments, bad_indices) @@ -331,4 +337,4 @@ end DT.extend_segments!(collinear_segments, e) @test collinear_segments == [(2, 15), (15, 28), (28, 41), (41, 54)] end -end \ No newline at end of file +end diff --git a/test/data_structures/adjacent.jl b/test/data_structures/adjacent.jl index 7f4988459..b4d77a3bc 100644 --- a/test/data_structures/adjacent.jl +++ b/test/data_structures/adjacent.jl @@ -4,12 +4,12 @@ using DataStructures using StaticArrays global def_adj = DT.∅ -global default_1 = Dict{NTuple{2,Int},Int}() -global default_2 = Dict{NTuple{2,Int32},Int32}() -global default_3 = Dict{Vector{Int},Int}() -global adj_1 = DT.Adjacent{Int,NTuple{2,Int}}() -global adj_2 = DT.Adjacent{Int32,NTuple{2,Int32}}() -global adj_3 = DT.Adjacent{Int,Vector{Int}}() +global default_1 = Dict{NTuple{2, Int}, Int}() +global default_2 = Dict{NTuple{2, Int32}, Int32}() +global default_3 = Dict{Vector{Int}, Int}() +global adj_1 = DT.Adjacent{Int, NTuple{2, Int}}() +global adj_2 = DT.Adjacent{Int32, NTuple{2, Int32}}() +global adj_3 = DT.Adjacent{Int, Vector{Int}}() @testset "Constructors and getters" begin @test adj_1.adjacent == default_1 @@ -24,10 +24,14 @@ global adj_3 = DT.Adjacent{Int,Vector{Int}}() end global dict_1 = Dict((1, 2) => 4, (2, 3) => 10, (5, 6) => 15, (20, 5) => 72) -global dict_2 = Dict(@SVector[1, 2] => 4, @SVector[2, 3] => 10, @SVector[5, 6] => 15, - @SVector[20, 5] => 72) -global dict_3 = Dict{NTuple{2,Int32},Int32}((1, 2) => 4, (2, 3) => 10, (5, 6) => 15, - (20, 5) => 72) +global dict_2 = Dict( + @SVector[1, 2] => 4, @SVector[2, 3] => 10, @SVector[5, 6] => 15, + @SVector[20, 5] => 72, +) +global dict_3 = Dict{NTuple{2, Int32}, Int32}( + (1, 2) => 4, (2, 3) => 10, (5, 6) => 15, + (20, 5) => 72, +) global ddict_1 = Dict(dict_1) global ddict_2 = Dict(dict_2) global ddict_3 = Dict(dict_3) @@ -107,4 +111,4 @@ end @test !isempty(get_adjacent(adj)) empty!(adj) @test isempty(get_adjacent(adj)) -end \ No newline at end of file +end diff --git a/test/data_structures/adjacent2vertex.jl b/test/data_structures/adjacent2vertex.jl index 76054c079..99d31f216 100644 --- a/test/data_structures/adjacent2vertex.jl +++ b/test/data_structures/adjacent2vertex.jl @@ -3,12 +3,12 @@ const DT = DelaunayTriangulation using DataStructures using StaticArrays -global dict_1 = Dict{Int,Set{NTuple{2,Int}}}() -global dict_2 = Dict{Int,Vector{NTuple{2,Int}}}() -global dict_3 = Dict{Int32,Set{SVector{2,Int32}}}() -global adj2v_1 = DT.Adjacent2Vertex{Int,Set{NTuple{2,Int}}}() -global adj2v_2 = DT.Adjacent2Vertex{Int,Vector{NTuple{2,Int}}}() -global adj2v_3 = DT.Adjacent2Vertex{Int32,Set{SVector{2,Int32}}}() +global dict_1 = Dict{Int, Set{NTuple{2, Int}}}() +global dict_2 = Dict{Int, Vector{NTuple{2, Int}}}() +global dict_3 = Dict{Int32, Set{SVector{2, Int32}}}() +global adj2v_1 = DT.Adjacent2Vertex{Int, Set{NTuple{2, Int}}}() +global adj2v_2 = DT.Adjacent2Vertex{Int, Vector{NTuple{2, Int}}}() +global adj2v_3 = DT.Adjacent2Vertex{Int32, Set{SVector{2, Int32}}}() @testset "Constructors and getters" begin @test adj2v_1.adjacent2vertex == dict_1 @@ -22,22 +22,40 @@ global adj2v_3 = DT.Adjacent2Vertex{Int32,Set{SVector{2,Int32}}}() @test get_adjacent2vertex(adj2v_3) == dict_3 end -global dict_1 = Dict(1 => Set(((1, 2), (3, 4), (10, 15), (2, 5))), +global dict_1 = Dict( + 1 => Set(((1, 2), (3, 4), (10, 15), (2, 5))), 2 => Set(((5, 7), (10, 14), (2, 3), (5, 9))), - 3 => Set(((10, 25), (23, 29)))) -global dict_2 = Dict(1 => [(1, 2), (3, 4), (10, 15), (2, 5)], + 3 => Set(((10, 25), (23, 29))), +) +global dict_2 = Dict( + 1 => [(1, 2), (3, 4), (10, 15), (2, 5)], 2 => [(5, 7), (10, 14), (2, 3), (5, 9)], - 3 => [(10, 25), (23, 29)]) -global dict_3 = Dict{Int32,Set{SVector{2,Int32}}}(1 => Set{SVector{2,Int32}}((@SVector[1, 2], - @SVector[3, 4], - @SVector[10, 15], - @SVector[2, 5])), - 2 => Set{SVector{2,Int32}}((@SVector[5, 7], - @SVector[10, 14], - @SVector[2, 3], - @SVector[5, 9])), - 3 => Set{SVector{2,Int32}}((@SVector[10, 25], - @SVector[23, 29]))) + 3 => [(10, 25), (23, 29)], +) +global dict_3 = Dict{Int32, Set{SVector{2, Int32}}}( + 1 => Set{SVector{2, Int32}}( + ( + @SVector[1, 2], + @SVector[3, 4], + @SVector[10, 15], + @SVector[2, 5], + ), + ), + 2 => Set{SVector{2, Int32}}( + ( + @SVector[5, 7], + @SVector[10, 14], + @SVector[2, 3], + @SVector[5, 9], + ), + ), + 3 => Set{SVector{2, Int32}}( + ( + @SVector[10, 25], + @SVector[23, 29], + ), + ), +) global adj2v_1 = DT.Adjacent2Vertex(dict_1) global adj2v_2 = DT.Adjacent2Vertex(dict_2) global adj2v_3 = DT.Adjacent2Vertex(dict_3) @@ -57,12 +75,20 @@ global adj2v_3 = DT.Adjacent2Vertex(dict_3) @test w3 == [(10, 25), (23, 29)] elseif adj2v === adj2v_3 @test w1 == - Set{SVector{2,Int32}}((@SVector[1, 2], @SVector[3, 4], @SVector[10, 15], - @SVector[2, 5])) + Set{SVector{2, Int32}}( + ( + @SVector[1, 2], @SVector[3, 4], @SVector[10, 15], + @SVector[2, 5], + ), + ) @test w2 == - Set{SVector{2,Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3], - @SVector[5, 9])) - @test w3 == Set{SVector{2,Int32}}((@SVector[10, 25], @SVector[23, 29])) + Set{SVector{2, Int32}}( + ( + @SVector[5, 7], @SVector[10, 14], @SVector[2, 3], + @SVector[5, 9], + ), + ) + @test w3 == Set{SVector{2, Int32}}((@SVector[10, 25], @SVector[23, 29])) end DT.add_adjacent2vertex!(adj2v, 1, 23, 50) @@ -77,13 +103,25 @@ global adj2v_3 = DT.Adjacent2Vertex(dict_3) @test w3 == [(10, 25), (23, 29), (38, 173)] elseif adj2v === adj2v_3 @test w1 == - Set{SVector{2,Int32}}((@SVector[1, 2], @SVector[3, 4], @SVector[10, 15], - @SVector[2, 5], @SVector[23, 50])) + Set{SVector{2, Int32}}( + ( + @SVector[1, 2], @SVector[3, 4], @SVector[10, 15], + @SVector[2, 5], @SVector[23, 50], + ), + ) @test w2 == - Set{SVector{2,Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3], - @SVector[5, 9])) - @test w3 == Set{SVector{2,Int32}}((@SVector[10, 25], @SVector[23, 29], - @SVector[38, 173])) + Set{SVector{2, Int32}}( + ( + @SVector[5, 7], @SVector[10, 14], @SVector[2, 3], + @SVector[5, 9], + ), + ) + @test w3 == Set{SVector{2, Int32}}( + ( + @SVector[10, 25], @SVector[23, 29], + @SVector[38, 173], + ), + ) end if !(adj2v === adj2v_2) @@ -99,12 +137,20 @@ global adj2v_3 = DT.Adjacent2Vertex(dict_3) @test w3 == [(10, 25), (23, 29), (38, 173)] elseif adj2v === adj2v_3 @test w1 == - Set{SVector{2,Int32}}((@SVector[1, 2], @SVector[10, 15], @SVector[2, 5], - @SVector[23, 50])) + Set{SVector{2, Int32}}( + ( + @SVector[1, 2], @SVector[10, 15], @SVector[2, 5], + @SVector[23, 50], + ), + ) @test w2 == - Set{SVector{2,Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3])) - @test w3 == Set{SVector{2,Int32}}((@SVector[10, 25], @SVector[23, 29], - @SVector[38, 173])) + Set{SVector{2, Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3])) + @test w3 == Set{SVector{2, Int32}}( + ( + @SVector[10, 25], @SVector[23, 29], + @SVector[38, 173], + ), + ) end end @@ -118,10 +164,14 @@ global adj2v_3 = DT.Adjacent2Vertex(dict_3) @test w2 == [(5, 7), (10, 14), (2, 3), (5, 9)] elseif adj2v === adj2v_3 @test w1 == - Set{SVector{2,Int32}}((@SVector[1, 2], @SVector[10, 15], @SVector[2, 5], - @SVector[23, 50])) + Set{SVector{2, Int32}}( + ( + @SVector[1, 2], @SVector[10, 15], @SVector[2, 5], + @SVector[23, 50], + ), + ) @test w2 == - Set{SVector{2,Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3])) + Set{SVector{2, Int32}}((@SVector[5, 7], @SVector[10, 14], @SVector[2, 3])) end DT.add_triangle!(adj2v, 51, 52, 53) @@ -168,7 +218,7 @@ global adj2v_3 = DT.Adjacent2Vertex(dict_3) end @testset "Seeing if Adjacent2Vertex is empty and clearing empty sets" begin - adj2v = DT.Adjacent2Vertex{Int,Set{NTuple{2,Int}}}() + adj2v = DT.Adjacent2Vertex{Int, Set{NTuple{2, Int}}}() DT.add_adjacent2vertex!(adj2v, 2, 5, 7) DT.add_adjacent2vertex!(adj2v, 2, 7, 13) DT.add_adjacent2vertex!(adj2v, 13, 5, 23) @@ -188,4 +238,4 @@ end @test !isempty(get_adjacent2vertex(adj2v)) empty!(adj2v) @test isempty(get_adjacent2vertex(adj2v)) -end \ No newline at end of file +end diff --git a/test/data_structures/bst.jl b/test/data_structures/bst.jl index 638a39e13..c445c1d44 100644 --- a/test/data_structures/bst.jl +++ b/test/data_structures/bst.jl @@ -1,6 +1,6 @@ -using ..DelaunayTriangulation -using Test -using DataStructures +using ..DelaunayTriangulation +using Test +using DataStructures const DT = DelaunayTriangulation tree = DT.BalancedBST{Int}() @@ -24,8 +24,8 @@ end @test DT.inorder(tree) == __inorder(tree_avl) @test length(DT.inorder(tree)) == tree.count -tree = DT.BalancedBST{NTuple{2,Int}}() -tree_avl = AVLTree{NTuple{2,Int}}() +tree = DT.BalancedBST{NTuple{2, Int}}() +tree_avl = AVLTree{NTuple{2, Int}}() for _ in 1:100000 i = (rand(1:10000), rand(1:10000)) push!(tree, i) @@ -36,11 +36,11 @@ end @test DT.inorder(tree) == __inorder(tree_avl) @test length(DT.inorder(tree)) == tree.count inord = DT.inorder(tree) -for i in [inord; (0,0); (-1,-1);(-2,-2);(-3,-3)] +for i in [inord; (0, 0); (-1, -1);(-2, -2);(-3, -3)] delete!(tree, i) delete!(tree_avl, i) end @test tree.count == tree_avl.count @test DT.get_height(tree.root) == DataStructures.get_height(tree_avl.root) @test DT.inorder(tree) == __inorder(tree_avl) -@test length(DT.inorder(tree)) == tree.count \ No newline at end of file +@test length(DT.inorder(tree)) == tree.count diff --git a/test/data_structures/convex_hull.jl b/test/data_structures/convex_hull.jl index 140c4a9bf..07afff0a3 100644 --- a/test/data_structures/convex_hull.jl +++ b/test/data_structures/convex_hull.jl @@ -66,7 +66,7 @@ end end @testset "empty!" begin - tri = triangulate(rand(2,50)) + tri = triangulate(rand(2, 50)) ch = get_convex_hull(tri) @test !isempty(DT.get_vertices(ch)) empty!(ch) @@ -76,4 +76,4 @@ end @testset "Issue #109" begin points = rand(2, 50) @test convex_hull(points).vertices == convex_hull(vcat(points, points)).vertices -end \ No newline at end of file +end diff --git a/test/data_structures/curves.jl b/test/data_structures/curves.jl index fabc77b93..b547d6c19 100644 --- a/test/data_structures/curves.jl +++ b/test/data_structures/curves.jl @@ -61,9 +61,9 @@ using ReferenceTests L = LineSegment(p, q) for t in LinRange(0, 1, 100) der1 = DT.differentiate(L, t) - h = 1e-8 + h = 1.0e-8 der2 = (L(t + h) .- L(t - h)) ./ (2h) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end @test DT.twice_differentiate(L, rand()) == (0.0, 0.0) @inferred DT.differentiate(L, rand()) @@ -74,10 +74,10 @@ using ReferenceTests ## Total variation TV = DT.total_variation(L) - @test TV ≈ 0.0 atol = 1e-6 + @test TV ≈ 0.0 atol = 1.0e-6 TV = DT.total_variation(L, 0.2, 0.5) - @test TV ≈ 0.0 atol = 1e-6 - @test TV ≈ slow_total_absolute_curvature(L, 0.2, 0.5) atol = 1e-3 + @test TV ≈ 0.0 atol = 1.0e-6 + @test TV ≈ slow_total_absolute_curvature(L, 0.2, 0.5) atol = 1.0e-3 ## Equidistant split t = DT.get_equidistant_split(L, 0, 1) @@ -186,21 +186,21 @@ end @test !DT.is_piecewise_linear(arc) @test !DT.is_interpolating(arc) @inferred CircularArc(p1, q1, center1) - negarc = CircularArc(p1, q1, center1, positive=false) + negarc = CircularArc(p1, q1, center1, positive = false) revarc = CircularArc(q1, p1, center1) - revnegarc = CircularArc(q1, p1, center1, positive=false) + revnegarc = CircularArc(q1, p1, center1, positive = false) center2 = (3.0, -5.0) p2 = (6.0, 5.0) circ = CircularArc(p2, p2, center2) - revcirc = CircularArc(p2, p2, center2, positive=false) + revcirc = CircularArc(p2, p2, center2, positive = false) @test arc.center == negarc.center == revarc.center == revnegarc.center == center1 @test circ.center == revcirc.center == center2 @test arc.radius == negarc.radius == revarc.radius == revnegarc.radius ≈ sqrt(41) @test circ.radius == revcirc.radius ≈ sqrt(109) - @test arc.start_angle ≈ 0.8960554793197029 rtol = 1e-6 - @test negarc.start_angle ≈ 0.8960554793197029 rtol = 1e-6 - @test arc.sector_angle ≈ deg2rad(167.3196155081802) rtol = 1e-6 - @test negarc.sector_angle ≈ deg2rad(167.3196155081802) - 2π rtol = 1e-6 + @test arc.start_angle ≈ 0.8960554793197029 rtol = 1.0e-6 + @test negarc.start_angle ≈ 0.8960554793197029 rtol = 1.0e-6 + @test arc.sector_angle ≈ deg2rad(167.3196155081802) rtol = 1.0e-6 + @test negarc.sector_angle ≈ deg2rad(167.3196155081802) - 2π rtol = 1.0e-6 @test arc.first == negarc.first == revarc.last == revnegarc.last == p1 @test arc.last == negarc.last == revarc.first == revnegarc.first == q1 @test circ.first == revcirc.first == circ.last == revcirc.last == p2 @@ -212,8 +212,8 @@ end ## Evaluation @test arc(0.0) ⪧ negarc(0.0) ⪧ revarc(1.0) ⪧ revnegarc(1.0) ⪧ p1 @test arc(1.0) ⪧ negarc(1.0) ⪧ revarc(0.0) ⪧ revnegarc(0.0) ⪧ q1 - @test arc(1e-16) ⪧ negarc(1e-16) ⪧ revarc(1 - 1e-16) ⪧ revnegarc(1 - 1e-16) ⪧ p1 - @test arc(1 - 1e-16) ⪧ negarc(1 - 1e-16) ⪧ revarc(1e-16) ⪧ revnegarc(1e-16) ⪧ q1 + @test arc(1.0e-16) ⪧ negarc(1.0e-16) ⪧ revarc(1 - 1.0e-16) ⪧ revnegarc(1 - 1.0e-16) ⪧ p1 + @test arc(1 - 1.0e-16) ⪧ negarc(1 - 1.0e-16) ⪧ revarc(1.0e-16) ⪧ revnegarc(1.0e-16) ⪧ q1 t = LinRange(0, 1, 500) θ₀_arc, θ₁_arc = arc.start_angle, arc.start_angle + arc.sector_angle @@ -295,9 +295,9 @@ end for c in (arc, negarc, revarc, revnegarc, circ, revcirc) for t in LinRange(0, 1, 100) der1 = DT.differentiate(c, t) - h = 1e-8 + h = 1.0e-8 der2 = (c(t + h) .- c(t - h)) ./ (2h) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -305,9 +305,9 @@ end for c in (arc, negarc, revarc, revnegarc, circ, revcirc) for t in LinRange(0, 1, 100) der1 = DT.twice_differentiate(c, t) - h = 1e-4 + h = 1.0e-4 der2 = (c(t + h) .- 2 .* c(t) .+ c(t - h)) ./ (h^2) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -320,7 +320,7 @@ end vec2 = [∂²x, ∂²y, 0.0] cur1 = DT.curvature(c, t) cur2 = cross(vec1, vec2)[3] / norm(vec1)^3 - @test cur1 ≈ cur2 rtol = 1e-5 atol = 1e-5 + @test cur1 ≈ cur2 rtol = 1.0e-5 atol = 1.0e-5 @test cur1 ≈ sign(c.sector_angle) / c.radius end end @@ -336,7 +336,7 @@ end TV = DT.total_variation(c, t1, t2) @inferred DT.total_variation(c, t1, t2) TVslow = slow_total_absolute_curvature(c, t1, t2) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-1 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-1 end end @@ -348,7 +348,7 @@ end t = DT.get_equidistant_split(c, t1, t2) s1 = DT.arc_length(c, t1, t) s2 = DT.arc_length(c, t, t2) - @test s1 ≈ s2 rtol = 1e-1 atol = 1e-1 + @test s1 ≈ s2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 @test DT.arc_length(c, t1, t2) ≈ 2s1 end @@ -362,7 +362,7 @@ end t, T = DT.get_equivariation_split(c, t1, t2) T1 = DT.total_variation(c, t1, t) T2 = DT.total_variation(c, t, t2) - @test T1 ≈ T2 rtol = 1e-1 atol = 1e-1 + @test T1 ≈ T2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 @test T ≈ T1 end @@ -386,12 +386,12 @@ end t₁, t₂, r = 0.0, 0.5, 0.5 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.22995991983967937 && q′ ⪧ (0.45551153816025436, -0.2057058712828833) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 c = CircularArc((0.0, 0.0), (0.0, 0.0), (0.5, 0.5)) t₁, t₂, r = 0.0, 0.5, 1.3 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.37124248496993983 && q′ ⪧ (1.2069097223005656, 0.48330735141035414) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 ## == @test arc ≠ negarc @@ -411,9 +411,9 @@ end @test !DT.is_piecewise_linear(arc) @test !DT.is_interpolating(arc) @inferred EllipticalArc(A, B, (Cx, Cy), Rx, Ry, s) - negarc = EllipticalArc(A, B, (Cx, Cy), Rx, Ry, s, positive=false) + negarc = EllipticalArc(A, B, (Cx, Cy), Rx, Ry, s, positive = false) revarc = EllipticalArc(B, A, (Cx, Cy), Rx, Ry, s) - revnegarc = EllipticalArc(B, A, (Cx, Cy), Rx, Ry, s, positive=false) + revnegarc = EllipticalArc(B, A, (Cx, Cy), Rx, Ry, s, positive = false) @test arc.center == negarc.center == revarc.center == revnegarc.center == (Cx, Cy) @test arc.first == negarc.first == revarc.last == revnegarc.last == A @test arc.last == negarc.last == revarc.first == revnegarc.first == B @@ -429,7 +429,7 @@ end @test revarc.sector_angle > 0 @test revnegarc.sector_angle < 0 closed_arc = EllipticalArc(A, A, (Cx, Cy), Rx, Ry, s) - revclosed_arc = EllipticalArc(A, A, (Cx, Cy), Rx, Ry, s, positive=false) + revclosed_arc = EllipticalArc(A, A, (Cx, Cy), Rx, Ry, s, positive = false) @test closed_arc.sector_angle ≈ 2π @test revclosed_arc.sector_angle ≈ -2π @test closed_arc.center == revclosed_arc.center == (Cx, Cy) @@ -440,12 +440,12 @@ end ## Evaluation @test arc(0.0) ⪧ negarc(0.0) ⪧ revarc(1.0) ⪧ revnegarc(1.0) ⪧ A @test arc(1.0) ⪧ negarc(1.0) ⪧ revarc(0.0) ⪧ revnegarc(0.0) ⪧ B - @test arc(1e-16) ⪧ negarc(1e-16) ⪧ revarc(1 - 1e-16) ⪧ revnegarc(1 - 1e-16) ⪧ A - @test arc(1 - 1e-16) ⪧ negarc(1 - 1e-16) ⪧ revarc(1e-16) ⪧ revnegarc(1e-16) ⪧ B + @test arc(1.0e-16) ⪧ negarc(1.0e-16) ⪧ revarc(1 - 1.0e-16) ⪧ revnegarc(1 - 1.0e-16) ⪧ A + @test arc(1 - 1.0e-16) ⪧ negarc(1 - 1.0e-16) ⪧ revarc(1.0e-16) ⪧ revnegarc(1.0e-16) ⪧ B @test closed_arc(0.0) ⪧ revclosed_arc(0.0) ⪧ A @test closed_arc(1.0) ⪧ revclosed_arc(1.0) ⪧ A - @test closed_arc(1e-16) ⪧ revclosed_arc(1e-16) ⪧ A - @test closed_arc(1 - 1e-16) ⪧ revclosed_arc(1 - 1e-16) ⪧ A + @test closed_arc(1.0e-16) ⪧ revclosed_arc(1.0e-16) ⪧ A + @test closed_arc(1 - 1.0e-16) ⪧ revclosed_arc(1 - 1.0e-16) ⪧ A arc1, arc2, arc3 = arc(0), arc(1 / 2), arc(1) negarc1, negarc2, negarc3 = negarc(0), negarc(1 / 2), negarc(1) revarc1, revarc2, revarc3 = revarc(0), revarc(1 / 2), revarc(1) @@ -544,9 +544,9 @@ end for c in (arc, negarc, revarc, revnegarc, closed_arc, revclosed_arc) for t in LinRange(0, 1, 100) der1 = DT.differentiate(c, t) - h = 1e-8 + h = 1.0e-8 der2 = (c(t + h) .- c(t - h)) ./ (2h) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -573,9 +573,9 @@ end for t in LinRange(0, 1, 100) der1 = DT.twice_differentiate(c, t) @inferred DT.twice_differentiate(c, t) - h = 1e-4 + h = 1.0e-4 der2 = (c(t + h) .- 2 .* c(t) .+ c(t - h)) ./ (h^2) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -588,7 +588,7 @@ end vec2 = [∂²x, ∂²y, 0.0] cur1 = DT.curvature(c, t) cur2 = cross(vec1, vec2)[3] / norm(vec1)^3 - @test cur1 ≈ cur2 rtol = 1e-5 atol = 1e-5 + @test cur1 ≈ cur2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -603,7 +603,7 @@ end TV = DT.total_variation(c, t1, t2) @inferred DT.total_variation(c, t1, t2) TVslow = slow_total_absolute_curvature(c, t1, t2) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-1 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-1 end end @@ -615,9 +615,9 @@ end t = DT.get_equidistant_split(c, t1, t2) s1 = DT.arc_length(c, t1, t) s2 = DT.arc_length(c, t, t2) - @test s1 ≈ s2 rtol = 1e-1 atol = 1e-1 + @test s1 ≈ s2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 - @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1e-1 + @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1.0e-1 end end @@ -629,9 +629,9 @@ end t, T = DT.get_equivariation_split(c, t1, t2) T1 = DT.total_variation(c, t1, t) T2 = DT.total_variation(c, t, t2) - @test T1 ≈ T2 rtol = 1e-1 atol = 1e-1 + @test T1 ≈ T2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 - @test T ≈ T1 rtol = 1e-1 atol = 1e-1 + @test T ≈ T1 rtol = 1.0e-1 atol = 1.0e-1 end end @@ -652,14 +652,14 @@ end Rx, Ry, Cx, Cy, s = 2.2, 2.75, 0.6, 0.65, 60.0 A, B = (-1.9827767129992, 1.4963893939715), (2.5063071261053, -1.2608915244961) c = EllipticalArc(A, B, (Cx, Cy), Rx, Ry, s) - t₁, t₂, r, = 0.2, 0.5, 0.8 + t₁, t₂, r = 0.2, 0.5, 0.8 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.32234468937857575 && q′ ⪧ (-1.489595166177109, -0.3863541400710244) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 - t₁, t₂, r, = 1.0, 0.5, 0.18889 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 + t₁, t₂, r = 1.0, 0.5, 0.18889 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.967434869739479 && q′ ⪧ (2.349597231970133, -1.368111418490932) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-2 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-2 ## == @test arc ≠ negarc @@ -678,7 +678,7 @@ end @test !DT.is_piecewise_linear(bezier) @test !DT.is_interpolating(bezier) @test bezier.control_points == control_points - @test typeof(bezier.cache) == Vector{NTuple{2,Float64}} && length(bezier.cache) == 5 + @test typeof(bezier.cache) == Vector{NTuple{2, Float64}} && length(bezier.cache) == 5 @test length(bezier.lookup_table) == 5000 for i in 1:5000 t = (i - 1) / 4999 @@ -687,8 +687,8 @@ end ## Evaluation @test bezier(0.0) ⪧ (0.0, 0.0) - @test bezier(1e-16) ⪧ (0.0, 0.0) atol = 1e-9 - @test bezier(1.0) ⪧ bezier(1 - 1e-16) ⪧ (1 / 2, 1 / 2) + @test bezier(1.0e-16) ⪧ (0.0, 0.0) atol = 1.0e-9 + @test bezier(1.0) ⪧ bezier(1 - 1.0e-16) ⪧ (1 / 2, 1 / 2) t = LinRange(0, 1, 1500) for t in t @test bezier(t) ⪧ slow_bezier_eval(control_points, t) @@ -699,7 +699,7 @@ end t = LinRange(0, 1, 1500) for t in t der1 = ForwardDiff.derivative(t -> slow_bezier_eval(control_points, t), t) - der2 = (bezier(t + 1e-6) .- bezier(t - 1e-6)) ./ (2 * 1e-6) + der2 = (bezier(t + 1.0e-6) .- bezier(t - 1.0e-6)) ./ (2 * 1.0e-6) der3 = DT.differentiate(bezier, t) @test der1 ⪧ der2 ⪧ der3 @inferred DT.differentiate(bezier, t) @@ -708,8 +708,8 @@ end ## Closest point invert(points) = let y = maximum(last.(points)) - return [(x, y - y′) for (x, y′) in points] - end # just to match my reference figure + return [(x, y - y′) for (x, y′) in points] + end # just to match my reference figure control_points = invert([(207.0, 65.0), (84.0, 97.0), (58.0, 196.0), (261.0, 130.0), (216.0, 217.0), (54.0, 122.0), (52.0, 276.0), (85.0, 330.0), (258.0, 334.0), (209.0, 286.0)]) for lookup_steps in (100, 500, 1000) if lookup_steps ≠ 500 @@ -725,16 +725,16 @@ end t′, q = DT.get_closest_point(bezier, p) @test q ⪧ bezier(t′) _t, _q = closest_point_on_curve(bezier, p) - @test _t ≈ t′ rtol = 1e-1 atol = 1e-1 - @test q ⪧ _q rtol = 1e-1 atol = 1e-1 - @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1e-1 atol = 1e-1 + @test _t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 + @test q ⪧ _q rtol = 1.0e-1 atol = 1.0e-1 + @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1.0e-1 atol = 1.0e-1 end for t in LinRange(0, 1, 150) p = bezier(t) t′, q = DT.get_closest_point(bezier, p) @test q ⪧ bezier(t′) - @test t ≈ t′ rtol = 1e-1 atol = 1e-1 - @test p ⪧ q rtol = 1e-1 atol = 1e-1 + @test t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 + @test p ⪧ q rtol = 1.0e-1 atol = 1.0e-1 end @test DT.get_closest_point(bezier, bezier(0.0))[1] == 0.0 @test DT.get_closest_point(bezier, bezier(1.0))[1] == 1.0 @@ -820,18 +820,18 @@ end bezier3 = BezierCurve(control_points3) bezier4 = BezierCurve(control_points4) for bezier in (bezier1, bezier2, bezier3, bezier4) - @test DT.arc_length(bezier) ≈ slow_arc_length(bezier, 0, 1) rtol = 1e-4 + @test DT.arc_length(bezier) ≈ slow_arc_length(bezier, 0, 1) rtol = 1.0e-4 @inferred DT.arc_length(bezier) @test DT.arc_length(bezier, 0.1, 0.15) ≈ slow_arc_length(bezier, 0.1, 0.15) @test DT.arc_length(bezier, 0.0, 0.0) ≈ 0.0 @test DT.arc_length(bezier, 1.0, 1.0) ≈ 0.0 - @test DT.arc_length(bezier, 0.0, 1.0) ≈ slow_arc_length(bezier, 0.0, 1.0) rtol = 1e-4 + @test DT.arc_length(bezier, 0.0, 1.0) ≈ slow_arc_length(bezier, 0.0, 1.0) rtol = 1.0e-4 @test DT.arc_length(bezier, 0.3, 0.9) ≈ slow_arc_length(bezier, 0.3, 0.9) @test DT.arc_length(bezier, 0.2, 0.21) ≈ slow_arc_length(bezier, 0.2, 0.21) for _ in 1:1000 t₁, t₂ = rand(2) t₁, t₂ = minmax(t₁, t₂) - @test DT.arc_length(bezier, t₁, t₂) ≈ slow_arc_length(bezier, t₁, t₂) rtol = 1e-2 + @test DT.arc_length(bezier, t₁, t₂) ≈ slow_arc_length(bezier, t₁, t₂) rtol = 1.0e-2 end end @@ -839,9 +839,9 @@ end for bezier in (bezier1, bezier2, bezier3, bezier4) for t in LinRange(0, 1, 1000) der1 = DT.twice_differentiate(bezier, t) - h = 1e-4 + h = 1.0e-4 der2 = (bezier(t + h) .- 2 .* bezier(t) .+ bezier(t - h)) ./ (h^2) - @test der1 ⪧ der2 rtol = 1e-5 atol = 1e-5 + @test der1 ⪧ der2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -849,10 +849,10 @@ end for bezier in (bezier1, bezier2, bezier3, bezier4) for t in LinRange(0, 1, 1000) der1 = DT.thrice_differentiate(bezier, t) - h = 1e-6 + h = 1.0e-6 f = t -> DT.twice_differentiate(bezier, t) der2 = (f(t + h) .- f(t - h)) ./ (2h) - @test der1 ⪧ der2 rtol = 1e-3 atol = 1e-3 + @test der1 ⪧ der2 rtol = 1.0e-3 atol = 1.0e-3 end end @@ -865,7 +865,7 @@ end vec2 = [∂²x, ∂²y, 0.0] cur1 = DT.curvature(c, t) cur2 = cross(vec1, vec2)[3] / norm(vec1)^3 - @test cur1 ≈ cur2 rtol = 1e-5 atol = 1e-5 + @test cur1 ≈ cur2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -931,14 +931,16 @@ end @test allt ≈ [0.0, 0.5, 1.0] @test allt == bezier.orientation_markers - control_points = [(-12.0, 5.0), (-9.77, 6.29), + control_points = [ + (-12.0, 5.0), (-9.77, 6.29), (-8.11, 4.55), (-7.47, 1.49), (-7.61, -1.29), (-9.63, -3.69), (-13.65, -4.37), (-15.65, -1.25), (-15.39, 0.93), (-14.17, 1.63), (-12.37, -0.93), (-13.51, -1.17), (-12.59, -2.39), (-10.6, -2.47), - (-9.19, 0.11), (-9.95, 2.79)] + (-9.19, 0.11), (-9.95, 2.79), + ] bezier = BezierCurve(control_points) tx = DT.horizontal_turning_points(bezier) ty = DT.vertical_turning_points(bezier) @@ -954,10 +956,12 @@ end @test allt ≈ sort([tx; ty; κx; κy; κ; 0.0; 1.0]) @test allt == bezier.orientation_markers - control_points = [(-12.0, -4.0), (-8.0, -8.0), (-4.0, -6.0), (-2.0, -4.0), + control_points = [ + (-12.0, -4.0), (-8.0, -8.0), (-4.0, -6.0), (-2.0, -4.0), (-6.0, 0.0), (-10.0, 4.0), (-14.0, 8.0), (-10.0, 12.0), (-4.0, 14.0), (4.0, 10.0), (0.0, 8.0), (-2.0, 6.0), (2.0, 4.0), (6.0, -2.0), (6.0, -8.0), (0.0, -12.0), (-10.0, -12.0), - (-18.0, -12.0), (-18.0, -2.0), (-18.0, -2.0), (-12.0, -4.0)] + (-18.0, -12.0), (-18.0, -2.0), (-18.0, -2.0), (-12.0, -4.0), + ] bezier = BezierCurve(control_points) tx = DT.horizontal_turning_points(bezier) ty = DT.vertical_turning_points(bezier) @@ -978,18 +982,22 @@ end control_points2 = invert([(207.0, 65.0), (84.0, 97.0), (58.0, 196.0), (261.0, 130.0), (216.0, 217.0), (54.0, 122.0), (52.0, 276.0), (85.0, 330.0), (258.0, 334.0), (209.0, 286.0)]) control_points3 = [(0.0, 0.0), (1.0, 1.0)] control_points4 = [(0.0, 0.0), (1 / 2, 1 / 2), (0.0, 1.0)] - control_points5 = [(-12.0, 5.0), (-9.77, 6.29), + control_points5 = [ + (-12.0, 5.0), (-9.77, 6.29), (-8.11, 4.55), (-7.47, 1.49), (-7.61, -1.29), (-9.63, -3.69), (-13.65, -4.37), (-15.65, -1.25), (-15.39, 0.93), (-14.17, 1.63), (-12.37, -0.93), (-13.51, -1.17), (-12.59, -2.39), (-10.6, -2.47), - (-9.19, 0.11), (-9.95, 2.79)] - control_points6 = [(-12.0, -4.0), (-8.0, -8.0), (-4.0, -6.0), (-2.0, -4.0), + (-9.19, 0.11), (-9.95, 2.79), + ] + control_points6 = [ + (-12.0, -4.0), (-8.0, -8.0), (-4.0, -6.0), (-2.0, -4.0), (-6.0, 0.0), (-10.0, 4.0), (-14.0, 8.0), (-10.0, 12.0), (-4.0, 14.0), (4.0, 10.0), (0.0, 8.0), (-2.0, 6.0), (2.0, 4.0), (6.0, -2.0), (6.0, -8.0), (0.0, -12.0), (-10.0, -12.0), - (-18.0, -12.0), (-18.0, -2.0), (-18.0, -2.0), (-12.0, -4.0)] # periodic + (-18.0, -12.0), (-18.0, -2.0), (-18.0, -2.0), (-12.0, -4.0), + ] # periodic control_points7 = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)] # periodic bezier1 = BezierCurve(control_points1) bezier2 = BezierCurve(control_points2) @@ -1003,13 +1011,13 @@ end TV = DT.total_variation(c) @inferred DT.total_variation(c) TVslow = slow_total_absolute_curvature(c, 0, 1) - @test TV ≈ TVslow rtol = 1e-3 atol = 1e-3 + @test TV ≈ TVslow rtol = 1.0e-3 atol = 1.0e-3 for _ in 1:1000 t1, t2 = minmax(rand(2)...) TV = DT.total_variation(c, t1, t2) @inferred DT.total_variation(c, t1, t2) TVslow = slow_total_absolute_curvature(c, t1, t2) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-1 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-1 end end @@ -1021,9 +1029,9 @@ end t = DT.get_equidistant_split(c, t1, t2) s1 = DT.arc_length(c, t1, t) s2 = DT.arc_length(c, t, t2) - @test s1 ≈ s2 rtol = 1e-2 atol = 1e-2 + @test s1 ≈ s2 rtol = 1.0e-2 atol = 1.0e-2 @test t1 ≤ t ≤ t2 - @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1e-1 + @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1.0e-1 end end @@ -1035,7 +1043,7 @@ end t, T = DT.get_equivariation_split(c, t1, t2) T1 = DT.total_variation(c, t1, t) T2 = DT.total_variation(c, t, t2) - @test T1 ≈ T2 rtol = 1e-1 atol = 1e-1 + @test T1 ≈ T2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 @test T ≈ T1 end @@ -1057,14 +1065,14 @@ end ## get_circle_intersection control_points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)] c = BezierCurve(control_points) - t₁, t₂, r, = 0.2, 0.5, 0.2 + t₁, t₂, r = 0.2, 0.5, 0.2 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.3019603920784157 && q′ ⪧ (0.6773887113970392, 0.34344590594423263) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 - t₁, t₂, r, = 1.0, 0.5, 0.6 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 + t₁, t₂, r = 1.0, 0.5, 0.6 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.7954590918183637 && q′ ⪧ (0.186063568848561, 0.5706424003210613) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-2 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-2 ## == ctrl1 = [(0.0, 0.0), (1.3, 1.5), (2.7, 5.3), (17.3, 5.2), (23.5, -0.5)] @@ -1081,7 +1089,7 @@ end @test !DT.is_piecewise_linear(spline) @test !DT.is_interpolating(spline) @test spline.control_points ⪧ control_points - @test typeof(spline.cache) == Vector{NTuple{2,Float64}} && length(spline.cache) == 4 + @test typeof(spline.cache) == Vector{NTuple{2, Float64}} && length(spline.cache) == 4 @test spline.knots == [0, 0, 0, 0, 1, 1, 1, 1] @test length(spline.lookup_table) == 5000 for i in 1:5000 @@ -1091,7 +1099,7 @@ end periodic_control_points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1 / 2, 1 / 2), (0.0, 0.0)] periodic_spline = BSpline(periodic_control_points) @test periodic_spline.control_points ⪧ [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1 / 2, 1 / 2), (0.0, 0.0)] - @test typeof(periodic_spline.cache) == Vector{NTuple{2,Float64}} && length(periodic_spline.cache) == 6 + @test typeof(periodic_spline.cache) == Vector{NTuple{2, Float64}} && length(periodic_spline.cache) == 6 @test periodic_spline.knots == [0, 0, 0, 0, 1, 2, 3, 3, 3, 3] @test length(periodic_spline.lookup_table) == 5000 for i in 1:5000 @@ -1099,9 +1107,9 @@ end end longer_control_points = [(0.3, 0.3), (0.5, -1.0), (2.0, 0.0), (2.5, 3.2), (-10.0, 10.0)] - longer_spline = BSpline(longer_control_points; lookup_steps=2500) + longer_spline = BSpline(longer_control_points; lookup_steps = 2500) @test longer_spline.control_points ⪧ longer_control_points - @test typeof(longer_spline.cache) == Vector{NTuple{2,Float64}} && length(longer_spline.cache) == 5 + @test typeof(longer_spline.cache) == Vector{NTuple{2, Float64}} && length(longer_spline.cache) == 5 @test longer_spline.knots == [0, 0, 0, 0, 1, 2, 2, 2, 2] @test length(longer_spline.lookup_table) == 2500 for i in 1:2500 @@ -1109,9 +1117,9 @@ end end quadratic_control_points = [(0.1, 0.1), (0.2, 0.2), (0.5, 0.8), (1.0, 2.0), (0.0, 15.0), (-5.0, 10.0), (-10.0, 0.0)] - quadratic_spline = BSpline(quadratic_control_points; degree=2) + quadratic_spline = BSpline(quadratic_control_points; degree = 2) @test quadratic_spline.control_points ⪧ quadratic_control_points - @test typeof(quadratic_spline.cache) == Vector{NTuple{2,Float64}} && length(quadratic_spline.cache) == 7 + @test typeof(quadratic_spline.cache) == Vector{NTuple{2, Float64}} && length(quadratic_spline.cache) == 7 @test quadratic_spline.knots == [0, 0, 0, 1, 2, 3, 4, 5, 5, 5] @test length(quadratic_spline.lookup_table) == 5000 for i in 1:5000 @@ -1119,9 +1127,9 @@ end end sextic_control_points = [(cos(t), sin(t)) for t in LinRange(0, π - π / 3, 10)] - sextic_spline = BSpline(sextic_control_points; degree=6) + sextic_spline = BSpline(sextic_control_points; degree = 6) @test sextic_spline.control_points ⪧ sextic_control_points - @test typeof(sextic_spline.cache) == Vector{NTuple{2,Float64}} && length(sextic_spline.cache) == 10 + @test typeof(sextic_spline.cache) == Vector{NTuple{2, Float64}} && length(sextic_spline.cache) == 10 @test sextic_spline.knots == [0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4] @test length(sextic_spline.lookup_table) == 5000 for i in 1:5000 @@ -1130,9 +1138,9 @@ end quadratic_periodic_control_points = [(cos(t), sin(t)) for t in LinRange(0, 2π, 5)] quadratic_periodic_control_points[end] = quadratic_periodic_control_points[1] - quadratic_periodic_spline = BSpline(quadratic_periodic_control_points; degree=2) + quadratic_periodic_spline = BSpline(quadratic_periodic_control_points; degree = 2) @test quadratic_periodic_spline.control_points ⪧ quadratic_periodic_control_points - @test typeof(quadratic_periodic_spline.cache) == Vector{NTuple{2,Float64}} && length(quadratic_periodic_spline.cache) == 5 + @test typeof(quadratic_periodic_spline.cache) == Vector{NTuple{2, Float64}} && length(quadratic_periodic_spline.cache) == 5 @test quadratic_periodic_spline.knots == [0, 0, 0, 1, 2, 3, 3, 3] @test length(quadratic_periodic_spline.lookup_table) == 5000 for i in 1:5000 @@ -1152,28 +1160,28 @@ end @test spline(0.0) ⪧ control_points[begin] @test spline(1.0) ⪧ control_points[end] - @test spline(1e-16) ⪧ control_points[begin] atol = 1e-9 - @test spline(1 - 1e-16) ⪧ control_points[end] atol = 1e-9 + @test spline(1.0e-16) ⪧ control_points[begin] atol = 1.0e-9 + @test spline(1 - 1.0e-16) ⪧ control_points[end] atol = 1.0e-9 @test periodic_spline(0.0) ⪧ periodic_control_points[begin] @test periodic_spline(1.0) ⪧ periodic_control_points[end] - @test periodic_spline(1e-16) ⪧ periodic_control_points[begin] atol = 1e-9 - @test periodic_spline(1 - 1e-16) ⪧ periodic_control_points[end] atol = 1e-9 + @test periodic_spline(1.0e-16) ⪧ periodic_control_points[begin] atol = 1.0e-9 + @test periodic_spline(1 - 1.0e-16) ⪧ periodic_control_points[end] atol = 1.0e-9 @test longer_spline(0.0) ⪧ longer_control_points[begin] @test longer_spline(1.0) ⪧ longer_control_points[end] - @test longer_spline(1e-16) ⪧ longer_control_points[begin] atol = 1e-9 - @test longer_spline(1 - 1e-16) ⪧ longer_control_points[end] atol = 1e-9 + @test longer_spline(1.0e-16) ⪧ longer_control_points[begin] atol = 1.0e-9 + @test longer_spline(1 - 1.0e-16) ⪧ longer_control_points[end] atol = 1.0e-9 @test quadratic_spline(0.0) ⪧ quadratic_control_points[begin] @test quadratic_spline(1.0) ⪧ quadratic_control_points[end] - @test quadratic_spline(1e-16) ⪧ quadratic_control_points[begin] atol = 1e-9 - @test quadratic_spline(1 - 1e-16) ⪧ quadratic_control_points[end] atol = 1e-9 + @test quadratic_spline(1.0e-16) ⪧ quadratic_control_points[begin] atol = 1.0e-9 + @test quadratic_spline(1 - 1.0e-16) ⪧ quadratic_control_points[end] atol = 1.0e-9 @test sextic_spline(0.0) ⪧ sextic_control_points[begin] @test sextic_spline(1.0) ⪧ sextic_control_points[end] - @test sextic_spline(1e-16) ⪧ sextic_control_points[begin] atol = 1e-9 - @test sextic_spline(1 - 1e-16) ⪧ sextic_control_points[end] atol = 1e-9 + @test sextic_spline(1.0e-16) ⪧ sextic_control_points[begin] atol = 1.0e-9 + @test sextic_spline(1 - 1.0e-16) ⪧ sextic_control_points[end] atol = 1.0e-9 @test quadratic_periodic_spline(0.0) ⪧ quadratic_periodic_control_points[begin] @test quadratic_periodic_spline(1.0) ⪧ quadratic_periodic_control_points[end] - @test quadratic_periodic_spline(1e-16) ⪧ quadratic_periodic_control_points[begin] atol = 1e-9 - @test quadratic_periodic_spline(1 - 1e-16) ⪧ quadratic_periodic_control_points[end] atol = 1e-9 + @test quadratic_periodic_spline(1.0e-16) ⪧ quadratic_periodic_control_points[begin] atol = 1.0e-9 + @test quadratic_periodic_spline(1 - 1.0e-16) ⪧ quadratic_periodic_control_points[end] atol = 1.0e-9 t = 0:0.1:1 spline_t = [ @@ -1187,7 +1195,7 @@ end [15.4883, 17.471899999999998], [16.471200000000003, 18.6896], [17.0869, 18.745700000000003], - [17.3, 17.3] + [17.3, 17.3], ] periodic_spline_t = [ [0, 0], @@ -1200,7 +1208,7 @@ end [0.286875, 0.8336250000000002], [0.315, 0.657], [0.2756250000000001, 0.3858750000000003], - [6.661338147750935e-16, 6.661338147750937e-16] + [6.661338147750935e-16, 6.661338147750937e-16], ] longer_spline_t = [ [0.3, 0.3], @@ -1213,7 +1221,7 @@ end [1.4300000000000004, 2.3716], [-0.3199999999999982, 4.038399999999999], [-3.929999999999996, 6.506799999999997], - [-9.999999999999995, 9.999999999999995] + [-9.999999999999995, 9.999999999999995], ] quadratic_spline_t = [ [0.1, 0.1], @@ -1226,7 +1234,7 @@ end [-0.5, 12.75], [-2.4999999999999982, 12.500000000000004], [-5.625, 8.125], - [-9.999999999999991, 1.7763568394002498e-14] + [-9.999999999999991, 1.7763568394002498e-14], ] sextic_spline_t = [ [1, 0], @@ -1239,7 +1247,7 @@ end [0.2246521007365532, 0.9523458140503687], [0.0622718120248865, 0.9784464185342435], [-0.1472786929037561, 0.9723545852185906], - [-0.49999999999999956, 0.8660254037844393] + [-0.49999999999999956, 0.8660254037844393], ] quadratic_periodic_spline_t = [ [1, 0], @@ -1252,7 +1260,7 @@ end [-0.3950000000000005, -0.5849999999999997], [-0.02000000000000024, -0.66], [0.44499999999999945, -0.4650000000000003], - [0.9999999999999991, -8.881784197001249e-16] + [0.9999999999999991, -8.881784197001249e-16], ] @test spline.(t) ⪧ spline_t @test periodic_spline.(t) ⪧ periodic_spline_t @@ -1268,10 +1276,10 @@ end t = LinRange(0, 1, 25000) f = tuple.(sin.(π .* t), cos.(π .* t)) spl = BSpline(f) - for t in t[3:end-2] - @test spl(t) ⪧ (sin(π * t), cos(π * t)) rtol = 1e-2 + for t in t[3:(end - 2)] + @test spl(t) ⪧ (sin(π * t), cos(π * t)) rtol = 1.0e-2 der = DT.differentiate(spl, t) - @test ⪧(der, (π * cos(π * t), -π * sin(π * t)); atol=1e-2) + @test ⪧(der, (π * cos(π * t), -π * sin(π * t)); atol = 1.0e-2) end t = LinRange(0, 1, 25000) @@ -1279,10 +1287,10 @@ end f[end] = f[begin] spl = BSpline(f) ctr = 0 - for t in t[3:end-2] - @test spl(t) ⪧ (sin(2π * t), cos(2π * t)) rtol = 1e-2 + for t in t[3:(end - 2)] + @test spl(t) ⪧ (sin(2π * t), cos(2π * t)) rtol = 1.0e-2 der = DT.differentiate(spl, t) - @test ⪧(der, (2π * cos(2π * t), -2π * sin(2π * t)); atol=1e-2) + @test ⪧(der, (2π * cos(2π * t), -2π * sin(2π * t)); atol = 1.0e-2) end t = LinRange(0, 1, 1500) @@ -1291,7 +1299,7 @@ end der1 = ForwardDiff.derivative(t -> slow_eval_bspline(spl.control_points, spl.knots, t), t) der2 = DT.differentiate(spl, t) @inferred DT.differentiate(spl, t) - h = 1e-4 + h = 1.0e-4 if h < t < 1 - h der3 = (spl(t + h) .- spl(t - h)) ./ (2h) elseif t < h @@ -1299,8 +1307,8 @@ end else der3 = (spl(t) .- spl(t - h)) ./ h end - flag1 = ⪧(der1, der2, rtol=1e-6, atol=1e-6) - flag2 = ⪧(der2, der3, rtol=1e-3, atol=1e-6) + flag1 = ⪧(der1, der2, rtol = 1.0e-6, atol = 1.0e-6) + flag2 = ⪧(der2, der3, rtol = 1.0e-3, atol = 1.0e-6) @test flag1 || flag2 end end @@ -1310,7 +1318,7 @@ end for t in LinRange(0, 1, 1500) der1 = DT.twice_differentiate(spl, t) @inferred DT.twice_differentiate(spl, t) - h = 1e-6 + h = 1.0e-6 if 3h < t < 1 - 3h der2 = (spl(t + h) .- 2 .* spl(t) .+ spl(t - h)) ./ (h^2) elseif t < 3h @@ -1320,16 +1328,16 @@ end # h = 1e-2 der2 = (2.0 .* spl(t) .- 5.0 .* spl(t - h) .+ 4.0 .* spl(t - 2h) .- spl(t - 3h)) ./ h^2 end - @test der1 ⪧ der2 rtol = 1e-1 atol = 1e-1 + @test der1 ⪧ der2 rtol = 1.0e-1 atol = 1.0e-1 end end t = LinRange(0, 1, 25000) f = tuple.(sin.(π .* t), cos.(π .* t)) spl = BSpline(f) - for t in t[4:end-4] + for t in t[4:(end - 4)] der = DT.twice_differentiate(spl, t) - @test ⪧(der, (-π^2 * sin(π * t), -π^2 * cos(π * t)); atol=1e-2) + @test ⪧(der, (-π^2 * sin(π * t), -π^2 * cos(π * t)); atol = 1.0e-2) end ## Thrice differentiate @@ -1340,7 +1348,7 @@ end der1 = _der1(t) der2 = DT.thrice_differentiate(spl, t) @inferred DT.thrice_differentiate(spl, t) - h = 1e-4 + h = 1.0e-4 if h < t < 1 - h der3 = (DT.twice_differentiate(spl, t + h) .- DT.twice_differentiate(spl, t - h)) ./ (2h) elseif t < h @@ -1348,8 +1356,8 @@ end else der3 = (DT.twice_differentiate(spl, t) .- DT.twice_differentiate(spl, t - h)) ./ h end - flag1 = ⪧(der1, der2, rtol=1e-6, atol=1e-6) - flag2 = ⪧(der2, der3, rtol=1e-3, atol=1e-6) + flag1 = ⪧(der1, der2, rtol = 1.0e-6, atol = 1.0e-6) + flag2 = ⪧(der2, der3, rtol = 1.0e-3, atol = 1.0e-6) @test flag1 || flag2 end end @@ -1357,9 +1365,9 @@ end t = LinRange(0, 1, 2500) f = tuple.(sin.(π .* t), cos.(π .* t)) spl = BSpline(f) - for t in t[4:end-4] + for t in t[4:(end - 4)] der = DT.thrice_differentiate(spl, t) - @test ⪧(der, (-π^3 * cos(π * t), π^3 * sin(π * t)); atol=1e-2, rtol=1e-2) + @test ⪧(der, (-π^3 * cos(π * t), π^3 * sin(π * t)); atol = 1.0e-2, rtol = 1.0e-2) end ## Closest point @@ -1370,23 +1378,23 @@ end @test q ⪧ spl(t′) _t, _q = closest_point_on_curve(spl, p) if !(spl == periodic_spline || spl == quadratic_periodic_spline) - @test _t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test _t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 elseif t ≠ 0 && t ≠ 1 - @test _t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test _t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 end - @test q ⪧ _q rtol = 1e-1 atol = 1e-1 - @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1e-1 atol = 1e-1 + @test q ⪧ _q rtol = 1.0e-1 atol = 1.0e-1 + @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1.0e-1 atol = 1.0e-1 end for t in LinRange(0, 1, 150) p = spl(t) t′, q = DT.get_closest_point(spl, p) @test q ⪧ spl(t′) if !(spl == periodic_spline || spl == quadratic_periodic_spline) - @test t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 elseif t ≠ 0 && t ≠ 1 - @test t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 end - @test p ⪧ q rtol = 1e-1 atol = 1e-1 + @test p ⪧ q rtol = 1.0e-1 atol = 1.0e-1 end @test DT.get_closest_point(spl, spl(0.0)) == (0.0, spl(0.0)) if spl ∉ (periodic_spline, quadratic_periodic_spline) @@ -1546,18 +1554,18 @@ end ## Arclength for spl in (spline, periodic_spline, longer_spline, quadratic_spline, sextic_spline, quadratic_periodic_spline) - @test DT.arc_length(spl) ≈ slow_arc_length(spl, 0, 1) rtol = 1e-4 + @test DT.arc_length(spl) ≈ slow_arc_length(spl, 0, 1) rtol = 1.0e-4 @inferred DT.arc_length(spl) - @test DT.arc_length(spl, 0.1, 0.15) ≈ slow_arc_length(spl, 0.1, 0.15) rtol = 1e-4 + @test DT.arc_length(spl, 0.1, 0.15) ≈ slow_arc_length(spl, 0.1, 0.15) rtol = 1.0e-4 @test DT.arc_length(spl, 0.0, 0.0) ≈ 0.0 @test DT.arc_length(spl, 1.0, 1.0) ≈ 0.0 - @test DT.arc_length(spl, 0.0, 1.0) ≈ slow_arc_length(spl, 0.0, 1.0) rtol = 1e-3 - @test DT.arc_length(spl, 0.3, 0.9) ≈ slow_arc_length(spl, 0.3, 0.9) rtol = 1e-3 - @test DT.arc_length(spl, 0.2, 0.21) ≈ slow_arc_length(spl, 0.2, 0.21) rtol = 1e-4 + @test DT.arc_length(spl, 0.0, 1.0) ≈ slow_arc_length(spl, 0.0, 1.0) rtol = 1.0e-3 + @test DT.arc_length(spl, 0.3, 0.9) ≈ slow_arc_length(spl, 0.3, 0.9) rtol = 1.0e-3 + @test DT.arc_length(spl, 0.2, 0.21) ≈ slow_arc_length(spl, 0.2, 0.21) rtol = 1.0e-4 for _ in 1:1000 t₁, t₂ = rand(2) t₁, t₂ = minmax(t₁, t₂) - @test DT.arc_length(spl, t₁, t₂) ≈ slow_arc_length(spl, t₁, t₂) rtol = 1e-2 + @test DT.arc_length(spl, t₁, t₂) ≈ slow_arc_length(spl, t₁, t₂) rtol = 1.0e-2 end end @@ -1570,7 +1578,7 @@ end vec2 = [∂²x, ∂²y, 0.0] cur1 = DT.curvature(c, t) cur2 = cross(vec1, vec2)[3] / norm(vec1)^3 - @test cur1 ≈ cur2 rtol = 1e-5 atol = 1e-5 + @test cur1 ≈ cur2 rtol = 1.0e-5 atol = 1.0e-5 end end @@ -1580,13 +1588,13 @@ end TV = DT.total_variation(c) @inferred DT.total_variation(c) TVslow = slow_total_absolute_curvature(c, 0, 1) - @test TV ≈ TVslow rtol = 1e-3 atol = 1e-3 + @test TV ≈ TVslow rtol = 1.0e-3 atol = 1.0e-3 for _ in 1:1000 t1, t2 = minmax(rand(2)...) TV = DT.total_variation(c, t1, t2) @inferred DT.total_variation(c, t1, t2) TVslow = slow_total_absolute_curvature(c, t1, t2) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-1 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-1 end end @@ -1598,9 +1606,9 @@ end t = DT.get_equidistant_split(c, t1, t2) s1 = DT.arc_length(c, t1, t) s2 = DT.arc_length(c, t, t2) - @test s1 ≈ s2 rtol = 1e-1 atol = 1e-1 + @test s1 ≈ s2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 - @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1e-1 + @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1.0e-1 end end @@ -1612,7 +1620,7 @@ end t, T = DT.get_equivariation_split(c, t1, t2) T1 = DT.total_variation(c, t1, t) T2 = DT.total_variation(c, t, t2) - @test T1 ≈ T2 rtol = 1e-1 atol = 1e-1 + @test T1 ≈ T2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 @test T ≈ T1 end @@ -1632,18 +1640,18 @@ end ## get_circle_intersection c = sextic_spline - t₁, t₂, r, = 0.0, 1.0, 1.0 + t₁, t₂, r = 0.0, 1.0, 1.0 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.5096019203840768 && q′ ⪧ (0.47649648275716505, 0.8518859813755716) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 - t₁, t₂, r, = 1.0, 0.0, 1.0 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 + t₁, t₂, r = 1.0, 0.0, 1.0 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.49019803960792163 && q′ ⪧ (0.4997446106449962, 0.8384596166783065) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-2 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-2 t₁, t₂, r = 0.0, 0.1, 0.2 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.04410882176435287 && q′ ⪧ (0.9666126168475349, 0.1970440391610145) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-2 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-2 ## == @test spline == spline @@ -1657,7 +1665,7 @@ end ctrl1 = [(0.0, 1.3), (17.3, 5.0), (-1.0, 2.0), (50.0, 23.0), (17.3, -2.0), (27.3, 50.1)] ctrl2 = [(5.3, 1.3), (17.5, 23.0), (17.3, 200.0), (173.0, 1.3), (0.0, 0.0)] @test BSpline(ctrl1) == BSpline(ctrl1) - @test BSpline(ctrl1) ≠ BSpline(ctrl1, degree=2) + @test BSpline(ctrl1) ≠ BSpline(ctrl1, degree = 2) @test BSpline(ctrl1) ≠ BSpline(ctrl2) end @@ -1684,12 +1692,12 @@ end end end t = LinRange(0, 1, 1500) - fig = Figure(fontsize=44) + fig = Figure(fontsize = 44) for i in 1:3 for j in 1:3 - ax = Axis(fig[i, j], xlabel=L"x", ylabel=L"y", title=L"α = %$(α[i]), τ = %$(τ[j])", titlealign=:left, width=400, height=400) - lines!(ax, spl[i, j].(t), color=:blue, linewidth=6) - scatter!(ax, [p₀, p₁, p₂, p₃], color=[:blue, :black, :red, :green], markersize=16) + ax = Axis(fig[i, j], xlabel = L"x", ylabel = L"y", title = L"α = %$(α[i]), τ = %$(τ[j])", titlealign = :left, width = 400, height = 400) + lines!(ax, spl[i, j].(t), color = :blue, linewidth = 6) + scatter!(ax, [p₀, p₁, p₂, p₃], color = [:blue, :black, :red, :green], markersize = 16) end end resize_to_layout!(fig) @@ -1701,7 +1709,7 @@ end for t in LinRange(0, 1, 15000) @test DT.differentiate(_spl, t) ⪧ 3.0 .* _spl.a .* t^2 .+ 2.0 .* _spl.b .* t .+ _spl.c @inferred DT.differentiate(_spl, t) - @test DT.differentiate(_spl, t) ⪧ (_spl(t + 1e-6) .- _spl(t - 1e-6)) ./ 2e-6 atol = 1e-4 rtol = 1e-4 + @test DT.differentiate(_spl, t) ⪧ (_spl(t + 1.0e-6) .- _spl(t - 1.0e-6)) ./ 2.0e-6 atol = 1.0e-4 rtol = 1.0e-4 @test DT.twice_differentiate(_spl, t) ⪧ 6.0 .* _spl.a .* t .+ 2.0 .* _spl.b @inferred DT.twice_differentiate(_spl, t) @test DT.thrice_differentiate(_spl, t) ⪧ 6.0 .* _spl.a @@ -1714,62 +1722,62 @@ end p₁, p₂, p₃, p₄, x = (2.571, 4.812), (2.05, 17.81), (17.3, -25.3), (0.5, 0.3), 10.0 perms_1234 = [ - 4 3 2 1 - 4 3 1 2 - 4 2 3 1 - 4 2 1 3 - 4 1 3 2 - 4 1 2 3 - 3 4 2 1 - 3 4 1 2 - 3 2 4 1 - 3 2 1 4 - 3 1 4 2 - 3 1 2 4 - 2 4 3 1 - 2 4 1 3 - 2 3 4 1 - 2 3 1 4 - 2 1 4 3 - 2 1 3 4 - 1 4 3 2 - 1 4 2 3 - 1 3 4 2 - 1 3 2 4 - 1 2 4 3 - 1 2 3 4 - ] + 4 3 2 1 + 4 3 1 2 + 4 2 3 1 + 4 2 1 3 + 4 1 3 2 + 4 1 2 3 + 3 4 2 1 + 3 4 1 2 + 3 2 4 1 + 3 2 1 4 + 3 1 4 2 + 3 1 2 4 + 2 4 3 1 + 2 4 1 3 + 2 3 4 1 + 2 3 1 4 + 2 1 4 3 + 2 1 3 4 + 1 4 3 2 + 1 4 2 3 + 1 3 4 2 + 1 3 2 4 + 1 2 4 3 + 1 2 3 4 + ] th4 = [DT.thiele4((p₁, p₂, p₃, p₄)[[i, j, k, ℓ]]..., x)[1] for (i, j, k, ℓ) in eachrow(perms_1234)] th3 = [DT.thiele3((p₁, p₂, p₃, p₄)[[i, j, k]]..., x)[1] for (i, j, k, ℓ) in eachrow(perms_1234)] quad = [DT.quadratic_interp((p₁, p₂, p₃, p₄)[[i, j, k]]..., x)[1] for (i, j, k, ℓ) in eachrow(perms_1234)] th4th3quad = [ - -12.5908 -31.3945 44.1259 - -12.5908 -91.4788 3.2565 - -12.5908 -31.3945 44.1259 - -12.5908 1.95457 -1214.16 - -12.5908 -91.4788 3.2565 - -12.5908 1.95457 -1214.16 - -12.5908 -31.3945 44.1259 - -12.5908 -91.4788 3.2565 - -12.5908 -31.3945 44.1259 - -12.5908 -22.2832 -91.8257 - -12.5908 -91.4788 3.2565 - -12.5908 -22.2832 -91.8257 - -12.5908 -31.3945 44.1259 - -12.5908 1.95457 -1214.16 - -12.5908 -31.3945 44.1259 - -12.5908 -22.2832 -91.8257 - -12.5908 1.95457 -1214.16 - -12.5908 -22.2832 -91.8257 - -12.5908 -91.4788 3.2565 - -12.5908 1.95457 -1214.16 - -12.5908 -91.4788 3.2565 - -12.5908 -22.2832 -91.8257 - -12.5908 1.95457 -1214.16 - -12.5908 -22.2832 -91.8257 - ] - @test [th4 th3 quad] ≈ th4th3quad rtol = 1e-5 + -12.5908 -31.3945 44.1259 + -12.5908 -91.4788 3.2565 + -12.5908 -31.3945 44.1259 + -12.5908 1.95457 -1214.16 + -12.5908 -91.4788 3.2565 + -12.5908 1.95457 -1214.16 + -12.5908 -31.3945 44.1259 + -12.5908 -91.4788 3.2565 + -12.5908 -31.3945 44.1259 + -12.5908 -22.2832 -91.8257 + -12.5908 -91.4788 3.2565 + -12.5908 -22.2832 -91.8257 + -12.5908 -31.3945 44.1259 + -12.5908 1.95457 -1214.16 + -12.5908 -31.3945 44.1259 + -12.5908 -22.2832 -91.8257 + -12.5908 1.95457 -1214.16 + -12.5908 -22.2832 -91.8257 + -12.5908 -91.4788 3.2565 + -12.5908 1.95457 -1214.16 + -12.5908 -91.4788 3.2565 + -12.5908 -22.2832 -91.8257 + -12.5908 1.95457 -1214.16 + -12.5908 -22.2832 -91.8257 + ] + @test [th4 th3 quad] ≈ th4th3quad rtol = 1.0e-5 control_points = [(-9.0, 5.0), (-7.0, 6.0), (-6.0, 4.0), (-3.0, 5.0)] periodic_control_points = [(-2.0, -2.0), (0.0, 0.0), (15.0, 0.0), (13.7, 5.3), (-10.0, 0.0), (-2.0, -2.0)] @@ -1808,16 +1816,16 @@ end alpha = 1 / 2 tension = 0.0 else - spl = CatmullRomSpline(control_points; lookup_steps, _alpha=alpha, _tension=tension) - pspl = CatmullRomSpline(periodic_control_points; lookup_steps, _alpha=alpha, _tension=tension) + spl = CatmullRomSpline(control_points; lookup_steps, _alpha = alpha, _tension = tension) + pspl = CatmullRomSpline(periodic_control_points; lookup_steps, _alpha = alpha, _tension = tension) end knots = zeros(4) pknots = zeros(6) for i in 2:4 - knots[i] = knots[i-1] + norm(control_points[i] .- control_points[i-1])^alpha + knots[i] = knots[i - 1] + norm(control_points[i] .- control_points[i - 1])^alpha end for i in 2:6 - pknots[i] = pknots[i-1] + norm(periodic_control_points[i] .- periodic_control_points[i-1])^alpha + pknots[i] = pknots[i - 1] + norm(periodic_control_points[i] .- periodic_control_points[i - 1])^alpha end left = DT.extend_left_control_point(control_points) right = DT.extend_right_control_point(control_points) @@ -1825,8 +1833,8 @@ end pright = DT.extend_right_control_point(periodic_control_points) knots ./= knots[end] pknots ./= pknots[end] - lookup_table = Vector{NTuple{2,Float64}}(undef, lookup_steps) - plookup_table = Vector{NTuple{2,Float64}}(undef, lookup_steps) + lookup_table = Vector{NTuple{2, Float64}}(undef, lookup_steps) + plookup_table = Vector{NTuple{2, Float64}}(undef, lookup_steps) for i in 1:lookup_steps t = (i - 1) / (lookup_steps - 1) lookup_table[i] = spl(t) @@ -1856,10 +1864,10 @@ end spl = CatmullRomSpline(control_points) pspl = CatmullRomSpline(periodic_control_points) @test DT.is_curve_bounded(spl) - @test spl(0) ⪧ spl(1e-16) ⪧ (-9.0, 5.0) - @test spl(1) ⪧ spl(1 - 1e-16) ⪧ (-9.0, 10.0) - @test pspl(0) ⪧ pspl(1e-16) ⪧ (-2.0, -2.0) - @test pspl(1) ⪧ pspl(1 - 1e-16) ⪧ (-2.0, -2.0) + @test spl(0) ⪧ spl(1.0e-16) ⪧ (-9.0, 5.0) + @test spl(1) ⪧ spl(1 - 1.0e-16) ⪧ (-9.0, 10.0) + @test pspl(0) ⪧ pspl(1.0e-16) ⪧ (-2.0, -2.0) + @test pspl(1) ⪧ pspl(1 - 1.0e-16) ⪧ (-2.0, -2.0) t_vals = LinRange(0.01, 0.99, 50) splt = spl.(t_vals) psplt = pspl.(t_vals) @@ -1915,7 +1923,7 @@ end (-4.82247, 10.6957) (-4.20389, -1.96817) (-6.61471, 10.3812) (-3.16042, -2.07246) (-8.25906, 10.1109) (-2.31858, -2.05861) - ] rtol = 1e-5 + ] rtol = 1.0e-5 for spl in (spl, pspl) for (i, t) in enumerate(spl.knots) @test spl(t) ⪧ spl.control_points[i] @@ -1928,7 +1936,7 @@ end for t in t der1 = DT.differentiate(spl, t) @inferred DT.differentiate(spl, t) - h = 1e-6 + h = 1.0e-6 if h < t < 1 - h der2 = (spl(t + h) .- spl(t - h)) ./ (2h) elseif t < h @@ -1936,7 +1944,7 @@ end else der2 = (spl(t) .- spl(t - h)) ./ h end - @test der1 ⪧ der2 rtol = 1e-4 atol = 1e-4 + @test der1 ⪧ der2 rtol = 1.0e-4 atol = 1.0e-4 end end @@ -1946,7 +1954,7 @@ end for t in t der1 = DT.twice_differentiate(spl, t) @inferred DT.twice_differentiate(spl, t) - h = 1e-6 + h = 1.0e-6 if 3h < t < 1 - 3h der2 = (spl(t + h) .- 2 .* spl(t) .+ spl(t - h)) ./ (h^2) elseif t < 3h @@ -1956,7 +1964,7 @@ end # h = 1e-2 der2 = (2.0 .* spl(t) .- 5.0 .* spl(t - h) .+ 4.0 .* spl(t - 2h) .- spl(t - 3h)) ./ h^2 end - @test der1 ⪧ der2 rtol = 1e-1 atol = 1e-1 + @test der1 ⪧ der2 rtol = 1.0e-1 atol = 1.0e-1 end end @@ -1964,7 +1972,7 @@ end t = LinRange(0, 1, 15000) for spl in (spl, pspl) for t in t - h = 1e-6 + h = 1.0e-6 der1 = DT.thrice_differentiate(spl, t) @inferred DT.thrice_differentiate(spl, t) if h < t < 1 - h @@ -1974,7 +1982,7 @@ end else der2 = (DT.twice_differentiate(spl, t) .- DT.twice_differentiate(spl, t - h)) ./ h end - @test der1 ⪧ der2 rtol = 1e-4 atol = 1e-4 + @test der1 ⪧ der2 rtol = 1.0e-4 atol = 1.0e-4 end end @@ -1986,23 +1994,23 @@ end @test q ⪧ spl(t′) _t, _q = closest_point_on_curve(spl, p) if !(spl == pspl) - @test _t ≈ t′ rtol = 1e-1 atol = 1e-1 - elseif !isapprox(_t, 0, atol=1e-3) && !isapprox(_t, 1, atol=1e-3) && !isapprox(t′, 0, atol=1e-3) && !isapprox(t′, 1, atol=1e-3) - @test _t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test _t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 + elseif !isapprox(_t, 0, atol = 1.0e-3) && !isapprox(_t, 1, atol = 1.0e-3) && !isapprox(t′, 0, atol = 1.0e-3) && !isapprox(t′, 1, atol = 1.0e-3) + @test _t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 end - @test q ⪧ _q rtol = 1e-1 atol = 1e-1 - @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1e-1 atol = 1e-1 + @test q ⪧ _q rtol = 1.0e-1 atol = 1.0e-1 + @test DT.dist(p, _q) ≈ DT.dist(p, q) rtol = 1.0e-1 atol = 1.0e-1 end for t in LinRange(0, 1, 150) p = spl(t) t′, q = DT.get_closest_point(spl, p) @test q ⪧ spl(t′) if !(spl == pspl) - @test t ≈ t′ rtol = 1e-1 atol = 1e-1 - elseif !isapprox(t, 0, atol=1e-3) && !isapprox(t, 1, atol=1e-3) - @test t ≈ t′ rtol = 1e-1 atol = 1e-1 + @test t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 + elseif !isapprox(t, 0, atol = 1.0e-3) && !isapprox(t, 1, atol = 1.0e-3) + @test t ≈ t′ rtol = 1.0e-1 atol = 1.0e-1 end - @test p ⪧ q rtol = 1e-1 atol = 1e-1 + @test p ⪧ q rtol = 1.0e-1 atol = 1.0e-1 end @test DT.get_closest_point(spl, spl.control_points[1]) == (0.0, spl.control_points[1]) if spl ≠ pspl @@ -2086,18 +2094,18 @@ end ## Arclength for spl in (spl, pspl) - @test DT.arc_length(spl) ≈ slow_arc_length(spl, 0, 1) rtol = 1e-4 + @test DT.arc_length(spl) ≈ slow_arc_length(spl, 0, 1) rtol = 1.0e-4 @inferred DT.arc_length(spl) - @test DT.arc_length(spl, 0.1, 0.15) ≈ slow_arc_length(spl, 0.1, 0.15) rtol = 1e-4 + @test DT.arc_length(spl, 0.1, 0.15) ≈ slow_arc_length(spl, 0.1, 0.15) rtol = 1.0e-4 @test DT.arc_length(spl, 0.0, 0.0) ≈ 0.0 @test DT.arc_length(spl, 1.0, 1.0) ≈ 0.0 - @test DT.arc_length(spl, 0.0, 1.0) ≈ slow_arc_length(spl, 0.0, 1.0) rtol = 1e-3 - @test DT.arc_length(spl, 0.3, 0.9) ≈ slow_arc_length(spl, 0.3, 0.9) rtol = 1e-3 - @test DT.arc_length(spl, 0.2, 0.21) ≈ slow_arc_length(spl, 0.2, 0.21) rtol = 1e-4 + @test DT.arc_length(spl, 0.0, 1.0) ≈ slow_arc_length(spl, 0.0, 1.0) rtol = 1.0e-3 + @test DT.arc_length(spl, 0.3, 0.9) ≈ slow_arc_length(spl, 0.3, 0.9) rtol = 1.0e-3 + @test DT.arc_length(spl, 0.2, 0.21) ≈ slow_arc_length(spl, 0.2, 0.21) rtol = 1.0e-4 for _ in 1:1000 t₁, t₂ = rand(2) t₁, t₂ = minmax(t₁, t₂) - @test DT.arc_length(spl, t₁, t₂) ≈ slow_arc_length(spl, t₁, t₂) rtol = 1e-2 + @test DT.arc_length(spl, t₁, t₂) ≈ slow_arc_length(spl, t₁, t₂) rtol = 1.0e-2 end end @@ -2110,7 +2118,7 @@ end vec2 = [∂²x, ∂²y, 0.0] cur1 = DT.curvature(c, t) cur2 = cross(vec1, vec2)[3] / norm(vec1)^3 - @test cur1 ≈ cur2 rtol = 1e-5 atol = 1e-5 + @test cur1 ≈ cur2 rtol = 1.0e-5 atol = 1.0e-5 @inferred DT.curvature(c, t) end end @@ -2121,13 +2129,13 @@ end TV = DT.total_variation(c) @inferred DT.total_variation(c) TVslow = slow_total_absolute_curvature(c, 0, 1) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-3 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-3 for _ in 1:1000 t1, t2 = minmax(rand(2)...) TV = DT.total_variation(c, t1, t2) @inferred DT.total_variation(c, t1, t2) TVslow = slow_total_absolute_curvature(c, t1, t2) - @test TV ≈ TVslow rtol = 1e-1 atol = 1e-1 + @test TV ≈ TVslow rtol = 1.0e-1 atol = 1.0e-1 end end @@ -2139,9 +2147,9 @@ end t = DT.get_equidistant_split(c, t1, t2) s1 = DT.arc_length(c, t1, t) s2 = DT.arc_length(c, t, t2) - @test s1 ≈ s2 rtol = 1e-1 atol = 1e-1 + @test s1 ≈ s2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 - @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1e-1 + @test DT.arc_length(c, t1, t2) ≈ 2s1 rtol = 1.0e-1 end end @@ -2153,7 +2161,7 @@ end t, T = DT.get_equivariation_split(c, t1, t2) T1 = DT.total_variation(c, t1, t) T2 = DT.total_variation(c, t, t2) - @test T1 ≈ T2 rtol = 1e-1 atol = 1e-1 + @test T1 ≈ T2 rtol = 1.0e-1 atol = 1.0e-1 @test t1 ≤ t ≤ t2 @test T ≈ T1 end @@ -2172,31 +2180,31 @@ end for t in LinRange(0, 1, 25000) t′ = DT.get_inverse(c, c(t)) if c ≠ pspl - @test t ≈ t′ rtol = 1e-3 + @test t ≈ t′ rtol = 1.0e-3 else - @test c(t) ⪧ c(t′) rtol = 1e-2 + @test c(t) ⪧ c(t′) rtol = 1.0e-2 end end end ## get_circle_intersection c = spl - t₁, t₂, r, = 0.0, 1.0, 1.0 + t₁, t₂, r = 0.0, 1.0, 1.0 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.03190638127625525 && q′ ⪧ (-8.130630223009339, 5.495953786102033) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 r = 13.0 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.43806261252250456 && q′ ⪧ (1.1435184529348763, -3.13023349324047) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-3 - t₁, t₂, r, = 1.0, 0.0, 1.0 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-3 + t₁, t₂, r = 1.0, 0.0, 1.0 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.9865973255686293 && q′ ⪧ (-7.9932950700471235, 10.152688406611302) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-1 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-1 t₁, t₂, r = 0.0, 0.1, 0.2 t′, q′ = DT.get_circle_intersection(c, t₁, t₂, r) @test t′ ≈ 0.007051410282056411 && q′ ⪧ (-8.812636716331587, 5.071072149949431) - @test DT.dist(c(t₁), q′) ≈ r rtol = 1e-2 + @test DT.dist(c(t₁), q′) ≈ r rtol = 1.0e-2 # == @test spl == spl @@ -2205,8 +2213,8 @@ end @test CatmullRomSpline(ctrl1) == CatmullRomSpline(ctrl1) @test CatmullRomSpline(ctrl1) ≠ CatmullRomSpline(ctrl2) @test CatmullRomSpline(ctrl2) == CatmullRomSpline(ctrl2) - @test CatmullRomSpline(ctrl1, _alpha=0.3) ≠ CatmullRomSpline(ctrl1) - @test CatmullRomSpline(ctrl1, _tension=0.2) ≠ CatmullRomSpline(ctrl1) + @test CatmullRomSpline(ctrl1, _alpha = 0.3) ≠ CatmullRomSpline(ctrl1) + @test CatmullRomSpline(ctrl1, _tension = 0.2) ≠ CatmullRomSpline(ctrl1) end @testset "angle_between" begin @@ -2284,10 +2292,10 @@ end @inferred DT.angle_between(L5, L1) A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V = (14.0, -2.0), (12.0, 2.0), - (0.0, 6.0), (12.0, -2.0), (0.0, -2.0), (2.0, -6.0), (0.0, -8.0), - (4.0, -8.0), (2.0, -4.0), (6.0, -4.0), (6.0, -14.0), (14.0, -14.0), - (8.0, -12.0), (14.0, -12.0), (8.0, -8.0), (16.0, -8.0), (8.0, -4.0), - (16.0, -4.0), (16.0, 6.0), (2.0, 6.0), (8.0, 4.0), (14.0, 4.0) + (0.0, 6.0), (12.0, -2.0), (0.0, -2.0), (2.0, -6.0), (0.0, -8.0), + (4.0, -8.0), (2.0, -4.0), (6.0, -4.0), (6.0, -14.0), (14.0, -14.0), + (8.0, -12.0), (14.0, -12.0), (8.0, -8.0), (16.0, -8.0), (8.0, -4.0), + (16.0, -4.0), (16.0, 6.0), (2.0, 6.0), (8.0, 4.0), (14.0, 4.0) LAB = LineSegment(A, B) LBC = LineSegment(B, C) LCD = LineSegment(C, D) @@ -2401,7 +2409,7 @@ end c₃ = CatmullRomSpline([(12.0, -3.0), (12.0, -4.0), (5.0, -10.0), (0.0, -10.0)]) c₄ = DT.PiecewiseLinear([(0.0, -10.0), (-10.0, -3.0), (-7.0, -3.0), (-5.0, -4.0), (-5.0, 2.0)], [1, 2, 3, 4, 5]) c₅ = BSpline([(-5.0, 2.0), (0.0, 8.0), (0.0, 10.0), (5.0, 1.0), (10.0, 0.0)]) - c₆ = CircularArc((10.0, 0.0), (0.0, 0.0), (5.0, 0.0), positive=false) + c₆ = CircularArc((10.0, 0.0), (0.0, 0.0), (5.0, 0.0), positive = false) θ12 = DT.angle_between(c₁, c₂) |> rad2deg θ23 = DT.angle_between(c₂, c₃) |> rad2deg θ34 = DT.angle_between(c₃, c₄) |> rad2deg @@ -2414,4 +2422,4 @@ end @test θ45 ≈ 360 - 140.19442890773482 @test θ56 ≈ 360 - 101.3099324740202 @test θ61 ≈ 360 - 348.6900675259798 -end \ No newline at end of file +end diff --git a/test/data_structures/graph.jl b/test/data_structures/graph.jl index 61ce12d89..a47e68a3b 100644 --- a/test/data_structures/graph.jl +++ b/test/data_structures/graph.jl @@ -7,19 +7,21 @@ using DataStructures g1 = DT.Graph{Int64}() g2 = DT.Graph{Int32}() @test g1.vertices == Set{Int64}() - @test g1.edges == Set{NTuple{2,Int64}}() - @test g1.neighbours == Dict{Int64,Set{Int64}}() + @test g1.edges == Set{NTuple{2, Int64}}() + @test g1.neighbours == Dict{Int64, Set{Int64}}() @test g2.vertices == Set{Int32}() - @test g2.edges == Set{NTuple{2,Int32}}() - @test g2.neighbours == Dict{Int32,Set{Int32}}() + @test g2.edges == Set{NTuple{2, Int32}}() + @test g2.neighbours == Dict{Int32, Set{Int32}}() end -global sg = [0 0 0 1 0 1 +global sg = [ + 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 1 0 0 0 1 0 0 - 1 0 1 1 0 0] + 1 0 1 1 0 0 +] global g = _make_graph_from_adjacency(sg) @testset "Getting graph and getting statistics" begin @@ -100,15 +102,17 @@ end DT.add_vertex!(g, bidx, bidx - 1, bidx - 2, bidx - 3, bidx - 4) DT.delete_ghost_vertices_from_graph!(g) @test bidx ∉ g.vertices && bidx - 1 ∉ g.vertices && bidx - 2 ∉ g.vertices && bidx - 3 ∉ g.vertices && - bidx - 4 ∉ g.vertices + bidx - 4 ∉ g.vertices end -global sg = [0 0 0 1 0 1 +global sg = [ + 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 1 0 0 0 1 0 0 - 1 0 1 1 0 0] + 1 0 1 1 0 0 +] global g = _make_graph_from_adjacency(sg) @testset "Removing empty parts" begin @@ -146,4 +150,4 @@ end @test isempty(get_neighbours(graph)) @test isempty(DT.get_edges(graph)) @test isempty(DT.get_vertices(graph)) -end \ No newline at end of file +end diff --git a/test/data_structures/max_priority_queue.jl b/test/data_structures/max_priority_queue.jl index 06c92e8c3..5f737260c 100644 --- a/test/data_structures/max_priority_queue.jl +++ b/test/data_structures/max_priority_queue.jl @@ -20,14 +20,14 @@ pmax = 1000 for n in [1:10; (11:50:10000)] if n ≠ 11 r = rand(1:pmax, n) - ks, vs = 1:n+1, rand(1:pmax, n) + ks, vs = 1:(n + 1), rand(1:pmax, n) else r = [670, 438, 251, 527, 40, 428, 913, 922, 756, 344, 562] - ks, vs = 1:n+1, [591, 242, 443, 24, 640, 173, 83, 409, 197, 125, 352] + ks, vs = 1:(n + 1), [591, 242, 443, 24, 640, 173, 83, 409, 197, 125, 352] end priorities = Dict(zip(ks, vs)) queue = DT.MaxPriorityQueue(priorities) - dt_queue = PriorityQueue{Int,Int}(Base.Reverse, priorities) + dt_queue = PriorityQueue{Int, Int}(Base.Reverse, priorities) if n == 11 @test sprint(show, MIME"text/plain"(), queue) == "DelaunayTriangulation.MaxPriorityQueue{Int64, Int64} with 11 entries:\n 5 => 640\n 1 => 591\n 3 => 443\n 8 => 409\n 11 => 352\n 2 => 242\n 9 => 197\n 6 => 173\n 10 => 125\n 7 => 83\n 4 => 24" end @@ -49,8 +49,8 @@ for n in [1:10; (11:50:10000)] @test queue[k] == dt_queue[k] end @test queue == dt_queue - pairs = Pair{Int,Int}[] - dt_pairs = Pair{Int,Int}[] + pairs = Pair{Int, Int}[] + dt_pairs = Pair{Int, Int}[] while !isempty(queue) pair = popfirst!(queue) dt_pair = dequeue_pair!(dt_queue) @@ -59,4 +59,4 @@ for n in [1:10; (11:50:10000)] end @test isempty(queue) && isempty(dt_queue) _compare_pairs(pairs, dt_pairs) -end \ No newline at end of file +end diff --git a/test/data_structures/polygon_hierarchy.jl b/test/data_structures/polygon_hierarchy.jl index b75eb6807..c0d08eb51 100644 --- a/test/data_structures/polygon_hierarchy.jl +++ b/test/data_structures/polygon_hierarchy.jl @@ -30,7 +30,7 @@ for _ in 1:20 # Run many times to make sure the segfault is gone points_II = [ (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), - (0.75, 0.75), (0.25, 0.25) + (0.75, 0.75), (0.25, 0.25), ] curve_III = [[[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 1]], [[15, 14, 13, 12], [12, 15]]] @@ -38,11 +38,11 @@ for _ in 1:20 # Run many times to make sure the segfault is gone (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), (0.0, 1.0), (0.0, 0.5), - (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75), (0.5, 0.5) + (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75), (0.5, 0.5), ] curve_IV = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0))] - points_IV = NTuple{2,Float64}[] + points_IV = NTuple{2, Float64}[] curve_V = [BezierCurve([(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)])] points_V = [(0.0, 0.0), (0.2, 0.25)] @@ -50,13 +50,13 @@ for _ in 1:20 # Run many times to make sure the segfault is gone curve_VI = [ [CircularArc((1.0, 0.0), (0.0, 1.0), (0.0, 0.0))], [BSpline([(0.0, 1.0), (-1.0, 2.0), (-2.0, 0.0), (-2.0, -1.0), (0.0, -2.0)])], - [5, 6, 10] + [5, 6, 10], ] points_VI = [(0.1, 0.1), (0.15, 0.15), (0.23, 0.23), (0.009, 0.11), (0.0, -2.0), (0.2, -1.7), (0.000591, 0.00019), (0.111, -0.005), (-0.0001, -0.00991), (1.0, 0.0)] curve_VII = [ [CircularArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0))], - [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])] + [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])], ] points_VII = [(2.0, 0.0), (0.0, 0.5)] @@ -64,53 +64,55 @@ for _ in 1:20 # Run many times to make sure the segfault is gone [1, 2, 3, 4, 5], [DT.EllipticalArc((0.0, 0.0), (2.0, -2.0), (1.0, -1.0), sqrt(2), sqrt(2), 45.0)], [6, 7, 8, 9, 10], - [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)])] + [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)])], + ] + points_VIII = [ + (10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), + (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, 12.0), (14.0, 0.0), ] - points_VIII = [(10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), - (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, 12.0), (14.0, 0.0)] curve_IX = [ - [ - [1, 2, 3, 4, 5, 6, 7, 1] - ], - [ - [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive=false)] - ], - ] + [ + [1, 2, 3, 4, 5, 6, 7, 1], + ], + [ + [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive = false)], + ], + ] points_IX = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.5), (0.0, 1.0), (0.0, 0.5), (0.0, 0.2)] curve_X = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]) - ] + [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]), + ], ] points_X = [ - (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2) + (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2), ] curve_XI = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))] + [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points_XI = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] @@ -241,10 +243,10 @@ for _ in 1:20 # Run many times to make sure the segfault is gone DT.BoundingBox(-10.0, -2.0, -12.0, -4.0), DT.BoundingBox(-8.0, -4.0, -10.0, -6.0), DT.BoundingBox(-9.0, -3.0, -11.0, -5.0), - DT.BoundingBox(-9.0, -2.0, -17.0, -15.0) + DT.BoundingBox(-9.0, -2.0, -17.0, -15.0), ] @test DT.get_polygon_orientations(hierarchy) == [ - false, false, false, false, true, true, true, true, true, true, true, false, false, true, true + false, false, false, false, true, true, true, true, true, true, true, false, false, true, true, ] trees = DT.get_trees(hierarchy) tree6 = trees[6] @@ -290,39 +292,41 @@ for _ in 1:20 # Run many times to make sure the segfault is gone @test DT.get_index(tree15) == 15 && DT.get_height(tree15) == 0 && !DT.has_children(tree15) && !DT.has_parent(tree15) DT.expand_bounds!(hierarchy) @test DT.get_bounding_boxes(hierarchy) ⊢ [ - DT.expand(DT.BoundingBox(-9.0, -2.0, -1.0, 7.0), 0.10), - DT.expand(DT.BoundingBox(0.0, 10.0, -5.0, 6.0), 0.10), - DT.expand(DT.BoundingBox(-1.0, 1.0, 6.0, 7.0), 0.10), - DT.expand(DT.BoundingBox(-20.0, -16.0, 8.0, 10.0), 0.10), - DT.expand(DT.BoundingBox(-22.0, -14.0, -14.0, 4.0), 0.10), - DT.expand(DT.BoundingBox(-22.0, -14.0, 6.0, 12.0), 0.10), - DT.expand(DT.BoundingBox(-12.0, 14.0, -14.0, 12.0), 0.10), - DT.expand(DT.BoundingBox(1.0, 8.0, -4.0, 2.0), 0.10), - DT.expand(DT.BoundingBox(1.0, 8.0, 3.0, 4.0), 0.10), - DT.expand(DT.BoundingBox(-8.0, -3.0, 0.0, 5.0), 0.10), - DT.expand(DT.BoundingBox(-8.0, -3.0, 4.0, 6.0), 0.10), - DT.expand(DT.BoundingBox(-10.0, -2.0, -12.0, -4.0), 0.10), - DT.expand(DT.BoundingBox(-8.0, -4.0, -10.0, -6.0), 0.10), - DT.expand(DT.BoundingBox(-9.0, -3.0, -11.0, -5.0), 0.10), - DT.expand(DT.BoundingBox(-9.0, -2.0, -17.0, -15.0), 0.10) + DT.expand(DT.BoundingBox(-9.0, -2.0, -1.0, 7.0), 0.1), + DT.expand(DT.BoundingBox(0.0, 10.0, -5.0, 6.0), 0.1), + DT.expand(DT.BoundingBox(-1.0, 1.0, 6.0, 7.0), 0.1), + DT.expand(DT.BoundingBox(-20.0, -16.0, 8.0, 10.0), 0.1), + DT.expand(DT.BoundingBox(-22.0, -14.0, -14.0, 4.0), 0.1), + DT.expand(DT.BoundingBox(-22.0, -14.0, 6.0, 12.0), 0.1), + DT.expand(DT.BoundingBox(-12.0, 14.0, -14.0, 12.0), 0.1), + DT.expand(DT.BoundingBox(1.0, 8.0, -4.0, 2.0), 0.1), + DT.expand(DT.BoundingBox(1.0, 8.0, 3.0, 4.0), 0.1), + DT.expand(DT.BoundingBox(-8.0, -3.0, 0.0, 5.0), 0.1), + DT.expand(DT.BoundingBox(-8.0, -3.0, 4.0, 6.0), 0.1), + DT.expand(DT.BoundingBox(-10.0, -2.0, -12.0, -4.0), 0.1), + DT.expand(DT.BoundingBox(-8.0, -4.0, -10.0, -6.0), 0.1), + DT.expand(DT.BoundingBox(-9.0, -3.0, -11.0, -5.0), 0.1), + DT.expand(DT.BoundingBox(-9.0, -2.0, -17.0, -15.0), 0.1), ] - @test all([ - DT.BoundingBox(-9.0, -2.0, -1.0, 7.0), - DT.BoundingBox(0.0, 10.0, -5.0, 6.0), - DT.BoundingBox(-1.0, 1.0, 6.0, 7.0), - DT.BoundingBox(-20.0, -16.0, 8.0, 10.0), - DT.BoundingBox(-22.0, -14.0, -14.0, 4.0), - DT.BoundingBox(-22.0, -14.0, 6.0, 12.0), - DT.BoundingBox(-12.0, 14.0, -14.0, 12.0), - DT.BoundingBox(1.0, 8.0, -4.0, 2.0), - DT.BoundingBox(1.0, 8.0, 3.0, 4.0), - DT.BoundingBox(-8.0, -3.0, 0.0, 5.0), - DT.BoundingBox(-8.0, -3.0, 4.0, 6.0), - DT.BoundingBox(-10.0, -2.0, -12.0, -4.0), - DT.BoundingBox(-8.0, -4.0, -10.0, -6.0), - DT.BoundingBox(-9.0, -3.0, -11.0, -5.0), - DT.BoundingBox(-9.0, -2.0, -17.0, -15.0) - ] .∈ DT.get_bounding_boxes(hierarchy)) + @test all( + [ + DT.BoundingBox(-9.0, -2.0, -1.0, 7.0), + DT.BoundingBox(0.0, 10.0, -5.0, 6.0), + DT.BoundingBox(-1.0, 1.0, 6.0, 7.0), + DT.BoundingBox(-20.0, -16.0, 8.0, 10.0), + DT.BoundingBox(-22.0, -14.0, -14.0, 4.0), + DT.BoundingBox(-22.0, -14.0, 6.0, 12.0), + DT.BoundingBox(-12.0, 14.0, -14.0, 12.0), + DT.BoundingBox(1.0, 8.0, -4.0, 2.0), + DT.BoundingBox(1.0, 8.0, 3.0, 4.0), + DT.BoundingBox(-8.0, -3.0, 0.0, 5.0), + DT.BoundingBox(-8.0, -3.0, 4.0, 6.0), + DT.BoundingBox(-10.0, -2.0, -12.0, -4.0), + DT.BoundingBox(-8.0, -4.0, -10.0, -6.0), + DT.BoundingBox(-9.0, -3.0, -11.0, -5.0), + DT.BoundingBox(-9.0, -2.0, -17.0, -15.0), + ] .∈ DT.get_bounding_boxes(hierarchy), + ) @test traverse_tree(hierarchy.trees[7]) ≠ traverse_tree(hierarchy.trees[15]) @test compare_trees(hierarchy, hierarchy) @test compare_trees(deepcopy(hierarchy), deepcopy(hierarchy)) @@ -348,7 +352,7 @@ for _ in 1:20 # Run many times to make sure the segfault is gone hierarchy = DT.construct_polygon_hierarchy(points, nnew_boundary_nodes, boundary_curves) DT.expand_bounds!(hierarchy, DT.ε(Float64)) @test DT.get_bounding_boxes(hierarchy) ⊢ [DT.BoundingBox(-1 - 2DT.ε(Float64), 1 + 2DT.ε(Float64), -1 - 2DT.ε(Float64), 1 + 2DT.ε(Float64))] && - DT.get_polygon_orientations(hierarchy) ⊢ BitVector([1]) + DT.get_polygon_orientations(hierarchy) ⊢ BitVector([1]) trees = DT.get_trees(hierarchy) @test length(trees) == 1 tree = trees[1] @@ -450,4 +454,4 @@ for _ in 1:20 # Run many times to make sure the segfault is gone tree2 = trees[2] @test DT.get_index(tree2) == 2 && DT.get_height(tree2) == 0 && !DT.has_parent(tree2) && !DT.has_children(tree2) end -end \ No newline at end of file +end diff --git a/test/data_structures/queue.jl b/test/data_structures/queue.jl index a17d29dee..3fa25fbc1 100644 --- a/test/data_structures/queue.jl +++ b/test/data_structures/queue.jl @@ -3,17 +3,17 @@ using ..DelaunayTriangulation const DT = DelaunayTriangulation queue = DT.Queue{Float64}() @test isempty(queue) -@test length(queue) == 0 +@test length(queue) == 0 @test eltype(queue) == Float64 dt_queue = DT.Queue{Float64}() els = Float64[] dt_els = Float64[] -for k in 1:100 +for k in 1:100 r = randn() push!(queue, r) push!(dt_queue, r) end -for k in 1:100 +for k in 1:100 push!(els, popfirst!(queue)) push!(dt_els, popfirst!(dt_queue)) end @@ -23,11 +23,11 @@ end queue = DT.Queue{Int}() points = rand(2, 50) DT.enqueue_all!(queue, DT.each_point_index(points)) -@test queue.data == 1:50 +@test queue.data == 1:50 q1 = DT.Queue{Int}() q2 = DT.Queue{Int}() -@test q1 == q2 +@test q1 == q2 push!(q1, 1) @test q1 ≠ q2 push!(q2, 1) diff --git a/test/data_structures/representative.jl b/test/data_structures/representative.jl index 2136a170d..aa46992b8 100644 --- a/test/data_structures/representative.jl +++ b/test/data_structures/representative.jl @@ -3,9 +3,8 @@ const DT = DelaunayTriangulation using StatsBase - @testset "Initialise" begin - c = DT.RepresentativeCoordinates{Int,Float64}() + c = DT.RepresentativeCoordinates{Int, Float64}() @test c == DT.RepresentativeCoordinates(0.0, 0.0, 0) end @@ -18,7 +17,7 @@ end @testset "Conversion" begin c = DT.RepresentativeCoordinates(0.39182, 0.5919198, 5) - newc = convert(DT.RepresentativeCoordinates{Int32,Float32}, c) + newc = convert(DT.RepresentativeCoordinates{Int32, Float32}, c) @test newc.x isa Float32 @test newc.y isa Float32 @test newc.n isa Int32 @@ -34,7 +33,7 @@ end end @testset "Adding and deleting points to representative coordinates" begin - c = DT.RepresentativeCoordinates{Int,Float64}() + c = DT.RepresentativeCoordinates{Int, Float64}() pts = [15randn(2) for _ in 1:200] foreach(p -> DT.add_point!(c, p), pts) mx, my = mean(pts) @@ -62,8 +61,8 @@ end tri = triangulate(points; boundary_nodes) DT.compute_representative_points!(tri) rep = DT.get_representative_point_list(tri) - @test rep[1].x ≈ 0.5 atol = 1e-12 - @test rep[1].y ≈ 0.5 atol = 1e-12 + @test rep[1].x ≈ 0.5 atol = 1.0e-12 + @test rep[1].y ≈ 0.5 atol = 1.0e-12 @test rep[1].n == 0 x = [[0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]] @@ -72,15 +71,15 @@ end tri = triangulate(points; boundary_nodes) rep = DT.get_representative_point_list(tri) DT.compute_representative_points!(tri) - @test rep[1].x ≈ 0.5 atol = 1e-12 - @test rep[1].y ≈ 0.5 atol = 1e-12 + @test rep[1].x ≈ 0.5 atol = 1.0e-12 + @test rep[1].y ≈ 0.5 atol = 1.0e-12 @test rep[1].n == 0 end @testset "Polylabel, representative points, and distance" begin x, y, x1, x2, x3, x4, x5, y1, y2, y3, y4, y5 = complicated_geometry() boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; boundary_nodes, delete_ghosts=false) + tri = triangulate(points; boundary_nodes, delete_ghosts = false) for i in (1, 2, 3) local x1, y1, x2, y2, x3, y3, x4, y4, x5, y5 if i == 3 @@ -104,16 +103,16 @@ end d4 = DT.distance_to_polygon((x4, y4), tri.points, tri.boundary_nodes[4]) d5 = DT.distance_to_polygon((x5, y5), tri.points, tri.boundary_nodes[5]) @test all(≥(0), (d1, d2, d3, d4, d5)) # all points are inside their respective regions - @test rep[1].x ≈ x1 atol = 1e-14 - @test rep[1].y ≈ y1 atol = 1e-14 - @test rep[2].x ≈ x2 atol = 1e-14 - @test rep[2].y ≈ y2 atol = 1e-14 - @test rep[3].x ≈ x3 atol = 1e-14 - @test rep[3].y ≈ y3 atol = 1e-14 - @test rep[4].x ≈ x4 atol = 1e-14 - @test rep[4].y ≈ y4 atol = 1e-14 - @test rep[5].x ≈ x5 atol = 1e-14 - @test rep[5].y ≈ y5 atol = 1e-14 + @test rep[1].x ≈ x1 atol = 1.0e-14 + @test rep[1].y ≈ y1 atol = 1.0e-14 + @test rep[2].x ≈ x2 atol = 1.0e-14 + @test rep[2].y ≈ y2 atol = 1.0e-14 + @test rep[3].x ≈ x3 atol = 1.0e-14 + @test rep[3].y ≈ y3 atol = 1.0e-14 + @test rep[4].x ≈ x4 atol = 1.0e-14 + @test rep[4].y ≈ y4 atol = 1.0e-14 + @test rep[5].x ≈ x5 atol = 1.0e-14 + @test rep[5].y ≈ y5 atol = 1.0e-14 @test collect(get_point(tri, -1)) ≈ [x1, y1] @test collect(get_point(tri, -2)) ≈ [x1, y1] @test collect(get_point(tri, -3)) ≈ [x1, y1] diff --git a/test/data_structures/rtree.jl b/test/data_structures/rtree.jl index 3defeabd9..b5c687db9 100644 --- a/test/data_structures/rtree.jl +++ b/test/data_structures/rtree.jl @@ -9,7 +9,7 @@ const SI = SpatialIndexing @testset "Expanding a BoundingBox" begin bbox = DT.BoundingBox(2, 5, 13, 20) - tol = 0.10 + tol = 0.1 bbox2 = DT.expand(bbox, tol) @test bbox2 == DT.BoundingBox(2 - 0.3, 5 + 0.3, 13 - 0.7, 20 + 0.7) end @@ -107,7 +107,7 @@ end for _ in 1:50 n = rand(1:1001) points = 5 .* randn(2, n) - tree_si = SI.RTree{Float64,2}(Int, NTuple{2,Int}; variant=SI.RTreeLinear) + tree_si = SI.RTree{Float64, 2}(Int, NTuple{2, Int}; variant = SI.RTreeLinear) tree = DT.RTree() for idx in axes(points, 2) |> shuffle x, y = get_point(points, idx) @@ -118,7 +118,7 @@ end for _ in 1:20 p = Tuple(10 .* randn(2)) - ints = DT.get_intersections(tree, p; cache_id=rand(1:2)) + ints = DT.get_intersections(tree, p; cache_id = rand(1:2)) ints_si = SI.intersects_with(tree_si, SI.Rect(SI.Point(p))) @test ints == ints_si @inferred collect(ints) @@ -147,7 +147,7 @@ end for _ in 1:25 n = rand(1:250) points = 5 .* randn(2, n) - tree_si = SI.RTree{Float64,2}(Int, NTuple{2,Int}; variant=SI.RTreeLinear) + tree_si = SI.RTree{Float64, 2}(Int, NTuple{2, Int}; variant = SI.RTreeLinear) tree = DT.BoundaryRTree(points) ctr = 1 range1 = rand(axes(points, 2), max(isqrt(n), 5)) @@ -168,7 +168,7 @@ end c, d = minmax(c, d) rect = DT.BoundingBox(a, b, c, d) rect_si = SI.Rect((a, c), (b, d)) - int = DT.get_intersections(tree, rect; cache_id=rand(1:2)) + int = DT.get_intersections(tree, rect; cache_id = rand(1:2)) int_si = SI.intersects_with(tree_si, rect_si) @test int == int_si @@ -186,7 +186,7 @@ end @test int == int_si i, j, k = rand(1:n, 3) - int = DT.get_intersections(tree, i, j, k; cache_id=rand(1:2)) + int = DT.get_intersections(tree, i, j, k; cache_id = rand(1:2)) bbox = DT.bounding_box(get_point(points, i, j, k)...) bbox_si = SI.Rect((bbox.x.a, bbox.y.a), (bbox.x.b, bbox.y.b)) int_si = SI.intersects_with(tree_si, bbox_si) @@ -277,4 +277,4 @@ end @test tree1 ≠ tree2 insert!(tree2, 1, 2) @test tree1 == tree2 -end \ No newline at end of file +end diff --git a/test/data_structures/shuffled_polygon_linked_list.jl b/test/data_structures/shuffled_polygon_linked_list.jl index 152396cda..7407c07a8 100644 --- a/test/data_structures/shuffled_polygon_linked_list.jl +++ b/test/data_structures/shuffled_polygon_linked_list.jl @@ -56,4 +56,4 @@ DT.swap_permutation!(list, 1, 2) @test π[2] == _π[1] DT.swap_permutation!(list, 3, 5) @test π[3] == _π[5] -@test π[5] == _π[3] \ No newline at end of file +@test π[5] == _π[3] diff --git a/test/data_structures/statistics.jl b/test/data_structures/statistics.jl index e973bc8c9..95326d089 100644 --- a/test/data_structures/statistics.jl +++ b/test/data_structures/statistics.jl @@ -4,33 +4,32 @@ using CairoMakie using ReferenceTests - @testset "Computing statistics" begin _x, _y = complicated_geometry() x = _x y = _y boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_1 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_1 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_1) # 2356 - refine!(tri_1; max_area=1e-3A, use_circumcenter=true) + refine!(tri_1; max_area = 1.0e-3A, use_circumcenter = true) boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) - tri_2 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_2 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_2) - refine!(tri_2; max_area=1e-3A, use_circumcenter=true) + refine!(tri_2; max_area = 1.0e-3A, use_circumcenter = true) boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) - tri_3 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_3 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_3) - refine!(tri_3; max_area=1e-3A, use_circumcenter=true) + refine!(tri_3; max_area = 1.0e-3A, use_circumcenter = true) boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) - tri_4 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_4 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_4) - refine!(tri_4; max_area=1e-3A, use_circumcenter=true) + refine!(tri_4; max_area = 1.0e-3A, use_circumcenter = true) a, b = 0.0, 5.0 c, d = 3.0, 7.0 nx = 3 ny = 3 - tri_5 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=false) - tri_6 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true) + tri_5 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = false) + tri_6 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true) for (i, tri) in enumerate((tri_1, tri_2, tri_3, tri_4, tri_5, tri_6)) validate_statistics(tri) @inferred statistics(tri) @@ -49,18 +48,18 @@ using ReferenceTests (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), - (1.34, 6.77), (1.24, 4.15) + (1.34, 6.77), (1.24, 4.15), ] boundary_points = [ (0.0, 0.0), (2.0, 1.0), (3.98, 2.85), (6.0, 5.0), (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), - (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0) + (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0), ] - boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=pts) - uncons_tri = triangulate(pts, delete_ghosts=false) - cons_tri = triangulate(pts; boundary_nodes, delete_ghosts=false) + boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = pts) + uncons_tri = triangulate(pts, delete_ghosts = false) + cons_tri = triangulate(pts; boundary_nodes, delete_ghosts = false) add_point!(cons_tri, 0.0, 5.0) add_segment!(cons_tri, 40, 26) add_segment!(cons_tri, 39, 27) @@ -184,13 +183,13 @@ end boundary_nodes, points = convert_boundary_points_to_indices(x, y) tri = triangulate(points; boundary_nodes) stats = statistics(tri) - interior_sinks = NTuple{2,Float64}[] + interior_sinks = NTuple{2, Float64}[] for T in each_solid_triangle(tri) is_interior_sink(tri, T) && push!(interior_sinks, DT.get_sink(stats, T)) end @test length(interior_sinks) == 1 == count(T -> is_interior_sink(tri, T), each_solid_triangle(tri)) fig, ax, sc = scatter(get_all_stat(stats, :sink)) - scatter!(ax, interior_sinks, color=:red) + scatter!(ax, interior_sinks, color = :red) triplot!(ax, tri) fig @test_reference "sink_figures.png" fig @@ -278,8 +277,8 @@ end @testset "Previously broken centroid" begin p = (1.25, -0.8947368421052633) - q=(1.6666666666666667, 1.2105263157894735) - r=(2.0833333333333335, 3.3157894736842106) + q = (1.6666666666666667, 1.2105263157894735) + r = (2.0833333333333335, 3.3157894736842106) c = DT.triangle_centroid(p, q, r) @test DT.is_on(DT.point_position_relative_to_triangle(p, q, r, c)) end diff --git a/test/data_structures/triangulation.jl b/test/data_structures/triangulation.jl index 7af7f05ed..97b454e7c 100644 --- a/test/data_structures/triangulation.jl +++ b/test/data_structures/triangulation.jl @@ -14,684 +14,692 @@ using ..DelaunayTriangulation: add_weight!, get_weight, get_weights using ..DelaunayTriangulation: Triangulation global pts = rand(2, 500) -global tri = Triangulation(pts; IntegerType=Int32) +global tri = Triangulation(pts; IntegerType = Int32) @testset "Initialising a triangulation" begin - @test tri ⊢ Triangulation(pts, # points - Set{NTuple{3,Int32}}(), # triangles - Int32[], # boundary_nodes - Set{NTuple{2,Int32}}(), # interior_segments - Set{NTuple{2,Int32}}(), # all_segments - DT.ZeroWeight(), # weights - DT.Adjacent{Int32,NTuple{2,Int32}}(), # adjacent - DT.Adjacent2Vertex{Int32,Set{NTuple{2,Int32}}}(), # adjacent2vertex - DT.Graph{Int32}(), # graph - (), # boundary_curves - Dict{NTuple{2,Int32},Tuple{Vector{Int32},Int32}}(), # boundary_edge_map - Dict{Int32,Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map - Dict{Int32,UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges - DT.ConvexHull(pts, Int32[]), # convex_hull - Dict{Int32,DT.RepresentativeCoordinates{Int32,Float64}}(), # representative_point_coordinate - DT.construct_polygon_hierarchy(pts; IntegerType=Int32), - nothing, - DT.TriangulationCache( - DT.Triangulation( - pts, - Set{NTuple{3,Int32}}(), # triangles - Int32[], # boundary_nodes - Set{NTuple{2,Int32}}(), # interior_segments - Set{NTuple{2,Int32}}(), # all_segments - DT.ZeroWeight(), # weights - DT.Adjacent{Int32,NTuple{2,Int32}}(), # adjacent - DT.Adjacent2Vertex{Int32,Set{NTuple{2,Int32}}}(), # adjacent2vertex - DT.Graph{Int32}(), # graph - (), # boundary_curves - Dict{NTuple{2,Int32},Tuple{Vector{Int32},Int32}}(), # boundary_edge_map - Dict{Int32,Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map - Dict{Int32,UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges - DT.ConvexHull(pts, Int32[]), # convex_hull - Dict{Int32,DT.RepresentativeCoordinates{Int32,Float64}}(), # representative_point_coordinate - DT.construct_polygon_hierarchy(pts; IntegerType=Int32), - nothing, # boundary_enricher - DT.TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing) - ), - DT.Triangulation( - pts, - Set{NTuple{3,Int32}}(), # triangles - Int32[], # boundary_nodes - Set{NTuple{2,Int32}}(), # interior_segments - Set{NTuple{2,Int32}}(), # all_segments - DT.ZeroWeight(), # weights - DT.Adjacent{Int32,NTuple{2,Int32}}(), # adjacent - DT.Adjacent2Vertex{Int32,Set{NTuple{2,Int32}}}(), # adjacent2vertex - DT.Graph{Int32}(), # graph - (), # boundary_curves - Dict{NTuple{2,Int32},Tuple{Vector{Int32},Int32}}(), # boundary_edge_map - Dict{Int32,Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map - Dict{Int32,UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges - DT.ConvexHull(pts, Int32[]), # convex_hull - Dict{Int32,DT.RepresentativeCoordinates{Int32,Float64}}(), # representative_point_coordinate - DT.construct_polygon_hierarchy(pts; IntegerType=Int32), - nothing, # boundary_enricher - DT.TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing) - ), - Int32[], - Set{NTuple{2,Int32}}(), - Vector{Int32}(), - Set{NTuple{3,Int32}}()) - ) + @test tri ⊢ Triangulation( + pts, # points + Set{NTuple{3, Int32}}(), # triangles + Int32[], # boundary_nodes + Set{NTuple{2, Int32}}(), # interior_segments + Set{NTuple{2, Int32}}(), # all_segments + DT.ZeroWeight(), # weights + DT.Adjacent{Int32, NTuple{2, Int32}}(), # adjacent + DT.Adjacent2Vertex{Int32, Set{NTuple{2, Int32}}}(), # adjacent2vertex + DT.Graph{Int32}(), # graph + (), # boundary_curves + Dict{NTuple{2, Int32}, Tuple{Vector{Int32}, Int32}}(), # boundary_edge_map + Dict{Int32, Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map + Dict{Int32, UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges + DT.ConvexHull(pts, Int32[]), # convex_hull + Dict{Int32, DT.RepresentativeCoordinates{Int32, Float64}}(), # representative_point_coordinate + DT.construct_polygon_hierarchy(pts; IntegerType = Int32), + nothing, + DT.TriangulationCache( + DT.Triangulation( + pts, + Set{NTuple{3, Int32}}(), # triangles + Int32[], # boundary_nodes + Set{NTuple{2, Int32}}(), # interior_segments + Set{NTuple{2, Int32}}(), # all_segments + DT.ZeroWeight(), # weights + DT.Adjacent{Int32, NTuple{2, Int32}}(), # adjacent + DT.Adjacent2Vertex{Int32, Set{NTuple{2, Int32}}}(), # adjacent2vertex + DT.Graph{Int32}(), # graph + (), # boundary_curves + Dict{NTuple{2, Int32}, Tuple{Vector{Int32}, Int32}}(), # boundary_edge_map + Dict{Int32, Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map + Dict{Int32, UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges + DT.ConvexHull(pts, Int32[]), # convex_hull + Dict{Int32, DT.RepresentativeCoordinates{Int32, Float64}}(), # representative_point_coordinate + DT.construct_polygon_hierarchy(pts; IntegerType = Int32), + nothing, # boundary_enricher + DT.TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing), + ), + DT.Triangulation( + pts, + Set{NTuple{3, Int32}}(), # triangles + Int32[], # boundary_nodes + Set{NTuple{2, Int32}}(), # interior_segments + Set{NTuple{2, Int32}}(), # all_segments + DT.ZeroWeight(), # weights + DT.Adjacent{Int32, NTuple{2, Int32}}(), # adjacent + DT.Adjacent2Vertex{Int32, Set{NTuple{2, Int32}}}(), # adjacent2vertex + DT.Graph{Int32}(), # graph + (), # boundary_curves + Dict{NTuple{2, Int32}, Tuple{Vector{Int32}, Int32}}(), # boundary_edge_map + Dict{Int32, Vector{Int32}}(DT.𝒢 => Int32[]), # ghost_vertex_map + Dict{Int32, UnitRange{Int32}}(-1 => -1:-1), # ghost_vertex_ranges + DT.ConvexHull(pts, Int32[]), # convex_hull + Dict{Int32, DT.RepresentativeCoordinates{Int32, Float64}}(), # representative_point_coordinate + DT.construct_polygon_hierarchy(pts; IntegerType = Int32), + nothing, # boundary_enricher + DT.TriangulationCache(nothing, nothing, nothing, nothing, nothing, nothing), + ), + Int32[], + Set{NTuple{2, Int32}}(), + Vector{Int32}(), + Set{NTuple{3, Int32}}(), + ), + ) end _x, _y = complicated_geometry() global x = _x global y = _y boundary_nodes, points = convert_boundary_points_to_indices(x, y) -global tri = triangulate(points; boundary_nodes, delete_ghosts=false) +global tri = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri) -refine!(tri; max_area=1e-1A, use_circumcenter=true, use_lens=false) +refine!(tri; max_area = 1.0e-1A, use_circumcenter = true, use_lens = false) boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) -global tri_2 = triangulate(points; boundary_nodes, delete_ghosts=false) +global tri_2 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_2) -refine!(tri_2; max_area=1e-1A, use_circumcenter=true, use_lens=false) +refine!(tri_2; max_area = 1.0e-1A, use_circumcenter = true, use_lens = false) boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) -global tri_3 = triangulate(points; boundary_nodes, delete_ghosts=false) +global tri_3 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_3) -refine!(tri_3; max_area=1e-1A, use_circumcenter=true, use_lens=false) +refine!(tri_3; max_area = 1.0e-1A, use_circumcenter = true, use_lens = false) boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) -global tri_4 = triangulate(points; boundary_nodes, delete_ghosts=false) +global tri_4 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_4) -refine!(tri_4; max_area=1e-1A, use_circumcenter=true, use_lens=false) +refine!(tri_4; max_area = 1.0e-1A, use_circumcenter = true, use_lens = false) @testset "Triangulation getters" begin - @test DT.get_points(tri) == tri.points - @test DT.get_triangles(tri) == tri.triangles - @test DT.get_boundary_nodes(tri) == tri.boundary_nodes - @test DT.get_interior_segments(tri) == tri.interior_segments - @test DT.get_all_segments(tri) == tri.all_segments - @test DT.get_weights(tri) == tri.weights - @test DT.get_adjacent(tri) == tri.adjacent - @test DT.get_adjacent2vertex(tri) == tri.adjacent2vertex - @test DT.get_graph(tri) == tri.graph - @test DT.get_boundary_curves(tri) == tri.boundary_curves - @test DT.get_boundary_edge_map(tri) == tri.boundary_edge_map - @test DT.get_ghost_vertex_map(tri) == tri.ghost_vertex_map - @test DT.get_ghost_vertex_ranges(tri) == tri.ghost_vertex_ranges - @test DT.get_convex_hull(tri) == tri.convex_hull - @test DT.get_representative_point_list(tri) == tri.representative_point_list - @test DT.get_exterior_curve_indices(tri) == keys(tri.polygon_hierarchy.trees) - @test DT.get_boundary_enricher(tri) === tri.boundary_enricher - @test compare_trees(DT.get_polygon_hierarchy(tri), DT.construct_polygon_hierarchy(tri.points, tri.boundary_nodes)) - @test compare_edge_vectors(collect(DT.get_all_segments(tri)), collect(tri.all_segments)) - @test compare_edge_vectors(collect(DT.get_all_segments(tri)), collect(DT.merge_segments(get_ghost_vertex_map(tri), get_boundary_nodes(tri), get_interior_segments(tri)))) - @test DT.get_ghost_vertex_map(tri) == tri.ghost_vertex_map == DT.construct_ghost_vertex_map(get_boundary_nodes(tri)) - @test DT.get_ghost_vertex_ranges(tri) == tri.ghost_vertex_ranges == DT.construct_ghost_vertex_ranges(get_boundary_nodes(tri)) - @test DT.get_boundary_edge_map(tri) == tri.boundary_edge_map == DT.construct_boundary_edge_map(get_boundary_nodes(tri)) - @test DT.get_cache(tri) == tri.cache - @inferred DT.get_points(tri) - @inferred DT.get_triangles(tri) - @inferred DT.get_boundary_nodes(tri) - @inferred DT.get_interior_segments(tri) - @inferred DT.get_all_segments(tri) - @inferred DT.get_weights(tri) - @inferred DT.get_adjacent(tri) - @inferred DT.get_adjacent2vertex(tri) - @inferred DT.get_graph(tri) - @inferred DT.get_boundary_curves(tri) - @inferred DT.get_boundary_edge_map(tri) - @inferred DT.get_ghost_vertex_map(tri) - @inferred DT.get_ghost_vertex_ranges(tri) - @inferred DT.get_convex_hull(tri) - @inferred DT.get_representative_point_list(tri) - @inferred DT.get_exterior_curve_indices(tri) + @test DT.get_points(tri) == tri.points + @test DT.get_triangles(tri) == tri.triangles + @test DT.get_boundary_nodes(tri) == tri.boundary_nodes + @test DT.get_interior_segments(tri) == tri.interior_segments + @test DT.get_all_segments(tri) == tri.all_segments + @test DT.get_weights(tri) == tri.weights + @test DT.get_adjacent(tri) == tri.adjacent + @test DT.get_adjacent2vertex(tri) == tri.adjacent2vertex + @test DT.get_graph(tri) == tri.graph + @test DT.get_boundary_curves(tri) == tri.boundary_curves + @test DT.get_boundary_edge_map(tri) == tri.boundary_edge_map + @test DT.get_ghost_vertex_map(tri) == tri.ghost_vertex_map + @test DT.get_ghost_vertex_ranges(tri) == tri.ghost_vertex_ranges + @test DT.get_convex_hull(tri) == tri.convex_hull + @test DT.get_representative_point_list(tri) == tri.representative_point_list + @test DT.get_exterior_curve_indices(tri) == keys(tri.polygon_hierarchy.trees) + @test DT.get_boundary_enricher(tri) === tri.boundary_enricher + @test compare_trees(DT.get_polygon_hierarchy(tri), DT.construct_polygon_hierarchy(tri.points, tri.boundary_nodes)) + @test compare_edge_vectors(collect(DT.get_all_segments(tri)), collect(tri.all_segments)) + @test compare_edge_vectors(collect(DT.get_all_segments(tri)), collect(DT.merge_segments(get_ghost_vertex_map(tri), get_boundary_nodes(tri), get_interior_segments(tri)))) + @test DT.get_ghost_vertex_map(tri) == tri.ghost_vertex_map == DT.construct_ghost_vertex_map(get_boundary_nodes(tri)) + @test DT.get_ghost_vertex_ranges(tri) == tri.ghost_vertex_ranges == DT.construct_ghost_vertex_ranges(get_boundary_nodes(tri)) + @test DT.get_boundary_edge_map(tri) == tri.boundary_edge_map == DT.construct_boundary_edge_map(get_boundary_nodes(tri)) + @test DT.get_cache(tri) == tri.cache + @inferred DT.get_points(tri) + @inferred DT.get_triangles(tri) + @inferred DT.get_boundary_nodes(tri) + @inferred DT.get_interior_segments(tri) + @inferred DT.get_all_segments(tri) + @inferred DT.get_weights(tri) + @inferred DT.get_adjacent(tri) + @inferred DT.get_adjacent2vertex(tri) + @inferred DT.get_graph(tri) + @inferred DT.get_boundary_curves(tri) + @inferred DT.get_boundary_edge_map(tri) + @inferred DT.get_ghost_vertex_map(tri) + @inferred DT.get_ghost_vertex_ranges(tri) + @inferred DT.get_convex_hull(tri) + @inferred DT.get_representative_point_list(tri) + @inferred DT.get_exterior_curve_indices(tri) end @testset "Forwarded methods" begin - @testset "Adjacent" begin - @test DT.get_adjacent(tri, 92, -6) == tri.adjacent.adjacent[(92, -6)] - @test DT.get_adjacent(tri, (723, 1356)) == get(tri.adjacent.adjacent, (723, 1356), DT.∅) - @inferred DT.get_adjacent(tri, (723, 1356)) - DT.add_adjacent!(tri, 101117, 20311, 5) - DT.add_adjacent!(tri, (27311, 50511), 10) - @test DT.get_adjacent(tri, 101117, 20311) == 5 - @inferred DT.get_adjacent(tri, 101117, 20311) - @test DT.get_adjacent(tri, 27311, 50511) == 10 - DT.delete_adjacent!(tri, 101117, 20311) - DT.delete_adjacent!(tri, (27311, 50511)) - @test DT.get_adjacent(tri, 101117, 20311) == DT.∅ - @test DT.get_adjacent(tri, 27311, 50511) == DT.∅ - @test DT.get_adjacent(tri, 711, DT.𝒢) == DT.∅ - end - - @testset "Adjacent2Vertex" begin - @test DT.get_adjacent2vertex(tri, -6) == tri.adjacent2vertex.adjacent2vertex[-6] - @inferred DT.get_adjacent2vertex(tri, -6) - DT.add_adjacent2vertex!(tri, 10005, 23, 27) - DT.add_adjacent2vertex!(tri, 19988, (50, 171)) - @test DT.contains_edge(23, 27, tri.adjacent2vertex.adjacent2vertex[10005]) - @test DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) - @inferred DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) - DT.delete_adjacent2vertex!(tri, 10005, 23, 27) - DT.delete_adjacent2vertex!(tri, 19988, (50, 171)) - @test !DT.contains_edge(23, 27, tri.adjacent2vertex.adjacent2vertex[10005]) - @test !DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) - @test 6 ∈ keys(tri.adjacent2vertex.adjacent2vertex) - DT.delete_adjacent2vertex!(tri, -6) - @test -6 ∉ keys(tri.adjacent2vertex.adjacent2vertex) - end - - @testset "Graph" begin - @test DT.get_edges(tri) == tri.graph.edges == DT.get_edges(tri.graph) - @inferred DT.get_edges(tri) - @test DT.get_neighbours(tri, 3) == tri.graph.neighbours[3] - @inferred DT.get_neighbours(tri, 3) - DT.add_vertex!(tri, 19998, 23721) - DT.add_vertex!(tri, 28371) - @test all(∈(tri.graph.vertices), (19998, 23721, 28371)) - DT.add_neighbour!(tri, 28371, 50912) - DT.add_neighbour!(tri, 28371, 271, 501) - @test all(∈(tri.graph.neighbours[28371]), (50912, 271, 501)) - DT.delete_neighbour!(tri, 28371, 50912) - DT.delete_neighbour!(tri, 28371, 271, 501) - @test all(∉(tri.graph.neighbours[28371]), (50912, 271, 501)) - DT.delete_vertex!(tri, 19998) - DT.delete_vertex!(tri, 28371, 3) - @test all(∉(tri.graph.vertices), (19998, 28371, 3)) - DT.delete_ghost_vertices_from_graph!(tri) - @test all(∉(tri.graph.vertices), -11:-1) - @test DT.get_neighbours(tri) == tri.graph.neighbours - @test DT.get_vertices(tri) == tri.graph.vertices - @test DT.get_vertices(tri) == each_vertex(tri) - @test num_vertices(tri) == length(DT.get_vertices(tri)) - @test all((DT.num_neighbours(tri, u) == DT.num_neighbours(DT.get_graph(tri), u) for u in DT.get_vertices(tri))) - end - - @testset "ConvexHull" begin - @test DT.get_convex_hull(tri) == tri.convex_hull - @test DT.get_convex_hull_vertices(tri) == tri.convex_hull.vertices - _tri = triangulate_rectangle(0.0, 2.0, 5.0, 7.3, 5, 15; single_boundary=true) - points = get_points(_tri) - ch = convex_hull(points) - @test ch.vertices == _tri.boundary_nodes - _indices = deepcopy(ch.vertices) - __indices = DT.get_convex_hull_vertices(_tri) - empty!(__indices) - DT.convex_hull!(_tri; reconstruct=false) - @test length(__indices) == length(_indices) - unique!(__indices) - unique!(ch.vertices) - shift = findfirst(ch.vertices .== first(__indices)) - ch.vertices .= circshift(ch.vertices, 1 - shift) - @test __indices == ch.vertices - DT.convex_hull!(_tri) - @test length(__indices) == length(_indices) - unique!(__indices) - shift = findfirst(ch.vertices .== first(__indices)) - ch.vertices .= circshift(ch.vertices, 1 - shift) - @test __indices == ch.vertices - delete_ghost_triangles!(_tri) - DT.convex_hull!(_tri; reconstruct=false) - @test length(__indices) == length(_indices) - unique!(__indices) - unique!(ch.vertices) - shift = findfirst(ch.vertices .== first(__indices)) - ch.vertices .= circshift(ch.vertices, 1 - shift) - @test __indices == ch.vertices - DT.convex_hull!(_tri) - @test length(__indices) == length(_indices) - unique!(__indices) - shift = findfirst(ch.vertices .== first(__indices)) - ch.vertices .= circshift(ch.vertices, 1 - shift) - @test __indices == ch.vertices - @test !DT.has_ghost_triangles(_tri) - end - - @testset "Boundary nodes" begin - @test DT.has_multiple_curves(tri) - @inferred DT.has_multiple_curves(tri) - @test !DT.has_multiple_curves(tri_2) - @test DT.has_multiple_sections(tri) - @test DT.has_multiple_sections(tri_2) - @test !DT.has_multiple_sections(tri_3) - @inferred DT.has_multiple_sections(tri_2) - @test DT.num_curves(tri) == 5 - @inferred DT.num_curves(tri) - a, b = 0.0, 5.0 - c, d = 3.0, 7.0 - nx = 12 - ny = 15 - @test DT.num_curves(triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 10, 10; delete_ghosts=false, single_boundary=false)) == 1 - @test DT.num_sections(tri_2) == 4 - @inferred DT.num_sections(tri_2) - @test DT.get_boundary_nodes(tri, 1) == tri.boundary_nodes[1] - @test DT.get_boundary_nodes(tri, 1, 3) == tri.boundary_nodes[1][3] - @test DT.get_boundary_nodes(tri, (5, 1)) == tri.boundary_nodes[5][1] - @test DT.get_boundary_nodes(tri_2, 1) == tri_2.boundary_nodes[1] - @test DT.get_boundary_nodes(tri_2, 3) == tri_2.boundary_nodes[3] - @test DT.get_boundary_nodes(tri_3) == tri_3.boundary_nodes - @test DT.get_boundary_nodes(tri_2, 3) == tri_2.boundary_nodes[3] - @test DT.get_curve_index(tri, -1) == 1 - @test DT.get_curve_index(tri, -3) == 1 - @test DT.get_curve_index(tri, -5) == 2 - @test DT.get_curve_index(tri, -11) == 5 - @test DT.get_curve_index(tri_2, -3) == 1 - @test DT.get_curve_index(tri_2, -2) == 1 - @test DT.get_curve_index(tri_3, -1) == 1 - @inferred DT.get_curve_index(tri_3, -1) - end - - @testset "Triangles" begin - rng = StableRNG(9882881) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) - A = get_area(tri) - refine!(tri; max_area=1e-1A, rng, use_circumcenter=true) - @test DT.triangle_type(tri) == NTuple{3,Int} - @inferred DT.triangle_type(tri) - @test DT.num_triangles(tri) == length(tri.triangles) - @test DT.each_triangle(tri) == tri.triangles - @inferred DT.num_triangles(tri) - @test DT.contains_triangle(tri, (68, 67, -6))[2] - @inferred DT.contains_triangle(tri, (68, 67, -6)) - @test !DT.contains_triangle(tri, (1, 1, 5))[2] - @test !DT.contains_triangle(tri, 1, 5, 5)[2] - @inferred DT.contains_triangle(tri, 3, 140, 1126) - @test DT.construct_positively_oriented_triangle(tri, 1, 10, 20) == (10, 1, 20) - @inferred DT.construct_positively_oriented_triangle(tri, 188, 394, 426) - _solid_itr = each_solid_triangle(tri) - @test DelaunayTriangulation.each_triangle(_solid_itr) == _solid_itr - @test Base.IteratorSize(_solid_itr) == Base.HasLength() - @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() - @test Base.eltype(_solid_itr) == NTuple{3,Int} - @test each_solid_triangle(tri) isa DT.EachSolidTriangle - _solid_tri = collect(_solid_itr) - @inferred collect(_solid_itr) - @test all(!DT.is_ghost_triangle, _solid_tri) - _ghost_itr = each_ghost_triangle(tri) - @test Base.IteratorSize(_ghost_itr) == Base.HasLength() - @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() - @test Base.eltype(_ghost_itr) == NTuple{3,Int} - @test each_ghost_triangle(tri) isa DT.EachGhostTriangle - _ghost_tri = collect(_ghost_itr) - @inferred collect(_ghost_itr) - @test DelaunayTriangulation.each_triangle(_ghost_itr) == _ghost_itr - @test all(DT.is_ghost_triangle, _ghost_tri) - @test length(_ghost_tri) + length(_solid_tri) == num_triangles(tri) - @test length(_solid_tri) == DT.num_solid_triangles(tri) == length(_solid_itr) - @test length(_ghost_tri) == DT.num_ghost_triangles(tri) == length(_ghost_itr) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - rng = StableRNG(9882881) - ___tri = triangulate(points; boundary_nodes, delete_ghosts=false, rng) - A = get_area(___tri) - refine!(___tri; max_area=1e-1A, rng, use_circumcenter=true) - DT.delete_ghost_triangles!(___tri) - @test collect(each_triangle(___tri)) == collect(each_solid_triangle(___tri)) - @test length(collect(each_ghost_triangle(___tri))) == 0 - @test sort(collect(filter(!DT.is_ghost_triangle, each_triangle(___tri)))) == sort(collect(each_solid_triangle(___tri))) - @test sort(collect(filter(DT.is_ghost_triangle, each_triangle(___tri)))) == sort(collect(each_ghost_triangle(___tri))) - @test DelaunayTriangulation.triangle_type(_ghost_itr) == DelaunayTriangulation.triangle_type(_ghost_itr) - @test DelaunayTriangulation.triangle_type(_solid_itr) == DelaunayTriangulation.triangle_type(_solid_itr) - end - - @testset "Edges" begin - rng = StableRNG(998871) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) - A = get_area(tri) - refine!(tri; max_area=1e-1A, rng, use_circumcenter=true) - @test DT.edge_type(tri) == NTuple{2,Int} - @inferred DT.edge_type(tri) - @test DT.num_edges(tri) == length(tri.graph.edges) - @inferred DT.num_edges(tri) - @test DT.each_edge(tri) == tri.graph.edges - @inferred DT.each_edge(tri) - _solid_itr = each_solid_edge(tri) - @test DelaunayTriangulation.each_edge(_solid_itr) == _solid_itr - @test Base.IteratorSize(_solid_itr) == Base.HasLength() - @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() - @test Base.eltype(_solid_itr) == NTuple{2,Int} - @test each_solid_edge(tri) isa DT.EachSolidEdge - _solid_tri = collect(_solid_itr) - @inferred collect(_solid_itr) - @test all(!DT.is_ghost_edge, _solid_tri) - _ghost_itr = each_ghost_edge(tri) - @test Base.IteratorSize(_ghost_itr) == Base.HasLength() - @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() - @test Base.eltype(_ghost_itr) == NTuple{2,Int} - @test each_ghost_edge(tri) isa DT.EachGhostEdge - _ghost_tri = collect(_ghost_itr) - @inferred collect(_ghost_itr) - @test DelaunayTriangulation.each_edge(_ghost_itr) == _ghost_itr - @test all(DT.is_ghost_edge, _ghost_tri) - @test length(_ghost_tri) + length(_solid_tri) == num_edges(tri) - rng = StableRNG(998871) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - ___tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) - A = get_area(___tri) - refine!(___tri; max_area=1e-1A, rng, use_circumcenter=true) - DT.delete_ghost_triangles!(___tri) - @test sort(collect(filter(!DT.is_ghost_edge, each_edge(___tri)))) == sort(collect(each_solid_edge(___tri))) - @test sort(collect(filter(DT.is_ghost_edge, each_edge(___tri)))) == sort(collect(each_ghost_edge(___tri))) - @test length(collect(each_ghost_edge(___tri))) == num_edges(___tri) .- length(sort(collect(filter(!DT.is_ghost_edge, each_edge(___tri))))) - @test length(collect(each_ghost_edge(___tri))) == DT.num_ghost_edges(___tri) == length(_ghost_itr) - @test length(collect(each_solid_edge(___tri))) == DT.num_solid_edges(___tri) == length(_solid_itr) - @test DelaunayTriangulation.edge_type(_ghost_itr) == DelaunayTriangulation.edge_type(_ghost_itr) - @test DelaunayTriangulation.edge_type(_solid_itr) == DelaunayTriangulation.edge_type(_solid_itr) - end - - @testset "Points" begin - @test DT.get_point(tri, 2) == Tuple(tri.points[2]) - @inferred DT.get_point(tri, 2) - @test DT.get_point(tri, 17) == Tuple(tri.points[17]) - @test DT.each_point_index(tri) == 1:length(tri.points) - @inferred DT.each_point_index(tri) - @test DT.each_point(tri) == tri.points - @inferred DT.each_point(tri) - @test DT.num_points(tri) == length(tri.points) - @inferred DT.num_points(tri) - @test DT.get_point(tri, 2, 5, 6, 10) == - ntuple(i -> Tuple(tri.points[(2, 5, 6, 10)[i]]), 4) - @inferred DT.get_point(tri, 2, 5, 6, 10) - rep = DT.get_representative_point_list(tri) - rep[1] = DT.RepresentativeCoordinates(0.5, 0.3, 2) - rep[2] = DT.RepresentativeCoordinates(2.5, 7.3, 7) - rep[3] = DT.RepresentativeCoordinates(6.5, -0.6, 13) - rep[4] = DT.RepresentativeCoordinates(6.5, -0.66234, 13) - rep[5] = DT.RepresentativeCoordinates(6.534234, -0.6, 13) - @test DT.get_point(tri, -1) == DT.getxy(rep[1]) - @test DT.get_point(tri, -2) == DT.getxy(rep[1]) - @test DT.get_point(tri, -3) == DT.getxy(rep[1]) - @test DT.get_point(tri, -4) == DT.getxy(rep[1]) - @test DT.get_point(tri, -5) == DT.getxy(rep[2]) - @test DT.get_point(tri, -6) == DT.getxy(rep[3]) - @test DT.get_point(tri, -7) == DT.getxy(rep[4]) - @test DT.get_point(tri, -8) == DT.getxy(rep[4]) - @test DT.get_point(tri, -9) == DT.getxy(rep[4]) - @test DT.get_point(tri, -10) == DT.getxy(rep[4]) - @test DT.get_point(tri, -11) == DT.getxy(rep[5]) - rep = DT.get_representative_point_list(tri_2) - @test DT.get_point(tri_2, -1) == DT.getxy(rep[1]) - @inferred DT.get_point(tri_2, -1) - @test DT.get_point(tri_2, -2) == DT.getxy(rep[1]) - @test DT.get_point(tri_2, -3) == DT.getxy(rep[1]) - @test DT.get_point(tri_2, -4) == DT.getxy(rep[1]) - @test DT.get_point(tri_3, -1) == DT.getxy(DT.get_representative_point_coordinates(tri_3, 1)) - @test_throws KeyError DT.get_point(tri, -12) - @test_throws KeyError DT.get_point(tri_2, -5) - @test_throws KeyError DT.get_point(tri_3, -2) - @test get_point(tri, tri.points[2]) == tri.points[2] - @inferred get_point(tri, tri.points[2]) - @test reverse(sort(collect(DT.all_ghost_vertices(tri)))) == [DT.𝒢, - DT.𝒢 - 1, - DT.𝒢 - 2, - DT.𝒢 - 3, - DT.𝒢 - 4, - DT.𝒢 - 5, - DT.𝒢 - 6, - DT.𝒢 - 7, - DT.𝒢 - 8, - DT.𝒢 - 9, - DT.𝒢 - 10]#(new_point, c′) = (436, (1.8363241117152609, 1.0864161502095007)) - rng = StableRNG(887271) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - _triq = triangulate(points; boundary_nodes, rng) - A = get_area(_triq) - refine!(_triq; max_area=1e-1A, rng, use_circumcenter=true, use_lens=false) - _solid_itr = each_solid_vertex(_triq) - @test DelaunayTriangulation.each_vertex(_solid_itr) == _solid_itr - @test Base.IteratorSize(_solid_itr) == Base.HasLength() - @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() - @test Base.eltype(_solid_itr) == Int - @test each_solid_vertex(_triq) isa DT.EachSolidVertex - _solid_tri = collect(_solid_itr) - @inferred collect(_solid_itr) - @test sort(_solid_tri) == sort(filter(i -> DT.has_vertex(_triq, i) && i ≥ 1, 1:DT.num_points(tri))) - @test all(!DT.is_ghost_vertex, _solid_tri) - _ghost_itr = each_ghost_vertex(_triq) - @test Base.IteratorSize(_ghost_itr) == Base.HasLength() - @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() - @test Base.eltype(_ghost_itr) == Int - @test each_ghost_vertex(_triq) isa DT.EachGhostVertex - _ghost_tri = collect(_ghost_itr) - @inferred collect(_ghost_itr) - @test DelaunayTriangulation.each_vertex(_ghost_itr) == _ghost_itr - @test all(DT.is_ghost_vertex, _ghost_tri) - @test reverse(sort(_ghost_tri)) == [DT.𝒢, - DT.𝒢 - 1, - DT.𝒢 - 2, - DT.𝒢 - 3, - DT.𝒢 - 4, - DT.𝒢 - 5, - DT.𝒢 - 6, - DT.𝒢 - 7, - DT.𝒢 - 8, - DT.𝒢 - 9, - DT.𝒢 - 10] - @test length(_ghost_tri) == length(_ghost_itr) == sum(<(0), keys(_triq.adjacent2vertex.adjacent2vertex)) - @test length(_solid_tri) == length(_solid_itr) == sort(filter(i -> DT.has_vertex(_triq, i) && i ≥ 1, 1:DT.num_points(tri))) |> length - rng = StableRNG(887271) - ___tri = triangulate(points; boundary_nodes, rng) - A = get_area(___tri) - refine!(___tri; max_area=1e-1A, rng, use_circumcenter=true) - DT.delete_ghost_triangles!(___tri) - @test sort(collect(filter(!DT.is_ghost_vertex, each_vertex(___tri)))) == sort(collect(each_solid_vertex(___tri))) - @test sort(collect(filter(DT.is_ghost_vertex, each_vertex(___tri)))) == sort(collect(each_ghost_vertex(___tri))) - @test length(collect(each_ghost_vertex(___tri))) == num_vertices(___tri) .- length(sort(collect(filter(!DT.is_ghost_vertex, each_vertex(___tri))))) - tri1 = Triangulation([[1.0, 2.0], [3.0, 4.0]]) - DT.push_point!(tri1, 13.7, 5.0) - @test get_points(tri1) == [[1.0, 2.0], [3.0, 4.0], [13.7, 5.0]] - @test get_point(tri1, 3) == (13.7, 5.0) - tri1 = Triangulation([(1.0, 2.0), (3.0, 4.0)]) - DT.push_point!(tri1, 13.7, 5.0) - @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0)] - @test get_point(tri1, 3) == (13.7, 5.0) - DT.push_point!(tri1, (19.0, 17.05)) - @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0), (19.0, 17.05)] - DT.pop_point!(tri1) - @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0)] - DT.pop_point!(tri1) - @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0)] - DT.set_point!(tri1, 2, 13.7, 5.0) - @test get_points(tri1) == [(1.0, 2.0), (13.7, 5.0)] - DT.set_point!(tri1, 2, (19.0, 17.05)) - @test get_points(tri1) == [(1.0, 2.0), (19.0, 17.05)] - end - - @testset "Miscellaneous" begin - @test DT.integer_type(tri) == Int - @test DT.number_type(tri) == Float64 - @test DT.edge_type(tri) == NTuple{2,Int} - @test DT.edges_type(tri) == Set{NTuple{2,Int}} - @test DT.triangles_type(tri) == Set{NTuple{3,Int}} - @test DT.triangle_type(tri) == NTuple{3,Int} - @inferred DT.integer_type(tri) - @inferred DT.number_type(tri) - DT.clear_empty_features!(tri) - clean_tri = deepcopy(tri) - get_adjacent(tri, 17, 32) - get_adjacent(tri, 58, 37) - DT.add_adjacent2vertex!(tri, 3, 58, 60) - DT.add_neighbour!(tri, 5, 171) - @test clean_tri ≠ tri - DT.delete_adjacent2vertex!(tri, 3, 58, 60) - DT.delete_neighbour!(tri, 5, 171) - @test clean_tri == tri - _tri = triangulate_rectangle(0.0, 10.0, 0.0, 20.0, 11, 21) - T = (51, 41, 52) - ℓ = (7.0, 3.5) - @test DT.find_edge(_tri, T, ℓ) == (41, 52) - ℓ = (6.5, 4.0) - @test DT.find_edge(_tri, T, ℓ) == (52, 51) - ℓ = (6.5, 3.5) - @test DT.find_edge(_tri, T, ℓ) == (51, 41) - @inferred DT.find_edge(_tri, T, ℓ) - push!(get_all_segments(_tri), (1, 2)) - @test DT.is_constrained(_tri) - empty!(get_all_segments(_tri)) - @test !DT.is_constrained(_tri) - @test reverse(sort(collect(DT.all_ghost_vertices(_tri)))) == - [DT.𝒢, DT.𝒢 - 1, DT.𝒢 - 2, DT.𝒢 - 3] - end + @testset "Adjacent" begin + @test DT.get_adjacent(tri, 92, -6) == tri.adjacent.adjacent[(92, -6)] + @test DT.get_adjacent(tri, (723, 1356)) == get(tri.adjacent.adjacent, (723, 1356), DT.∅) + @inferred DT.get_adjacent(tri, (723, 1356)) + DT.add_adjacent!(tri, 101117, 20311, 5) + DT.add_adjacent!(tri, (27311, 50511), 10) + @test DT.get_adjacent(tri, 101117, 20311) == 5 + @inferred DT.get_adjacent(tri, 101117, 20311) + @test DT.get_adjacent(tri, 27311, 50511) == 10 + DT.delete_adjacent!(tri, 101117, 20311) + DT.delete_adjacent!(tri, (27311, 50511)) + @test DT.get_adjacent(tri, 101117, 20311) == DT.∅ + @test DT.get_adjacent(tri, 27311, 50511) == DT.∅ + @test DT.get_adjacent(tri, 711, DT.𝒢) == DT.∅ + end + + @testset "Adjacent2Vertex" begin + @test DT.get_adjacent2vertex(tri, -6) == tri.adjacent2vertex.adjacent2vertex[-6] + @inferred DT.get_adjacent2vertex(tri, -6) + DT.add_adjacent2vertex!(tri, 10005, 23, 27) + DT.add_adjacent2vertex!(tri, 19988, (50, 171)) + @test DT.contains_edge(23, 27, tri.adjacent2vertex.adjacent2vertex[10005]) + @test DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) + @inferred DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) + DT.delete_adjacent2vertex!(tri, 10005, 23, 27) + DT.delete_adjacent2vertex!(tri, 19988, (50, 171)) + @test !DT.contains_edge(23, 27, tri.adjacent2vertex.adjacent2vertex[10005]) + @test !DT.contains_edge(50, 171, tri.adjacent2vertex.adjacent2vertex[19988]) + @test 6 ∈ keys(tri.adjacent2vertex.adjacent2vertex) + DT.delete_adjacent2vertex!(tri, -6) + @test -6 ∉ keys(tri.adjacent2vertex.adjacent2vertex) + end + + @testset "Graph" begin + @test DT.get_edges(tri) == tri.graph.edges == DT.get_edges(tri.graph) + @inferred DT.get_edges(tri) + @test DT.get_neighbours(tri, 3) == tri.graph.neighbours[3] + @inferred DT.get_neighbours(tri, 3) + DT.add_vertex!(tri, 19998, 23721) + DT.add_vertex!(tri, 28371) + @test all(∈(tri.graph.vertices), (19998, 23721, 28371)) + DT.add_neighbour!(tri, 28371, 50912) + DT.add_neighbour!(tri, 28371, 271, 501) + @test all(∈(tri.graph.neighbours[28371]), (50912, 271, 501)) + DT.delete_neighbour!(tri, 28371, 50912) + DT.delete_neighbour!(tri, 28371, 271, 501) + @test all(∉(tri.graph.neighbours[28371]), (50912, 271, 501)) + DT.delete_vertex!(tri, 19998) + DT.delete_vertex!(tri, 28371, 3) + @test all(∉(tri.graph.vertices), (19998, 28371, 3)) + DT.delete_ghost_vertices_from_graph!(tri) + @test all(∉(tri.graph.vertices), -11:-1) + @test DT.get_neighbours(tri) == tri.graph.neighbours + @test DT.get_vertices(tri) == tri.graph.vertices + @test DT.get_vertices(tri) == each_vertex(tri) + @test num_vertices(tri) == length(DT.get_vertices(tri)) + @test all((DT.num_neighbours(tri, u) == DT.num_neighbours(DT.get_graph(tri), u) for u in DT.get_vertices(tri))) + end + + @testset "ConvexHull" begin + @test DT.get_convex_hull(tri) == tri.convex_hull + @test DT.get_convex_hull_vertices(tri) == tri.convex_hull.vertices + _tri = triangulate_rectangle(0.0, 2.0, 5.0, 7.3, 5, 15; single_boundary = true) + points = get_points(_tri) + ch = convex_hull(points) + @test ch.vertices == _tri.boundary_nodes + _indices = deepcopy(ch.vertices) + __indices = DT.get_convex_hull_vertices(_tri) + empty!(__indices) + DT.convex_hull!(_tri; reconstruct = false) + @test length(__indices) == length(_indices) + unique!(__indices) + unique!(ch.vertices) + shift = findfirst(ch.vertices .== first(__indices)) + ch.vertices .= circshift(ch.vertices, 1 - shift) + @test __indices == ch.vertices + DT.convex_hull!(_tri) + @test length(__indices) == length(_indices) + unique!(__indices) + shift = findfirst(ch.vertices .== first(__indices)) + ch.vertices .= circshift(ch.vertices, 1 - shift) + @test __indices == ch.vertices + delete_ghost_triangles!(_tri) + DT.convex_hull!(_tri; reconstruct = false) + @test length(__indices) == length(_indices) + unique!(__indices) + unique!(ch.vertices) + shift = findfirst(ch.vertices .== first(__indices)) + ch.vertices .= circshift(ch.vertices, 1 - shift) + @test __indices == ch.vertices + DT.convex_hull!(_tri) + @test length(__indices) == length(_indices) + unique!(__indices) + shift = findfirst(ch.vertices .== first(__indices)) + ch.vertices .= circshift(ch.vertices, 1 - shift) + @test __indices == ch.vertices + @test !DT.has_ghost_triangles(_tri) + end + + @testset "Boundary nodes" begin + @test DT.has_multiple_curves(tri) + @inferred DT.has_multiple_curves(tri) + @test !DT.has_multiple_curves(tri_2) + @test DT.has_multiple_sections(tri) + @test DT.has_multiple_sections(tri_2) + @test !DT.has_multiple_sections(tri_3) + @inferred DT.has_multiple_sections(tri_2) + @test DT.num_curves(tri) == 5 + @inferred DT.num_curves(tri) + a, b = 0.0, 5.0 + c, d = 3.0, 7.0 + nx = 12 + ny = 15 + @test DT.num_curves(triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 10, 10; delete_ghosts = false, single_boundary = false)) == 1 + @test DT.num_sections(tri_2) == 4 + @inferred DT.num_sections(tri_2) + @test DT.get_boundary_nodes(tri, 1) == tri.boundary_nodes[1] + @test DT.get_boundary_nodes(tri, 1, 3) == tri.boundary_nodes[1][3] + @test DT.get_boundary_nodes(tri, (5, 1)) == tri.boundary_nodes[5][1] + @test DT.get_boundary_nodes(tri_2, 1) == tri_2.boundary_nodes[1] + @test DT.get_boundary_nodes(tri_2, 3) == tri_2.boundary_nodes[3] + @test DT.get_boundary_nodes(tri_3) == tri_3.boundary_nodes + @test DT.get_boundary_nodes(tri_2, 3) == tri_2.boundary_nodes[3] + @test DT.get_curve_index(tri, -1) == 1 + @test DT.get_curve_index(tri, -3) == 1 + @test DT.get_curve_index(tri, -5) == 2 + @test DT.get_curve_index(tri, -11) == 5 + @test DT.get_curve_index(tri_2, -3) == 1 + @test DT.get_curve_index(tri_2, -2) == 1 + @test DT.get_curve_index(tri_3, -1) == 1 + @inferred DT.get_curve_index(tri_3, -1) + end + + @testset "Triangles" begin + rng = StableRNG(9882881) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) + A = get_area(tri) + refine!(tri; max_area = 1.0e-1A, rng, use_circumcenter = true) + @test DT.triangle_type(tri) == NTuple{3, Int} + @inferred DT.triangle_type(tri) + @test DT.num_triangles(tri) == length(tri.triangles) + @test DT.each_triangle(tri) == tri.triangles + @inferred DT.num_triangles(tri) + @test DT.contains_triangle(tri, (68, 67, -6))[2] + @inferred DT.contains_triangle(tri, (68, 67, -6)) + @test !DT.contains_triangle(tri, (1, 1, 5))[2] + @test !DT.contains_triangle(tri, 1, 5, 5)[2] + @inferred DT.contains_triangle(tri, 3, 140, 1126) + @test DT.construct_positively_oriented_triangle(tri, 1, 10, 20) == (10, 1, 20) + @inferred DT.construct_positively_oriented_triangle(tri, 188, 394, 426) + _solid_itr = each_solid_triangle(tri) + @test DelaunayTriangulation.each_triangle(_solid_itr) == _solid_itr + @test Base.IteratorSize(_solid_itr) == Base.HasLength() + @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() + @test Base.eltype(_solid_itr) == NTuple{3, Int} + @test each_solid_triangle(tri) isa DT.EachSolidTriangle + _solid_tri = collect(_solid_itr) + @inferred collect(_solid_itr) + @test all(!DT.is_ghost_triangle, _solid_tri) + _ghost_itr = each_ghost_triangle(tri) + @test Base.IteratorSize(_ghost_itr) == Base.HasLength() + @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() + @test Base.eltype(_ghost_itr) == NTuple{3, Int} + @test each_ghost_triangle(tri) isa DT.EachGhostTriangle + _ghost_tri = collect(_ghost_itr) + @inferred collect(_ghost_itr) + @test DelaunayTriangulation.each_triangle(_ghost_itr) == _ghost_itr + @test all(DT.is_ghost_triangle, _ghost_tri) + @test length(_ghost_tri) + length(_solid_tri) == num_triangles(tri) + @test length(_solid_tri) == DT.num_solid_triangles(tri) == length(_solid_itr) + @test length(_ghost_tri) == DT.num_ghost_triangles(tri) == length(_ghost_itr) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + rng = StableRNG(9882881) + ___tri = triangulate(points; boundary_nodes, delete_ghosts = false, rng) + A = get_area(___tri) + refine!(___tri; max_area = 1.0e-1A, rng, use_circumcenter = true) + DT.delete_ghost_triangles!(___tri) + @test collect(each_triangle(___tri)) == collect(each_solid_triangle(___tri)) + @test length(collect(each_ghost_triangle(___tri))) == 0 + @test sort(collect(filter(!DT.is_ghost_triangle, each_triangle(___tri)))) == sort(collect(each_solid_triangle(___tri))) + @test sort(collect(filter(DT.is_ghost_triangle, each_triangle(___tri)))) == sort(collect(each_ghost_triangle(___tri))) + @test DelaunayTriangulation.triangle_type(_ghost_itr) == DelaunayTriangulation.triangle_type(_ghost_itr) + @test DelaunayTriangulation.triangle_type(_solid_itr) == DelaunayTriangulation.triangle_type(_solid_itr) + end + + @testset "Edges" begin + rng = StableRNG(998871) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) + A = get_area(tri) + refine!(tri; max_area = 1.0e-1A, rng, use_circumcenter = true) + @test DT.edge_type(tri) == NTuple{2, Int} + @inferred DT.edge_type(tri) + @test DT.num_edges(tri) == length(tri.graph.edges) + @inferred DT.num_edges(tri) + @test DT.each_edge(tri) == tri.graph.edges + @inferred DT.each_edge(tri) + _solid_itr = each_solid_edge(tri) + @test DelaunayTriangulation.each_edge(_solid_itr) == _solid_itr + @test Base.IteratorSize(_solid_itr) == Base.HasLength() + @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() + @test Base.eltype(_solid_itr) == NTuple{2, Int} + @test each_solid_edge(tri) isa DT.EachSolidEdge + _solid_tri = collect(_solid_itr) + @inferred collect(_solid_itr) + @test all(!DT.is_ghost_edge, _solid_tri) + _ghost_itr = each_ghost_edge(tri) + @test Base.IteratorSize(_ghost_itr) == Base.HasLength() + @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() + @test Base.eltype(_ghost_itr) == NTuple{2, Int} + @test each_ghost_edge(tri) isa DT.EachGhostEdge + _ghost_tri = collect(_ghost_itr) + @inferred collect(_ghost_itr) + @test DelaunayTriangulation.each_edge(_ghost_itr) == _ghost_itr + @test all(DT.is_ghost_edge, _ghost_tri) + @test length(_ghost_tri) + length(_solid_tri) == num_edges(tri) + rng = StableRNG(998871) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + ___tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) + A = get_area(___tri) + refine!(___tri; max_area = 1.0e-1A, rng, use_circumcenter = true) + DT.delete_ghost_triangles!(___tri) + @test sort(collect(filter(!DT.is_ghost_edge, each_edge(___tri)))) == sort(collect(each_solid_edge(___tri))) + @test sort(collect(filter(DT.is_ghost_edge, each_edge(___tri)))) == sort(collect(each_ghost_edge(___tri))) + @test length(collect(each_ghost_edge(___tri))) == num_edges(___tri) .- length(sort(collect(filter(!DT.is_ghost_edge, each_edge(___tri))))) + @test length(collect(each_ghost_edge(___tri))) == DT.num_ghost_edges(___tri) == length(_ghost_itr) + @test length(collect(each_solid_edge(___tri))) == DT.num_solid_edges(___tri) == length(_solid_itr) + @test DelaunayTriangulation.edge_type(_ghost_itr) == DelaunayTriangulation.edge_type(_ghost_itr) + @test DelaunayTriangulation.edge_type(_solid_itr) == DelaunayTriangulation.edge_type(_solid_itr) + end + + @testset "Points" begin + @test DT.get_point(tri, 2) == Tuple(tri.points[2]) + @inferred DT.get_point(tri, 2) + @test DT.get_point(tri, 17) == Tuple(tri.points[17]) + @test DT.each_point_index(tri) == 1:length(tri.points) + @inferred DT.each_point_index(tri) + @test DT.each_point(tri) == tri.points + @inferred DT.each_point(tri) + @test DT.num_points(tri) == length(tri.points) + @inferred DT.num_points(tri) + @test DT.get_point(tri, 2, 5, 6, 10) == + ntuple(i -> Tuple(tri.points[(2, 5, 6, 10)[i]]), 4) + @inferred DT.get_point(tri, 2, 5, 6, 10) + rep = DT.get_representative_point_list(tri) + rep[1] = DT.RepresentativeCoordinates(0.5, 0.3, 2) + rep[2] = DT.RepresentativeCoordinates(2.5, 7.3, 7) + rep[3] = DT.RepresentativeCoordinates(6.5, -0.6, 13) + rep[4] = DT.RepresentativeCoordinates(6.5, -0.66234, 13) + rep[5] = DT.RepresentativeCoordinates(6.534234, -0.6, 13) + @test DT.get_point(tri, -1) == DT.getxy(rep[1]) + @test DT.get_point(tri, -2) == DT.getxy(rep[1]) + @test DT.get_point(tri, -3) == DT.getxy(rep[1]) + @test DT.get_point(tri, -4) == DT.getxy(rep[1]) + @test DT.get_point(tri, -5) == DT.getxy(rep[2]) + @test DT.get_point(tri, -6) == DT.getxy(rep[3]) + @test DT.get_point(tri, -7) == DT.getxy(rep[4]) + @test DT.get_point(tri, -8) == DT.getxy(rep[4]) + @test DT.get_point(tri, -9) == DT.getxy(rep[4]) + @test DT.get_point(tri, -10) == DT.getxy(rep[4]) + @test DT.get_point(tri, -11) == DT.getxy(rep[5]) + rep = DT.get_representative_point_list(tri_2) + @test DT.get_point(tri_2, -1) == DT.getxy(rep[1]) + @inferred DT.get_point(tri_2, -1) + @test DT.get_point(tri_2, -2) == DT.getxy(rep[1]) + @test DT.get_point(tri_2, -3) == DT.getxy(rep[1]) + @test DT.get_point(tri_2, -4) == DT.getxy(rep[1]) + @test DT.get_point(tri_3, -1) == DT.getxy(DT.get_representative_point_coordinates(tri_3, 1)) + @test_throws KeyError DT.get_point(tri, -12) + @test_throws KeyError DT.get_point(tri_2, -5) + @test_throws KeyError DT.get_point(tri_3, -2) + @test get_point(tri, tri.points[2]) == tri.points[2] + @inferred get_point(tri, tri.points[2]) + @test reverse(sort(collect(DT.all_ghost_vertices(tri)))) == [ + DT.𝒢, + DT.𝒢 - 1, + DT.𝒢 - 2, + DT.𝒢 - 3, + DT.𝒢 - 4, + DT.𝒢 - 5, + DT.𝒢 - 6, + DT.𝒢 - 7, + DT.𝒢 - 8, + DT.𝒢 - 9, + DT.𝒢 - 10, + ]#(new_point, c′) = (436, (1.8363241117152609, 1.0864161502095007)) + rng = StableRNG(887271) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + _triq = triangulate(points; boundary_nodes, rng) + A = get_area(_triq) + refine!(_triq; max_area = 1.0e-1A, rng, use_circumcenter = true, use_lens = false) + _solid_itr = each_solid_vertex(_triq) + @test DelaunayTriangulation.each_vertex(_solid_itr) == _solid_itr + @test Base.IteratorSize(_solid_itr) == Base.HasLength() + @test Base.IteratorEltype(_solid_itr) == Base.HasEltype() + @test Base.eltype(_solid_itr) == Int + @test each_solid_vertex(_triq) isa DT.EachSolidVertex + _solid_tri = collect(_solid_itr) + @inferred collect(_solid_itr) + @test sort(_solid_tri) == sort(filter(i -> DT.has_vertex(_triq, i) && i ≥ 1, 1:DT.num_points(tri))) + @test all(!DT.is_ghost_vertex, _solid_tri) + _ghost_itr = each_ghost_vertex(_triq) + @test Base.IteratorSize(_ghost_itr) == Base.HasLength() + @test Base.IteratorEltype(_ghost_itr) == Base.HasEltype() + @test Base.eltype(_ghost_itr) == Int + @test each_ghost_vertex(_triq) isa DT.EachGhostVertex + _ghost_tri = collect(_ghost_itr) + @inferred collect(_ghost_itr) + @test DelaunayTriangulation.each_vertex(_ghost_itr) == _ghost_itr + @test all(DT.is_ghost_vertex, _ghost_tri) + @test reverse(sort(_ghost_tri)) == [ + DT.𝒢, + DT.𝒢 - 1, + DT.𝒢 - 2, + DT.𝒢 - 3, + DT.𝒢 - 4, + DT.𝒢 - 5, + DT.𝒢 - 6, + DT.𝒢 - 7, + DT.𝒢 - 8, + DT.𝒢 - 9, + DT.𝒢 - 10, + ] + @test length(_ghost_tri) == length(_ghost_itr) == sum(<(0), keys(_triq.adjacent2vertex.adjacent2vertex)) + @test length(_solid_tri) == length(_solid_itr) == sort(filter(i -> DT.has_vertex(_triq, i) && i ≥ 1, 1:DT.num_points(tri))) |> length + rng = StableRNG(887271) + ___tri = triangulate(points; boundary_nodes, rng) + A = get_area(___tri) + refine!(___tri; max_area = 1.0e-1A, rng, use_circumcenter = true) + DT.delete_ghost_triangles!(___tri) + @test sort(collect(filter(!DT.is_ghost_vertex, each_vertex(___tri)))) == sort(collect(each_solid_vertex(___tri))) + @test sort(collect(filter(DT.is_ghost_vertex, each_vertex(___tri)))) == sort(collect(each_ghost_vertex(___tri))) + @test length(collect(each_ghost_vertex(___tri))) == num_vertices(___tri) .- length(sort(collect(filter(!DT.is_ghost_vertex, each_vertex(___tri))))) + tri1 = Triangulation([[1.0, 2.0], [3.0, 4.0]]) + DT.push_point!(tri1, 13.7, 5.0) + @test get_points(tri1) == [[1.0, 2.0], [3.0, 4.0], [13.7, 5.0]] + @test get_point(tri1, 3) == (13.7, 5.0) + tri1 = Triangulation([(1.0, 2.0), (3.0, 4.0)]) + DT.push_point!(tri1, 13.7, 5.0) + @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0)] + @test get_point(tri1, 3) == (13.7, 5.0) + DT.push_point!(tri1, (19.0, 17.05)) + @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0), (19.0, 17.05)] + DT.pop_point!(tri1) + @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0), (13.7, 5.0)] + DT.pop_point!(tri1) + @test get_points(tri1) == [(1.0, 2.0), (3.0, 4.0)] + DT.set_point!(tri1, 2, 13.7, 5.0) + @test get_points(tri1) == [(1.0, 2.0), (13.7, 5.0)] + DT.set_point!(tri1, 2, (19.0, 17.05)) + @test get_points(tri1) == [(1.0, 2.0), (19.0, 17.05)] + end + + @testset "Miscellaneous" begin + @test DT.integer_type(tri) == Int + @test DT.number_type(tri) == Float64 + @test DT.edge_type(tri) == NTuple{2, Int} + @test DT.edges_type(tri) == Set{NTuple{2, Int}} + @test DT.triangles_type(tri) == Set{NTuple{3, Int}} + @test DT.triangle_type(tri) == NTuple{3, Int} + @inferred DT.integer_type(tri) + @inferred DT.number_type(tri) + DT.clear_empty_features!(tri) + clean_tri = deepcopy(tri) + get_adjacent(tri, 17, 32) + get_adjacent(tri, 58, 37) + DT.add_adjacent2vertex!(tri, 3, 58, 60) + DT.add_neighbour!(tri, 5, 171) + @test clean_tri ≠ tri + DT.delete_adjacent2vertex!(tri, 3, 58, 60) + DT.delete_neighbour!(tri, 5, 171) + @test clean_tri == tri + _tri = triangulate_rectangle(0.0, 10.0, 0.0, 20.0, 11, 21) + T = (51, 41, 52) + ℓ = (7.0, 3.5) + @test DT.find_edge(_tri, T, ℓ) == (41, 52) + ℓ = (6.5, 4.0) + @test DT.find_edge(_tri, T, ℓ) == (52, 51) + ℓ = (6.5, 3.5) + @test DT.find_edge(_tri, T, ℓ) == (51, 41) + @inferred DT.find_edge(_tri, T, ℓ) + push!(get_all_segments(_tri), (1, 2)) + @test DT.is_constrained(_tri) + empty!(get_all_segments(_tri)) + @test !DT.is_constrained(_tri) + @test reverse(sort(collect(DT.all_ghost_vertices(_tri)))) == + [DT.𝒢, DT.𝒢 - 1, DT.𝒢 - 2, DT.𝒢 - 3] + end end @testset "merge_segments" begin - all_bn = get_boundary_nodes(tri) - i = rand(1:100000, 50) - j = rand(1:100000, 50) - all_ce = Set(((i, j) for (i, j) in zip(i, j))) - bn_map = get_ghost_vertex_map(tri) - bn1 = all_bn[1] - bn11 = bn1[1] - bn12 = bn1[2] - bn13 = bn1[3] - bn14 = bn1[4] - bn2 = all_bn[2][1] - bn3 = all_bn[3][1] - bn4 = all_bn[4] - bn41 = bn4[1] - bn42 = bn4[2] - bn43 = bn4[3] - bn44 = bn4[4] - bn5 = all_bn[5][1] - e11 = Set(((bn11[i], bn11[i+1]) for i in 1:(length(bn11)-1))) - e12 = Set(((bn12[i], bn12[i+1]) for i in 1:(length(bn12)-1))) - e13 = Set(((bn13[i], bn13[i+1]) for i in 1:(length(bn13)-1))) - e14 = Set(((bn14[i], bn14[i+1]) for i in 1:(length(bn14)-1))) - e2 = Set(((bn2[i], bn2[i+1]) for i in 1:(length(bn2)-1))) - e3 = Set(((bn3[i], bn3[i+1]) for i in 1:(length(bn3)-1))) - e41 = Set(((bn41[i], bn41[i+1]) for i in 1:(length(bn41)-1))) - e42 = Set(((bn42[i], bn42[i+1]) for i in 1:(length(bn42)-1))) - e43 = Set(((bn43[i], bn43[i+1]) for i in 1:(length(bn43)-1))) - e44 = Set(((bn44[i], bn44[i+1]) for i in 1:(length(bn44)-1))) - e5 = Set(((bn5[i], bn5[i+1]) for i in 1:(length(bn5)-1))) - ace = Set{NTuple{2,Int}}() - for es in (e11, e12, e13, e14, e2, e3, e41, e42, e43, e44, e5) - for e in es - push!(ace, e) - end - end - for e in all_ce - push!(ace, e) - end - @test ace == DT.merge_segments(bn_map, all_bn, all_ce) - - all_bn = get_boundary_nodes(tri_2) - i = rand(1:100000, 50) - j = rand(1:100000, 50) - all_ce = Set(((i, j) for (i, j) in zip(i, j))) - bn_map = get_ghost_vertex_map(tri_2) - bn1 = all_bn[1] - bn2 = all_bn[2] - bn3 = all_bn[3] - bn4 = all_bn[4] - e1 = Set(((bn1[i], bn1[i+1]) for i in 1:(length(bn1)-1))) - e2 = Set(((bn2[i], bn2[i+1]) for i in 1:(length(bn2)-1))) - e3 = Set(((bn3[i], bn3[i+1]) for i in 1:(length(bn3)-1))) - e4 = Set(((bn4[i], bn4[i+1]) for i in 1:(length(bn4)-1))) - ace = Set{NTuple{2,Int}}() - for es in (e1, e2, e3, e4) - for e in es - push!(ace, e) - end - end - for e in all_ce - push!(ace, e) - end - @test ace == DT.merge_segments(bn_map, all_bn, all_ce) - - all_bn = get_boundary_nodes(tri_3) - i = rand(1:100000, 50) - j = rand(1:100000, 50) - all_ce = Set(((i, j) for (i, j) in zip(i, j))) - bn_map = get_ghost_vertex_map(tri_3) - e = Set(((all_bn[i], all_bn[i+1]) for i in 1:(length(all_bn)-1))) - ace = Set{NTuple{2,Int}}() - for e in e + all_bn = get_boundary_nodes(tri) + i = rand(1:100000, 50) + j = rand(1:100000, 50) + all_ce = Set(((i, j) for (i, j) in zip(i, j))) + bn_map = get_ghost_vertex_map(tri) + bn1 = all_bn[1] + bn11 = bn1[1] + bn12 = bn1[2] + bn13 = bn1[3] + bn14 = bn1[4] + bn2 = all_bn[2][1] + bn3 = all_bn[3][1] + bn4 = all_bn[4] + bn41 = bn4[1] + bn42 = bn4[2] + bn43 = bn4[3] + bn44 = bn4[4] + bn5 = all_bn[5][1] + e11 = Set(((bn11[i], bn11[i + 1]) for i in 1:(length(bn11) - 1))) + e12 = Set(((bn12[i], bn12[i + 1]) for i in 1:(length(bn12) - 1))) + e13 = Set(((bn13[i], bn13[i + 1]) for i in 1:(length(bn13) - 1))) + e14 = Set(((bn14[i], bn14[i + 1]) for i in 1:(length(bn14) - 1))) + e2 = Set(((bn2[i], bn2[i + 1]) for i in 1:(length(bn2) - 1))) + e3 = Set(((bn3[i], bn3[i + 1]) for i in 1:(length(bn3) - 1))) + e41 = Set(((bn41[i], bn41[i + 1]) for i in 1:(length(bn41) - 1))) + e42 = Set(((bn42[i], bn42[i + 1]) for i in 1:(length(bn42) - 1))) + e43 = Set(((bn43[i], bn43[i + 1]) for i in 1:(length(bn43) - 1))) + e44 = Set(((bn44[i], bn44[i + 1]) for i in 1:(length(bn44) - 1))) + e5 = Set(((bn5[i], bn5[i + 1]) for i in 1:(length(bn5) - 1))) + ace = Set{NTuple{2, Int}}() + for es in (e11, e12, e13, e14, e2, e3, e41, e42, e43, e44, e5) + for e in es push!(ace, e) - end - for e in all_ce + end + end + for e in all_ce + push!(ace, e) + end + @test ace == DT.merge_segments(bn_map, all_bn, all_ce) + + all_bn = get_boundary_nodes(tri_2) + i = rand(1:100000, 50) + j = rand(1:100000, 50) + all_ce = Set(((i, j) for (i, j) in zip(i, j))) + bn_map = get_ghost_vertex_map(tri_2) + bn1 = all_bn[1] + bn2 = all_bn[2] + bn3 = all_bn[3] + bn4 = all_bn[4] + e1 = Set(((bn1[i], bn1[i + 1]) for i in 1:(length(bn1) - 1))) + e2 = Set(((bn2[i], bn2[i + 1]) for i in 1:(length(bn2) - 1))) + e3 = Set(((bn3[i], bn3[i + 1]) for i in 1:(length(bn3) - 1))) + e4 = Set(((bn4[i], bn4[i + 1]) for i in 1:(length(bn4) - 1))) + ace = Set{NTuple{2, Int}}() + for es in (e1, e2, e3, e4) + for e in es push!(ace, e) - end - @test ace == DT.merge_segments(bn_map, all_bn, all_ce) - - all_bn = get_boundary_nodes(tri_4)[1] - i = rand(1:100000, 50) - j = rand(1:100000, 50) - all_ce = Set(((i, j) for (i, j) in zip(i, j))) - bn_map = get_ghost_vertex_map(tri_4) - e = Set(((all_bn[i], all_bn[i+1]) for i in 1:(length(all_bn)-1))) - ace = Set{NTuple{2,Int}}() - for e in e - push!(ace, e) - end - for e in all_ce - push!(ace, e) - end - @test ace == DT.merge_segments(bn_map, [all_bn], all_ce) + end + end + for e in all_ce + push!(ace, e) + end + @test ace == DT.merge_segments(bn_map, all_bn, all_ce) + + all_bn = get_boundary_nodes(tri_3) + i = rand(1:100000, 50) + j = rand(1:100000, 50) + all_ce = Set(((i, j) for (i, j) in zip(i, j))) + bn_map = get_ghost_vertex_map(tri_3) + e = Set(((all_bn[i], all_bn[i + 1]) for i in 1:(length(all_bn) - 1))) + ace = Set{NTuple{2, Int}}() + for e in e + push!(ace, e) + end + for e in all_ce + push!(ace, e) + end + @test ace == DT.merge_segments(bn_map, all_bn, all_ce) + + all_bn = get_boundary_nodes(tri_4)[1] + i = rand(1:100000, 50) + j = rand(1:100000, 50) + all_ce = Set(((i, j) for (i, j) in zip(i, j))) + bn_map = get_ghost_vertex_map(tri_4) + e = Set(((all_bn[i], all_bn[i + 1]) for i in 1:(length(all_bn) - 1))) + ace = Set{NTuple{2, Int}}() + for e in e + push!(ace, e) + end + for e in all_ce + push!(ace, e) + end + @test ace == DT.merge_segments(bn_map, [all_bn], all_ce) end @testset "sort_edge_by_degree" begin - tri = triangulate(rand(2, 500); delete_ghosts=false) - for e in each_edge(tri) - new_e = DT.sort_edge_by_degree(tri, e) - d1 = DT.num_neighbours(tri, e[1]) - d2 = DT.num_neighbours(tri, e[2]) - if d1 ≤ d2 - @test new_e == e - else - @test new_e == (e[2], e[1]) - end - end + tri = triangulate(rand(2, 500); delete_ghosts = false) + for e in each_edge(tri) + new_e = DT.sort_edge_by_degree(tri, e) + d1 = DT.num_neighbours(tri, e[1]) + d2 = DT.num_neighbours(tri, e[2]) + if d1 ≤ d2 + @test new_e == e + else + @test new_e == (e[2], e[1]) + end + end end @testset "triangle_line_segment_intersection" begin - n = 20 - for _ in 1:10 - n += rand(1:5) - tri1 = triangulate(12randn(2, n), delete_ghosts=false) - tri2 = triangulate(12randn(2, n), delete_ghosts=true) - for tri in (tri1, tri2) - for qi in each_solid_vertex(tri) - for k in each_solid_vertex(tri) - q = get_point(tri, qi) - history = DT.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}() - find_triangle(tri, q; - k, - store_history=true, - history) - visited_triangles = history.triangles - collinear_segments = history.collinear_segments - @test all(T -> DT.is_positively_oriented(DT.triangle_orientation(tri, T...)), visited_triangles) - @test all(!DT.is_none, [DT.triangle_line_segment_intersection(tri, T..., (qi, k)...) for T in visited_triangles]) - @test allunique(visited_triangles) - if !isempty(collinear_segments) - @test all(E -> DT.is_collinear(DT.point_position_relative_to_line(tri, qi, k, E[1])), collinear_segments) - @test all(E -> DT.is_collinear(DT.point_position_relative_to_line(tri, qi, k, E[2])), collinear_segments) - end - end - end + n = 20 + for _ in 1:10 + n += rand(1:5) + tri1 = triangulate(12randn(2, n), delete_ghosts = false) + tri2 = triangulate(12randn(2, n), delete_ghosts = true) + for tri in (tri1, tri2) + for qi in each_solid_vertex(tri) + for k in each_solid_vertex(tri) + q = get_point(tri, qi) + history = DT.PointLocationHistory{NTuple{3, Int}, NTuple{2, Int}, Int}() + find_triangle( + tri, q; + k, + store_history = true, + history, + ) + visited_triangles = history.triangles + collinear_segments = history.collinear_segments + @test all(T -> DT.is_positively_oriented(DT.triangle_orientation(tri, T...)), visited_triangles) + @test all(!DT.is_none, [DT.triangle_line_segment_intersection(tri, T..., (qi, k)...) for T in visited_triangles]) + @test allunique(visited_triangles) + if !isempty(collinear_segments) + @test all(E -> DT.is_collinear(DT.point_position_relative_to_line(tri, qi, k, E[1])), collinear_segments) + @test all(E -> DT.is_collinear(DT.point_position_relative_to_line(tri, qi, k, E[2])), collinear_segments) + end + end end - end + end + end end @testset "point_closest_to_line" begin - tri = fixed_shewchuk_example_constrained() - i, j = 2, 7 - u, v = 9, 8 - @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) - @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) - u, v = 3, 11 - @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) - @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) - i, j = 7, 2 - u, v = 6, 1 - @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) - @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) - u, v = 2, 6 - @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) - @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) - u, v = 7, 4 - @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) - @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) + tri = fixed_shewchuk_example_constrained() + i, j = 2, 7 + u, v = 9, 8 + @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) + @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) + u, v = 3, 11 + @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) + @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) + i, j = 7, 2 + u, v = 6, 1 + @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) + @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) + u, v = 2, 6 + @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) + @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) + u, v = 7, 4 + @test DT.is_closer(DT.point_closest_to_line(tri, i, j, u, v)) + @test DT.is_further(DT.point_closest_to_line(tri, i, j, v, u)) end rng = StableRNG(91928281) @@ -699,751 +707,761 @@ pts = [(rand(rng), rand(rng)) for _ in 1:50] bnd_pts = [(0.3cos(θ), 0.3sin(θ)) .+ 0.5 for θ in LinRange(0, 2π - 1 / 250, 25)] bnd_id = [(51:75)..., 51] append!(pts, bnd_pts) -global tric = triangulate(pts; boundary_nodes=bnd_id, rng) +global tric = triangulate(pts; boundary_nodes = bnd_id, rng) @testset "each_segment" begin - @test each_segment(tric) == each_edge(get_all_segments(tric)) + @test each_segment(tric) == each_edge(get_all_segments(tric)) end @testset "contains_segment" begin - @test !DT.contains_segment(tric, 12, 17) - @test DT.contains_segment(tric, 69, 70) - @test DT.contains_segment(tric, 70, 69) - @test !DT.contains_segment(tric, 32, 41) - @test !DT.contains_segment(tric, 45, 38) - @test DT.contains_segment(tric, 63, 64) - @test !DT.contains_segment(tric, (45, 38)) - @test !DT.contains_segment(tric, 26, 22) - @test DT.contains_segment(tric, 64, 65) - @test DT.contains_segment(tric, 55, 54) - @test DT.contains_segment(tric, 58, 57) - @test DT.contains_segment(tric, 59, 60) - @test !DT.contains_segment(tric, 30, 70) - @test !DT.contains_segment(tric, 56, 37) - @test DT.contains_segment(tric, 73, 74) + @test !DT.contains_segment(tric, 12, 17) + @test DT.contains_segment(tric, 69, 70) + @test DT.contains_segment(tric, 70, 69) + @test !DT.contains_segment(tric, 32, 41) + @test !DT.contains_segment(tric, 45, 38) + @test DT.contains_segment(tric, 63, 64) + @test !DT.contains_segment(tric, (45, 38)) + @test !DT.contains_segment(tric, 26, 22) + @test DT.contains_segment(tric, 64, 65) + @test DT.contains_segment(tric, 55, 54) + @test DT.contains_segment(tric, 58, 57) + @test DT.contains_segment(tric, 59, 60) + @test !DT.contains_segment(tric, 30, 70) + @test !DT.contains_segment(tric, 56, 37) + @test DT.contains_segment(tric, 73, 74) end @testset "get_all_boundary_nodes" begin - x, y = complicated_geometry() - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; rng, boundary_nodes) - A = get_area(tri) - refine!(tri, rng=rng, max_area=1e-1A, use_circumcenter=true, use_lens=false) - all_bn = DT.get_all_boundary_nodes(tri) - @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri)))) - tri2, label_map, index_map = simple_geometry() - all_bn = DT.get_all_boundary_nodes(tri2) - @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri2)))) - tri3 = triangulate_rectangle(0, 1, 0, 1, 50, 50; delete_ghosts=false, single_boundary=false) - all_bn = DT.get_all_boundary_nodes(tri3) - @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri3)))) - tri4 = triangulate_rectangle(0, 1, 0, 1, 50, 50; delete_ghosts=false, single_boundary=true) - all_bn = DT.get_all_boundary_nodes(tri4) - @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri4)))) - tri = triangulate(rand(2, 50)) - @test isempty(DT.get_all_boundary_nodes(tri)) + x, y = complicated_geometry() + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri = triangulate(points; rng, boundary_nodes) + A = get_area(tri) + refine!(tri, rng = rng, max_area = 1.0e-1A, use_circumcenter = true, use_lens = false) + all_bn = DT.get_all_boundary_nodes(tri) + @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri)))) + tri2, label_map, index_map = simple_geometry() + all_bn = DT.get_all_boundary_nodes(tri2) + @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri2)))) + tri3 = triangulate_rectangle(0, 1, 0, 1, 50, 50; delete_ghosts = false, single_boundary = false) + all_bn = DT.get_all_boundary_nodes(tri3) + @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri3)))) + tri4 = triangulate_rectangle(0, 1, 0, 1, 50, 50; delete_ghosts = false, single_boundary = true) + all_bn = DT.get_all_boundary_nodes(tri4) + @test all_bn == Set(reduce(vcat, reduce(vcat, get_boundary_nodes(tri4)))) + tri = triangulate(rand(2, 50)) + @test isempty(DT.get_all_boundary_nodes(tri)) end @testset "get_boundary_edge_map" begin - x, y = complicated_geometry() - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; rng, boundary_nodes) - A = get_area(tri) - refine!(tri, rng=rng, max_area=1e-2A, use_circumcenter=true) - for (e, (s, i)) in tri.boundary_edge_map - @test DT.get_boundary_edge_map(tri, e) == (s, i) - @test DT.get_boundary_edge_map(tri, e...) == (s, i) - @test get_boundary_nodes(DT.get_boundary_nodes(tri, s), i) == e[1] - end + x, y = complicated_geometry() + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri = triangulate(points; rng, boundary_nodes) + A = get_area(tri) + refine!(tri, rng = rng, max_area = 1.0e-2A, use_circumcenter = true) + for (e, (s, i)) in tri.boundary_edge_map + @test DT.get_boundary_edge_map(tri, e) == (s, i) + @test DT.get_boundary_edge_map(tri, e...) == (s, i) + @test get_boundary_nodes(DT.get_boundary_nodes(tri, s), i) == e[1] + end end @testset "split_boundary_edge!" begin - x, y = complicated_geometry() - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_1 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_1) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) - tri_2 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_2) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) - tri_3 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_3) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) - tri_4 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_4) - - DT.split_boundary_edge!(tri_1, (21, 22), 500) - @test tri_1.boundary_nodes[2][1][1:11] == [13, 14, 15, 16, 17, 18, 19, 20, 21, 500, 22] - @test DT.get_boundary_edge_map(tri_1, 21, 500) == ((2, 1), 9) - @test DT.get_boundary_edge_map(tri_1, 500, 22) == ((2, 1), 10) - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 21, 22) - @test !DT.contains_unoriented_edge((21, 22), DT.get_all_segments(tri_1)) - @test DT.contains_unoriented_edge((21, 500), DT.get_all_segments(tri_1)) - @test DT.contains_unoriented_edge((500, 22), DT.get_all_segments(tri_1)) - - DT.split_boundary_edge!(tri_1, (7, 8), 5000) - @test tri_1.boundary_nodes[1][3] == [7, 5000, 8, 9, 10] - @test DT.get_boundary_edge_map(tri_1, 7, 5000) == ((1, 3), 1) - @test DT.get_boundary_edge_map(tri_1, 5000, 8) == ((1, 3), 2) - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 7, 8) - @test !DT.contains_unoriented_edge((7, 8), DT.get_all_segments(tri_1)) - @test DT.contains_unoriented_edge((7, 5000), DT.get_all_segments(tri_1)) - @test DT.contains_unoriented_edge((5000, 8), DT.get_all_segments(tri_1)) - - DT.split_boundary_edge!(tri_2, 8, 9, 300) - @test tri_2.boundary_nodes[3] == [7, 8, 300, 9, 10] - @test DT.get_boundary_edge_map(tri_2, 8, 300) == (3, 2) - @test DT.get_boundary_edge_map(tri_2, 300, 9) == (3, 3) - @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8, 9) - @test !DT.contains_unoriented_edge((8, 9), DT.get_all_segments(tri_2)) - @test DT.contains_unoriented_edge((8, 300), DT.get_all_segments(tri_2)) - @test DT.contains_unoriented_edge((300, 9), DT.get_all_segments(tri_2)) - - DT.split_boundary_edge!(tri_3, 3, 4, 5000) - @test tri_3.boundary_nodes == [1, 2, 3, 5000, 4, 1] - @test DT.get_boundary_edge_map(tri_3, 3, 5000) == (tri_3.boundary_nodes, 3) - @test DT.get_boundary_edge_map(tri_3, 5000, 4) == (tri_3.boundary_nodes, 4) - @test_throws KeyError DT.get_boundary_edge_map(tri_3, 3, 4) - @test !DT.contains_unoriented_edge((3, 4), DT.get_all_segments(tri_3)) - @test DT.contains_unoriented_edge((3, 5000), DT.get_all_segments(tri_3)) - @test DT.contains_unoriented_edge((5000, 4), DT.get_all_segments(tri_3)) - - DT.split_boundary_edge!(tri_4, 6, 7, 1200) - @test DT.get_boundary_edge_map(tri_4, 6, 1200) == (1, 6) - @test DT.get_boundary_edge_map(tri_4, 1200, 7) == (1, 7) - @test_throws KeyError DT.get_boundary_edge_map(tri_4, 6, 7) - @test !DT.contains_unoriented_edge((6, 7), DT.get_all_segments(tri_4)) - @test DT.contains_unoriented_edge((6, 1200), DT.get_all_segments(tri_4)) - @test DT.contains_unoriented_edge((1200, 7), DT.get_all_segments(tri_4)) + x, y = complicated_geometry() + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri_1 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_1) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) + tri_2 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_2) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) + tri_3 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_3) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) + tri_4 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_4) + + DT.split_boundary_edge!(tri_1, (21, 22), 500) + @test tri_1.boundary_nodes[2][1][1:11] == [13, 14, 15, 16, 17, 18, 19, 20, 21, 500, 22] + @test DT.get_boundary_edge_map(tri_1, 21, 500) == ((2, 1), 9) + @test DT.get_boundary_edge_map(tri_1, 500, 22) == ((2, 1), 10) + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 21, 22) + @test !DT.contains_unoriented_edge((21, 22), DT.get_all_segments(tri_1)) + @test DT.contains_unoriented_edge((21, 500), DT.get_all_segments(tri_1)) + @test DT.contains_unoriented_edge((500, 22), DT.get_all_segments(tri_1)) + + DT.split_boundary_edge!(tri_1, (7, 8), 5000) + @test tri_1.boundary_nodes[1][3] == [7, 5000, 8, 9, 10] + @test DT.get_boundary_edge_map(tri_1, 7, 5000) == ((1, 3), 1) + @test DT.get_boundary_edge_map(tri_1, 5000, 8) == ((1, 3), 2) + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 7, 8) + @test !DT.contains_unoriented_edge((7, 8), DT.get_all_segments(tri_1)) + @test DT.contains_unoriented_edge((7, 5000), DT.get_all_segments(tri_1)) + @test DT.contains_unoriented_edge((5000, 8), DT.get_all_segments(tri_1)) + + DT.split_boundary_edge!(tri_2, 8, 9, 300) + @test tri_2.boundary_nodes[3] == [7, 8, 300, 9, 10] + @test DT.get_boundary_edge_map(tri_2, 8, 300) == (3, 2) + @test DT.get_boundary_edge_map(tri_2, 300, 9) == (3, 3) + @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8, 9) + @test !DT.contains_unoriented_edge((8, 9), DT.get_all_segments(tri_2)) + @test DT.contains_unoriented_edge((8, 300), DT.get_all_segments(tri_2)) + @test DT.contains_unoriented_edge((300, 9), DT.get_all_segments(tri_2)) + + DT.split_boundary_edge!(tri_3, 3, 4, 5000) + @test tri_3.boundary_nodes == [1, 2, 3, 5000, 4, 1] + @test DT.get_boundary_edge_map(tri_3, 3, 5000) == (tri_3.boundary_nodes, 3) + @test DT.get_boundary_edge_map(tri_3, 5000, 4) == (tri_3.boundary_nodes, 4) + @test_throws KeyError DT.get_boundary_edge_map(tri_3, 3, 4) + @test !DT.contains_unoriented_edge((3, 4), DT.get_all_segments(tri_3)) + @test DT.contains_unoriented_edge((3, 5000), DT.get_all_segments(tri_3)) + @test DT.contains_unoriented_edge((5000, 4), DT.get_all_segments(tri_3)) + + DT.split_boundary_edge!(tri_4, 6, 7, 1200) + @test DT.get_boundary_edge_map(tri_4, 6, 1200) == (1, 6) + @test DT.get_boundary_edge_map(tri_4, 1200, 7) == (1, 7) + @test_throws KeyError DT.get_boundary_edge_map(tri_4, 6, 7) + @test !DT.contains_unoriented_edge((6, 7), DT.get_all_segments(tri_4)) + @test DT.contains_unoriented_edge((6, 1200), DT.get_all_segments(tri_4)) + @test DT.contains_unoriented_edge((1200, 7), DT.get_all_segments(tri_4)) end @testset "merge_boundary_edge!" begin - x, y = complicated_geometry() - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_1 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_1) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) - tri_2 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_2) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) - tri_3 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_3) - - rng = StableRNG(91818) - boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) - tri_4 = triangulate(points; rng, boundary_nodes) - A = get_area(tri_4) - - orig_bn = deepcopy(get_boundary_nodes(tri_1)) - orig_bnn = deepcopy(get_boundary_edge_map(tri_1)) - DT.split_boundary_edge!(tri_1, (21, 22), 170) - @test get_boundary_nodes(tri_1) ≠ orig_bn - @test get_boundary_edge_map(tri_1) ≠ orig_bnn - DT.merge_boundary_edge!(tri_1, (21, 22), 170) - @test get_boundary_nodes(tri_1) == orig_bn - @test get_boundary_edge_map(tri_1) == orig_bnn - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 21, 170) - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 170, 22) - @test DT.contains_unoriented_edge((21, 22), DT.get_all_segments(tri_1)) - @test !DT.contains_unoriented_edge((21, 170), DT.get_all_segments(tri_1)) - @test !DT.contains_unoriented_edge((170, 22), DT.get_all_segments(tri_1)) - - orig_bn = deepcopy(get_boundary_nodes(tri_1)) - orig_bnn = deepcopy(get_boundary_edge_map(tri_1)) - DT.split_boundary_edge!(tri_1, (7, 8), 5000) - @test get_boundary_nodes(tri_1) ≠ orig_bn - @test get_boundary_edge_map(tri_1) ≠ orig_bnn - DT.merge_boundary_edge!(tri_1, (7, 8), 5000) - @test get_boundary_nodes(tri_1) == orig_bn - @test get_boundary_edge_map(tri_1) == orig_bnn - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 7, 5000) - @test_throws KeyError DT.get_boundary_edge_map(tri_1, 5000, 8) - @test DT.contains_unoriented_edge((7, 8), DT.get_all_segments(tri_1)) - @test !DT.contains_unoriented_edge((7, 5000), DT.get_all_segments(tri_1)) - @test !DT.contains_unoriented_edge((5000, 8), DT.get_all_segments(tri_1)) - - orig_bn = deepcopy(get_boundary_nodes(tri_2)) - orig_bnn = deepcopy(get_boundary_edge_map(tri_2)) - DT.split_boundary_edge!(tri_2, 8, 9, 8182) - @test get_boundary_nodes(tri_2) ≠ orig_bn - @test get_boundary_edge_map(tri_2) ≠ orig_bnn - DT.merge_boundary_edge!(tri_2, 8, 9, 8182) - @test get_boundary_nodes(tri_2) == orig_bn - @test get_boundary_edge_map(tri_2) == orig_bnn - @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8, 8182) - @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8182, 9) - @test DT.contains_unoriented_edge((8, 9), DT.get_all_segments(tri_2)) - @test !DT.contains_unoriented_edge((8, 8182), DT.get_all_segments(tri_2)) - @test !DT.contains_unoriented_edge((8182, 9), DT.get_all_segments(tri_2)) - - orig_bn = deepcopy(get_boundary_nodes(tri_3)) - orig_bnn = deepcopy(get_boundary_edge_map(tri_3)) - DT.split_boundary_edge!(tri_3, 3, 4, 18289) - @test get_boundary_nodes(tri_3) ≠ orig_bn - @test get_boundary_edge_map(tri_3) ≠ orig_bnn - DT.merge_boundary_edge!(tri_3, 3, 4, 18289) - @test get_boundary_nodes(tri_3) == orig_bn - @test get_boundary_edge_map(tri_3) == orig_bnn - @test_throws KeyError DT.get_boundary_edge_map(tri_3, 3, 18289) - @test_throws KeyError DT.get_boundary_edge_map(tri_3, 18289, 4) - @test DT.contains_unoriented_edge((3, 4), DT.get_all_segments(tri_3)) - @test !DT.contains_unoriented_edge((3, 18289), DT.get_all_segments(tri_3)) - @test !DT.contains_unoriented_edge((18289, 4), DT.get_all_segments(tri_3)) - - orig_bn = deepcopy(get_boundary_nodes(tri_4)) - orig_bnn = deepcopy(get_boundary_edge_map(tri_4)) - DT.split_boundary_edge!(tri_4, 6, 7, 1200) - @test get_boundary_nodes(tri_4) ≠ orig_bn - @test get_boundary_edge_map(tri_4) ≠ orig_bnn - DT.merge_boundary_edge!(tri_4, 6, 7, 1200) - @test get_boundary_nodes(tri_4) == orig_bn - @test get_boundary_edge_map(tri_4) == orig_bnn - @test_throws KeyError DT.get_boundary_edge_map(tri_4, 6, 1200) - @test_throws KeyError DT.get_boundary_edge_map(tri_4, 1200, 7) - @test DT.contains_unoriented_edge((6, 7), DT.get_all_segments(tri_4)) - @test !DT.contains_unoriented_edge((6, 1200), DT.get_all_segments(tri_4)) - @test !DT.contains_unoriented_edge((1200, 7), DT.get_all_segments(tri_4)) + x, y = complicated_geometry() + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri_1 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_1) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) + tri_2 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_2) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) + tri_3 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_3) + + rng = StableRNG(91818) + boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) + tri_4 = triangulate(points; rng, boundary_nodes) + A = get_area(tri_4) + + orig_bn = deepcopy(get_boundary_nodes(tri_1)) + orig_bnn = deepcopy(get_boundary_edge_map(tri_1)) + DT.split_boundary_edge!(tri_1, (21, 22), 170) + @test get_boundary_nodes(tri_1) ≠ orig_bn + @test get_boundary_edge_map(tri_1) ≠ orig_bnn + DT.merge_boundary_edge!(tri_1, (21, 22), 170) + @test get_boundary_nodes(tri_1) == orig_bn + @test get_boundary_edge_map(tri_1) == orig_bnn + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 21, 170) + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 170, 22) + @test DT.contains_unoriented_edge((21, 22), DT.get_all_segments(tri_1)) + @test !DT.contains_unoriented_edge((21, 170), DT.get_all_segments(tri_1)) + @test !DT.contains_unoriented_edge((170, 22), DT.get_all_segments(tri_1)) + + orig_bn = deepcopy(get_boundary_nodes(tri_1)) + orig_bnn = deepcopy(get_boundary_edge_map(tri_1)) + DT.split_boundary_edge!(tri_1, (7, 8), 5000) + @test get_boundary_nodes(tri_1) ≠ orig_bn + @test get_boundary_edge_map(tri_1) ≠ orig_bnn + DT.merge_boundary_edge!(tri_1, (7, 8), 5000) + @test get_boundary_nodes(tri_1) == orig_bn + @test get_boundary_edge_map(tri_1) == orig_bnn + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 7, 5000) + @test_throws KeyError DT.get_boundary_edge_map(tri_1, 5000, 8) + @test DT.contains_unoriented_edge((7, 8), DT.get_all_segments(tri_1)) + @test !DT.contains_unoriented_edge((7, 5000), DT.get_all_segments(tri_1)) + @test !DT.contains_unoriented_edge((5000, 8), DT.get_all_segments(tri_1)) + + orig_bn = deepcopy(get_boundary_nodes(tri_2)) + orig_bnn = deepcopy(get_boundary_edge_map(tri_2)) + DT.split_boundary_edge!(tri_2, 8, 9, 8182) + @test get_boundary_nodes(tri_2) ≠ orig_bn + @test get_boundary_edge_map(tri_2) ≠ orig_bnn + DT.merge_boundary_edge!(tri_2, 8, 9, 8182) + @test get_boundary_nodes(tri_2) == orig_bn + @test get_boundary_edge_map(tri_2) == orig_bnn + @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8, 8182) + @test_throws KeyError DT.get_boundary_edge_map(tri_2, 8182, 9) + @test DT.contains_unoriented_edge((8, 9), DT.get_all_segments(tri_2)) + @test !DT.contains_unoriented_edge((8, 8182), DT.get_all_segments(tri_2)) + @test !DT.contains_unoriented_edge((8182, 9), DT.get_all_segments(tri_2)) + + orig_bn = deepcopy(get_boundary_nodes(tri_3)) + orig_bnn = deepcopy(get_boundary_edge_map(tri_3)) + DT.split_boundary_edge!(tri_3, 3, 4, 18289) + @test get_boundary_nodes(tri_3) ≠ orig_bn + @test get_boundary_edge_map(tri_3) ≠ orig_bnn + DT.merge_boundary_edge!(tri_3, 3, 4, 18289) + @test get_boundary_nodes(tri_3) == orig_bn + @test get_boundary_edge_map(tri_3) == orig_bnn + @test_throws KeyError DT.get_boundary_edge_map(tri_3, 3, 18289) + @test_throws KeyError DT.get_boundary_edge_map(tri_3, 18289, 4) + @test DT.contains_unoriented_edge((3, 4), DT.get_all_segments(tri_3)) + @test !DT.contains_unoriented_edge((3, 18289), DT.get_all_segments(tri_3)) + @test !DT.contains_unoriented_edge((18289, 4), DT.get_all_segments(tri_3)) + + orig_bn = deepcopy(get_boundary_nodes(tri_4)) + orig_bnn = deepcopy(get_boundary_edge_map(tri_4)) + DT.split_boundary_edge!(tri_4, 6, 7, 1200) + @test get_boundary_nodes(tri_4) ≠ orig_bn + @test get_boundary_edge_map(tri_4) ≠ orig_bnn + DT.merge_boundary_edge!(tri_4, 6, 7, 1200) + @test get_boundary_nodes(tri_4) == orig_bn + @test get_boundary_edge_map(tri_4) == orig_bnn + @test_throws KeyError DT.get_boundary_edge_map(tri_4, 6, 1200) + @test_throws KeyError DT.get_boundary_edge_map(tri_4, 1200, 7) + @test DT.contains_unoriented_edge((6, 7), DT.get_all_segments(tri_4)) + @test !DT.contains_unoriented_edge((6, 1200), DT.get_all_segments(tri_4)) + @test !DT.contains_unoriented_edge((1200, 7), DT.get_all_segments(tri_4)) end @testset "get_adjacent concurrency" begin # Shouldn't be an issue anymore since we removed DefaultDict, but let's keep this here anyway. The test here is simply that it doesn't error. - tri = triangulate(rand(2, 50), delete_ghosts=false) - Base.Threads.@threads for _ in 1:5000 - get_adjacent(tri, -5, rand(1:1000)) - end + tri = triangulate(rand(2, 50), delete_ghosts = false) + Base.Threads.@threads for _ in 1:5000 + get_adjacent(tri, -5, rand(1:1000)) + end end @testset "has_vertex and has_ghost_vertices" begin - tri = triangulate(rand(2, 50), delete_ghosts=false) - @test DT.has_vertex(tri, 1) - @test !DT.has_vertex(tri, 57) - @test DT.has_ghost_vertices(tri) - @test DT.has_vertex(tri, -1) - DT.delete_ghost_vertices_from_graph!(tri) - @test !DT.has_vertex(tri, -1) - @test !DT.has_ghost_vertices(tri) + tri = triangulate(rand(2, 50), delete_ghosts = false) + @test DT.has_vertex(tri, 1) + @test !DT.has_vertex(tri, 57) + @test DT.has_ghost_vertices(tri) + @test DT.has_vertex(tri, -1) + DT.delete_ghost_vertices_from_graph!(tri) + @test !DT.has_vertex(tri, -1) + @test !DT.has_ghost_vertices(tri) end @testset "Issue #70" begin - points = [(-1.0, -1.0), (1.0, -1.0), (0.0, 1.0)] - tri = triangulate(points) - delete_ghost_triangles!(tri) - DelaunayTriangulation.delete_ghost_vertices_from_graph!(tri) - @test collect(each_solid_vertex(tri)) == collect(each_vertex(tri)) - @test !DelaunayTriangulation.has_ghost_vertices(tri) - @test DelaunayTriangulation.num_ghost_vertices(tri) == 0 - @test DelaunayTriangulation.num_solid_vertices(tri) == 3 - @test isempty(collect(each_ghost_vertex(tri))) + points = [(-1.0, -1.0), (1.0, -1.0), (0.0, 1.0)] + tri = triangulate(points) + delete_ghost_triangles!(tri) + DelaunayTriangulation.delete_ghost_vertices_from_graph!(tri) + @test collect(each_solid_vertex(tri)) == collect(each_vertex(tri)) + @test !DelaunayTriangulation.has_ghost_vertices(tri) + @test DelaunayTriangulation.num_ghost_vertices(tri) == 0 + @test DelaunayTriangulation.num_solid_vertices(tri) == 3 + @test isempty(collect(each_ghost_vertex(tri))) end @testset "Boundary curve orientation" begin - tri = triangulate(rand(2, 500)) - @test DT.is_positively_oriented(tri, 1) - lock_convex_hull!(tri) - @test DT.is_positively_oriented(tri, 1) - - pts = [ - (-7.36, 12.55), (-9.32, 8.59), (-9.0, 3.0), (-6.32, -0.27), - (-4.78, -1.53), (2.78, -1.41), (-5.42, 1.45), (7.86, 0.67), - (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), - (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), - (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), - (1.34, 6.77), (1.24, 4.15) - ] - boundary_points = [ - (0.0, 0.0), (2.0, 1.0), (3.98, 2.85), (6.0, 5.0), - (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), - (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), - (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), - (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0) - ] - boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=pts) - tri = triangulate(pts; boundary_nodes, delete_ghosts=false) - @test DT.is_positively_oriented(tri, 1) - - points = [ - (2.0, 8.0), (6.0, 4.0), (2.0, 6.0), - (2.0, 4.0), (8.0, 2.0) - ] - segment_1 = [(0.0, 0.0), (14.0, 0.0)] - segment_2 = [(14.0, 0.0), (10.0, 4.0), (4.0, 6.0), (2.0, 12.0), (0.0, 14.0)] - segment_3 = [(0.0, 14.0), (0.0, 0.0)] - boundary_points = [segment_1, segment_2, segment_3] - boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points=points) - tri = triangulate(points; boundary_nodes) - @test DT.is_positively_oriented(tri, 1) - - curve_1 = [[ + tri = triangulate(rand(2, 500)) + @test DT.is_positively_oriented(tri, 1) + lock_convex_hull!(tri) + @test DT.is_positively_oriented(tri, 1) + + pts = [ + (-7.36, 12.55), (-9.32, 8.59), (-9.0, 3.0), (-6.32, -0.27), + (-4.78, -1.53), (2.78, -1.41), (-5.42, 1.45), (7.86, 0.67), + (10.92, 0.23), (9.9, 7.39), (8.14, 4.77), (13.4, 8.61), + (7.4, 12.27), (2.2, 13.85), (-3.48, 10.21), (-4.56, 7.35), + (3.44, 8.99), (3.74, 5.87), (-2.0, 8.0), (-2.52, 4.81), + (1.34, 6.77), (1.24, 4.15), + ] + boundary_points = [ + (0.0, 0.0), (2.0, 1.0), (3.98, 2.85), (6.0, 5.0), + (7.0, 7.0), (7.0, 9.0), (6.0, 11.0), (4.0, 12.0), + (2.0, 12.0), (1.0, 11.0), (0.0, 9.13), (-1.0, 11.0), + (-2.0, 12.0), (-4.0, 12.0), (-6.0, 11.0), (-7.0, 9.0), + (-6.94, 7.13), (-6.0, 5.0), (-4.0, 3.0), (-2.0, 1.0), (0.0, 0.0), + ] + boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = pts) + tri = triangulate(pts; boundary_nodes, delete_ghosts = false) + @test DT.is_positively_oriented(tri, 1) + + points = [ + (2.0, 8.0), (6.0, 4.0), (2.0, 6.0), + (2.0, 4.0), (8.0, 2.0), + ] + segment_1 = [(0.0, 0.0), (14.0, 0.0)] + segment_2 = [(14.0, 0.0), (10.0, 4.0), (4.0, 6.0), (2.0, 12.0), (0.0, 14.0)] + segment_3 = [(0.0, 14.0), (0.0, 0.0)] + boundary_points = [segment_1, segment_2, segment_3] + boundary_nodes, points = convert_boundary_points_to_indices(boundary_points; existing_points = points) + tri = triangulate(points; boundary_nodes) + @test DT.is_positively_oriented(tri, 1) + + curve_1 = [ + [ (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), (-4.0, 0.0), (0.0, 0.0), - ]] - curve_2 = [[ + ], + ] + curve_2 = [ + [ (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ]] - curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] - curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] - curves = [curve_1, curve_2, curve_3, curve_4] - points = [ - (2.0, 26.0), (2.0, 24.0), (6.0, 24.0), (6.0, 22.0), (8.0, 24.0), (8.0, 22.0), - (2.0, 22.0), (0.0, 26.0), (10.0, 18.0), (8.0, 18.0), (4.0, 18.0), (2.0, 16.0), - (2.0, 12.0), (6.0, 12.0), (2.0, 8.0), (2.0, 4.0), (4.0, 2.0), - (-2.0, 2.0), (4.0, 6.0), (10.0, 2.0), (10.0, 6.0), (8.0, 10.0), (4.0, 10.0), - (10.0, 12.0), (12.0, 12.0), (14.0, 26.0), (16.0, 24.0), (18.0, 28.0), - (16.0, 20.0), (18.0, 12.0), (16.0, 8.0), (14.0, 4.0), (14.0, -2.0), - (6.0, -2.0), (2.0, -4.0), (-4.0, -2.0), (-2.0, 8.0), (-2.0, 16.0), - (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), - (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), - (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] - boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) - tri = triangulate(points; boundary_nodes=boundary_nodes) - @test DT.is_positively_oriented(tri, 1) - @test !DT.is_positively_oriented(tri, 2) - @test !DT.is_positively_oriented(tri, 3) - @test !DT.is_positively_oriented(tri, 4) - - curve_1 = [ - [(0.0, 0.0), (5.0, 0.0), (10.0, 0.0), (15.0, 0.0), (20.0, 0.0), (25.0, 0.0)], - [(25.0, 0.0), (25.0, 5.0), (25.0, 10.0), (25.0, 15.0), (25.0, 20.0), (25.0, 25.0)], - [(25.0, 25.0), (20.0, 25.0), (15.0, 25.0), (10.0, 25.0), (5.0, 25.0), (0.0, 25.0)], - [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)] - ] # outer-most boundary: counter-clockwise - curve_2 = [ - [(4.0, 6.0), (4.0, 14.0), (4.0, 20.0), (18.0, 20.0), (20.0, 20.0)], - [(20.0, 20.0), (20.0, 16.0), (20.0, 12.0), (20.0, 8.0), (20.0, 4.0)], - [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)] - ] # inner boundary: clockwise - curve_3 = [ - [(12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), - (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912)] - ] # this is inside curve_2, so it's counter-clockwise - curves = [curve_1, curve_2, curve_3] - points = [ - (3.0, 23.0), (9.0, 24.0), (9.2, 22.0), (14.8, 22.8), (16.0, 22.0), - (23.0, 23.0), (22.6, 19.0), (23.8, 17.8), (22.0, 14.0), (22.0, 11.0), - (24.0, 6.0), (23.0, 2.0), (19.0, 1.0), (16.0, 3.0), (10.0, 1.0), (11.0, 3.0), - (6.0, 2.0), (6.2, 3.0), (2.0, 3.0), (2.6, 6.2), (2.0, 8.0), (2.0, 11.0), - (5.0, 12.0), (2.0, 17.0), (3.0, 19.0), (6.0, 18.0), (6.5, 14.5), - (13.0, 19.0), (13.0, 12.0), (16.0, 8.0), (9.8, 8.0), (7.5, 6.0), - (12.0, 13.0), (19.0, 15.0) - ] - boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) - tri = triangulate(points; boundary_nodes=boundary_nodes) - @test DT.is_positively_oriented(tri, 1) - @test !DT.is_positively_oriented(tri, 2) - @test DT.is_positively_oriented(tri, 3) - - θ = LinRange(0, 2π, 20) |> collect - θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 - xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() - cx = 0.0 - for i in 1:2 - # Make the exterior circle - push!(xy, [[(cx + cos(θ), sin(θ)) for θ in θ]]) - # Now the interior circle - clockwise - push!(xy, [[(cx + 0.5cos(θ), 0.5sin(θ)) for θ in reverse(θ)]]) - cx += 3.0 - end - boundary_nodes, points = convert_boundary_points_to_indices(xy) - tri = triangulate(points; boundary_nodes=boundary_nodes) - @test DT.is_positively_oriented(tri, 1) - @test !DT.is_positively_oriented(tri, 2) - @test DT.is_positively_oriented(tri, 3) - @test !DT.is_positively_oriented(tri, 4) - - C = (15.7109521325776, 33.244486807457) - D = (14.2705719699703, 32.8530791545746) - E = (14.3, 27.2) - F = (14.1, 27.0) - G = (13.7, 27.2) - H = (13.4, 27.5) - I = (13.1, 27.6) - J = (12.7, 27.4) - K = (12.5, 27.1) - L = (12.7, 26.7) - M = (13.1, 26.5) - N = (13.6, 26.4) - O = (14.0, 26.4) - P = (14.6, 26.5) - Q = (15.1983491346581, 26.8128534095401) - R = (15.6, 27.6) - S = (15.6952958264624, 28.2344688505621) - T = (17.8088971520274, 33.1192363585346) - U = (16.3058917649589, 33.0722674401887) - V = (16.3215480710742, 29.7374742376305) - W = (16.3841732955354, 29.393035503094) - Z = (16.6190178872649, 28.9233463196351) - A1 = (17.0417381523779, 28.5319386667527) - B1 = (17.5114273358368, 28.3753756055997) - C1 = (18.1376795804487, 28.3597192994844) - D1 = (18.7169629067146, 28.5632512789833) - E1 = (19.2805899268653, 28.8920337074045) - F1 = (19.26493362075, 28.4536571361762) - G1 = (20.6426885588962, 28.4223445239456) - H1 = (20.689657477242, 33.1035800524193) - I1 = (19.2805899268653, 33.0722674401887) - J1 = (19.2962462329806, 29.7531305437458) - K1 = (19.0614016412512, 29.393035503094) - L1 = (18.7482755189452, 29.236472441941) - M1 = (18.4508057027546, 29.1425346052493) - N1 = (18.1689921926793, 29.3147539725175) - O1 = (17.7932408459121, 29.6278800948235) - P1 = (22.6466957416542, 35.4207133574833) - Q1 = (21.2219718851621, 34.9979930923702) - R1 = (21.2376281912774, 28.4693134422915) - S1 = (22.6780083538847, 28.4380008300609) - T1 = (24.5724213938357, 33.1975178891111) - U1 = (23.3512295168425, 32.8530791545746) - V1 = (23.3199169046119, 28.4380008300609) - W1 = (24.6663592305274, 28.3753756055997) - Z1 = (15.1942940307729, 35.4363696635986) - A2 = (14.7246048473139, 35.3737444391374) - B2 = (14.3645098066621, 35.1858687657538) - C2 = (14.1766341332786, 34.8570863373326) - D2 = (14.1140089088174, 34.3247719294125) - E2 = (14.2705719699703, 33.8394264398383) - F2 = (14.7246048473139, 33.6202381542241) - G2 = (15.4604512347329, 33.6045818481088) - H2 = (16.0, 34.0) - I2 = (15.9771093365377, 34.6848669700643) - J2 = (15.6170142958859, 35.2328376840997) - K2 = (24.1653574348379, 35.4520259697138) - L2 = (23.7739497819555, 35.4363696635986) - M2 = (23.4608236596496, 35.2641502963303) - N2 = (23.272947986266, 34.9040552556785) - O2 = (23.1320412312284, 34.5909291333725) - P2 = (23.1163849251131, 34.2151777866054) - Q2 = (23.2886042923813, 33.8081138276077) - R2 = (23.8209187003014, 33.6045818481088) - S2 = (24.3062641898756, 33.5576129297629) - T2 = (24.7602970672192, 33.8550827459536) - U2 = (25.010797965064, 34.4656786844502) - V2 = (24.8385785977957, 34.9666804801397) - W2 = (24.5254524754898, 35.2641502963303) - Z2 = (25.3708930057158, 37.4716894585871) - A3 = (24.7916096794498, 37.3464390096648) - B3 = (24.4471709449133, 36.9550313567823) - C3 = (24.3062641898756, 36.5636237038999) - D3 = (24.4941398632592, 35.9999966837492) - E3 = (25.0264542711793, 35.5929327247515) - F3 = (25.5587686790994, 35.5929327247515) - F3 = (25.5587686790994, 35.5929327247515) - G3 = (26.0, 36.0) - H3 = (26.1380520053653, 36.5792800100152) - I3 = (26.0, 37.0) - J3 = (25.7466443524829, 37.2838137852036) - K3 = (26.3885529032101, 35.4676822758291) - L3 = (25.9814889442124, 35.3580881330221) - M3 = (25.6840191280217, 35.1858687657538) - N3 = (25.5274560668688, 34.9040552556785) - O3 = (25.4961434546382, 34.5596165211419) - P3 = (25.5274560668688, 34.246490398836) - Q3 = (25.6683628219064, 33.8394264398383) - R3 = (26.0284578625583, 33.6358944603394) - S3 = (26.5451159643631, 33.6202381542241) - T3 = (27.0, 34.0) - U3 = (27.280962351782, 34.5596165211419) - V3 = (27.0304614539373, 35.2171813779844) - W3 = (26.1693646175959, 33.087923746304) - Z3 = (26.0, 33.0) - A4 = (25.5274560668688, 32.7278287056522) - B4 = (25.2612988629087, 32.4147025833463) - C4 = (25.1830173323322, 32.0702638488098) - D4 = (25.2299862506781, 31.7727940326191) - E4 = (25.6527065157911, 31.5222931347744) - F4 = (26.2946150665183, 31.7258251142732) - G4 = (26.5607722704784, 32.5086404200381) - H4 = (27.1557119028596, 32.7434850117675) - I4 = (27.6097447802033, 32.4929841139228) - J4 = (27.6410573924338, 32.1015764610403) - K4 = (27.7193389230103, 31.6005746653509) - L4 = (27.437525412935, 31.4283552980826) - M4 = (26.9834925355914, 31.2561359308143) - N4 = (26.5764285765937, 31.0995728696614) - O4 = (26.0441141686736, 30.7864467473554) - P4 = (25.6527065157911, 30.5672584617413) - Q4 = (25.3239240873699, 30.1915071149741) - R4 = (25.1673610262169, 29.8783809926682) - S4 = (25.1047358017558, 29.6122237887082) - T4 = (25.0890794956405, 29.1895035235952) - U4 = (25.2926114751393, 28.8294084829433) - V4 = (25.6840191280217, 28.5632512789833) - W4 = (26.1537083114806, 28.3753756055997) - Z4 = (26.8269294744384, 28.391031911715) - A5 = (27.4844943312809, 28.6102201973292) - B5 = (27.7342002330051, 28.7239579596219) - C5 = (27.7264126450755, 28.4202565942047) - D5 = (29.1825559185446, 28.3922538389457) - E5 = (29.1545531632856, 32.2146299318021) - F5 = (29.000538009361, 32.5786657501693) - G5 = (28.6785063238822, 32.9006974356481) - H5 = (28.3144705055149, 33.0827153448317) - I5 = (27.9084305542591, 33.2367304987563) - J5 = (27.3343740714492, 33.3207387645334) - K5 = (26.8303244767868, 33.2367304987563) - L5 = (27.6564057569279, 30.786489413592) - M5 = (27.6984098898165, 30.3944508399657) - N5 = (27.6984098898165, 29.7363860913787) - O5 = (27.5863988687804, 29.4143544059) - P5 = (27.2643671833016, 29.2043337414573) - Q5 = (26.9843396307114, 29.1763309861983) - R5 = (26.6903107004917, 29.3163447624934) - S5 = (26.5782996794556, 29.7503874690082) - T5 = (26.7603175886393, 30.3384453294476) - U5 = (27.3203726938197, 30.7024811478149) - J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] - U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] - L_curve = [[P1, Q1, R1, S1, P1]] - I_curve = [[T1, U1, V1, W1, T1]] - A_curve_outline = [[ + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], + ] + curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] + curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] + curves = [curve_1, curve_2, curve_3, curve_4] + points = [ + (2.0, 26.0), (2.0, 24.0), (6.0, 24.0), (6.0, 22.0), (8.0, 24.0), (8.0, 22.0), + (2.0, 22.0), (0.0, 26.0), (10.0, 18.0), (8.0, 18.0), (4.0, 18.0), (2.0, 16.0), + (2.0, 12.0), (6.0, 12.0), (2.0, 8.0), (2.0, 4.0), (4.0, 2.0), + (-2.0, 2.0), (4.0, 6.0), (10.0, 2.0), (10.0, 6.0), (8.0, 10.0), (4.0, 10.0), + (10.0, 12.0), (12.0, 12.0), (14.0, 26.0), (16.0, 24.0), (18.0, 28.0), + (16.0, 20.0), (18.0, 12.0), (16.0, 8.0), (14.0, 4.0), (14.0, -2.0), + (6.0, -2.0), (2.0, -4.0), (-4.0, -2.0), (-2.0, 8.0), (-2.0, 16.0), + (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), + (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), + (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), + (7.0, 7.8), (7.0, 7.4), + ] + boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) + tri = triangulate(points; boundary_nodes = boundary_nodes) + @test DT.is_positively_oriented(tri, 1) + @test !DT.is_positively_oriented(tri, 2) + @test !DT.is_positively_oriented(tri, 3) + @test !DT.is_positively_oriented(tri, 4) + + curve_1 = [ + [(0.0, 0.0), (5.0, 0.0), (10.0, 0.0), (15.0, 0.0), (20.0, 0.0), (25.0, 0.0)], + [(25.0, 0.0), (25.0, 5.0), (25.0, 10.0), (25.0, 15.0), (25.0, 20.0), (25.0, 25.0)], + [(25.0, 25.0), (20.0, 25.0), (15.0, 25.0), (10.0, 25.0), (5.0, 25.0), (0.0, 25.0)], + [(0.0, 25.0), (0.0, 20.0), (0.0, 15.0), (0.0, 10.0), (0.0, 5.0), (0.0, 0.0)], + ] # outer-most boundary: counter-clockwise + curve_2 = [ + [(4.0, 6.0), (4.0, 14.0), (4.0, 20.0), (18.0, 20.0), (20.0, 20.0)], + [(20.0, 20.0), (20.0, 16.0), (20.0, 12.0), (20.0, 8.0), (20.0, 4.0)], + [(20.0, 4.0), (16.0, 4.0), (12.0, 4.0), (8.0, 4.0), (4.0, 4.0), (4.0, 6.0)], + ] # inner boundary: clockwise + curve_3 = [ + [ + (12.906, 10.912), (16.0, 12.0), (16.16, 14.46), (16.29, 17.06), + (13.13, 16.86), (8.92, 16.4), (8.8, 10.9), (12.906, 10.912), + ], + ] # this is inside curve_2, so it's counter-clockwise + curves = [curve_1, curve_2, curve_3] + points = [ + (3.0, 23.0), (9.0, 24.0), (9.2, 22.0), (14.8, 22.8), (16.0, 22.0), + (23.0, 23.0), (22.6, 19.0), (23.8, 17.8), (22.0, 14.0), (22.0, 11.0), + (24.0, 6.0), (23.0, 2.0), (19.0, 1.0), (16.0, 3.0), (10.0, 1.0), (11.0, 3.0), + (6.0, 2.0), (6.2, 3.0), (2.0, 3.0), (2.6, 6.2), (2.0, 8.0), (2.0, 11.0), + (5.0, 12.0), (2.0, 17.0), (3.0, 19.0), (6.0, 18.0), (6.5, 14.5), + (13.0, 19.0), (13.0, 12.0), (16.0, 8.0), (9.8, 8.0), (7.5, 6.0), + (12.0, 13.0), (19.0, 15.0), + ] + boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) + tri = triangulate(points; boundary_nodes = boundary_nodes) + @test DT.is_positively_oriented(tri, 1) + @test !DT.is_positively_oriented(tri, 2) + @test DT.is_positively_oriented(tri, 3) + + θ = LinRange(0, 2π, 20) |> collect + θ[end] = 0 # need to make sure that 2π gives the exact same coordinates as 0 + xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() + cx = 0.0 + for i in 1:2 + # Make the exterior circle + push!(xy, [[(cx + cos(θ), sin(θ)) for θ in θ]]) + # Now the interior circle - clockwise + push!(xy, [[(cx + 0.5cos(θ), 0.5sin(θ)) for θ in reverse(θ)]]) + cx += 3.0 + end + boundary_nodes, points = convert_boundary_points_to_indices(xy) + tri = triangulate(points; boundary_nodes = boundary_nodes) + @test DT.is_positively_oriented(tri, 1) + @test !DT.is_positively_oriented(tri, 2) + @test DT.is_positively_oriented(tri, 3) + @test !DT.is_positively_oriented(tri, 4) + + C = (15.7109521325776, 33.244486807457) + D = (14.2705719699703, 32.8530791545746) + E = (14.3, 27.2) + F = (14.1, 27.0) + G = (13.7, 27.2) + H = (13.4, 27.5) + I = (13.1, 27.6) + J = (12.7, 27.4) + K = (12.5, 27.1) + L = (12.7, 26.7) + M = (13.1, 26.5) + N = (13.6, 26.4) + O = (14.0, 26.4) + P = (14.6, 26.5) + Q = (15.1983491346581, 26.8128534095401) + R = (15.6, 27.6) + S = (15.6952958264624, 28.2344688505621) + T = (17.8088971520274, 33.1192363585346) + U = (16.3058917649589, 33.0722674401887) + V = (16.3215480710742, 29.7374742376305) + W = (16.3841732955354, 29.393035503094) + Z = (16.6190178872649, 28.9233463196351) + A1 = (17.0417381523779, 28.5319386667527) + B1 = (17.5114273358368, 28.3753756055997) + C1 = (18.1376795804487, 28.3597192994844) + D1 = (18.7169629067146, 28.5632512789833) + E1 = (19.2805899268653, 28.8920337074045) + F1 = (19.26493362075, 28.4536571361762) + G1 = (20.6426885588962, 28.4223445239456) + H1 = (20.689657477242, 33.1035800524193) + I1 = (19.2805899268653, 33.0722674401887) + J1 = (19.2962462329806, 29.7531305437458) + K1 = (19.0614016412512, 29.393035503094) + L1 = (18.7482755189452, 29.236472441941) + M1 = (18.4508057027546, 29.1425346052493) + N1 = (18.1689921926793, 29.3147539725175) + O1 = (17.7932408459121, 29.6278800948235) + P1 = (22.6466957416542, 35.4207133574833) + Q1 = (21.2219718851621, 34.9979930923702) + R1 = (21.2376281912774, 28.4693134422915) + S1 = (22.6780083538847, 28.4380008300609) + T1 = (24.5724213938357, 33.1975178891111) + U1 = (23.3512295168425, 32.8530791545746) + V1 = (23.3199169046119, 28.4380008300609) + W1 = (24.6663592305274, 28.3753756055997) + Z1 = (15.1942940307729, 35.4363696635986) + A2 = (14.7246048473139, 35.3737444391374) + B2 = (14.3645098066621, 35.1858687657538) + C2 = (14.1766341332786, 34.8570863373326) + D2 = (14.1140089088174, 34.3247719294125) + E2 = (14.2705719699703, 33.8394264398383) + F2 = (14.7246048473139, 33.6202381542241) + G2 = (15.4604512347329, 33.6045818481088) + H2 = (16.0, 34.0) + I2 = (15.9771093365377, 34.6848669700643) + J2 = (15.6170142958859, 35.2328376840997) + K2 = (24.1653574348379, 35.4520259697138) + L2 = (23.7739497819555, 35.4363696635986) + M2 = (23.4608236596496, 35.2641502963303) + N2 = (23.272947986266, 34.9040552556785) + O2 = (23.1320412312284, 34.5909291333725) + P2 = (23.1163849251131, 34.2151777866054) + Q2 = (23.2886042923813, 33.8081138276077) + R2 = (23.8209187003014, 33.6045818481088) + S2 = (24.3062641898756, 33.5576129297629) + T2 = (24.7602970672192, 33.8550827459536) + U2 = (25.010797965064, 34.4656786844502) + V2 = (24.8385785977957, 34.9666804801397) + W2 = (24.5254524754898, 35.2641502963303) + Z2 = (25.3708930057158, 37.4716894585871) + A3 = (24.7916096794498, 37.3464390096648) + B3 = (24.4471709449133, 36.9550313567823) + C3 = (24.3062641898756, 36.5636237038999) + D3 = (24.4941398632592, 35.9999966837492) + E3 = (25.0264542711793, 35.5929327247515) + F3 = (25.5587686790994, 35.5929327247515) + F3 = (25.5587686790994, 35.5929327247515) + G3 = (26.0, 36.0) + H3 = (26.1380520053653, 36.5792800100152) + I3 = (26.0, 37.0) + J3 = (25.7466443524829, 37.2838137852036) + K3 = (26.3885529032101, 35.4676822758291) + L3 = (25.9814889442124, 35.3580881330221) + M3 = (25.6840191280217, 35.1858687657538) + N3 = (25.5274560668688, 34.9040552556785) + O3 = (25.4961434546382, 34.5596165211419) + P3 = (25.5274560668688, 34.246490398836) + Q3 = (25.6683628219064, 33.8394264398383) + R3 = (26.0284578625583, 33.6358944603394) + S3 = (26.5451159643631, 33.6202381542241) + T3 = (27.0, 34.0) + U3 = (27.280962351782, 34.5596165211419) + V3 = (27.0304614539373, 35.2171813779844) + W3 = (26.1693646175959, 33.087923746304) + Z3 = (26.0, 33.0) + A4 = (25.5274560668688, 32.7278287056522) + B4 = (25.2612988629087, 32.4147025833463) + C4 = (25.1830173323322, 32.0702638488098) + D4 = (25.2299862506781, 31.7727940326191) + E4 = (25.6527065157911, 31.5222931347744) + F4 = (26.2946150665183, 31.7258251142732) + G4 = (26.5607722704784, 32.5086404200381) + H4 = (27.1557119028596, 32.7434850117675) + I4 = (27.6097447802033, 32.4929841139228) + J4 = (27.6410573924338, 32.1015764610403) + K4 = (27.7193389230103, 31.6005746653509) + L4 = (27.437525412935, 31.4283552980826) + M4 = (26.9834925355914, 31.2561359308143) + N4 = (26.5764285765937, 31.0995728696614) + O4 = (26.0441141686736, 30.7864467473554) + P4 = (25.6527065157911, 30.5672584617413) + Q4 = (25.3239240873699, 30.1915071149741) + R4 = (25.1673610262169, 29.8783809926682) + S4 = (25.1047358017558, 29.6122237887082) + T4 = (25.0890794956405, 29.1895035235952) + U4 = (25.2926114751393, 28.8294084829433) + V4 = (25.6840191280217, 28.5632512789833) + W4 = (26.1537083114806, 28.3753756055997) + Z4 = (26.8269294744384, 28.391031911715) + A5 = (27.4844943312809, 28.6102201973292) + B5 = (27.7342002330051, 28.7239579596219) + C5 = (27.7264126450755, 28.4202565942047) + D5 = (29.1825559185446, 28.3922538389457) + E5 = (29.1545531632856, 32.2146299318021) + F5 = (29.000538009361, 32.5786657501693) + G5 = (28.6785063238822, 32.9006974356481) + H5 = (28.3144705055149, 33.0827153448317) + I5 = (27.9084305542591, 33.2367304987563) + J5 = (27.3343740714492, 33.3207387645334) + K5 = (26.8303244767868, 33.2367304987563) + L5 = (27.6564057569279, 30.786489413592) + M5 = (27.6984098898165, 30.3944508399657) + N5 = (27.6984098898165, 29.7363860913787) + O5 = (27.5863988687804, 29.4143544059) + P5 = (27.2643671833016, 29.2043337414573) + Q5 = (26.9843396307114, 29.1763309861983) + R5 = (26.6903107004917, 29.3163447624934) + S5 = (26.5782996794556, 29.7503874690082) + T5 = (26.7603175886393, 30.3384453294476) + U5 = (27.3203726938197, 30.7024811478149) + J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] + U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] + L_curve = [[P1, Q1, R1, S1, P1]] + I_curve = [[T1, U1, V1, W1, T1]] + A_curve_outline = [ + [ K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] - A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] - dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] - dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] - dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] - dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] - curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] - nodes, points = convert_boundary_points_to_indices(curves) - tri = triangulate(points; boundary_nodes=nodes) - @test DT.is_positively_oriented(tri, 1) - @test DT.is_positively_oriented(tri, 2) - @test DT.is_positively_oriented(tri, 3) - @test DT.is_positively_oriented(tri, 4) - @test DT.is_positively_oriented(tri, 5) - @test !DT.is_positively_oriented(tri, 6) - @test DT.is_positively_oriented(tri, 7) - @test DT.is_positively_oriented(tri, 8) - @test DT.is_positively_oriented(tri, 9) - @test DT.is_positively_oriented(tri, 10) - @test DT.num_curves(tri) == 10 + H5, I5, J5, K5, + ], + ] + A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] + dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] + dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] + dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] + dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] + curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] + nodes, points = convert_boundary_points_to_indices(curves) + tri = triangulate(points; boundary_nodes = nodes) + @test DT.is_positively_oriented(tri, 1) + @test DT.is_positively_oriented(tri, 2) + @test DT.is_positively_oriented(tri, 3) + @test DT.is_positively_oriented(tri, 4) + @test DT.is_positively_oriented(tri, 5) + @test !DT.is_positively_oriented(tri, 6) + @test DT.is_positively_oriented(tri, 7) + @test DT.is_positively_oriented(tri, 8) + @test DT.is_positively_oriented(tri, 9) + @test DT.is_positively_oriented(tri, 10) + @test DT.num_curves(tri) == 10 end @testset "Full constructor" begin - # Simple example - tri1 = triangulate(rand(2, 50)) - tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1)) - unlock_convex_hull!(tri2) - @test tri1 == tri2 - - # With boundaries - points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.2, 0.2), (0.8, 0.2), (0.8, 0.8), (0.2, 0.8)] - boundary_nodes = [[[1, 2], [2, 3], [3, 4], [4, 1]], [[8, 7], [7, 6], [6, 5], [5, 8]]] - tri1 = triangulate(points; boundary_nodes) - tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_boundary_nodes(tri1)) - @test tri1 == tri2 - - # Custom types - tri1 = triangulate(rand(2, 50); IntegerType=Int32) - tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1); IntegerType=Int32) - unlock_convex_hull!(tri2) - @test tri1 == tri2 - @test tri1 ⊢ tri2 - - # Delete ghosts works properly - tri1 = triangulate(rand(2, 50), delete_ghosts=true) - tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1), delete_ghosts=true) - unlock_convex_hull!(tri2) - @test tri1 == tri2 - - # Weights work properly - weights = rand(50) - tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1), weights=weights) - @test DT.is_weighted(tri2) && get_weights(tri2) == weights + # Simple example + tri1 = triangulate(rand(2, 50)) + tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1)) + unlock_convex_hull!(tri2) + @test tri1 == tri2 + + # With boundaries + points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.2, 0.2), (0.8, 0.2), (0.8, 0.8), (0.2, 0.8)] + boundary_nodes = [[[1, 2], [2, 3], [3, 4], [4, 1]], [[8, 7], [7, 6], [6, 5], [5, 8]]] + tri1 = triangulate(points; boundary_nodes) + tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_boundary_nodes(tri1)) + @test tri1 == tri2 + + # Custom types + tri1 = triangulate(rand(2, 50); IntegerType = Int32) + tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1); IntegerType = Int32) + unlock_convex_hull!(tri2) + @test tri1 == tri2 + @test tri1 ⊢ tri2 + + # Delete ghosts works properly + tri1 = triangulate(rand(2, 50), delete_ghosts = true) + tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1), delete_ghosts = true) + unlock_convex_hull!(tri2) + @test tri1 == tri2 + + # Weights work properly + weights = rand(50) + tri2 = Triangulation(get_points(tri1), each_solid_triangle(tri1), get_convex_hull_vertices(tri1), weights = weights) + @test DT.is_weighted(tri2) && get_weights(tri2) == weights end @testset "Random sampling of triangles, edges, and vertices" begin - # Get the triangulation - A = (0.0, 0.0) - B = (0.0, 25.0) - C = (5.0, 25.0) - D = (5.0, 5.0) - E = (10.0, 5.0) - F = (10.0, 10.0) - G = (25.0, 10.0) - H = (25.0, 15.0) - I = (10.0, 15.0) - J = (10.0, 25.0) - K = (45.0, 25.0) - L = (45.0, 20.0) - M = (40.0, 20.0) - N = (40.0, 5.0) - O = (45.0, 5.0) - P = (45.0, 0.0) - Q = (10.0, 0.0) - R = (10.0, -5.0) - S = (15.0, -5.0) - T = (15.0, -10.0) - U = (10.0, -10.0) - V = (5.0, -10.0) - W = (5.0, -5.0) - Z = (5.0, 0.0) - A1 = (5.0, 2.5) - B1 = (10.0, 2.5) - C1 = (38.0, 2.5) - D1 = (38.0, 20.0) - E1 = (27.0, 20.0) - F1 = (27.0, 11.0) - G1 = (27.0, 4.0) - H1 = (2.0, 4.0) - I1 = (2.0, 0.0) - pts = [A, I1, H1, G1, F1, E1, D1, C1, B1, A1, Z, W, V, U, T, S, R, Q, P, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A] - J1 = (17.0603265896789, 7.623652007194) - K1 = (14.8552854162067, 6.5423337394336) - L1 = (16.6998871670921, 6.9875824379232) - M1 = (16.0, 6.0) - N1 = (16.9755173137761, 6.6483453343121) - O1 = (17.0391242707032, 4.8885528593294) - P1 = (17.4207660122657, 6.4575244635308) - Q1 = (17.6327892020226, 4.9945644542079) - R1 = (22.6789411182379, 6.1818943168468) - S1 = (21.8096460402344, 6.4787267825065) - T1 = (26.0, 8.0) - U1 = (15.0673086059636, 9.086612016517) - W1 = (15.0, 8.5) - Z1 = (17.7913089332764, 8.3603005983396) - inner_pts = [Z1, W1, U1, T1, S1, R1, Q1, P1, O1, N1, M1, L1, K1, J1, Z1] - boundary_pts = [[pts], [inner_pts]] - nodes, points = convert_boundary_points_to_indices(boundary_pts) - push!(points, (20.0, 20.0)) - rng = StableRNG(19191919) - C = Set{NTuple{2,Int}}() - for i in 1:50 - θ = 2π * rand(rng) - r = 4sqrt(rand(rng)) - x = 20 + r * cos(θ) - y = 20 + r * sin(θ) - push!(points, (x, y)) - push!(C, (48, 48 + i)) - end - tri = triangulate(points; boundary_nodes=nodes, segments=C, rng) - - # Vertices - ns = 5_000_000 - function test_vertex_sampler(tri, ns) - solid_vertices = DefaultDict{Int,Float64,Float64}(0.0) - ghost_vertices = DefaultDict{Int,Float64,Float64}(0.0) - for _ in 1:ns - sv = rand(each_solid_vertex(tri)) - gv = rand(each_ghost_vertex(tri)) - solid_vertices[sv] += 1 / ns - ghost_vertices[gv] += 1 / ns - end - return solid_vertices, ghost_vertices - end - solid_vertices, ghost_vertices = test_vertex_sampler(tri, ns) - @inferred rand(each_solid_vertex(tri)) - @inferred rand(each_ghost_vertex(tri)) - @test all(!DT.is_ghost_vertex, keys(solid_vertices)) - @test all(DT.is_ghost_vertex, keys(ghost_vertices)) - sm = mean(values(solid_vertices)) # sm for solid mean - gm = mean(values(ghost_vertices)) - @test sm ≈ 1 / DT.num_solid_vertices(tri) - @test gm ≈ 1 / 2 - @test all(y -> isapprox(y, sm, rtol=1e-1), values(solid_vertices)) - @test all(y -> isapprox(y, gm, rtol=1e-1), values(ghost_vertices)) - for i in 1:250 - for f in (each_vertex, each_solid_vertex, each_ghost_vertex) - rng = StableRNG(i) - V1 = rand(rng, f(tri)) - V2 = rand(rng, f(tri)) - V3 = rand(rng, f(tri)) - rng = StableRNG(i) - @test rand(rng, f(tri)) == V1 - @test rand(rng, f(tri)) == V2 - @test rand(rng, f(tri)) == V3 - end - end - - # Triangles - ns = 5_000_000 - function test_triangle_sampler(tri, ns) - solid_triangles = DefaultDict{NTuple{3,Int},Float64,Float64}(0.0) - ghost_triangles = DefaultDict{NTuple{3,Int},Float64,Float64}(0.0) - for _ in 1:ns - st = rand(each_solid_triangle(tri)) - gt = rand(each_ghost_triangle(tri)) - solid_triangles[st] += 1 / ns - ghost_triangles[gt] += 1 / ns - end - return solid_triangles, ghost_triangles - end - solid_triangles, ghost_triangles = test_triangle_sampler(tri, ns) - @inferred rand(each_solid_triangle(tri)) - @inferred rand(each_ghost_triangle(tri)) - @test all(!DT.is_ghost_triangle, keys(solid_triangles)) - @test all(DT.is_ghost_triangle, keys(ghost_triangles)) - sm = mean(values(solid_triangles)) # sm for solid mean - gm = mean(values(ghost_triangles)) - @test sm ≈ 1 / DT.num_solid_triangles(tri) - @test gm ≈ 1 / DT.num_ghost_triangles(tri) - @test all(y -> isapprox(y, sm, rtol=1e-1), values(solid_triangles)) - @test all(y -> isapprox(y, gm, rtol=1e-1), values(ghost_triangles)) - for i in 1:250 - for f in (each_triangle, each_solid_triangle, each_ghost_triangle) - rng = StableRNG(i) - V1 = rand(rng, f(tri)) - V2 = rand(rng, f(tri)) - V3 = rand(rng, f(tri)) - rng = StableRNG(i) - @test rand(rng, f(tri)) == V1 - @test rand(rng, f(tri)) == V2 - @test rand(rng, f(tri)) == V3 - end - end - - # Edges - ns = 5_000_000 - function test_edge_sampler(tri, ns) - solid_edges = DefaultDict{NTuple{2,Int},Float64,Float64}(0.0) - ghost_edges = DefaultDict{NTuple{2,Int},Float64,Float64}(0.0) - for _ in 1:ns - se = rand(each_solid_edge(tri)) - ge = rand(each_ghost_edge(tri)) - solid_edges[se] += 1 / ns - ghost_edges[ge] += 1 / ns - end - return solid_edges, ghost_edges - end - solid_edges, ghost_edges = test_edge_sampler(tri, ns) - @inferred rand(each_solid_edge(tri)) - @inferred rand(each_ghost_edge(tri)) - @test all(!DT.is_ghost_edge, keys(solid_edges)) - @test all(DT.is_ghost_edge, keys(ghost_edges)) - sm = mean(values(solid_edges)) # sm for solid mean - gm = mean(values(ghost_edges)) - @test sm ≈ 1 / DT.num_solid_edges(tri) - @test gm ≈ 1 / DT.num_ghost_edges(tri) - @test all(y -> isapprox(y, sm, rtol=1e-1), values(solid_edges)) - @test all(y -> isapprox(y, gm, rtol=1e-1), values(ghost_edges)) - for i in 1:250 - for f in (each_edge, each_solid_edge, each_ghost_edge) - rng = StableRNG(i) - V1 = rand(rng, f(tri)) - V2 = rand(rng, f(tri)) - rng = StableRNG(i) - @test rand(rng, f(tri)) == V1 - @test rand(rng, f(tri)) == V2 - end - end -end \ No newline at end of file + # Get the triangulation + A = (0.0, 0.0) + B = (0.0, 25.0) + C = (5.0, 25.0) + D = (5.0, 5.0) + E = (10.0, 5.0) + F = (10.0, 10.0) + G = (25.0, 10.0) + H = (25.0, 15.0) + I = (10.0, 15.0) + J = (10.0, 25.0) + K = (45.0, 25.0) + L = (45.0, 20.0) + M = (40.0, 20.0) + N = (40.0, 5.0) + O = (45.0, 5.0) + P = (45.0, 0.0) + Q = (10.0, 0.0) + R = (10.0, -5.0) + S = (15.0, -5.0) + T = (15.0, -10.0) + U = (10.0, -10.0) + V = (5.0, -10.0) + W = (5.0, -5.0) + Z = (5.0, 0.0) + A1 = (5.0, 2.5) + B1 = (10.0, 2.5) + C1 = (38.0, 2.5) + D1 = (38.0, 20.0) + E1 = (27.0, 20.0) + F1 = (27.0, 11.0) + G1 = (27.0, 4.0) + H1 = (2.0, 4.0) + I1 = (2.0, 0.0) + pts = [A, I1, H1, G1, F1, E1, D1, C1, B1, A1, Z, W, V, U, T, S, R, Q, P, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A] + J1 = (17.0603265896789, 7.623652007194) + K1 = (14.8552854162067, 6.5423337394336) + L1 = (16.6998871670921, 6.9875824379232) + M1 = (16.0, 6.0) + N1 = (16.9755173137761, 6.6483453343121) + O1 = (17.0391242707032, 4.8885528593294) + P1 = (17.4207660122657, 6.4575244635308) + Q1 = (17.6327892020226, 4.9945644542079) + R1 = (22.6789411182379, 6.1818943168468) + S1 = (21.8096460402344, 6.4787267825065) + T1 = (26.0, 8.0) + U1 = (15.0673086059636, 9.086612016517) + W1 = (15.0, 8.5) + Z1 = (17.7913089332764, 8.3603005983396) + inner_pts = [Z1, W1, U1, T1, S1, R1, Q1, P1, O1, N1, M1, L1, K1, J1, Z1] + boundary_pts = [[pts], [inner_pts]] + nodes, points = convert_boundary_points_to_indices(boundary_pts) + push!(points, (20.0, 20.0)) + rng = StableRNG(19191919) + C = Set{NTuple{2, Int}}() + for i in 1:50 + θ = 2π * rand(rng) + r = 4sqrt(rand(rng)) + x = 20 + r * cos(θ) + y = 20 + r * sin(θ) + push!(points, (x, y)) + push!(C, (48, 48 + i)) + end + tri = triangulate(points; boundary_nodes = nodes, segments = C, rng) + + # Vertices + ns = 5_000_000 + function test_vertex_sampler(tri, ns) + solid_vertices = DefaultDict{Int, Float64, Float64}(0.0) + ghost_vertices = DefaultDict{Int, Float64, Float64}(0.0) + for _ in 1:ns + sv = rand(each_solid_vertex(tri)) + gv = rand(each_ghost_vertex(tri)) + solid_vertices[sv] += 1 / ns + ghost_vertices[gv] += 1 / ns + end + return solid_vertices, ghost_vertices + end + solid_vertices, ghost_vertices = test_vertex_sampler(tri, ns) + @inferred rand(each_solid_vertex(tri)) + @inferred rand(each_ghost_vertex(tri)) + @test all(!DT.is_ghost_vertex, keys(solid_vertices)) + @test all(DT.is_ghost_vertex, keys(ghost_vertices)) + sm = mean(values(solid_vertices)) # sm for solid mean + gm = mean(values(ghost_vertices)) + @test sm ≈ 1 / DT.num_solid_vertices(tri) + @test gm ≈ 1 / 2 + @test all(y -> isapprox(y, sm, rtol = 1.0e-1), values(solid_vertices)) + @test all(y -> isapprox(y, gm, rtol = 1.0e-1), values(ghost_vertices)) + for i in 1:250 + for f in (each_vertex, each_solid_vertex, each_ghost_vertex) + rng = StableRNG(i) + V1 = rand(rng, f(tri)) + V2 = rand(rng, f(tri)) + V3 = rand(rng, f(tri)) + rng = StableRNG(i) + @test rand(rng, f(tri)) == V1 + @test rand(rng, f(tri)) == V2 + @test rand(rng, f(tri)) == V3 + end + end + + # Triangles + ns = 5_000_000 + function test_triangle_sampler(tri, ns) + solid_triangles = DefaultDict{NTuple{3, Int}, Float64, Float64}(0.0) + ghost_triangles = DefaultDict{NTuple{3, Int}, Float64, Float64}(0.0) + for _ in 1:ns + st = rand(each_solid_triangle(tri)) + gt = rand(each_ghost_triangle(tri)) + solid_triangles[st] += 1 / ns + ghost_triangles[gt] += 1 / ns + end + return solid_triangles, ghost_triangles + end + solid_triangles, ghost_triangles = test_triangle_sampler(tri, ns) + @inferred rand(each_solid_triangle(tri)) + @inferred rand(each_ghost_triangle(tri)) + @test all(!DT.is_ghost_triangle, keys(solid_triangles)) + @test all(DT.is_ghost_triangle, keys(ghost_triangles)) + sm = mean(values(solid_triangles)) # sm for solid mean + gm = mean(values(ghost_triangles)) + @test sm ≈ 1 / DT.num_solid_triangles(tri) + @test gm ≈ 1 / DT.num_ghost_triangles(tri) + @test all(y -> isapprox(y, sm, rtol = 1.0e-1), values(solid_triangles)) + @test all(y -> isapprox(y, gm, rtol = 1.0e-1), values(ghost_triangles)) + for i in 1:250 + for f in (each_triangle, each_solid_triangle, each_ghost_triangle) + rng = StableRNG(i) + V1 = rand(rng, f(tri)) + V2 = rand(rng, f(tri)) + V3 = rand(rng, f(tri)) + rng = StableRNG(i) + @test rand(rng, f(tri)) == V1 + @test rand(rng, f(tri)) == V2 + @test rand(rng, f(tri)) == V3 + end + end + + # Edges + ns = 5_000_000 + function test_edge_sampler(tri, ns) + solid_edges = DefaultDict{NTuple{2, Int}, Float64, Float64}(0.0) + ghost_edges = DefaultDict{NTuple{2, Int}, Float64, Float64}(0.0) + for _ in 1:ns + se = rand(each_solid_edge(tri)) + ge = rand(each_ghost_edge(tri)) + solid_edges[se] += 1 / ns + ghost_edges[ge] += 1 / ns + end + return solid_edges, ghost_edges + end + solid_edges, ghost_edges = test_edge_sampler(tri, ns) + @inferred rand(each_solid_edge(tri)) + @inferred rand(each_ghost_edge(tri)) + @test all(!DT.is_ghost_edge, keys(solid_edges)) + @test all(DT.is_ghost_edge, keys(ghost_edges)) + sm = mean(values(solid_edges)) # sm for solid mean + gm = mean(values(ghost_edges)) + @test sm ≈ 1 / DT.num_solid_edges(tri) + @test gm ≈ 1 / DT.num_ghost_edges(tri) + @test all(y -> isapprox(y, sm, rtol = 1.0e-1), values(solid_edges)) + @test all(y -> isapprox(y, gm, rtol = 1.0e-1), values(ghost_edges)) + for i in 1:250 + for f in (each_edge, each_solid_edge, each_ghost_edge) + rng = StableRNG(i) + V1 = rand(rng, f(tri)) + V2 = rand(rng, f(tri)) + rng = StableRNG(i) + @test rand(rng, f(tri)) == V1 + @test rand(rng, f(tri)) == V2 + end + end +end diff --git a/test/data_structures/triangulation_cache.jl b/test/data_structures/triangulation_cache.jl index e63855854..0241d9f8a 100644 --- a/test/data_structures/triangulation_cache.jl +++ b/test/data_structures/triangulation_cache.jl @@ -7,7 +7,7 @@ using ..DelaunayTriangulation: add_weight!, get_weight, get_weights @struct_equal DT.TriangulationCache -tri = triangulate(rand(2, 50); weights=DT.ZeroWeight()) +tri = triangulate(rand(2, 50); weights = DT.ZeroWeight()) cache = DT.get_cache(tri) @test get_weights(DT.get_triangulation(DT.get_cache(tri))) === get_weights(tri) DT.unconstrained_triangulation!(DT.get_triangulation(cache)) diff --git a/test/geo_utils.jl b/test/geo_utils.jl index 63a2c312d..936579c03 100644 --- a/test/geo_utils.jl +++ b/test/geo_utils.jl @@ -5,1173 +5,1268 @@ using Random using CairoMakie @testset "Getting polygon features" begin - tri, label_map, index_map = simple_geometry() - pts = get_points(tri) - boundary_nodes = [index_map["a"], + tri, label_map, index_map = simple_geometry() + pts = get_points(tri) + boundary_nodes = [ + index_map["a"], + index_map["b"], + index_map["c"], + index_map["d"], + index_map["e"], + index_map["f"], + index_map["g"], + index_map["h"], + index_map["a"], + ] + a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) + @inferred DT.polygon_features(pts, boundary_nodes) + @test a ≈ 400.0 && cx ≈ 10.0 && cy ≈ 10.0 + boundary_nodes = [ + index_map["j"], + index_map["k"], + index_map["ℓ"], + index_map["i"], + index_map["j"], + ] + a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) + @test a ≈ 40.0 && cx ≈ 6.0 && cy ≈ 11.0 + boundary_nodes = [ + [ + index_map["a"], index_map["b"], index_map["c"], index_map["d"], + ], + [ + index_map["d"], index_map["e"], index_map["f"], index_map["g"], + ], + [ + index_map["g"], index_map["h"], - index_map["a"]] - a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) - @inferred DT.polygon_features(pts, boundary_nodes) - @test a ≈ 400.0 && cx ≈ 10.0 && cy ≈ 10.0 - boundary_nodes = [index_map["j"], + index_map["a"], + ], + ] + a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) + @inferred DT.polygon_features(pts, boundary_nodes) + @test a ≈ 400.0 && cx ≈ 10.0 && cy ≈ 10.0 + boundary_nodes = [ + [ + index_map["j"], + index_map["k"], + ], + [ index_map["k"], index_map["ℓ"], index_map["i"], - index_map["j"]] - a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) - @test a ≈ 40.0 && cx ≈ 6.0 && cy ≈ 11.0 - boundary_nodes = [[index_map["a"], - index_map["b"], - index_map["c"], - index_map["d"]], - [index_map["d"], - index_map["e"], - index_map["f"], - index_map["g"]], - [index_map["g"], - index_map["h"], - index_map["a"]]] - a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) - @inferred DT.polygon_features(pts, boundary_nodes) - @test a ≈ 400.0 && cx ≈ 10.0 && cy ≈ 10.0 - boundary_nodes = [[index_map["j"], - index_map["k"]], - [index_map["k"], - index_map["ℓ"], - index_map["i"]], - [index_map["i"], - index_map["j"]]] - a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) - @test a ≈ 40.0 && cx ≈ 6.0 && cy ≈ 11.0 - a, (cx, cy) = DT.polygon_features(pts, tri.boundary_nodes) - @inferred DT.polygon_features(pts, tri.boundary_nodes) - a1, a2, a3 = 400.0, 32.0, 40.0 - c1, c2, c3 = (10.0, 10.0), (15.58333333333, 7.0), (6.0, 11.0) - @test a ≈ a1 - a2 - a3 - @test cx ≈ (c1[1] * a1 - c2[1] * a2 - c3[1] * a3) / (a1 - a2 - a3) - @test cy ≈ (c1[2] * a1 - c2[2] * a2 - c3[2] * a3) / (a1 - a2 - a3) + ], + [ + index_map["i"], + index_map["j"], + ], + ] + a, (cx, cy) = DT.polygon_features(pts, boundary_nodes) + @test a ≈ 40.0 && cx ≈ 6.0 && cy ≈ 11.0 + a, (cx, cy) = DT.polygon_features(pts, tri.boundary_nodes) + @inferred DT.polygon_features(pts, tri.boundary_nodes) + a1, a2, a3 = 400.0, 32.0, 40.0 + c1, c2, c3 = (10.0, 10.0), (15.58333333333, 7.0), (6.0, 11.0) + @test a ≈ a1 - a2 - a3 + @test cx ≈ (c1[1] * a1 - c2[1] * a2 - c3[1] * a3) / (a1 - a2 - a3) + @test cy ≈ (c1[2] * a1 - c2[2] * a2 - c3[2] * a3) / (a1 - a2 - a3) end @testset "Another test for area" begin - tri = triangulate(rand(2, 50)) - for T in each_solid_triangle(tri) - u, v, w = T - p, q, r = get_point(tri, u, v, w) - a1 = DT.triangle_area(p, q, r) - a2 = DT.polygon_features(get_points(tri), [u, v, w, u])[1] - @test a1 ≈ a2 atol = 1e-4 - end + tri = triangulate(rand(2, 50)) + for T in each_solid_triangle(tri) + u, v, w = T + p, q, r = get_point(tri, u, v, w) + a1 = DT.triangle_area(p, q, r) + a2 = DT.polygon_features(get_points(tri), [u, v, w, u])[1] + @test a1 ≈ a2 atol = 1.0e-4 + end end @testset "Degenerate area calculation" begin #72 - p = (0.007668495f0, 0.7747718f0) - q = (0.0044495463f0, 0.97074896f0) - r = (0.015137732f0, 0.31555605f0) - a1 = DT.triangle_area(p, q, r) - @test a1 isa Float32 - a2 = DT.polygon_features([p, q, r], [1, 2, 3, 1])[1] - @test a1 ≈ a2 atol = 1e-4 + p = (0.007668495f0, 0.7747718f0) + q = (0.0044495463f0, 0.97074896f0) + r = (0.015137732f0, 0.31555605f0) + a1 = DT.triangle_area(p, q, r) + @test a1 isa Float32 + a2 = DT.polygon_features([p, q, r], [1, 2, 3, 1])[1] + @test a1 ≈ a2 atol = 1.0e-4 end @testset "Distance to a segment" begin - p1 = [0.0, 0.0] - p2 = [10.0, 0.0] - q = [0.0, 5.0] - d = DT.squared_distance_to_segment(p1..., p2..., q...) - @test sqrt(d) == q[2] - @inferred DT.squared_distance_to_segment(p1..., p2..., q...) - for _ in 1:10000 - local q - pᵢ = 10randn(2) - pⱼ = 10randn(2) - q = 10randn(2) - pᵢx, pᵢy = pᵢ - pⱼx, pⱼy = pⱼ - qx, qy = q - t = ((pᵢx - pⱼx) * (pᵢx - qx) + (pᵢy - pⱼy) * (pᵢy - qy)) / - ((pᵢx - pⱼx)^2 + (pᵢy - pⱼy)^2) # solve (d/dt)||q - (pᵢ + t(pⱼ - pᵢ))|| = 0 for t - if t < 0 - @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ norm(q - pᵢ)^2 - elseif t > 1 - @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ norm(q - pⱼ)^2 - else - @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ - norm(q - (pᵢ + t * (pⱼ - pᵢ)))^2 - end - end + p1 = [0.0, 0.0] + p2 = [10.0, 0.0] + q = [0.0, 5.0] + d = DT.squared_distance_to_segment(p1..., p2..., q...) + @test sqrt(d) == q[2] + @inferred DT.squared_distance_to_segment(p1..., p2..., q...) + for _ in 1:10000 + local q + pᵢ = 10randn(2) + pⱼ = 10randn(2) + q = 10randn(2) + pᵢx, pᵢy = pᵢ + pⱼx, pⱼy = pⱼ + qx, qy = q + t = ((pᵢx - pⱼx) * (pᵢx - qx) + (pᵢy - pⱼy) * (pᵢy - qy)) / + ((pᵢx - pⱼx)^2 + (pᵢy - pⱼy)^2) # solve (d/dt)||q - (pᵢ + t(pⱼ - pᵢ))|| = 0 for t + if t < 0 + @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ norm(q - pᵢ)^2 + elseif t > 1 + @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ norm(q - pⱼ)^2 + else + @test DT.squared_distance_to_segment(pᵢ..., pⱼ..., q...) ≈ + norm(q - (pᵢ + t * (pⱼ - pᵢ)))^2 + end + end end @testset "Distance to a polygon" begin - tri, label_map, index_map = simple_geometry() - pts = get_points(tri) - @testset "Single boundary" begin - boundary_nodes = [index_map["a"], - index_map["b"], - index_map["c"], - index_map["d"], - index_map["e"], - index_map["f"], - index_map["g"], - index_map["h"], - index_map["a"]] - q = (28.0, 18.0) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ -8.0 - @inferred DT.distance_to_polygon(q, pts, boundary_nodes) - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (26.9116654358588, 23.0120339025522) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ -7.5394606788132 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (9.5687897994641, 11.7840765682329) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ 20.0 - q[2] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ q[1] - 8.0 - q = (2.0, 2.0) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ 2.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (-2.0, 0.0) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ -2.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (0.0, 0.0) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ 0.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (10.0, 0.0) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @inferred DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ 0.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (4.6998638334488, 13.8273575177129) - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ q[1] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ -(q[1] - 4.0) - q = [-0.181375963606, 9.9696497047896] - dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) - @test dist ≈ q[1] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - end + tri, label_map, index_map = simple_geometry() + pts = get_points(tri) + @testset "Single boundary" begin + boundary_nodes = [ + index_map["a"], + index_map["b"], + index_map["c"], + index_map["d"], + index_map["e"], + index_map["f"], + index_map["g"], + index_map["h"], + index_map["a"], + ] + q = (28.0, 18.0) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ -8.0 + @inferred DT.distance_to_polygon(q, pts, boundary_nodes) + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (26.9116654358588, 23.0120339025522) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ -7.5394606788132 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (9.5687897994641, 11.7840765682329) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ 20.0 - q[2] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ q[1] - 8.0 + q = (2.0, 2.0) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ 2.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (-2.0, 0.0) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ -2.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (0.0, 0.0) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ 0.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (10.0, 0.0) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @inferred DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ 0.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (4.6998638334488, 13.8273575177129) + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ q[1] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ -(q[1] - 4.0) + q = [-0.181375963606, 9.9696497047896] + dist = DT.distance_to_polygon_single_segment(q, pts, boundary_nodes) + @test dist ≈ q[1] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + end - @testset "Multiple boundary segments" begin - boundary_nodes = [[index_map["a"], - index_map["b"], - index_map["c"], - index_map["d"]], - [index_map["d"], - index_map["e"], - index_map["f"], - index_map["g"]], - [index_map["g"], - index_map["h"], - index_map["a"]]] - q = (28.0, 18.0) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ -8.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (26.9116654358588, 23.0120339025522) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ -7.5394606788132 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (9.5687897994641, 11.7840765682329) - @inferred DT.distance_to_polygon(q, pts, boundary_nodes) - @inferred DT.distance_to_polygon(q, pts, tri.boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ 20.0 - q[2] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - q = (2.0, 2.0) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ 2.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (-2.0, 0.0) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ -2.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (0.0, 0.0) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ 0.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (10.0, 0.0) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @inferred DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ 0.0 - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == - DT.distance_to_polygon(q, pts, tri.boundary_nodes) - q = (4.6998638334488, 13.8273575177129) - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ q[1] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - q = [-0.181375963606, 9.9696497047896] - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ q[1] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - q = [14.2840577995064, 9.7320720329939] - dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) - @test dist ≈ 20.0 - q[1] - @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) - @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ -(q[1] - 14.0) - end + @testset "Multiple boundary segments" begin + boundary_nodes = [ + [ + index_map["a"], + index_map["b"], + index_map["c"], + index_map["d"], + ], + [ + index_map["d"], + index_map["e"], + index_map["f"], + index_map["g"], + ], + [ + index_map["g"], + index_map["h"], + index_map["a"], + ], + ] + q = (28.0, 18.0) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ -8.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (26.9116654358588, 23.0120339025522) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ -7.5394606788132 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (9.5687897994641, 11.7840765682329) + @inferred DT.distance_to_polygon(q, pts, boundary_nodes) + @inferred DT.distance_to_polygon(q, pts, tri.boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ 20.0 - q[2] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + q = (2.0, 2.0) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ 2.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (-2.0, 0.0) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ -2.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (0.0, 0.0) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ 0.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (10.0, 0.0) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @inferred DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ 0.0 + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) == + DT.distance_to_polygon(q, pts, tri.boundary_nodes) + q = (4.6998638334488, 13.8273575177129) + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ q[1] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + q = [-0.181375963606, 9.9696497047896] + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ q[1] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + q = [14.2840577995064, 9.7320720329939] + dist = DT.distance_to_polygon_multiple_segments(q, pts, boundary_nodes) + @test dist ≈ 20.0 - q[1] + @test dist == DT.distance_to_polygon(q, pts, boundary_nodes) + @test DT.distance_to_polygon(q, pts, tri.boundary_nodes) ≈ -(q[1] - 14.0) + end end @testset "Bounding box of a polygon" begin - tri, label_map, index_map = simple_geometry() - pts = get_points(tri) - boundary_nodes = [index_map["a"], + tri, label_map, index_map = simple_geometry() + pts = get_points(tri) + boundary_nodes = [ + index_map["a"], + index_map["b"], + index_map["c"], + index_map["d"], + index_map["e"], + index_map["f"], + index_map["g"], + index_map["h"], + index_map["a"], + ] + @test DT.polygon_bounds(pts, boundary_nodes) == (0.0, 20.0, 0.0, 20.0) + @inferred DT.polygon_bounds(pts, boundary_nodes) + boundary_nodes = [ + [ + index_map["a"], index_map["b"], index_map["c"], index_map["d"], + ], + [ + index_map["d"], index_map["e"], index_map["f"], index_map["g"], + ], + [ + index_map["g"], index_map["h"], - index_map["a"]] - @test DT.polygon_bounds(pts, boundary_nodes) == (0.0, 20.0, 0.0, 20.0) - @inferred DT.polygon_bounds(pts, boundary_nodes) - boundary_nodes = [[index_map["a"], - index_map["b"], - index_map["c"], - index_map["d"]], - [index_map["d"], - index_map["e"], - index_map["f"], - index_map["g"]], - [index_map["g"], - index_map["h"], - index_map["a"]]] - @test DT.polygon_bounds(pts, boundary_nodes) == (0.0, 20.0, 0.0, 20.0) - @inferred DT.polygon_bounds(pts, boundary_nodes) - @test DT.polygon_bounds(pts, tri.boundary_nodes) == (0.0, 20.0, 0.0, 20.0) - @inferred DT.polygon_bounds(pts, tri.boundary_nodes) + index_map["a"], + ], + ] + @test DT.polygon_bounds(pts, boundary_nodes) == (0.0, 20.0, 0.0, 20.0) + @inferred DT.polygon_bounds(pts, boundary_nodes) + @test DT.polygon_bounds(pts, tri.boundary_nodes) == (0.0, 20.0, 0.0, 20.0) + @inferred DT.polygon_bounds(pts, tri.boundary_nodes) - # this example used to give ymin = ∞! - pts = - [ - (0.42128834958962136, 0.33007028464908217) - (0.11356454007618466, 0.7448537954874419) - (0.7546603355923669, 0.9543777463196534) - (0.4891168285858787, 0.633382367024488) - (0.6747495735823583, 0.45029401396930835) - (0.4974345692650808, 0.5149317175333161) - (0.5484553916212294, 0.5711900118327666) - (0.11175023541896634, 0.990159314424705) - (0.4879170832093027, 0.08984797306499748) - (0.1335657114656048, 0.35758096957091445) - (0.7400877461824955, 0.8325280694798072) - (0.3299481327824305, 0.3440909795000966) - (0.1962438207259194, 0.6775012296614791) - (0.3403201981957973, 0.012234115125469014) - (0.39090662279892596, 0.6232084829209825) - (0.05180909728733263, 0.008306644625064141) - (0.4469104766158789, 0.5039047194497466) - (0.33193129503638996, 0.1768246437543215) - (0.24763476605581736, 0.9547830758766014) - (0.8626957317918005, 0.8901670309728742) - (0.16962017427458131, 0.8788693051101659) - (0.6974737865767218, 0.3655018057608477) - (0.5781761692908192, 0.49368701064930676) - (0.802284945950765, 0.6391848231098498) - (0.24014031334952324, 0.03642844544263135) - (0.29635836817046646, 0.49234998547822206) - (0.6537526603197776, 0.9534202877086324) - (0.22033649109831877, 0.6097719755673441) - (0.5794841917252405, 0.6525875695433809) - (0.48634161888118377, 0.7185107690604786) - (0.5345141678719951, 0.5951779828559485) - (0.07485448974139897, 0.3652052168490376) - (0.9456233879280223, 0.20388899534798632) - (0.27834285268176084, 0.8083123815440214) - (0.6267933326859505, 0.39246432872096704) - (0.7616653549409313, 0.6567908542485912) - (0.7064053508954178, 0.5295025690789412) - (0.6402160832134494, 0.7577312997966936) - (0.3919353829681529, 0.8457590619098538) - (0.9716293296512977, 0.5682387373301687) - ] - boundary_nodes = [16, 14, 33, 40, 20, 3, 8, 16] - _pts = pts[boundary_nodes] - xmin = minimum(getindex.(_pts, 1)) - xmax = maximum(getindex.(_pts, 1)) - ymin = minimum(getindex.(_pts, 2)) - ymax = maximum(getindex.(_pts, 2)) - _xmin, _xmax, _ymin, _ymax = DT.polygon_bounds(pts, boundary_nodes) - @test xmin == _xmin - @test ymin == _ymin - @test xmax == _xmax - @test ymax == _ymax + # this example used to give ymin = ∞! + pts = + [ + (0.42128834958962136, 0.33007028464908217) + (0.11356454007618466, 0.7448537954874419) + (0.7546603355923669, 0.9543777463196534) + (0.4891168285858787, 0.633382367024488) + (0.6747495735823583, 0.45029401396930835) + (0.4974345692650808, 0.5149317175333161) + (0.5484553916212294, 0.5711900118327666) + (0.11175023541896634, 0.990159314424705) + (0.4879170832093027, 0.08984797306499748) + (0.1335657114656048, 0.35758096957091445) + (0.7400877461824955, 0.8325280694798072) + (0.3299481327824305, 0.3440909795000966) + (0.1962438207259194, 0.6775012296614791) + (0.3403201981957973, 0.012234115125469014) + (0.39090662279892596, 0.6232084829209825) + (0.05180909728733263, 0.008306644625064141) + (0.4469104766158789, 0.5039047194497466) + (0.33193129503638996, 0.1768246437543215) + (0.24763476605581736, 0.9547830758766014) + (0.8626957317918005, 0.8901670309728742) + (0.16962017427458131, 0.8788693051101659) + (0.6974737865767218, 0.3655018057608477) + (0.5781761692908192, 0.49368701064930676) + (0.802284945950765, 0.6391848231098498) + (0.24014031334952324, 0.03642844544263135) + (0.29635836817046646, 0.49234998547822206) + (0.6537526603197776, 0.9534202877086324) + (0.22033649109831877, 0.6097719755673441) + (0.5794841917252405, 0.6525875695433809) + (0.48634161888118377, 0.7185107690604786) + (0.5345141678719951, 0.5951779828559485) + (0.07485448974139897, 0.3652052168490376) + (0.9456233879280223, 0.20388899534798632) + (0.27834285268176084, 0.8083123815440214) + (0.6267933326859505, 0.39246432872096704) + (0.7616653549409313, 0.6567908542485912) + (0.7064053508954178, 0.5295025690789412) + (0.6402160832134494, 0.7577312997966936) + (0.3919353829681529, 0.8457590619098538) + (0.9716293296512977, 0.5682387373301687) + ] + boundary_nodes = [16, 14, 33, 40, 20, 3, 8, 16] + _pts = pts[boundary_nodes] + xmin = minimum(getindex.(_pts, 1)) + xmax = maximum(getindex.(_pts, 1)) + ymin = minimum(getindex.(_pts, 2)) + ymax = maximum(getindex.(_pts, 2)) + _xmin, _xmax, _ymin, _ymax = DT.polygon_bounds(pts, boundary_nodes) + @test xmin == _xmin + @test ymin == _ymin + @test xmax == _xmax + @test ymax == _ymax end @testset "Cell data structure" begin - tri, label_map, index_map = simple_geometry() - pts = get_points(tri) - @testset "Constructor and operations" begin - p = DT.Cell(10.0, 10.0, 10.0, pts, tri.boundary_nodes) - @test p.dist == DT.distance_to_polygon((10.0, 10.0), pts, tri.boundary_nodes) - @test p.max_dist ≈ p.dist + 10.0 * sqrt(2) - q = DT.Cell(7.0, 17.0, 0.3, pts, tri.boundary_nodes) - @test (p < q) == (p.max_dist < q.max_dist) - @test (p > q) == (p.max_dist > q.max_dist) - @test (p == q) == (p.max_dist == q.max_dist) - @test (p ≤ q) == (p.max_dist ≤ q.max_dist) - @test (p ≥ q) == (p.max_dist ≥ q.max_dist) - @test p.x == 10.0 - @test p.y == 10.0 - @test p.half_width == 10.0 - @test q.x == 7.0 - @test q.y == 17.0 - @test q.half_width == 0.3 - @inferred p < q - end + tri, label_map, index_map = simple_geometry() + pts = get_points(tri) + @testset "Constructor and operations" begin + p = DT.Cell(10.0, 10.0, 10.0, pts, tri.boundary_nodes) + @test p.dist == DT.distance_to_polygon((10.0, 10.0), pts, tri.boundary_nodes) + @test p.max_dist ≈ p.dist + 10.0 * sqrt(2) + q = DT.Cell(7.0, 17.0, 0.3, pts, tri.boundary_nodes) + @test (p < q) == (p.max_dist < q.max_dist) + @test (p > q) == (p.max_dist > q.max_dist) + @test (p == q) == (p.max_dist == q.max_dist) + @test (p ≤ q) == (p.max_dist ≤ q.max_dist) + @test (p ≥ q) == (p.max_dist ≥ q.max_dist) + @test p.x == 10.0 + @test p.y == 10.0 + @test p.half_width == 10.0 + @test q.x == 7.0 + @test q.y == 17.0 + @test q.half_width == 0.3 + @inferred p < q + end - @testset "CellQueue" begin - boundary_nodes = [[index_map["a"], - index_map["b"], - index_map["c"], - index_map["d"]], - [index_map["d"], - index_map["e"], - index_map["f"], - index_map["g"]], - [index_map["g"], - index_map["h"], - index_map["a"]]] - q = DT.CellQueue{Float64}() - @test isempty(q) - c = DT.Cell(DT.polygon_features(pts, boundary_nodes)[2]..., 10.0, pts, boundary_nodes) - DT.insert_cell!(q, c) - @test q.queue[c] == c.max_dist - @inferred DT.get_next_cell!(q) - end + @testset "CellQueue" begin + boundary_nodes = [ + [ + index_map["a"], + index_map["b"], + index_map["c"], + index_map["d"], + ], + [ + index_map["d"], + index_map["e"], + index_map["f"], + index_map["g"], + ], + [ + index_map["g"], + index_map["h"], + index_map["a"], + ], + ] + q = DT.CellQueue{Float64}() + @test isempty(q) + c = DT.Cell(DT.polygon_features(pts, boundary_nodes)[2]..., 10.0, pts, boundary_nodes) + DT.insert_cell!(q, c) + @test q.queue[c] == c.max_dist + @inferred DT.get_next_cell!(q) + end end @testset "Pole of inaccessibility" begin - pts = [(0.0, 10.0), (0.0, 8.0), (0.0, 6.0), (0.0, 4.0), (0.0, 2.0), - (0.0, 0.0), (2.0, 0.0), (4.0, 0.0), (6.0, 0.0), (8.0, 0.0), (10.0, 0.0), - (10.0, 2.0), (10.0, 4.0), (8.0, 4.0), (6.0, 4.0), - (4.0, 4.0), (4.0, 6.0), (4.0, 8.0), (4.0, 10.0), (2.0, 10.0), - (0.0, 10.0)] - @testset "Single segment" begin - boundary_nodes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @inferred DT.pole_of_inaccessibility(pts, boundary_nodes) - @test x == 2.5 && y == 2.5 - end + pts = [ + (0.0, 10.0), (0.0, 8.0), (0.0, 6.0), (0.0, 4.0), (0.0, 2.0), + (0.0, 0.0), (2.0, 0.0), (4.0, 0.0), (6.0, 0.0), (8.0, 0.0), (10.0, 0.0), + (10.0, 2.0), (10.0, 4.0), (8.0, 4.0), (6.0, 4.0), + (4.0, 4.0), (4.0, 6.0), (4.0, 8.0), (4.0, 10.0), (2.0, 10.0), + (0.0, 10.0), + ] + @testset "Single segment" begin + boundary_nodes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @inferred DT.pole_of_inaccessibility(pts, boundary_nodes) + @test x == 2.5 && y == 2.5 + end - @testset "Multiple segments" begin - push!(pts, - (2.4988557436664, 2.4749992804628), - (1.258244761794, 3.494679539536), - (1.2242554198249, 1.4553190213896), - (3.3825786348632, 1.2683776405595), - (3.3825786348632, 3.4097061846133), - (2.0, 4.0)) - boundary_nodes = [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 1]], - [reverse([21, 22, 23, 24, 25, 21])]] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @inferred DT.pole_of_inaccessibility(pts, boundary_nodes) - @test (x ≈ 8.125 || x ≈ 5.625) && y ≈ 1.875 - end + @testset "Multiple segments" begin + push!( + pts, + (2.4988557436664, 2.4749992804628), + (1.258244761794, 3.494679539536), + (1.2242554198249, 1.4553190213896), + (3.3825786348632, 1.2683776405595), + (3.3825786348632, 3.4097061846133), + (2.0, 4.0), + ) + boundary_nodes = [ + [ + [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 1, + ], + ], + [reverse([21, 22, 23, 24, 25, 21])], + ] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @inferred DT.pole_of_inaccessibility(pts, boundary_nodes) + @test (x ≈ 8.125 || x ≈ 5.625) && y ≈ 1.875 + end - @testset "Multiply connected" begin - push!(pts, - (7.4103156582024, 2.4749992804628), - (7.0, 1.0), - (8.8548626918894, 0.8775002079148), - (9.2797294665033, 2.2370738866791)) - boundary_nodes = [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 1]], - [reverse([21, 22, 23, 24, 25, 21])], - [reverse([26, 27, 28, 29, 26])]] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @test x ≈ 2.5 && y ≈ 7.5 - end + @testset "Multiply connected" begin + push!( + pts, + (7.4103156582024, 2.4749992804628), + (7.0, 1.0), + (8.8548626918894, 0.8775002079148), + (9.2797294665033, 2.2370738866791), + ) + boundary_nodes = [ + [ + [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 1, + ], + ], + [reverse([21, 22, 23, 24, 25, 21])], + [reverse([26, 27, 28, 29, 26])], + ] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @test x ≈ 2.5 && y ≈ 7.5 + end - @testset "More complicated examples" begin - pts = [0.0 8.0 - 2.0 5.0 - 3.0 7.0 - 1.8190689042843 8.1342247183191 - 3.2296265960022 8.864995570655 - 4.2493068550754 7.7433472856744 - 4.5042269198437 5.8739334773735 - 3.6714880416006 4.3784024307328 - 2.7367811374502 2.6279513193238 - 5.5069125079324 1.3873403374514 - 8.4299959172756 2.7469140162157 - 9.7045962411171 5.5340400576824 - 8.565953285152 7.7943312986281 - 6.7135341478357 9.0349422805005 - 4.1303441581835 9.663745106929 - 2.7537758084347 10.3775212882802 - 1.0882980519485 10.4964839851721 - -1.1380038470281 9.8336918167745 - -2.2596521320086 8.4571234670257 - -2.7864869325298 5.9419121613117 - -1.3929239117964 3.647631578397 - 0.3235378576436 4.9732159151922 - -0.9000784532443 6.6216990006939 - 0.9863300260411 9.6807397779135 - 0.153591147798 9.5447824100371 - 0.2725538446899 8.6610595188403 - 2.9067278472957 8.1852087312728 - 2.1249729820062 9.4258197131452]' - A = Dict('a':'z' .=> 1:26) - boundary_nodes = [[[A['a'], A['d'], A['c'], A['b']], - [A['b'], A['i'], A['j'], A['k'], A['h'], A['g'], A['l']], - [A['l'], A['f'], A['m'], A['e'], A['n'], A['o'], A['p'], A['q'], A['p']], - [A['p'], A['q'], A['r'], A['s'], A['t'], A['u'], A['v'], A['w'], A['a']]], - [[28 - 2, 27 - 2, 26 - 2], - [26 - 2, 30 - 2, 29 - 2, 28 - 2]]] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @testset "More complicated examples" begin + pts = [ + 0.0 8.0 + 2.0 5.0 + 3.0 7.0 + 1.8190689042843 8.1342247183191 + 3.2296265960022 8.864995570655 + 4.2493068550754 7.7433472856744 + 4.5042269198437 5.8739334773735 + 3.6714880416006 4.3784024307328 + 2.7367811374502 2.6279513193238 + 5.5069125079324 1.3873403374514 + 8.4299959172756 2.7469140162157 + 9.7045962411171 5.5340400576824 + 8.565953285152 7.7943312986281 + 6.7135341478357 9.0349422805005 + 4.1303441581835 9.663745106929 + 2.7537758084347 10.3775212882802 + 1.0882980519485 10.4964839851721 + -1.1380038470281 9.8336918167745 + -2.2596521320086 8.4571234670257 + -2.7864869325298 5.9419121613117 + -1.3929239117964 3.647631578397 + 0.3235378576436 4.9732159151922 + -0.9000784532443 6.6216990006939 + 0.9863300260411 9.6807397779135 + 0.153591147798 9.5447824100371 + 0.2725538446899 8.6610595188403 + 2.9067278472957 8.1852087312728 + 2.1249729820062 9.4258197131452 + ]' + A = Dict('a':'z' .=> 1:26) + boundary_nodes = [ + [ + [A['a'], A['d'], A['c'], A['b']], + [A['b'], A['i'], A['j'], A['k'], A['h'], A['g'], A['l']], + [A['l'], A['f'], A['m'], A['e'], A['n'], A['o'], A['p'], A['q'], A['p']], + [A['p'], A['q'], A['r'], A['s'], A['t'], A['u'], A['v'], A['w'], A['a']], + ], + [ + [28 - 2, 27 - 2, 26 - 2], + [26 - 2, 30 - 2, 29 - 2, 28 - 2], + ], + ] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @test x ≈ 4.6146922812432685 && y ≈ 3.0953047713990314 - len = size(pts, 2) - pts = hcat(pts, [7.274358290326 3.0 5.3369657980869; 2.7978980291693 4.0 1.8801857960034]) - boundary_nodes = [[[A['a'], A['d'], A['c'], A['b']], - [A['b'], A['i'], A['j'], A['k'], A['h'], A['g'], A['l']], - [A['l'], A['f'], A['m'], A['e'], A['n'], A['o'], A['p'], A['q'], A['p']], - [A['p'], A['q'], A['r'], A['s'], A['t'], A['u'], A['v'], A['w'], A['a']]], - [[28 - 2, 27 - 2, 26 - 2], - [26 - 2, 30 - 2, 29 - 2, 28 - 2]], - [[len + 1, len + 2, len + 3, len + 1]]] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @test x ≈ -1.0785224985822 && y ≈ 5.3725906833292 - end + @test x ≈ 4.6146922812432685 && y ≈ 3.0953047713990314 + len = size(pts, 2) + pts = hcat(pts, [7.274358290326 3.0 5.3369657980869; 2.7978980291693 4.0 1.8801857960034]) + boundary_nodes = [ + [ + [A['a'], A['d'], A['c'], A['b']], + [A['b'], A['i'], A['j'], A['k'], A['h'], A['g'], A['l']], + [A['l'], A['f'], A['m'], A['e'], A['n'], A['o'], A['p'], A['q'], A['p']], + [A['p'], A['q'], A['r'], A['s'], A['t'], A['u'], A['v'], A['w'], A['a']], + ], + [ + [28 - 2, 27 - 2, 26 - 2], + [26 - 2, 30 - 2, 29 - 2, 28 - 2], + ], + [[len + 1, len + 2, len + 3, len + 1]], + ] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @test x ≈ -1.0785224985822 && y ≈ 5.3725906833292 + end end @testset "Making a figure" begin - pts = [0.0 8.0 - 2.0 5.0 - 3.0 7.0 - 1.81907 8.13422 - 3.22963 8.865 - 4.24931 7.74335 - 4.50423 5.87393 - 3.67149 4.3784 - 2.73678 2.62795 - 5.50691 1.38734 - 8.43 2.74691 - 9.7046 5.53404 - 8.56595 7.79433 - 6.71353 9.03494 - 4.13034 9.66375 - 2.75378 10.3775 - 1.0883 10.4965 - -1.138 9.83369 - -2.25965 8.45712 - -2.78649 5.94191 - -1.39292 3.64763 - 0.323538 4.97322 - -0.900078 6.6217 - 0.98633 9.68074 - 0.153591 9.54478 - 0.272554 8.66106 - 2.90673 8.18521 - 2.12497 9.42582 - 7.27436 2.7979 - 3.0 4.0 - 5.33697 1.88019]' - boundary_nodes = [ - [[1, 4, 3, 2], [2, 9, 10, 11, 8, 7, 12], [12, 6, 13, 5, 14, 15, 16, 17, 16], [16, 17, 18, 19, 20, 21, 22, 23, 1]], - [[26, 25, 24], [24, 28, 27, 26]], - [[29,31,30,29]] - ] - x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) - @test x ≈ -1.0785225000000000003 - @test y ≈ 5.37259749999999999999 + pts = [ + 0.0 8.0 + 2.0 5.0 + 3.0 7.0 + 1.81907 8.13422 + 3.22963 8.865 + 4.24931 7.74335 + 4.50423 5.87393 + 3.67149 4.3784 + 2.73678 2.62795 + 5.50691 1.38734 + 8.43 2.74691 + 9.7046 5.53404 + 8.56595 7.79433 + 6.71353 9.03494 + 4.13034 9.66375 + 2.75378 10.3775 + 1.0883 10.4965 + -1.138 9.83369 + -2.25965 8.45712 + -2.78649 5.94191 + -1.39292 3.64763 + 0.323538 4.97322 + -0.900078 6.6217 + 0.98633 9.68074 + 0.153591 9.54478 + 0.272554 8.66106 + 2.90673 8.18521 + 2.12497 9.42582 + 7.27436 2.7979 + 3.0 4.0 + 5.33697 1.88019 + ]' + boundary_nodes = [ + [[1, 4, 3, 2], [2, 9, 10, 11, 8, 7, 12], [12, 6, 13, 5, 14, 15, 16, 17, 16], [16, 17, 18, 19, 20, 21, 22, 23, 1]], + [[26, 25, 24], [24, 28, 27, 26]], + [[29, 31, 30, 29]], + ] + x, y = DT.pole_of_inaccessibility(pts, boundary_nodes) + @test x ≈ -1.0785225000000000003 + @test y ≈ 5.37259749999999999999 - tri = triangulate(pts; boundary_nodes) - @test collect(DT.getxy(DT.get_representative_point_coordinates(tri, 1))) ≈ [x, y] + tri = triangulate(pts; boundary_nodes) + @test collect(DT.getxy(DT.get_representative_point_coordinates(tri, 1))) ≈ [x, y] end @testset "A previously broken example" begin - PT = [-3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, - 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, - 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, - 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, - 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, - 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, - -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, - -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, - -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, - -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, - 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, - 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, - 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, - 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, - 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, - -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, - -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, - -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, - -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, - 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, - 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, - 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, - 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, - 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, - -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, - -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, - -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, - -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, - -4.927587132008278, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, - -3.304869996725775, -3.304869996725775, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, - -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, - -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, - 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, - 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, - 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, - 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, - 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, - 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, - 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, - 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, - 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, - 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, - 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, - 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, - 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, - 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, - 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, - 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, - 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, - 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, - 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929, - 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929] - PT = [PT[1:216]'; PT[217:end]'] - BN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 27, 36, 45, 54, 63, 72, - 81, 90, 99, 108, 117, 126, 135, 144, 153, 162, 171, 180, 189, - 198, 207, 216, 215, 214, 213, 212, 211, 210, 209, 208, 199, - 190, 181, 172, 163, 154, 145, 136, 127, 118, 109, 100, 91, 82, - 73, 64, 55, 46, 37, 28, 19, 10, 1] - pc = DT.pole_of_inaccessibility(PT, BN) - @test collect(pc) ≈ collect(DT.polygon_features(PT, BN)[2]) + PT = [ + -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, + 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, + 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, + 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, + 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, + 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, + -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, + -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, + -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, + -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, + 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, + 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, + 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, + 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, + 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, + -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, + -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, + -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, + -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, + 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, + 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, + 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, + 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, -0.569282706070557, + 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, -1.4572528434350467, + -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, -2.3452229807995364, + -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, -3.233193118164026, + -2.3452229807995364, -1.4572528434350467, -0.569282706070557, 0.31868743129393273, 1.2066575686584224, 2.094627706022912, 2.982597843387402, 3.8705679807518916, + -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, -4.927587132008278, + -4.927587132008278, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, -3.304869996725775, + -3.304869996725775, -3.304869996725775, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, + -1.6821528614432721, -1.6821528614432721, -1.6821528614432721, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, + -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, -0.05943572616076942, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, + 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 1.5632814091217337, 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, + 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, 3.185998544404236, 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, + 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, 4.808715679686739, 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, + 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, 6.431432814969242, 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, + 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, 8.054149950251745, 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, + 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, 9.676867085534248, 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, + 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, 11.299584220816751, 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, + 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, 12.922301356099254, 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, + 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, 14.545018491381757, 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, + 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, 16.16773562666426, 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, + 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, 17.790452761946764, 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, + 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, 19.413169897229267, 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, + 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, 21.03588703251177, 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, + 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, 22.658604167794273, 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, + 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, 24.281321303076776, 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, + 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, 25.90403843835928, 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, + 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, 27.52675557364178, 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, + 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, 29.149472708924286, 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, + 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, 30.772189844206785, 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929, + 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929, 32.39490697948929, + ] + PT = [PT[1:216]'; PT[217:end]'] + BN = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 27, 36, 45, 54, 63, 72, + 81, 90, 99, 108, 117, 126, 135, 144, 153, 162, 171, 180, 189, + 198, 207, 216, 215, 214, 213, 212, 211, 210, 209, 208, 199, + 190, 181, 172, 163, 154, 145, 136, 127, 118, 109, 100, 91, 82, + 73, 64, 55, 46, 37, 28, 19, 10, 1, + ] + pc = DT.pole_of_inaccessibility(PT, BN) + @test collect(pc) ≈ collect(DT.polygon_features(PT, BN)[2]) end @testset "Bounding box for a multiple polygon" begin - C = (15.7109521325776, 33.244486807457) - D = (14.2705719699703, 32.8530791545746) - E = (14.3, 27.2) - F = (14.1, 27.0) - G = (13.7, 27.2) - H = (13.4, 27.5) - I = (13.1, 27.6) - J = (12.7, 27.4) - K = (12.5, 27.1) - L = (12.7, 26.7) - M = (13.1, 26.5) - N = (13.6, 26.4) - O = (14.0, 26.4) - P = (14.6, 26.5) - Q = (15.1983491346581, 26.8128534095401) - R = (15.6, 27.6) - S = (15.6952958264624, 28.2344688505621) - T = (17.8088971520274, 33.1192363585346) - U = (16.3058917649589, 33.0722674401887) - V = (16.3215480710742, 29.7374742376305) - W = (16.3841732955354, 29.393035503094) - Z = (16.6190178872649, 28.9233463196351) - A1 = (17.0417381523779, 28.5319386667527) - B1 = (17.5114273358368, 28.3753756055997) - C1 = (18.1376795804487, 28.3597192994844) - D1 = (18.7169629067146, 28.5632512789833) - E1 = (19.2805899268653, 28.8920337074045) - F1 = (19.26493362075, 28.4536571361762) - G1 = (20.6426885588962, 28.4223445239456) - H1 = (20.689657477242, 33.1035800524193) - I1 = (19.2805899268653, 33.0722674401887) - J1 = (19.2962462329806, 29.7531305437458) - K1 = (19.0614016412512, 29.393035503094) - L1 = (18.7482755189452, 29.236472441941) - M1 = (18.4508057027546, 29.1425346052493) - N1 = (18.1689921926793, 29.3147539725175) - O1 = (17.7932408459121, 29.6278800948235) - P1 = (22.6466957416542, 35.4207133574833) - Q1 = (21.2219718851621, 34.9979930923702) - R1 = (21.2376281912774, 28.4693134422915) - S1 = (22.6780083538847, 28.4380008300609) - T1 = (24.5724213938357, 33.1975178891111) - U1 = (23.3512295168425, 32.8530791545746) - V1 = (23.3199169046119, 28.4380008300609) - W1 = (24.6663592305274, 28.3753756055997) - Z1 = (15.1942940307729, 35.4363696635986) - A2 = (14.7246048473139, 35.3737444391374) - B2 = (14.3645098066621, 35.1858687657538) - C2 = (14.1766341332786, 34.8570863373326) - D2 = (14.1140089088174, 34.3247719294125) - E2 = (14.2705719699703, 33.8394264398383) - F2 = (14.7246048473139, 33.6202381542241) - G2 = (15.4604512347329, 33.6045818481088) - H2 = (16.0, 34.0) - I2 = (15.9771093365377, 34.6848669700643) - J2 = (15.6170142958859, 35.2328376840997) - K2 = (24.1653574348379, 35.4520259697138) - L2 = (23.7739497819555, 35.4363696635986) - M2 = (23.4608236596496, 35.2641502963303) - N2 = (23.272947986266, 34.9040552556785) - O2 = (23.1320412312284, 34.5909291333725) - P2 = (23.1163849251131, 34.2151777866054) - Q2 = (23.2886042923813, 33.8081138276077) - R2 = (23.8209187003014, 33.6045818481088) - S2 = (24.3062641898756, 33.5576129297629) - T2 = (24.7602970672192, 33.8550827459536) - U2 = (25.010797965064, 34.4656786844502) - V2 = (24.8385785977957, 34.9666804801397) - W2 = (24.5254524754898, 35.2641502963303) - Z2 = (25.3708930057158, 37.4716894585871) - A3 = (24.7916096794498, 37.3464390096648) - B3 = (24.4471709449133, 36.9550313567823) - C3 = (24.3062641898756, 36.5636237038999) - D3 = (24.4941398632592, 35.9999966837492) - E3 = (25.0264542711793, 35.5929327247515) - F3 = (25.5587686790994, 35.5929327247515) - F3 = (25.5587686790994, 35.5929327247515) - G3 = (26.0, 36.0) - H3 = (26.1380520053653, 36.5792800100152) - I3 = (26.0, 37.0) - J3 = (25.7466443524829, 37.2838137852036) - K3 = (26.3885529032101, 35.4676822758291) - L3 = (25.9814889442124, 35.3580881330221) - M3 = (25.6840191280217, 35.1858687657538) - N3 = (25.5274560668688, 34.9040552556785) - O3 = (25.4961434546382, 34.5596165211419) - P3 = (25.5274560668688, 34.246490398836) - Q3 = (25.6683628219064, 33.8394264398383) - R3 = (26.0284578625583, 33.6358944603394) - S3 = (26.5451159643631, 33.6202381542241) - T3 = (27.0, 34.0) - U3 = (27.280962351782, 34.5596165211419) - V3 = (27.0304614539373, 35.2171813779844) - W3 = (26.1693646175959, 33.087923746304) - Z3 = (26.0, 33.0) - A4 = (25.5274560668688, 32.7278287056522) - B4 = (25.2612988629087, 32.4147025833463) - C4 = (25.1830173323322, 32.0702638488098) - D4 = (25.2299862506781, 31.7727940326191) - E4 = (25.6527065157911, 31.5222931347744) - F4 = (26.2946150665183, 31.7258251142732) - G4 = (26.5607722704784, 32.5086404200381) - H4 = (27.1557119028596, 32.7434850117675) - I4 = (27.6097447802033, 32.4929841139228) - J4 = (27.6410573924338, 32.1015764610403) - K4 = (27.7193389230103, 31.6005746653509) - L4 = (27.437525412935, 31.4283552980826) - M4 = (26.9834925355914, 31.2561359308143) - N4 = (26.5764285765937, 31.0995728696614) - O4 = (26.0441141686736, 30.7864467473554) - P4 = (25.6527065157911, 30.5672584617413) - Q4 = (25.3239240873699, 30.1915071149741) - R4 = (25.1673610262169, 29.8783809926682) - S4 = (25.1047358017558, 29.6122237887082) - T4 = (25.0890794956405, 29.1895035235952) - U4 = (25.2926114751393, 28.8294084829433) - V4 = (25.6840191280217, 28.5632512789833) - W4 = (26.1537083114806, 28.3753756055997) - Z4 = (26.8269294744384, 28.391031911715) - A5 = (27.4844943312809, 28.6102201973292) - B5 = (27.7342002330051, 28.7239579596219) - C5 = (27.7264126450755, 28.4202565942047) - D5 = (29.1825559185446, 28.3922538389457) - E5 = (29.1545531632856, 32.2146299318021) - F5 = (29.000538009361, 32.5786657501693) - G5 = (28.6785063238822, 32.9006974356481) - H5 = (28.3144705055149, 33.0827153448317) - I5 = (27.9084305542591, 33.2367304987563) - J5 = (27.3343740714492, 33.3207387645334) - K5 = (26.8303244767868, 33.2367304987563) - L5 = (27.6564057569279, 30.786489413592) - M5 = (27.6984098898165, 30.3944508399657) - N5 = (27.6984098898165, 29.7363860913787) - O5 = (27.5863988687804, 29.4143544059) - P5 = (27.2643671833016, 29.2043337414573) - Q5 = (26.9843396307114, 29.1763309861983) - R5 = (26.6903107004917, 29.3163447624934) - S5 = (26.5782996794556, 29.7503874690082) - T5 = (26.7603175886393, 30.3384453294476) - U5 = (27.3203726938197, 30.7024811478149) - J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] - U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] - L_curve = [[P1, Q1, R1, S1, P1]] - I_curve = [[T1, U1, V1, W1, T1]] - A_curve_outline = [[ + C = (15.7109521325776, 33.244486807457) + D = (14.2705719699703, 32.8530791545746) + E = (14.3, 27.2) + F = (14.1, 27.0) + G = (13.7, 27.2) + H = (13.4, 27.5) + I = (13.1, 27.6) + J = (12.7, 27.4) + K = (12.5, 27.1) + L = (12.7, 26.7) + M = (13.1, 26.5) + N = (13.6, 26.4) + O = (14.0, 26.4) + P = (14.6, 26.5) + Q = (15.1983491346581, 26.8128534095401) + R = (15.6, 27.6) + S = (15.6952958264624, 28.2344688505621) + T = (17.8088971520274, 33.1192363585346) + U = (16.3058917649589, 33.0722674401887) + V = (16.3215480710742, 29.7374742376305) + W = (16.3841732955354, 29.393035503094) + Z = (16.6190178872649, 28.9233463196351) + A1 = (17.0417381523779, 28.5319386667527) + B1 = (17.5114273358368, 28.3753756055997) + C1 = (18.1376795804487, 28.3597192994844) + D1 = (18.7169629067146, 28.5632512789833) + E1 = (19.2805899268653, 28.8920337074045) + F1 = (19.26493362075, 28.4536571361762) + G1 = (20.6426885588962, 28.4223445239456) + H1 = (20.689657477242, 33.1035800524193) + I1 = (19.2805899268653, 33.0722674401887) + J1 = (19.2962462329806, 29.7531305437458) + K1 = (19.0614016412512, 29.393035503094) + L1 = (18.7482755189452, 29.236472441941) + M1 = (18.4508057027546, 29.1425346052493) + N1 = (18.1689921926793, 29.3147539725175) + O1 = (17.7932408459121, 29.6278800948235) + P1 = (22.6466957416542, 35.4207133574833) + Q1 = (21.2219718851621, 34.9979930923702) + R1 = (21.2376281912774, 28.4693134422915) + S1 = (22.6780083538847, 28.4380008300609) + T1 = (24.5724213938357, 33.1975178891111) + U1 = (23.3512295168425, 32.8530791545746) + V1 = (23.3199169046119, 28.4380008300609) + W1 = (24.6663592305274, 28.3753756055997) + Z1 = (15.1942940307729, 35.4363696635986) + A2 = (14.7246048473139, 35.3737444391374) + B2 = (14.3645098066621, 35.1858687657538) + C2 = (14.1766341332786, 34.8570863373326) + D2 = (14.1140089088174, 34.3247719294125) + E2 = (14.2705719699703, 33.8394264398383) + F2 = (14.7246048473139, 33.6202381542241) + G2 = (15.4604512347329, 33.6045818481088) + H2 = (16.0, 34.0) + I2 = (15.9771093365377, 34.6848669700643) + J2 = (15.6170142958859, 35.2328376840997) + K2 = (24.1653574348379, 35.4520259697138) + L2 = (23.7739497819555, 35.4363696635986) + M2 = (23.4608236596496, 35.2641502963303) + N2 = (23.272947986266, 34.9040552556785) + O2 = (23.1320412312284, 34.5909291333725) + P2 = (23.1163849251131, 34.2151777866054) + Q2 = (23.2886042923813, 33.8081138276077) + R2 = (23.8209187003014, 33.6045818481088) + S2 = (24.3062641898756, 33.5576129297629) + T2 = (24.7602970672192, 33.8550827459536) + U2 = (25.010797965064, 34.4656786844502) + V2 = (24.8385785977957, 34.9666804801397) + W2 = (24.5254524754898, 35.2641502963303) + Z2 = (25.3708930057158, 37.4716894585871) + A3 = (24.7916096794498, 37.3464390096648) + B3 = (24.4471709449133, 36.9550313567823) + C3 = (24.3062641898756, 36.5636237038999) + D3 = (24.4941398632592, 35.9999966837492) + E3 = (25.0264542711793, 35.5929327247515) + F3 = (25.5587686790994, 35.5929327247515) + F3 = (25.5587686790994, 35.5929327247515) + G3 = (26.0, 36.0) + H3 = (26.1380520053653, 36.5792800100152) + I3 = (26.0, 37.0) + J3 = (25.7466443524829, 37.2838137852036) + K3 = (26.3885529032101, 35.4676822758291) + L3 = (25.9814889442124, 35.3580881330221) + M3 = (25.6840191280217, 35.1858687657538) + N3 = (25.5274560668688, 34.9040552556785) + O3 = (25.4961434546382, 34.5596165211419) + P3 = (25.5274560668688, 34.246490398836) + Q3 = (25.6683628219064, 33.8394264398383) + R3 = (26.0284578625583, 33.6358944603394) + S3 = (26.5451159643631, 33.6202381542241) + T3 = (27.0, 34.0) + U3 = (27.280962351782, 34.5596165211419) + V3 = (27.0304614539373, 35.2171813779844) + W3 = (26.1693646175959, 33.087923746304) + Z3 = (26.0, 33.0) + A4 = (25.5274560668688, 32.7278287056522) + B4 = (25.2612988629087, 32.4147025833463) + C4 = (25.1830173323322, 32.0702638488098) + D4 = (25.2299862506781, 31.7727940326191) + E4 = (25.6527065157911, 31.5222931347744) + F4 = (26.2946150665183, 31.7258251142732) + G4 = (26.5607722704784, 32.5086404200381) + H4 = (27.1557119028596, 32.7434850117675) + I4 = (27.6097447802033, 32.4929841139228) + J4 = (27.6410573924338, 32.1015764610403) + K4 = (27.7193389230103, 31.6005746653509) + L4 = (27.437525412935, 31.4283552980826) + M4 = (26.9834925355914, 31.2561359308143) + N4 = (26.5764285765937, 31.0995728696614) + O4 = (26.0441141686736, 30.7864467473554) + P4 = (25.6527065157911, 30.5672584617413) + Q4 = (25.3239240873699, 30.1915071149741) + R4 = (25.1673610262169, 29.8783809926682) + S4 = (25.1047358017558, 29.6122237887082) + T4 = (25.0890794956405, 29.1895035235952) + U4 = (25.2926114751393, 28.8294084829433) + V4 = (25.6840191280217, 28.5632512789833) + W4 = (26.1537083114806, 28.3753756055997) + Z4 = (26.8269294744384, 28.391031911715) + A5 = (27.4844943312809, 28.6102201973292) + B5 = (27.7342002330051, 28.7239579596219) + C5 = (27.7264126450755, 28.4202565942047) + D5 = (29.1825559185446, 28.3922538389457) + E5 = (29.1545531632856, 32.2146299318021) + F5 = (29.000538009361, 32.5786657501693) + G5 = (28.6785063238822, 32.9006974356481) + H5 = (28.3144705055149, 33.0827153448317) + I5 = (27.9084305542591, 33.2367304987563) + J5 = (27.3343740714492, 33.3207387645334) + K5 = (26.8303244767868, 33.2367304987563) + L5 = (27.6564057569279, 30.786489413592) + M5 = (27.6984098898165, 30.3944508399657) + N5 = (27.6984098898165, 29.7363860913787) + O5 = (27.5863988687804, 29.4143544059) + P5 = (27.2643671833016, 29.2043337414573) + Q5 = (26.9843396307114, 29.1763309861983) + R5 = (26.6903107004917, 29.3163447624934) + S5 = (26.5782996794556, 29.7503874690082) + T5 = (26.7603175886393, 30.3384453294476) + U5 = (27.3203726938197, 30.7024811478149) + J_curve = [[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, C]] + U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] + L_curve = [[P1, Q1, R1, S1, P1]] + I_curve = [[T1, U1, V1, W1, T1]] + A_curve_outline = [ + [ K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] - A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] - dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] - dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] - dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] - dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] - curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] - nodes, points = convert_boundary_points_to_indices(curves) - xmin, xmax, ymin, ymax = DelaunayTriangulation.polygon_bounds(points, nodes, Val(true)) # Val(true) => check all parts of the polygon - @test xmin ≈ 12.5 && xmax ≈ 29.1825559185446 && ymin ≈ 26.4 && ymax ≈ 37.4716894585871 + H5, I5, J5, K5, + ], + ] + A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] + dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] + dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] + dot_3 = [[K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, V2, W2, K2]] + dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] + curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] + nodes, points = convert_boundary_points_to_indices(curves) + xmin, xmax, ymin, ymax = DelaunayTriangulation.polygon_bounds(points, nodes, Val(true)) # Val(true) => check all parts of the polygon + @test xmin ≈ 12.5 && xmax ≈ 29.1825559185446 && ymin ≈ 26.4 && ymax ≈ 37.4716894585871 end @testset "segment_intersection_coordinates" begin - a, b, c, d = (0.5, 4.0), (1.5, 3.5), (2.0, 4.0), (0.5, 3.0) - u, v = DT.segment_intersection_coordinates(a, b, c, d) - @test u ≈ 1.3571428571429 && v ≈ 3.57142857 - a, b, c, d = (0.5, 3.5), (1.5, 3.5), (1.0, 4.0), (1.0, 3.0) - u, v = DT.segment_intersection_coordinates(a, b, c, d) - @test u ≈ 1.0 && v ≈ 3.5 - a, b, c, d = (0.5, 4.0), (1.5, 4.0), (1.0, 4.0), (1.0, 3.0) - u, v = DT.segment_intersection_coordinates(a, b, c, d) - @test u ≈ 1.0 && v ≈ 4.0 + a, b, c, d = (0.5, 4.0), (1.5, 3.5), (2.0, 4.0), (0.5, 3.0) + u, v = DT.segment_intersection_coordinates(a, b, c, d) + @test u ≈ 1.3571428571429 && v ≈ 3.57142857 + a, b, c, d = (0.5, 3.5), (1.5, 3.5), (1.0, 4.0), (1.0, 3.0) + u, v = DT.segment_intersection_coordinates(a, b, c, d) + @test u ≈ 1.0 && v ≈ 3.5 + a, b, c, d = (0.5, 4.0), (1.5, 4.0), (1.0, 4.0), (1.0, 3.0) + u, v = DT.segment_intersection_coordinates(a, b, c, d) + @test u ≈ 1.0 && v ≈ 4.0 end @testset "intersection_of_edge_and_bisector_ray" begin - a = (-7.0, 3.0) - b = (-5.0, 7.0) - c = (-10.0, 7.0) - cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) - @test all(isnan, m) - c = (-4.86, 4.47) - cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) - @test m == (-6.0, 5.0) - c = (-4.0, 4.0) - cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) - @test m == (-6.0, 5.0) - p = (0.0, 3.0) - q = (3.0, 3.0) - r = (1.5, 2.9) - @test DT.intersection_of_edge_and_bisector_ray(p, q, r)[2] == (1.5, 3.0) - a = (-5.0, 3.0) - b = (-5.0, 7.0) - c = (-5.0, 5.0) - @test DT.intersection_of_edge_and_bisector_ray(a, b, c)[2] == (-5.0, 5.0) - @test DT.is_collinear(DT.intersection_of_edge_and_bisector_ray(a, b, c)[1]) - c = (-5.0, 4.5) - @test DT.intersection_of_edge_and_bisector_ray(a, b, c)[2] == (-5.0, 5.0) + a = (-7.0, 3.0) + b = (-5.0, 7.0) + c = (-10.0, 7.0) + cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) + @test all(isnan, m) + c = (-4.86, 4.47) + cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) + @test m == (-6.0, 5.0) + c = (-4.0, 4.0) + cert, m = DT.intersection_of_edge_and_bisector_ray(a, b, c) + @test m == (-6.0, 5.0) + p = (0.0, 3.0) + q = (3.0, 3.0) + r = (1.5, 2.9) + @test DT.intersection_of_edge_and_bisector_ray(p, q, r)[2] == (1.5, 3.0) + a = (-5.0, 3.0) + b = (-5.0, 7.0) + c = (-5.0, 5.0) + @test DT.intersection_of_edge_and_bisector_ray(a, b, c)[2] == (-5.0, 5.0) + @test DT.is_collinear(DT.intersection_of_edge_and_bisector_ray(a, b, c)[1]) + c = (-5.0, 4.5) + @test DT.intersection_of_edge_and_bisector_ray(a, b, c)[2] == (-5.0, 5.0) end @testset "classify_and_compute_segment_intersection" begin - a = (-2.0, 3.0) - b = (-2.0, 5.0) - c = (-4.97, 4.82) - d = (-4.0, 4.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.is_none(cert) - @test DT.is_left(cert_c) - @test DT.is_left(cert_d) - @test all(isnan, p) - d = (2.0, -1.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.is_none(cert) - @test DT.is_left(cert_c) - @test DT.is_right(cert_d) - c = (-5.0, 4.0) - d = (1.0, 4.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.has_one_intersection(cert) - @test DT.is_left(cert_c) - @test DT.is_right(cert_d) - @test p == (-2.0, 4.0) - a = (0.0, 5.0) - b = (0.0, 7.0) - c = (-5.0, 4.0) - d = (0.0, 6.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.is_touching(cert) - @test DT.is_left(cert_c) - @test DT.is_collinear(cert_d) - @test p == (0.0, 6.0) - c = (2.0, 6.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.is_touching(cert) - @test DT.is_right(cert_c) - @test DT.is_collinear(cert_d) - @test p == (0.0, 6.0) - d = (1.0, 5.0) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) - @test DT.is_none(cert) - @test DT.is_right(cert_c) - @test DT.is_right(cert_d) - @test all(isnan, p) + a = (-2.0, 3.0) + b = (-2.0, 5.0) + c = (-4.97, 4.82) + d = (-4.0, 4.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.is_none(cert) + @test DT.is_left(cert_c) + @test DT.is_left(cert_d) + @test all(isnan, p) + d = (2.0, -1.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.is_none(cert) + @test DT.is_left(cert_c) + @test DT.is_right(cert_d) + c = (-5.0, 4.0) + d = (1.0, 4.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.has_one_intersection(cert) + @test DT.is_left(cert_c) + @test DT.is_right(cert_d) + @test p == (-2.0, 4.0) + a = (0.0, 5.0) + b = (0.0, 7.0) + c = (-5.0, 4.0) + d = (0.0, 6.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.is_touching(cert) + @test DT.is_left(cert_c) + @test DT.is_collinear(cert_d) + @test p == (0.0, 6.0) + c = (2.0, 6.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.is_touching(cert) + @test DT.is_right(cert_c) + @test DT.is_collinear(cert_d) + @test p == (0.0, 6.0) + d = (1.0, 5.0) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, d) + @test DT.is_none(cert) + @test DT.is_right(cert_c) + @test DT.is_right(cert_d) + @test all(isnan, p) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection((NaN, NaN), b, c, d) - @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, (Inf, Inf), c, d) - @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, (NaN, NaN), d) - @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) - cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, (Inf, Inf)) - @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection((NaN, NaN), b, c, d) + @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, (Inf, Inf), c, d) + @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, (NaN, NaN), d) + @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) + cert, cert_c, cert_d, p = DT.classify_and_compute_segment_intersection(a, b, c, (Inf, Inf)) + @test DT.is_none(cert) && DT.is_none(cert_c) && DT.is_none(cert_d) && all(isnan, p) end @testset "sort_convex_polygon!" begin - for _ in 1:50 - tri = triangulate(rand(2, 500)) - ch = get_convex_hull(tri) - pts = get_points(ch) - verts = DT.get_vertices(ch) - orig_verts = deepcopy(verts) - pop!(verts) - shuffle!(verts) - DT.sort_convex_polygon!(verts, pts) - push!(verts, verts[begin]) - @test DT.circular_equality(verts, orig_verts) - A = DT.polygon_features(pts, verts)[1] - @test A ≥ 0.0 - end + for _ in 1:50 + tri = triangulate(rand(2, 500)) + ch = get_convex_hull(tri) + pts = get_points(ch) + verts = DT.get_vertices(ch) + orig_verts = deepcopy(verts) + pop!(verts) + shuffle!(verts) + DT.sort_convex_polygon!(verts, pts) + push!(verts, verts[begin]) + @test DT.circular_equality(verts, orig_verts) + A = DT.polygon_features(pts, verts)[1] + @test A ≥ 0.0 + end end @testset "Degenerate pole_of_inaccessibility" begin - points = [(0.0, 0.0), (0.0, 1.0), (0.0, 2.0), (0.0, 3.0)] - boundary_nodes = [1, 2, 3, 4, 1] - @test DT.pole_of_inaccessibility(points, boundary_nodes) == (0.0, 1.5) - points = [(2.0, 0.0), (3.5, 0.0), (5.0, 0.0)] - boundary_nodes = [1, 2, 3, 1] - @test DT.pole_of_inaccessibility(points, boundary_nodes) == (3.5, 0.0) + points = [(0.0, 0.0), (0.0, 1.0), (0.0, 2.0), (0.0, 3.0)] + boundary_nodes = [1, 2, 3, 4, 1] + @test DT.pole_of_inaccessibility(points, boundary_nodes) == (0.0, 1.5) + points = [(2.0, 0.0), (3.5, 0.0), (5.0, 0.0)] + boundary_nodes = [1, 2, 3, 1] + @test DT.pole_of_inaccessibility(points, boundary_nodes) == (3.5, 0.0) end @testset "identify_side and intersection_of_ray_with_bounding_box" begin - a, b, c, d = 0.5, 1.3, 2.7, 5.8 - p = (0.7378963231985, 4.6758264584035) - q = (2.17804800057, 3.5917562397227) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (1.3, 4.252704459932) - @test collect(r) ≈ collect(rtrue) - p = (1.0, 4.5) - q = (2.0, 4.5) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (1.3, 4.5) - @test collect(r) ≈ collect(rtrue) + a, b, c, d = 0.5, 1.3, 2.7, 5.8 + p = (0.7378963231985, 4.6758264584035) + q = (2.17804800057, 3.5917562397227) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (1.3, 4.252704459932) + @test collect(r) ≈ collect(rtrue) + p = (1.0, 4.5) + q = (2.0, 4.5) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (1.3, 4.5) + @test collect(r) ≈ collect(rtrue) - a, b, c, d = 0.0, 1.0, 0.0, 1.0 - p = (0.5, 0.5) - q = (2.5, 0.5) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (1.0, 0.5) - @test collect(r) ≈ collect(rtrue) - q = (0.5, 1.5) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.5, 1.0) - @test collect(r) ≈ collect(rtrue) - q = (0.202587350495, 1.5151867707735) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.353517464218, 1.0) - @test collect(r) ≈ collect(rtrue) rtol = 1e-6 - q = (-0.5, 1.5) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.0, 1.0) - @test collect(r) ≈ collect(rtrue) - q = (-1.0, 0.5) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.0, 0.5) - @test collect(r) ≈ collect(rtrue) - q = (-1.5, 0.0) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.0, 0.375) - @test collect(r) ≈ collect(rtrue) - q = (-1.0, -1.0) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.0, 0.0) - @test collect(r) ≈ collect(rtrue) atol = 1e-6 - q = (0.0, -1.0) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (1 / 3, 0.0) - @test collect(r) ≈ collect(rtrue) - q = (0.5, -1.0) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.5, 0.0) - @test collect(r) ≈ collect(rtrue) - q = (2.0, -1.0) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (1.0, 0.0) - @test collect(r) ≈ collect(rtrue) - q = (0.4026485332004, 0.7749544176151) - r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) - rtrue = (0.3229679893052, 1.0) - @test collect(r) ≈ collect(rtrue) - u, v = (a, d), (b, d) - newr = DT.segment_intersection_coordinates(p, r, u, v) - @test collect(newr) ≈ collect(r) - cert = DT.line_segment_intersection_type(p, r, u, v) - @test DT.is_touching(cert) + a, b, c, d = 0.0, 1.0, 0.0, 1.0 + p = (0.5, 0.5) + q = (2.5, 0.5) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (1.0, 0.5) + @test collect(r) ≈ collect(rtrue) + q = (0.5, 1.5) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.5, 1.0) + @test collect(r) ≈ collect(rtrue) + q = (0.202587350495, 1.5151867707735) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.353517464218, 1.0) + @test collect(r) ≈ collect(rtrue) rtol = 1.0e-6 + q = (-0.5, 1.5) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.0, 1.0) + @test collect(r) ≈ collect(rtrue) + q = (-1.0, 0.5) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.0, 0.5) + @test collect(r) ≈ collect(rtrue) + q = (-1.5, 0.0) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.0, 0.375) + @test collect(r) ≈ collect(rtrue) + q = (-1.0, -1.0) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.0, 0.0) + @test collect(r) ≈ collect(rtrue) atol = 1.0e-6 + q = (0.0, -1.0) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (1 / 3, 0.0) + @test collect(r) ≈ collect(rtrue) + q = (0.5, -1.0) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.5, 0.0) + @test collect(r) ≈ collect(rtrue) + q = (2.0, -1.0) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (1.0, 0.0) + @test collect(r) ≈ collect(rtrue) + q = (0.4026485332004, 0.7749544176151) + r = DT.intersection_of_ray_with_bounding_box(p, q, a, b, c, d) + rtrue = (0.3229679893052, 1.0) + @test collect(r) ≈ collect(rtrue) + u, v = (a, d), (b, d) + newr = DT.segment_intersection_coordinates(p, r, u, v) + @test collect(newr) ≈ collect(r) + cert = DT.line_segment_intersection_type(p, r, u, v) + @test DT.is_touching(cert) end @testset "Polygon" begin - verts = [1, 11, 18, 26, 32, 72] - _verts = [verts; 1] - points = [rand(2) for _ in 1:maximum(verts)] - for verts in (verts, _verts) - poly = DT.Polygon(verts, points) - @test length(poly) == 6 - @test size(poly) == (6,) - @test poly[1] == Tuple(points[1]) - @test poly[2] == Tuple(points[11]) - @test poly[3] == Tuple(points[18]) - @test poly[4] == Tuple(points[26]) - @test poly[5] == Tuple(points[32]) - @test poly[6] == Tuple(points[72]) - @test eachindex(poly) == 1:6 - @test collect(poly) == Tuple.(getindex.(Ref(points), [1, 11, 18, 26, 32, 72])) - @test poly[begin:end] == [poly[i] for i in 1:6] - @inferred poly[1] - @inferred poly[5] - end + verts = [1, 11, 18, 26, 32, 72] + _verts = [verts; 1] + points = [rand(2) for _ in 1:maximum(verts)] + for verts in (verts, _verts) + poly = DT.Polygon(verts, points) + @test length(poly) == 6 + @test size(poly) == (6,) + @test poly[1] == Tuple(points[1]) + @test poly[2] == Tuple(points[11]) + @test poly[3] == Tuple(points[18]) + @test poly[4] == Tuple(points[26]) + @test poly[5] == Tuple(points[32]) + @test poly[6] == Tuple(points[72]) + @test eachindex(poly) == 1:6 + @test collect(poly) == Tuple.(getindex.(Ref(points), [1, 11, 18, 26, 32, 72])) + @test poly[begin:end] == [poly[i] for i in 1:6] + @inferred poly[1] + @inferred poly[5] + end end @testset "Sutherland-Hodgman algorithm" begin - # rectangular - verts = [1, 2, 3, 4, 5, 6, 7, 8, 9] - points = [(50.0, 150.0), (200.0, 50.0), (350.0, 150.0), (350.0, 300.0), - (250.0, 300.0), (200.0, 250.0), (150.0, 350.0), (100.0, 250.0), (100.0, 200.0)] - clip_verts = [1, 2, 3, 4] - clip_points = [(100.0, 100.0), (300.0, 100.0), (300.0, 300.0), (100.0, 300.0)] - spoly = DT.Polygon(verts, points) - cpoly = DT.Polygon(clip_verts, clip_points) - result = DT.clip_polygon(spoly, cpoly) - @inferred DT.clip_polygon(spoly, cpoly) - @test collect.(result) ≈ [ - [100.0, 116 + 2 / 3], - [125, 100], - [275, 100], - [300, 116 + 2 / 3], - [300, 300], - [250, 300], - [200, 250], - [175, 300], - [125, 300], - [100, 250], - [100.0, 116 + 2 / 3] - ] - @test DT.clip_polygon(verts, points, clip_verts, clip_points) == result - @test DT.polygon_features(result, eachindex(result))[1] > 0 + # rectangular + verts = [1, 2, 3, 4, 5, 6, 7, 8, 9] + points = [ + (50.0, 150.0), (200.0, 50.0), (350.0, 150.0), (350.0, 300.0), + (250.0, 300.0), (200.0, 250.0), (150.0, 350.0), (100.0, 250.0), (100.0, 200.0), + ] + clip_verts = [1, 2, 3, 4] + clip_points = [(100.0, 100.0), (300.0, 100.0), (300.0, 300.0), (100.0, 300.0)] + spoly = DT.Polygon(verts, points) + cpoly = DT.Polygon(clip_verts, clip_points) + result = DT.clip_polygon(spoly, cpoly) + @inferred DT.clip_polygon(spoly, cpoly) + @test collect.(result) ≈ [ + [100.0, 116 + 2 / 3], + [125, 100], + [275, 100], + [300, 116 + 2 / 3], + [300, 300], + [250, 300], + [200, 250], + [175, 300], + [125, 300], + [100, 250], + [100.0, 116 + 2 / 3], + ] + @test DT.clip_polygon(verts, points, clip_verts, clip_points) == result + @test DT.polygon_features(result, eachindex(result))[1] > 0 - # bigger example - function to_rand_point_verts(___points) - _points = [Tuple(rand(2)) for _ in 1:500] - _points = [_points; ___points] - shuffle!(_points) - vertices = identity.(indexin(___points, _points)) # identity to convert eltype from Union{Nothing, Int} - return _points, vertices - end - a = (-4.0, 4.0) - b = (-1.0, 6.0) - c = (3.0, 6.0) - d = (4.0, 4.0) - e = (4.0, -1.0) - f = (2.0, -3.0) - g = (-2.94, -1.32) - points = [g, f, e, d, c, b, a] # ccw - npoints, nvertices = to_rand_point_verts(deepcopy(points)) - h = (-2.0, 7.0) - i = (-5.0, 6.0) - j = (-5.0, 2.0) - k = (-4.0, -2.0) - ℓ = (-1.0, -3.0) - m = (2.0, 2.0) - n = (1.0, 5.0) - clip_points = [h, i, j, k, ℓ, m, n] - nclip_points, nclip_vertices = to_rand_point_verts(deepcopy(clip_points)) - result = DT.clip_polygon(nvertices, npoints, nclip_vertices, nclip_points) - @test DT.circular_equality(collect.(result), collect.([ - g, - (-0.4915938130464, -2.1526563550773), - m, - n, - (-0.5, 6.0), - b, - a, - g - ]), ≈) + # bigger example + function to_rand_point_verts(___points) + _points = [Tuple(rand(2)) for _ in 1:500] + _points = [_points; ___points] + shuffle!(_points) + vertices = identity.(indexin(___points, _points)) # identity to convert eltype from Union{Nothing, Int} + return _points, vertices + end + a = (-4.0, 4.0) + b = (-1.0, 6.0) + c = (3.0, 6.0) + d = (4.0, 4.0) + e = (4.0, -1.0) + f = (2.0, -3.0) + g = (-2.94, -1.32) + points = [g, f, e, d, c, b, a] # ccw + npoints, nvertices = to_rand_point_verts(deepcopy(points)) + h = (-2.0, 7.0) + i = (-5.0, 6.0) + j = (-5.0, 2.0) + k = (-4.0, -2.0) + ℓ = (-1.0, -3.0) + m = (2.0, 2.0) + n = (1.0, 5.0) + clip_points = [h, i, j, k, ℓ, m, n] + nclip_points, nclip_vertices = to_rand_point_verts(deepcopy(clip_points)) + result = DT.clip_polygon(nvertices, npoints, nclip_vertices, nclip_points) + @test DT.circular_equality( + collect.(result), collect.( + [ + g, + (-0.4915938130464, -2.1526563550773), + m, + n, + (-0.5, 6.0), + b, + a, + g, + ], + ), ≈, + ) end @testset "Liang-Barsky algorithm" begin - p, q = (-7.0, 5.0), (1.0, 8.0) - a, b, c, d = 0.0, 8.0, 0.0, 4.0 - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test all(isnan, u) && all(isnan, v) - p, q = (-3.0, 1.0), (10.0, 5.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [0, 1.9230769230769] - @test collect(v) ≈ [6.75, 4.0] - p, q = (0.0, -2.0), (0.0, 6.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [0, 0] - @test collect(v) ≈ [0, 4] - p, q = (2.0, 6.0), (-2.0, 2.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test u == v && (collect(u) ≈ [0, 4]) - p, q = (10.0, 6.0), (-2.0, 6.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test all(isnan, u) && all(isnan, v) - p, q = (4.0, 6.0), (4.0, -2.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [4.0, 4.0] - @test collect(v) ≈ [4.0, 0.0] - p, q = (2.0, 6.0), (10.0, -2.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [4.0, 4.0] - @test collect(v) ≈ [8.0, 0.0] - a, b, c, d = 4, 10, 2, 8 - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [4.0, 4.0] - @test collect(v) ≈ [6.0, 2.0] - p, q = (2.0, 6.0), (14.0, 8.0) - u, v = DT.liang_barsky(a, b, c, d, p, q) - @test collect(u) ≈ [4, 6 + 1 / 3] - @test collect(v) ≈ [10, 7 + 1 / 3] + p, q = (-7.0, 5.0), (1.0, 8.0) + a, b, c, d = 0.0, 8.0, 0.0, 4.0 + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test all(isnan, u) && all(isnan, v) + p, q = (-3.0, 1.0), (10.0, 5.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [0, 1.9230769230769] + @test collect(v) ≈ [6.75, 4.0] + p, q = (0.0, -2.0), (0.0, 6.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [0, 0] + @test collect(v) ≈ [0, 4] + p, q = (2.0, 6.0), (-2.0, 2.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test u == v && (collect(u) ≈ [0, 4]) + p, q = (10.0, 6.0), (-2.0, 6.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test all(isnan, u) && all(isnan, v) + p, q = (4.0, 6.0), (4.0, -2.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [4.0, 4.0] + @test collect(v) ≈ [4.0, 0.0] + p, q = (2.0, 6.0), (10.0, -2.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [4.0, 4.0] + @test collect(v) ≈ [8.0, 0.0] + a, b, c, d = 4, 10, 2, 8 + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [4.0, 4.0] + @test collect(v) ≈ [6.0, 2.0] + p, q = (2.0, 6.0), (14.0, 8.0) + u, v = DT.liang_barsky(a, b, c, d, p, q) + @test collect(u) ≈ [4, 6 + 1 / 3] + @test collect(v) ≈ [10, 7 + 1 / 3] end @testset "get_plane_through_three_points" begin - @static if VERSION ≥ v"1.10" - _plane_mat(p, q, r) = + @static if VERSION ≥ v"1.10" + _plane_mat(p, q, r) = let c = (p .+ q .+ r) ./ 3 - [c... 1; p... 1; q... 1; r... 1] - end - else - _plane_mat(p, q, r) = - let c = (p .+ q .+ r) ./ 3 - vcat([c... 1], [p... 1], [q... 1], [r... 1]) - end - end - _plane_norm(p, q, r) = begin - x = q .- p - y = r .- p - nv = cross(x |> collect, y |> collect) - return nv ./ norm(nv) - end - for _ in 1:10000 - p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - @inferred DT.get_plane_through_three_points(p, q, r) - @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1e-14 - n = _plane_norm(p, q, r) - @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) + [c... 1; p... 1; q... 1; r... 1] + end + else + _plane_mat(p, q, r) = + let c = (p .+ q .+ r) ./ 3 + vcat([c... 1], [p... 1], [q... 1], [r... 1]) + end + end + _plane_norm(p, q, r) = begin + x = q .- p + y = r .- p + nv = cross(x |> collect, y |> collect) + return nv ./ norm(nv) + end + for _ in 1:10000 + p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + @inferred DT.get_plane_through_three_points(p, q, r) + @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1.0e-14 + n = _plane_norm(p, q, r) + @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) - p, q, r = (rand(2)..., 0.0), (rand(2)..., 0.0), (rand(2)..., 0.0) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1e-14 - n = [0, 0, 1] - @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) - p, q, r = (rand(), 2.0, rand()), (rand(), 2.0, rand()), (rand(), 2.0, rand()) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1e-14 - n = [0, 1, 0] - @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) - p, q, r = (2.0, rand(), rand()), (2.0, rand(), rand()), (2.0, rand(), rand()) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1e-14 - n = [1, 0, 0] - @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) - end - p, q, r = (1.3, 0.5, 5.5), (2.5, 2.22, 3.86), (5.3, 1.39, 2.85) - a, b, c, d = DT.get_plane_through_three_points(p, q, r) - @test a ≈ -3.0984 - @test b ≈ -3.38 - @test c ≈ -5.812 - @test d ≈ 37.68392 + p, q, r = (rand(2)..., 0.0), (rand(2)..., 0.0), (rand(2)..., 0.0) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1.0e-14 + n = [0, 0, 1] + @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) + p, q, r = (rand(), 2.0, rand()), (rand(), 2.0, rand()), (rand(), 2.0, rand()) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1.0e-14 + n = [0, 1, 0] + @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) + p, q, r = (2.0, rand(), rand()), (2.0, rand(), rand()), (2.0, rand(), rand()) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + @test det(_plane_mat(p, q, r)) ≈ 0.0 atol = 1.0e-14 + n = [1, 0, 0] + @test n ≈ [α, β, γ] / norm([α, β, γ]) || n ≈ -[α, β, γ] / norm([α, β, γ]) + end + p, q, r = (1.3, 0.5, 5.5), (2.5, 2.22, 3.86), (5.3, 1.39, 2.85) + a, b, c, d = DT.get_plane_through_three_points(p, q, r) + @test a ≈ -3.0984 + @test b ≈ -3.38 + @test c ≈ -5.812 + @test d ≈ 37.68392 end @testset "get_steepest_descent_direction" begin - for _ in 1:10000 - p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - x, y = DT.get_steepest_descent_direction(p, q, r) - @inferred DT.get_steepest_descent_direction(p, q, r) - @test x ≈ sign(γ) * α && sign(γ) * y ≈ β - p1 = DT.get_steepest_descent_direction(p, q, r) |> collect - p2 = DT.get_steepest_descent_direction(q, r, p) |> collect - p3 = DT.get_steepest_descent_direction(r, p, q) |> collect - p4 = DT.get_steepest_descent_direction(r, q, p) |> collect - @test p1 ≈ p2 ≈ p3 ≈ p4 - end - p, q, r = (1.3, 0.5, 5.5), (2.5, 2.22, 3.86), (5.3, 1.39, 2.9) - x, y = DT.get_steepest_descent_direction(p, q, r) - @test x ≈ 3.0124 && y ≈ 3.44 + for _ in 1:10000 + p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + x, y = DT.get_steepest_descent_direction(p, q, r) + @inferred DT.get_steepest_descent_direction(p, q, r) + @test x ≈ sign(γ) * α && sign(γ) * y ≈ β + p1 = DT.get_steepest_descent_direction(p, q, r) |> collect + p2 = DT.get_steepest_descent_direction(q, r, p) |> collect + p3 = DT.get_steepest_descent_direction(r, p, q) |> collect + p4 = DT.get_steepest_descent_direction(r, q, p) |> collect + @test p1 ≈ p2 ≈ p3 ≈ p4 + end + p, q, r = (1.3, 0.5, 5.5), (2.5, 2.22, 3.86), (5.3, 1.39, 2.9) + x, y = DT.get_steepest_descent_direction(p, q, r) + @test x ≈ 3.0124 && y ≈ 3.44 end @testset "get_distance_to_plane" begin - for _ in 1:10000 - p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) - s = Tuple(rand(3)) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - d = DT.get_vertical_distance_to_plane(p, q, r, s) - @inferred DT.get_vertical_distance_to_plane(p, q, r, s) - @test d ≈ s[3] + (α * s[1] + β * s[2] + δ) / γ + for _ in 1:10000 + p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) + s = Tuple(rand(3)) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + d = DT.get_vertical_distance_to_plane(p, q, r, s) + @inferred DT.get_vertical_distance_to_plane(p, q, r, s) + @test d ≈ s[3] + (α * s[1] + β * s[2] + δ) / γ - p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) - s = Tuple(rand(3)) - α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) - n = [α, β, γ] / norm([α, β, γ]) - x, y, z = s - z₀ = -(α * x + β * y + δ) / γ - Q = [x, y, z₀] - P = [x, y, z] - v = Q - P - δ = dot(v, n) - d = DT.get_distance_to_plane(p, q, r, s) - @inferred DT.get_distance_to_plane(p, q, r, s) - @test abs(d) ≈ abs(δ) - @test sign(d) == sign(DT.get_vertical_distance_to_plane(p, q, r, s)) - end + p, q, r = Tuple(rand(3)), Tuple(rand(3)), Tuple(rand(3)) + s = Tuple(rand(3)) + α, β, γ, δ = DT.get_plane_through_three_points(p, q, r) + n = [α, β, γ] / norm([α, β, γ]) + x, y, z = s + z₀ = -(α * x + β * y + δ) / γ + Q = [x, y, z₀] + P = [x, y, z] + v = Q - P + δ = dot(v, n) + d = DT.get_distance_to_plane(p, q, r, s) + @inferred DT.get_distance_to_plane(p, q, r, s) + @test abs(d) ≈ abs(δ) + @test sign(d) == sign(DT.get_vertical_distance_to_plane(p, q, r, s)) + end - for _ in 1:1000 - p, q, r = (rand(), rand(), 2.0), (rand(), rand(), 2.0), (rand(), rand(), 2.0) - s = (rand(), rand(), 10 * randn()) - d = DT.get_distance_to_plane(p, q, r, s) - @test d ≈ s[3] - 2 ≈ DT.get_vertical_distance_to_plane(p, q, r, s) - if s[3] > 2.0 - @test d > 0.0 - else - @test d ≤ 0.0 - end - end + for _ in 1:1000 + p, q, r = (rand(), rand(), 2.0), (rand(), rand(), 2.0), (rand(), rand(), 2.0) + s = (rand(), rand(), 10 * randn()) + d = DT.get_distance_to_plane(p, q, r, s) + @test d ≈ s[3] - 2 ≈ DT.get_vertical_distance_to_plane(p, q, r, s) + if s[3] > 2.0 + @test d > 0.0 + else + @test d ≤ 0.0 + end + end end @testset "angle_between" begin - p = (2.0, 9.0) - q = (2.0, -5.0) - θ = DT.angle_between(p, q) - @test rad2deg(θ) ≈ 145.6697828044967 rtol = 1e-4 - θ = DT.angle_between(q, p) - @test rad2deg(θ) ≈ 214.3302171955033 rtol = 1e-4 - p = (7.0, 1.0) - q = (2.0, -5.0) - θ = DT.angle_between(p, q) - @test rad2deg(θ) ≈ 76.3286928678042 - θ = DT.angle_between(q, p) - @test rad2deg(θ) ≈ 283.6713071321958 - p = (0.0, 9.0) - q = (0.0, -4.0) - θ = DT.angle_between(p, q) - @test rad2deg(θ) ≈ 180.0 - θ = DT.angle_between(q, p) - @test rad2deg(θ) ≈ 180.0 - p = (0.0, -5.0) - q = (0.0, -4.0) - θ = DT.angle_between(p, q) - @test rad2deg(θ) ≈ 0.0 - θ = DT.angle_between(q, p) - @test rad2deg(θ) ≈ 0.0 - p = (-0.27, -4.96) - q = (0.0, -4.0) - θ = DT.angle_between(p, q) - @test rad2deg(θ) ≈ 356.8841517402107 rtol = 1e-4 - θ = DT.angle_between(q, p) - @test rad2deg(θ) ≈ 3.1158482597894 rtol = 1e-4 -end \ No newline at end of file + p = (2.0, 9.0) + q = (2.0, -5.0) + θ = DT.angle_between(p, q) + @test rad2deg(θ) ≈ 145.6697828044967 rtol = 1.0e-4 + θ = DT.angle_between(q, p) + @test rad2deg(θ) ≈ 214.3302171955033 rtol = 1.0e-4 + p = (7.0, 1.0) + q = (2.0, -5.0) + θ = DT.angle_between(p, q) + @test rad2deg(θ) ≈ 76.3286928678042 + θ = DT.angle_between(q, p) + @test rad2deg(θ) ≈ 283.6713071321958 + p = (0.0, 9.0) + q = (0.0, -4.0) + θ = DT.angle_between(p, q) + @test rad2deg(θ) ≈ 180.0 + θ = DT.angle_between(q, p) + @test rad2deg(θ) ≈ 180.0 + p = (0.0, -5.0) + q = (0.0, -4.0) + θ = DT.angle_between(p, q) + @test rad2deg(θ) ≈ 0.0 + θ = DT.angle_between(q, p) + @test rad2deg(θ) ≈ 0.0 + p = (-0.27, -4.96) + q = (0.0, -4.0) + θ = DT.angle_between(p, q) + @test rad2deg(θ) ≈ 356.8841517402107 rtol = 1.0e-4 + θ = DT.angle_between(q, p) + @test rad2deg(θ) ≈ 3.1158482597894 rtol = 1.0e-4 +end diff --git a/test/helper_function_tests.jl b/test/helper_function_tests.jl index c0ef9134c..518e0e38c 100644 --- a/test/helper_function_tests.jl +++ b/test/helper_function_tests.jl @@ -13,33 +13,33 @@ const DT = DelaunayTriangulation g = [2.0, -2.0] h = [6.0, 4.0] pts = [a, b, c, d, e, f, g, h] - tri = triangulate(pts; delete_ghosts=false) - @test validate_triangulation(tri; print_result=false) + tri = triangulate(pts; delete_ghosts = false) + @test validate_triangulation(tri; print_result = false) DT.delete_triangle!(tri, 6, 2, 3) - @test !validate_triangulation(tri; print_result=false) + @test !validate_triangulation(tri; print_result = false) DT.add_triangle!(tri, 6, 3, 2) @test !test_state(test_triangle_orientation(tri)) - @test !validate_triangulation(tri; print_result=false) + @test !validate_triangulation(tri; print_result = false) tri.points[7] = [2, -0.5] - @test !validate_triangulation(tri; print_result=false) + @test !validate_triangulation(tri; print_result = false) tri.points[7] = [2.0, -2.0] tri.adjacent.adjacent[(6, 3)] = DT.∅ @test !test_state(test_each_edge_has_two_incident_triangles(tri)) - @test !validate_triangulation(tri; print_result=false) + @test !validate_triangulation(tri; print_result = false) tri.adjacent.adjacent[(6, 3)] = 2 tri.adjacent.adjacent[(6, 17)] = 10 @test !test_state(test_adjacent2vertex_map_matches_adjacent_map(tri)) @test !test_state(test_adjacent_map_matches_adjacent2vertex_map(tri)) - tri = triangulate(pts; delete_ghosts=false) + tri = triangulate(pts; delete_ghosts = false) DT.delete_vertex!(tri, 3) - @test !validate_triangulation(tri; print_result=false) - tri = triangulate(pts; delete_ghosts=false) + @test !validate_triangulation(tri; print_result = false) + tri = triangulate(pts; delete_ghosts = false) push!(tri.triangles, (11, 17, 20)) @test any(!test_state, test_iterators(tri)) - tri = triangulate(pts; delete_ghosts=true) + tri = triangulate(pts; delete_ghosts = true) push!(tri.triangles, (11, 17, -20)) @test any(!test_state, test_iterators(tri)) - tri = triangulate(pts; delete_ghosts=false) + tri = triangulate(pts; delete_ghosts = false) push!(tri.triangles, (11, 17, 20000)) @test any(!test_state, test_iterators(tri)) end @@ -52,29 +52,29 @@ end boundary_nodes, points = convert_boundary_points_to_indices(x, y) tri_1 = triangulate(points; boundary_nodes) A = get_area(tri_1) - refine!(tri_1; max_area=1e-3A, use_circumcenter=true) + refine!(tri_1; max_area = 1.0e-3A, use_circumcenter = true) @test validate_triangulation(tri_1) boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) - tri_2 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_2 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_2) - refine!(tri_2; max_area=1e-3A, use_circumcenter=true) + refine!(tri_2; max_area = 1.0e-3A, use_circumcenter = true) @test validate_triangulation(tri_2) x = [0.0, 2.0, 2.0, 0.0, 0.0] y = [0.0, 0.0, 2.0, 2.0, 0.0] boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_3 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_3 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_3) - refine!(tri_3; max_area=1e-3A, use_circumcenter=true) + refine!(tri_3; max_area = 1.0e-3A, use_circumcenter = true) @test validate_triangulation(tri_3) x = reverse(reverse.(_x[2])) y = reverse(reverse.(_y[2])) boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_4 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_4 = triangulate(points; boundary_nodes, delete_ghosts = false) A = get_area(tri_4) - refine!(tri_4; max_area=1e-3A, use_circumcenter=true) + refine!(tri_4; max_area = 1.0e-3A, use_circumcenter = true) @test validate_triangulation(tri_4) end @@ -92,9 +92,7 @@ end @testset "test_visibility" begin points = [(0.0, 0.0), (6.0, 0.0), (6.0, 6.0), (0.0, 6.0), (1.0, 1.0), (3.5, 5.5), (4.5, 4.0)] boundary_nodes = [1, 2, 3, 4, 1] - tri = triangulate(points; boundary_nodes, segments=Set([(2, 4)])) + tri = triangulate(points; boundary_nodes, segments = Set([(2, 4)])) @test DT.is_visible(DT.test_visibility(tri, 4, 2, 3)) @test DT.is_invisible(DT.test_visibility(tri, 5, 1, 7)) end - - diff --git a/test/helper_functions.jl b/test/helper_functions.jl index cc174e3f9..58ed95d31 100644 --- a/test/helper_functions.jl +++ b/test/helper_functions.jl @@ -18,14 +18,18 @@ const DT = DelaunayTriangulation using DelaunayTriangulation: validate_triangulation function complicated_geometry() - x1 = [collect(LinRange(0, 2, 4)), + x1 = [ + collect(LinRange(0, 2, 4)), collect(LinRange(2, 2, 4)), collect(LinRange(2, 0, 4)), - collect(LinRange(0, 0, 4))] - y1 = [collect(LinRange(0, 0, 4)), + collect(LinRange(0, 0, 4)), + ] + y1 = [ + collect(LinRange(0, 0, 4)), collect(LinRange(0, 6, 4)), collect(LinRange(6, 6, 4)), - collect(LinRange(6, 0, 4))] + collect(LinRange(6, 0, 4)), + ] r = 0.5 h = k = 0.6 θ = LinRange(2π, 0, 50) @@ -36,14 +40,26 @@ function complicated_geometry() k = 0.5 x3 = [h .+ r .* cos.(θ)] y3 = [k .+ r .* sin.(θ)] - x4 = reverse(reverse.([collect(LinRange(1, 1.5, 4)), - collect(LinRange(1.5, 1.5, 4)), - collect(LinRange(1.5, 1, 4)), - collect(LinRange(1, 1, 4))])) - y4 = reverse(reverse.([collect(LinRange(2, 2, 4)), - collect(LinRange(2, 5, 4)), - collect(LinRange(5, 5, 4)), - collect(LinRange(5, 2, 4))])) + x4 = reverse( + reverse.( + [ + collect(LinRange(1, 1.5, 4)), + collect(LinRange(1.5, 1.5, 4)), + collect(LinRange(1.5, 1, 4)), + collect(LinRange(1, 1, 4)), + ], + ), + ) + y4 = reverse( + reverse.( + [ + collect(LinRange(2, 2, 4)), + collect(LinRange(2, 5, 4)), + collect(LinRange(5, 5, 4)), + collect(LinRange(5, 2, 4)), + ], + ), + ) x5 = [reverse([0.2, 0.5, 0.75, 0.75, 0.2, 0.2])] y5 = [reverse([2.0, 2.0, 3.0, 4.0, 5.0, 2.0])] x = [x1, x2, x3, x4, x5] @@ -78,9 +94,12 @@ function simple_geometry() z = (18.0, 16.0) a1 = (4.0, 18.0) b1 = (2.0, 12.0) - pts = [a, b, c, d, e, f, g, h, i, j, k, ℓ, - m, n, o, p, q, r, s, t, u, v, w, z, a1, b1] - T = [h a s + pts = [ + a, b, c, d, e, f, g, h, i, j, k, ℓ, + m, n, o, p, q, r, s, t, u, v, w, z, a1, b1, + ] + T = [ + h a s h s j b1 h j i b1 j @@ -115,20 +134,29 @@ function simple_geometry() p b c q p c d q c - r q d] + r q d + ] T = indexin(T, pts) - T = Set{NTuple{3,Int}}((Tuple(T) for T in eachrow(T))) + T = Set{NTuple{3, Int}}((Tuple(T) for T in eachrow(T))) outer = [[indexin([a, b, c, d, e, f, g, h, a], pts)...]] inner1 = [[indexin([ℓ, k, j, i, ℓ], pts)...]] inner2 = [[indexin([r, q, p], pts)...], [indexin([p, o, n, m, r], pts)...]] boundary_nodes = [outer, inner1, inner2] - label_map = Dict(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "ℓ", - "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "z", "a1", - "b1"] .=> pts) - index_map = Dict(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "ℓ", - "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "z", "a1", - "b1"] .=> DT.each_point_index(pts)) - return DT.Triangulation(pts, T, boundary_nodes, delete_ghosts=true, predicates=DT.ExactKernel()), label_map, index_map + label_map = Dict( + [ + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "ℓ", + "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "z", "a1", + "b1", + ] .=> pts, + ) + index_map = Dict( + [ + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "ℓ", + "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "z", "a1", + "b1", + ] .=> DT.each_point_index(pts), + ) + return DT.Triangulation(pts, T, boundary_nodes, delete_ghosts = true, predicates = DT.ExactKernel()), label_map, index_map end macro _adj(i, j, k) @@ -146,13 +174,15 @@ function example_triangulation() p7 = @SVector[2.0, 1.0] p8 = @SVector[5.0, 1.0] pts = [p1, p2, p3, p4, p5, p6, p7, p8] - T = Set{NTuple{3,Int}}([ - (6, 3, 1), - (3, 2, 5), - (4, 1, 5), - (4, 6, 1), - (5, 1, 3) - ]) + T = Set{NTuple{3, Int}}( + [ + (6, 3, 1), + (3, 2, 5), + (4, 1, 5), + (4, 6, 1), + (5, 1, 3), + ], + ) A = [ 0 0 1 1 1 1 1 0 0 0 1 1 1 1 @@ -173,24 +203,30 @@ function example_triangulation() (5, 1) => 3, (1, 3) => 5, (3, 5) => 1, (4, 5) => DT.𝒢, (5, 2) => DT.𝒢, (2, 3) => DT.𝒢, (3, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (6, 4) => DT.𝒢, + ), ) - adj2v = DT.Adjacent2Vertex(Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(5, 4), (3, 5), (6, 3), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3)]), - 3 => Set{NTuple{2,Int}}([(1, 6), (5, 1), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(1, 4), (3, 1)]) - )) - rep = Dict{Int,DT.RepresentativeCoordinates{Int,Float64}}() - tri = DT.Triangulation(pts, T, Int[], Set{NTuple{2,Int}}(), Set{NTuple{2,Int}}(), + adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(5, 4), (3, 5), (6, 3), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3)]), + 3 => Set{NTuple{2, Int}}([(1, 6), (5, 1), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(1, 4), (3, 1)]), + ), + ) + rep = Dict{Int, DT.RepresentativeCoordinates{Int, Float64}}() + tri = DT.Triangulation( + pts, T, Int[], Set{NTuple{2, Int}}(), Set{NTuple{2, Int}}(), DT.ZeroWeight(), adj, adj2v, DG, (), DT.construct_boundary_edge_map(Int[]), - Dict{Int,Vector{Int}}(), Dict{Int,UnitRange{Int}}(), DT.ConvexHull(pts, [2, 6, 4, 5, 2]), rep, DT.construct_polygon_hierarchy(pts), nothing, - DT._build_cache(pts, Int, NTuple{2,Int}, NTuple{3,Int}, - Set{NTuple{2,Int}}, Set{NTuple{3,Int}}, DT.ZeroWeight(), Val(true))) + Dict{Int, Vector{Int}}(), Dict{Int, UnitRange{Int}}(), DT.ConvexHull(pts, [2, 6, 4, 5, 2]), rep, DT.construct_polygon_hierarchy(pts), nothing, + DT._build_cache( + pts, Int, NTuple{2, Int}, NTuple{3, Int}, + Set{NTuple{2, Int}}, Set{NTuple{3, Int}}, DT.ZeroWeight(), Val(true), + ), + ) DT.compute_representative_points!(tri) return tri end @@ -200,18 +236,22 @@ function example_empty_triangulation() p2 = @SVector[3.0, -1.0] p3 = @SVector[2.0, 0.0] pts = [p1, p2, p3] - T = Set{NTuple{3,Int}}() + T = Set{NTuple{3, Int}}() A = zeros(Int, 0, 0) DG = SimpleGraphs.relabel(SimpleGraphs.UndirectedGraph(A), Dict(1:7 .=> [-1, (1:6)...])) DG = DT.Graph(DG.V, DG.E, DG.N) - adj = DT.Adjacent(Dict{NTuple{2,Int},Int}()) - adj2v = DT.Adjacent2Vertex(Dict(DT.𝒢 => Set{NTuple{2,Int}}())) - rep = Dict{Int,DT.RepresentativeCoordinates{Int,Float64}}() - tri = DT.Triangulation(pts, T, Int[], Set{NTuple{2,Int}}(), Set{NTuple{2,Int}}(), + adj = DT.Adjacent(Dict{NTuple{2, Int}, Int}()) + adj2v = DT.Adjacent2Vertex(Dict(DT.𝒢 => Set{NTuple{2, Int}}())) + rep = Dict{Int, DT.RepresentativeCoordinates{Int, Float64}}() + tri = DT.Triangulation( + pts, T, Int[], Set{NTuple{2, Int}}(), Set{NTuple{2, Int}}(), DT.ZeroWeight(), adj, adj2v, DG, (), DT.construct_boundary_edge_map(Int[]), - Dict{Int,Vector{Int}}(), Dict{Int,UnitRange{Int}}(), DT.ConvexHull(pts, [1, 2, 3, 1]), rep, DT.construct_polygon_hierarchy(pts), nothing, - DT._build_cache(pts, Int, NTuple{2,Int}, NTuple{3,Int}, - Set{NTuple{2,Int}}, Set{NTuple{3,Int}}, DT.ZeroWeight(), Val(true))) + Dict{Int, Vector{Int}}(), Dict{Int, UnitRange{Int}}(), DT.ConvexHull(pts, [1, 2, 3, 1]), rep, DT.construct_polygon_hierarchy(pts), nothing, + DT._build_cache( + pts, Int, NTuple{2, Int}, NTuple{3, Int}, + Set{NTuple{2, Int}}, Set{NTuple{3, Int}}, DT.ZeroWeight(), Val(true), + ), + ) DT.compute_representative_points!(tri) return tri end @@ -237,7 +277,7 @@ function example_with_special_corners() r = [3.0, 8.0] pts = [a, b, c, d, e, f, g, h, i, j, k, ℓ, m, n, o, p, q, r] rng = StableRNG(29292929292) - tri = triangulate(pts; rng, delete_ghosts=false, randomise=false, predicates=DT.ExactKernel()) + tri = triangulate(pts; rng, delete_ghosts = false, randomise = false, predicates = DT.ExactKernel()) return tri end @@ -255,7 +295,7 @@ function shewchuk_example_constrained() k = [8.0, 4.0] pts = [a, b, c, d, e, f, g, h, i, j, k] rng = StableRNG(213) - tri = triangulate(pts; rng, delete_ghosts=false, randomise=false) + tri = triangulate(pts; rng, delete_ghosts = false, randomise = false) return tri end @@ -273,7 +313,7 @@ function fixed_shewchuk_example_constrained() k = [8.0, 2.5] pts = [a, b, c, d, e, f, g, h, i, j, k] rng = StableRNG(213) - tri = triangulate(pts; rng, delete_ghosts=false, randomise=false, predicates=DT.ExactKernel()) + tri = triangulate(pts; rng, delete_ghosts = false, randomise = false, predicates = DT.ExactKernel()) return tri end @@ -342,12 +382,12 @@ function test_segment_triangle_intersections(tri, edge, true_triangles, true_col !isnothing(current_constrained_edges) && @test compare_edge_vectors(constrained_edges, current_constrained_edges) end -function get_random_vertices_and_constrained_edges(nverts1, nverts2, nedges, rng=Random.default_rng()) +function get_random_vertices_and_constrained_edges(nverts1, nverts2, nedges, rng = Random.default_rng()) ## To generate a random set of constrained edges, we get a random small triangulation, ## and we just take the edges from that triangulation. points = [Tuple(rand(rng, 2)) for _ in 1:nverts1] - tri = triangulate(points; predicates=DT.FastKernel(), rng) - edges = Set{NTuple{2,Int}}() + tri = triangulate(points; predicates = DT.FastKernel(), rng) + edges = Set{NTuple{2, Int}}() all_edges = collect(each_solid_edge(tri)) iter = 0 while length(edges) < nedges && iter < 10000 @@ -356,7 +396,7 @@ function get_random_vertices_and_constrained_edges(nverts1, nverts2, nedges, rng iter += 1 end ## Now get the rest of the points - append!(points, [Tuple(rand(rng, 2)) for _ in 1:(nverts2-nverts1)]) + append!(points, [Tuple(rand(rng, 2)) for _ in 1:(nverts2 - nverts1)]) return points, edges, vec(hcat(getindex.(edges, 1), getindex.(edges, 2))') end @@ -405,11 +445,13 @@ function second_shewchuk_example_constrained() (21, 22), (23, 24), (25, 26), - (27, 28) + (27, 28), ] - pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, + pts = [ + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, - p25, p26, p27, p28] + p25, p26, p27, p28, + ] return pts, Set(C) end @@ -432,11 +474,11 @@ function example_for_testing_add_point_on_constrained_triangulation() return P, Set([(1, 2)]) end -function validate_statistics(tri::DT.Triangulation, stats=statistics(tri)) +function validate_statistics(tri::DT.Triangulation, stats = statistics(tri)) ## Build up the array (see also test_iterators) I = DT.integer_type(tri) - T = NTuple{3,I} - E = NTuple{2,I} + T = NTuple{3, I} + E = NTuple{2, I} solid_triangles = T[] ghost_triangles = T[] all_triangles = T[] @@ -501,19 +543,19 @@ function validate_statistics(tri::DT.Triangulation, stats=statistics(tri)) sort!(ghost_vertices) NT = DT.number_type(tri) ## Build up the individual statistics - areas = Dict{T,NT}() - lengths = Dict{T,NTuple{3,NT}}() - circumcenters = Dict{T,NTuple{2,NT}}() - circumradii = Dict{T,NT}() - angles = Dict{T,NTuple{3,NT}}() - radius_edge_ratio = Dict{T,NT}() - edge_midpoints = Dict{T,NTuple{3,NTuple{2,NT}}}() - aspect_ratio = Dict{T,NT}() - inradius = Dict{T,NT}() - perimeter = Dict{T,NT}() - centroid = Dict{T,NTuple{2,NT}}() - offcenters = Dict{T,NTuple{2,NT}}() - sinks = Dict{T,NTuple{2,NT}}() + areas = Dict{T, NT}() + lengths = Dict{T, NTuple{3, NT}}() + circumcenters = Dict{T, NTuple{2, NT}}() + circumradii = Dict{T, NT}() + angles = Dict{T, NTuple{3, NT}}() + radius_edge_ratio = Dict{T, NT}() + edge_midpoints = Dict{T, NTuple{3, NTuple{2, NT}}}() + aspect_ratio = Dict{T, NT}() + inradius = Dict{T, NT}() + perimeter = Dict{T, NT}() + centroid = Dict{T, NTuple{2, NT}}() + offcenters = Dict{T, NTuple{2, NT}}() + sinks = Dict{T, NTuple{2, NT}}() total_A = zero(NT) for T in each_solid_triangle(tri) u, v, w = DT.triangle_vertices(T) @@ -538,8 +580,8 @@ function validate_statistics(tri::DT.Triangulation, stats=statistics(tri)) circumcenters[triangle_vertices(T)] = (ox, oy) circumradii[triangle_vertices(T)] = norm(r - collect(circumcenters[triangle_vertices(T)])) all_angles = [(norm(p - r)^2 + norm(q - r)^2 - norm(p - q)^2) / (2norm(p - r) * norm(q - r)) for (p, q, r) in ((p, q, r), (q, r, p), (r, p, q))] - all_angles[all_angles.<-1.0] .= -1.0 - all_angles[all_angles.>1.0] .= 1.0 + all_angles[all_angles .< -1.0] .= -1.0 + all_angles[all_angles .> 1.0] .= 1.0 all_angles = acos.(all_angles) sort!(all_angles) radius_edge_ratio[triangle_vertices(T)] = circumradii[triangle_vertices(T)] / ℓ1 @@ -559,38 +601,38 @@ function validate_statistics(tri::DT.Triangulation, stats=statistics(tri)) ## Now compare the statistics for T in each_solid_triangle(tri) - @test areas[triangle_vertices(T)] ≈ DT.get_area(stats, T) rtol = 1e-4 atol = 1e-4 - @test areas[triangle_vertices(T)] ≈ DT.triangle_area((lengths[triangle_vertices(T)].^2)...) rtol=1e-4 atol=1e-4 - @test collect(lengths[triangle_vertices(T)]) ≈ collect(DT.get_lengths(stats, T)) rtol = 1e-4 atol = 1e-4 - @test collect(circumcenters[triangle_vertices(T)]) ≈ collect(DT.get_circumcenter(stats, T)) rtol = 1e-4 atol = 1e-4 - @test circumradii[triangle_vertices(T)] ≈ DT.get_circumradius(stats, T) rtol = 1e-4 atol = 1e-4 - @test radius_edge_ratio[triangle_vertices(T)] ≈ DT.get_radius_edge_ratio(stats, T) rtol = 1e-4 atol = 1e-4 - @test collect(collect.(edge_midpoints[triangle_vertices(T)])) ≈ collect(collect.(DT.get_edge_midpoints(stats, T))) rtol = 1e-4 atol = 1e-4 - @test aspect_ratio[triangle_vertices(T)] ≈ DT.get_aspect_ratio(stats, T) rtol = 1e-4 atol = 1e-4 - @test aspect_ratio[triangle_vertices(T)] ≈ DT.triangle_aspect_ratio(get_point(tri, triangle_vertices(T)...)...) rtol = 1e-4 atol = 1e-4 - @test inradius[triangle_vertices(T)] ≈ DT.get_inradius(stats, T) rtol = 1e-4 atol = 1e-4 - @test inradius[triangle_vertices(T)] ≈ DT.triangle_inradius(get_point(tri, triangle_vertices(T)...)...) rtol = 1e-4 atol = 1e-4 - @test perimeter[triangle_vertices(T)] ≈ DT.get_perimeter(stats, T) rtol = 1e-4 atol = 1e-4 - @test radius_edge_ratio[triangle_vertices(T)] ≈ 1 / (2sin(angles[triangle_vertices(T)][1])) rtol = 1e-4 atol = 1e-4 + @test areas[triangle_vertices(T)] ≈ DT.get_area(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test areas[triangle_vertices(T)] ≈ DT.triangle_area((lengths[triangle_vertices(T)] .^ 2)...) rtol = 1.0e-4 atol = 1.0e-4 + @test collect(lengths[triangle_vertices(T)]) ≈ collect(DT.get_lengths(stats, T)) rtol = 1.0e-4 atol = 1.0e-4 + @test collect(circumcenters[triangle_vertices(T)]) ≈ collect(DT.get_circumcenter(stats, T)) rtol = 1.0e-4 atol = 1.0e-4 + @test circumradii[triangle_vertices(T)] ≈ DT.get_circumradius(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test radius_edge_ratio[triangle_vertices(T)] ≈ DT.get_radius_edge_ratio(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test collect(collect.(edge_midpoints[triangle_vertices(T)])) ≈ collect(collect.(DT.get_edge_midpoints(stats, T))) rtol = 1.0e-4 atol = 1.0e-4 + @test aspect_ratio[triangle_vertices(T)] ≈ DT.get_aspect_ratio(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test aspect_ratio[triangle_vertices(T)] ≈ DT.triangle_aspect_ratio(get_point(tri, triangle_vertices(T)...)...) rtol = 1.0e-4 atol = 1.0e-4 + @test inradius[triangle_vertices(T)] ≈ DT.get_inradius(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test inradius[triangle_vertices(T)] ≈ DT.triangle_inradius(get_point(tri, triangle_vertices(T)...)...) rtol = 1.0e-4 atol = 1.0e-4 + @test perimeter[triangle_vertices(T)] ≈ DT.get_perimeter(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test radius_edge_ratio[triangle_vertices(T)] ≈ 1 / (2sin(angles[triangle_vertices(T)][1])) rtol = 1.0e-4 atol = 1.0e-4 @test (2sin(DT.get_minimum_angle(stats, T) / 2)^2 - 0.1 ≤ DT.get_aspect_ratio(stats, T) ≤ 2tan(DT.get_minimum_angle(stats, T) / 2) + 0.1) - @test DT.get_radius_edge_ratio(stats, T) ≈ 1 / (2(sin(DT.get_minimum_angle(stats, T)))) rtol = 1e-4 atol = 1e-4 - @test areas[triangle_vertices(T)] ≈ inradius[triangle_vertices(T)] * 0.5perimeter[triangle_vertices(T)] rtol = 1e-4 atol = 1e-4 - @test DT.get_area(stats, T) ≈ DT.get_inradius(stats, T) * 0.5DT.get_perimeter(stats, T) rtol = 1e-4 atol = 1e-4 - @test collect(centroid[triangle_vertices(T)]) ≈ collect(DT.get_centroid(stats, T)) rtol = 1e-4 atol = 1e-4 - @test DT.get_angles(stats, T)[1] ≈ angles[triangle_vertices(T)][1] rtol = 1e-4 atol = 1e-4 - @test DT.get_angles(stats, T)[2] ≈ angles[triangle_vertices(T)][2] rtol = 1e-4 atol = 1e-4 - @test DT.get_angles(stats, T)[3] ≈ angles[triangle_vertices(T)][3] rtol = 1e-4 atol = 1e-4 - @test sum(DT.get_angles(stats, T)) ≈ π rtol = 1e-4 atol = 1e-4 - @test DT.get_minimum_angle(stats, T) ≈ angles[triangle_vertices(T)][1] rtol = 1e-4 atol = 1e-4 - @test DT.get_maximum_angle(stats, T) ≈ angles[triangle_vertices(T)][3] rtol = 1e-4 atol = 1e-4 - @test DT.get_minimum_angle(stats, T) ≈ DT.get_angles(stats, T)[1] rtol = 1e-4 atol = 1e-4 - @test DT.get_maximum_angle(stats, T) ≈ DT.get_angles(stats, T)[3] rtol = 1e-4 atol = 1e-4 - @test collect(offcenters[triangle_vertices(T)]) ≈ collect(DT.get_offcenter(stats, T)) rtol = 1e-4 atol = 1e-2 - @test collect(sinks[triangle_vertices(T)]) ≈ collect(DT.get_sink(stats, T)) rtol = 1e-4 atol = 1e-4 + @test DT.get_radius_edge_ratio(stats, T) ≈ 1 / (2(sin(DT.get_minimum_angle(stats, T)))) rtol = 1.0e-4 atol = 1.0e-4 + @test areas[triangle_vertices(T)] ≈ inradius[triangle_vertices(T)] * 0.5perimeter[triangle_vertices(T)] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_area(stats, T) ≈ DT.get_inradius(stats, T) * 0.5DT.get_perimeter(stats, T) rtol = 1.0e-4 atol = 1.0e-4 + @test collect(centroid[triangle_vertices(T)]) ≈ collect(DT.get_centroid(stats, T)) rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_angles(stats, T)[1] ≈ angles[triangle_vertices(T)][1] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_angles(stats, T)[2] ≈ angles[triangle_vertices(T)][2] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_angles(stats, T)[3] ≈ angles[triangle_vertices(T)][3] rtol = 1.0e-4 atol = 1.0e-4 + @test sum(DT.get_angles(stats, T)) ≈ π rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_minimum_angle(stats, T) ≈ angles[triangle_vertices(T)][1] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_maximum_angle(stats, T) ≈ angles[triangle_vertices(T)][3] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_minimum_angle(stats, T) ≈ DT.get_angles(stats, T)[1] rtol = 1.0e-4 atol = 1.0e-4 + @test DT.get_maximum_angle(stats, T) ≈ DT.get_angles(stats, T)[3] rtol = 1.0e-4 atol = 1.0e-4 + @test collect(offcenters[triangle_vertices(T)]) ≈ collect(DT.get_offcenter(stats, T)) rtol = 1.0e-4 atol = 1.0e-2 + @test collect(sinks[triangle_vertices(T)]) ≈ collect(DT.get_sink(stats, T)) rtol = 1.0e-4 atol = 1.0e-4 end @test stats.individual_statistics == DT.get_individual_statistics(stats) - @test stats.area ≈ DT.get_area(stats) rtol = 1e-4 atol = 1e-4 - @test stats.area ≈ total_A rtol = 1e-4 atol = 1e-4 + @test stats.area ≈ DT.get_area(stats) rtol = 1.0e-4 atol = 1.0e-4 + @test stats.area ≈ total_A rtol = 1.0e-4 atol = 1.0e-4 ## Inference for _ in 1:5 @@ -634,12 +676,12 @@ function validate_statistics(tri::DT.Triangulation, stats=statistics(tri)) largest_area = maximum([areas[triangle_vertices(T)] for T in each_solid_triangle(tri)]) smallest_radius_edge_ratio = minimum([radius_edge_ratio[triangle_vertices(T)] for T in each_solid_triangle(tri)]) largest_radius_edge_ratio = maximum([radius_edge_ratio[triangle_vertices(T)] for T in each_solid_triangle(tri)]) - @test DT.get_smallest_angle(stats) ≈ smallest_angle rtol = 1e-2 - @test DT.get_largest_angle(stats) ≈ largest_angle rtol = 1e-2 - @test DT.get_smallest_area(stats) ≈ smallest_area rtol = 1e-2 - @test DT.get_largest_area(stats) ≈ largest_area rtol = 1e-2 - @test DT.get_smallest_radius_edge_ratio(stats) ≈ smallest_radius_edge_ratio rtol = 1e-2 - @test DT.get_largest_radius_edge_ratio(stats) ≈ largest_radius_edge_ratio rtol = 1e-2 + @test DT.get_smallest_angle(stats) ≈ smallest_angle rtol = 1.0e-2 + @test DT.get_largest_angle(stats) ≈ largest_angle rtol = 1.0e-2 + @test DT.get_smallest_area(stats) ≈ smallest_area rtol = 1.0e-2 + @test DT.get_largest_area(stats) ≈ largest_area rtol = 1.0e-2 + @test DT.get_smallest_radius_edge_ratio(stats) ≈ smallest_radius_edge_ratio rtol = 1.0e-2 + @test DT.get_largest_radius_edge_ratio(stats) ≈ largest_radius_edge_ratio rtol = 1.0e-2 @test DT.get_smallest_radius_edge_ratio(stats) ≥ 1 / sqrt(3) - 0.1 @test DT.get_smallest_angle(stats) ≤ deg2rad(60) + 0.01 end @@ -647,7 +689,7 @@ end function slow_encroachment_test(tri::DT.Triangulation) E = DT.edge_type(tri) I = DT.integer_type(tri) - ch = Channel{Pair{E,Tuple{Bool,I}}}(Inf) # https://discourse.julialang.org/t/can-dicts-be-threadsafe/27172/17 + ch = Channel{Pair{E, Tuple{Bool, I}}}(Inf) # https://discourse.julialang.org/t/can-dicts-be-threadsafe/27172/17 @sync for i in collect(each_solid_vertex(tri)) Base.Threads.@spawn begin for j in each_solid_vertex(tri) @@ -674,8 +716,8 @@ function slow_encroachment_test(tri::DT.Triangulation) end end end - not_in_dt_encroached_edges = Dict{E,Tuple{Bool,I}}() - in_dt_encroached_edges = Dict{E,Tuple{Bool,I}}() + not_in_dt_encroached_edges = Dict{E, Tuple{Bool, I}}() + in_dt_encroached_edges = Dict{E, Tuple{Bool, I}}() while !isempty(ch) e, (b, k) = take!(ch) if DT.edge_exists(tri, e) || DT.edge_exists(tri, DT.reverse_edge(e)) @@ -690,7 +732,7 @@ end function slow_encroachment_test_diametral_lens(tri::DT.Triangulation, lens_angle) E = DT.edge_type(tri) I = DT.integer_type(tri) - ch = Channel{Pair{E,Tuple{Bool,I}}}(Inf) # https://discourse.julialang.org/t/can-dicts-be-threadsafe/27172/17 + ch = Channel{Pair{E, Tuple{Bool, I}}}(Inf) # https://discourse.julialang.org/t/can-dicts-be-threadsafe/27172/17 @sync for i in collect(each_solid_vertex(tri)) Base.Threads.@spawn begin for j in each_solid_vertex(tri) @@ -722,8 +764,8 @@ function slow_encroachment_test_diametral_lens(tri::DT.Triangulation, lens_angle end end end - not_in_dt_encroached_edges = Dict{E,Tuple{Bool,I}}() - in_dt_encroached_edges = Dict{E,Tuple{Bool,I}}() + not_in_dt_encroached_edges = Dict{E, Tuple{Bool, I}}() + in_dt_encroached_edges = Dict{E, Tuple{Bool, I}}() while !isempty(ch) e, (b, k) = take!(ch) if DT.edge_exists(tri, e) || DT.edge_exists(tri, DT.reverse_edge(e)) @@ -809,7 +851,7 @@ end ## TODO: Implement a brute-force DT.VoronoiTessellation that we can compare with -function validate_tessellation(vorn::DT.VoronoiTessellation; check_convex=true, check_adjacent=true, predicates::DT.AbstractPredicateKernel=DT.AdaptiveKernel()) +function validate_tessellation(vorn::DT.VoronoiTessellation; check_convex = true, check_adjacent = true, predicates::DT.AbstractPredicateKernel = DT.AdaptiveKernel()) tri = DT.get_triangulation(vorn) for (i, p) in DT.get_generators(vorn) flag = get_point(tri, i) == get_generator(vorn, i) == p @@ -911,7 +953,7 @@ function validate_tessellation(vorn::DT.VoronoiTessellation; check_convex=true, if i ∉ DT.get_unbounded_polygons(vorn) verts = get_polygon(vorn, i) poly_points = get_polygon_point.(Ref(vorn), verts) - flag = @views allunique(poly_points[begin:end-1]) + flag = @views allunique(poly_points[begin:(end - 1)]) if !flag println("Polygon $i has repeated vertices.") return false @@ -933,12 +975,12 @@ function validate_tessellation(vorn::DT.VoronoiTessellation; check_convex=true, for i in each_polygon_index(vorn) A += get_area(vorn, i) end - @test isapprox(A, get_area(vorn.triangulation), rtol=1e-4) + @test isapprox(A, get_area(vorn.triangulation), rtol = 1.0e-4) end return true end -function _make_graph_from_adjacency(A, labels=Dict(axes(A, 1) .=> axes(A, 1))) +function _make_graph_from_adjacency(A, labels = Dict(axes(A, 1) .=> axes(A, 1))) g = DT.Graph{Int}() foreach(axes(A, 1)) do i push!(g.vertices, labels[i]) @@ -991,7 +1033,7 @@ function _validate_offcenter(p, q, r, β) m = (p .+ q) ./ 2 # Check orientations - @test _orient(m, c, offcenter) ≈ 0.0 atol = 1e-6 + @test _orient(m, c, offcenter) ≈ 0.0 atol = 1.0e-6 @test _orient(p, q, offcenter) > 0 # Check the radius-edge ratios @@ -1076,7 +1118,7 @@ function compute_diametral_lens(p, q, lens_angle) end function get_points_in_diametral_circle(p, q) tri = triangulate(rand(2, 50)) - args = DT.RefinementArguments(tri; use_lens=false) + args = DT.RefinementArguments(tri; use_lens = false) θ = LinRange(0, 2π, 250) r = LinRange(0, norm(p .- q) / 2, 250) m = (p .+ q) ./ 2 @@ -1086,7 +1128,7 @@ function get_points_in_diametral_circle(p, q) end function get_points_in_diametral_lens(p, q, lens_angle) tri = triangulate(rand(2, 50)) - args = DT.RefinementArguments(tri; use_lens=true, min_angle=lens_angle) + args = DT.RefinementArguments(tri; use_lens = true, min_angle = lens_angle) θ = LinRange(0, 2π, 250) r = LinRange(0, norm(p .- q) / 2, 250) m = (p .+ q) ./ 2 @@ -1096,7 +1138,7 @@ function get_points_in_diametral_lens(p, q, lens_angle) end function get_random_convex_polygon(points) - tri = triangulate(points; predicates=DT.ExactKernel()) + tri = triangulate(points; predicates = DT.ExactKernel()) S = get_convex_hull_vertices(tri) pop!(S) # Want S[begin] ≠ S[end] return S @@ -1112,7 +1154,7 @@ function _lexicographically_sort_pair_vector(pairs) return key_x < key_y end end - return sort(pairs, lt=lt) + return sort(pairs, lt = lt) end function _compare_pairs(pairs, dt_pairs) @test length(pairs) == length(dt_pairs) @@ -1188,7 +1230,7 @@ function validate_insertion_event_history(tri::Triangulation, orig_tri::Triangul @test DT.compare_unoriented_edge_collections(manual_history.added_boundary_segments, history.added_boundary_segments) end -_approx_ispow2(x) = ispow2(x) || isapprox(log2(x), round(log2(x)), atol=1e-9, rtol=1e-9) +_approx_ispow2(x) = ispow2(x) || isapprox(log2(x), round(log2(x)), atol = 1.0e-9, rtol = 1.0e-9) function compare_encroach_queues(args::DT.RefinementArguments, manual_enqueue) _manual_enqueue_pairs = collect(manual_enqueue) @@ -1216,7 +1258,7 @@ function compare_triangle_queues(args::DT.RefinementArguments, manual_enqueue) _compare_pairs(_manual_enqueue_pairs, _args_queue_triangle_pairs) end -function is_conformal(tri::Triangulation; predicates::DT.AbstractPredicateKernel=DT.AdaptiveKernel()) +function is_conformal(tri::Triangulation; predicates::DT.AbstractPredicateKernel = DT.AdaptiveKernel()) points = get_points(tri) segment_tree = DT.BoundaryRTree(points) for e in each_segment(tri) @@ -1224,7 +1266,7 @@ function is_conformal(tri::Triangulation; predicates::DT.AbstractPredicateKernel insert!(segment_tree, i, j) end for r in each_solid_vertex(tri) - intersects = DT.get_intersections(segment_tree, r, cache_id=1) # can't use multithreading here + intersects = DT.get_intersections(segment_tree, r, cache_id = 1) # can't use multithreading here c = get_point(tri, r) for box in intersects i, j = DT.get_edge(box) @@ -1246,8 +1288,8 @@ function is_conformal(tri::Triangulation; predicates::DT.AbstractPredicateKernel end function slow_triangle_assess(tri, args) - good_T = NTuple{3,Int}[] - bad_T = NTuple{3,Int}[] + good_T = NTuple{3, Int}[] + bad_T = NTuple{3, Int}[] for T in each_solid_triangle(tri) u, v, w = T p, q, r = get_point(tri, u, v, w) @@ -1273,7 +1315,7 @@ end function slow_triangle_assess_queue(tri, args) good_T, bad_T = slow_triangle_assess(tri, args) - queue = PriorityQueue{NTuple{3,Int},Float64}(Base.Order.Reverse) + queue = PriorityQueue{NTuple{3, Int}, Float64}(Base.Order.Reverse) for T in bad_T queue[T] = DT.triangle_radius_edge_ratio(get_point(tri, T...)...) end @@ -1329,7 +1371,7 @@ function compute_φmin(tri) return φmin end -function validate_refinement(tri, args; check_conformal=true, warn=true) +function validate_refinement(tri, args; check_conformal = true, warn = true) ## Things to check: ## 1. All angle constraints are met, except for seditious and nestled triangles. ## 2. If !use_lens, the triangulation is conformal. @@ -1364,7 +1406,7 @@ function validate_refinement(tri, args; check_conformal=true, warn=true) minθ = min(minθ, t1, t2, t3) maxθ = max(maxθ, t1, t2, t3) end - V = find_triangle(tri, steiner_point; predicates=DT.ExactKernel()) + V = find_triangle(tri, steiner_point; predicates = DT.ExactKernel()) flag = DT.point_position_relative_to_triangle(DT.ExactKernel(), tri, V, steiner_point) if DT.is_on(flag) && DT.is_ghost_triangle(V) V = DT.replace_ghost_triangle_with_boundary_triangle(tri, V) @@ -1377,7 +1419,7 @@ function validate_refinement(tri, args; check_conformal=true, warn=true) show_print && println("Triangle $T has maximum angle $(max(t1, t2, t3)), which is greater than the maximum angle constraint $(args.constraints.max_angle).") return false end - flag = args.constraints.min_area - 1e-16 ≤ A ≤ args.constraints.max_area + flag = args.constraints.min_area - 1.0e-16 ≤ A ≤ args.constraints.max_area if !flag show_print && println("Triangle $T has area $A, which is not in the range $(args.constraints.min_area) to $(args.constraints.max_area).") DT.is_none(_flag) && return false @@ -1390,7 +1432,7 @@ function validate_refinement(tri, args; check_conformal=true, warn=true) if !args.use_lens flag = DT.dist(tri, steiner_point) > -eps(Float64) if !flag - show_print && println("The Steiner point associated with the triangle $T is a distance $(-DT.dist(tri,steiner_point)) away from the domain.") + show_print && println("The Steiner point associated with the triangle $T is a distance $(-DT.dist(tri, steiner_point)) away from the domain.") DT.is_none(_flag) && return false end end @@ -1420,7 +1462,7 @@ function validate_refinement(tri, args; check_conformal=true, warn=true) end end if !args.use_lens && check_conformal - flag = is_conformal(tri; predicates=DT.ExactKernel()) + flag = is_conformal(tri; predicates = DT.ExactKernel()) if !flag println("The triangulation is not conformal.") return false @@ -1454,7 +1496,7 @@ function validate_refinement(tri, args; check_conformal=true, warn=true) end return true end -validate_refinement(tri; check_conformal=true, warn=true, predicates=DT.ExactKernel(), kwargs...) = validate_refinement(tri, DT.RefinementArguments(tri; predicates, kwargs...); warn, check_conformal) +validate_refinement(tri; check_conformal = true, warn = true, predicates = DT.ExactKernel(), kwargs...) = validate_refinement(tri, DT.RefinementArguments(tri; predicates, kwargs...); warn, check_conformal) function why_not_equal(tri1, tri2) !DT.has_ghost_triangles(tri1) && DT.has_ghost_triangles(tri2) && println("!has_ghost_triangles(tri1) && has_ghost_triangles(tri2)") @@ -1603,7 +1645,7 @@ function get_weighted_example(i) num_pts = Int(mat[1, 1]) points = mat[2:num_pts, 1:2] weights = mat[2:num_pts, 3] - triangles = Int.(mat[num_pts+1:end, :]) + triangles = Int.(mat[(num_pts + 1):end, :]) triangles = Set([Tuple(tri) for tri in eachrow(triangles)]) _triangles = empty(triangles) for T in triangles @@ -1622,7 +1664,7 @@ function get_weighted_example(i) # since some of the vertices might be submerged, we can't just get the # convex hull of points to find the boundary (in cases of collinear points). instead, let's find # all the edges which have only one adjoining triangle, and then sort them. - d = Dict{NTuple{2,Int},Int}() + d = Dict{NTuple{2, Int}, Int}() for T in triangles i, j, k = T d[(i, j)] = k @@ -1654,7 +1696,7 @@ function get_weighted_example(i) # return tri = Triangulation(points, triangles, boundary_nodes; weights) unlock_convex_hull!(tri) - return (tri=tri, submerged_vertices=submerged_vertices, nonsubmerged_vertices=nonsubmerged_vertices, weights=weights) + return (tri = tri, submerged_vertices = submerged_vertices, nonsubmerged_vertices = nonsubmerged_vertices, weights = weights) end get_unstructured_weighted_example(i) = get_weighted_example(i) function get_convex_polygon_weighted_example(i) @@ -1663,11 +1705,11 @@ function get_convex_polygon_weighted_example(i) representative_point_list = DT.get_representative_point_list(tri) cx, cy = DT.mean_points(get_points(tri), S) representative_point_list[1] = DT.RepresentativeCoordinates(cx, cy, length(S)) - return (tri=tri, submerged_vertices=submerged_vertices, nonsubmerged_vertices=nonsubmerged_vertices, weights=weights, S=S) + return (tri = tri, submerged_vertices = submerged_vertices, nonsubmerged_vertices = nonsubmerged_vertices, weights = weights, S = S) end function get_all_distances_to_witness_planes(tri, i) - distances = Dict{NTuple{3,Int},Float64}() + distances = Dict{NTuple{3, Int}, Float64}() for T in each_solid_triangle(tri) T = DT.sort_triangle(T) δ = DT.get_distance_to_witness_plane(tri, i, T) @@ -1677,7 +1719,7 @@ function get_all_distances_to_witness_planes(tri, i) end function get_nearest_power_point(tri, i) - all_dists = Dict{Int,Float64}() + all_dists = Dict{Int, Float64}() for j in each_solid_vertex(tri) p = DT.get_point(tri, i) q = DT.get_point(tri, j) @@ -1687,7 +1729,7 @@ function get_nearest_power_point(tri, i) end ⪧(a::Vector{Tuple}, b::Vector{Tuple}; kwargs...) = ⪧(collect.(a), collect.(b); kwargs...) -⪧(a::Vector{<:Union{Vector,Number}}, b::Vector; kwargs...) = isapprox(a, b; kwargs...) +⪧(a::Vector{<:Union{Vector, Number}}, b::Vector; kwargs...) = isapprox(a, b; kwargs...) ⪧(a, b; kwargs...) = isapprox(collect(collect.(a)), collect(collect.(b)); kwargs...) function closest_point_on_curve(c, p) @@ -1702,8 +1744,8 @@ end function slow_arc_length(c, t₁, t₂) t = LinRange(t₁, t₂, 15000) s = 0.0 - for i in 1:(length(t)-1) - s += norm(c(t[i+1]) .- c(t[i])) + for i in 1:(length(t) - 1) + s += norm(c(t[i + 1]) .- c(t[i])) end return s end @@ -1711,9 +1753,9 @@ end function slow_total_absolute_curvature(c, t₁, t₂) t = LinRange(t₁, t₂, 1500) s = 0.0 - for i in 1:(length(t)-1) + for i in 1:(length(t) - 1) T₁ = DT.differentiate(c, t[i]) - T₂ = DT.differentiate(c, t[i+1]) + T₂ = DT.differentiate(c, t[i + 1]) _rat = dot(T₁, T₂) / (norm(T₁) * norm(T₂)) _dot = _rat > 1 ? 1 : _rat < -1 ? -1 : _rat θ = acos(_dot) @@ -1725,32 +1767,32 @@ end function slow_get_segment(control_points, knots, alpha, tension, t) L = 0.0 for i in 2:lastindex(control_points) - L += norm(control_points[i] .- control_points[i-1])^alpha + L += norm(control_points[i] .- control_points[i - 1])^alpha end is_closed = control_points[begin] == control_points[end] s = 0 for outer s in eachindex(knots) - knots[s] ≤ t ≤ knots[s+1] && break + knots[s] ≤ t ≤ knots[s + 1] && break end - points = NTuple{2,Float64}[] + points = NTuple{2, Float64}[] if s == 1 if is_closed - push!(points, control_points[end-1]) + push!(points, control_points[end - 1]) else push!(points, DT.extend_left_control_point(control_points)) end else - push!(points, control_points[s-1]) + push!(points, control_points[s - 1]) end - push!(points, control_points[s], control_points[s+1]) + push!(points, control_points[s], control_points[s + 1]) if s == length(knots) - 1 if is_closed - push!(points, control_points[begin+1]) + push!(points, control_points[begin + 1]) else push!(points, DT.extend_right_control_point(control_points)) end else - push!(points, control_points[s+2]) + push!(points, control_points[s + 2]) end return DT.catmull_rom_spline_segment(points..., alpha, tension), s end @@ -1763,7 +1805,7 @@ function slow_eval_bspline(control_points, knots, t) end val = Real[0, 0] order = length(knots) - length(control_points) - a, b = knots[order], knots[length(control_points)+1] + a, b = knots[order], knots[length(control_points) + 1] t = a + (b - a) * t for i in eachindex(control_points) val = val .+ control_points[i] .* slow_eval_bspline_basis(knots, i, order, t) @@ -1772,10 +1814,10 @@ function slow_eval_bspline(control_points, knots, t) end function slow_eval_bspline_basis(knots, i, order, t) if order == 1 - return (knots[i] ≤ t < knots[i+1]) ? 1.0 : 0.0 + return (knots[i] ≤ t < knots[i + 1]) ? 1.0 : 0.0 else - coeff1 = (t - knots[i]) / (knots[i+order-1] - knots[i]) - coeff2 = (knots[i+order] - t) / (knots[i+order] - knots[i+1]) + coeff1 = (t - knots[i]) / (knots[i + order - 1] - knots[i]) + coeff2 = (knots[i + order] - t) / (knots[i + order] - knots[i + 1]) coeff1 = isfinite(coeff1) ? coeff1 : 0.0 coeff2 = isfinite(coeff2) ? coeff2 : 0.0 return coeff1 * slow_eval_bspline_basis(knots, i, order - 1, t) + coeff2 * slow_eval_bspline_basis(knots, i + 1, order - 1, t) @@ -1785,11 +1827,11 @@ end function slow_bezier_eval(points, t) points = collect.(points) n = length(points) - 1 - return collect(sum([binomial(n, i) .* (1 - t)^(n - i) .* t^i .* points[i+1] for i in 0:n])) + return collect(sum([binomial(n, i) .* (1 - t)^(n - i) .* t^i .* points[i + 1] for i in 0:n])) end -function flatten_boundary_nodes(points, boundary_nodes, segments=nothing) - _points = NTuple{2,Float64}[] +function flatten_boundary_nodes(points, boundary_nodes, segments = nothing) + _points = NTuple{2, Float64}[] if DT.has_multiple_curves(boundary_nodes) nc = DT.num_curves(boundary_nodes) for i in 1:nc @@ -1799,7 +1841,7 @@ function flatten_boundary_nodes(points, boundary_nodes, segments=nothing) __boundary_nodes = get_boundary_nodes(_boundary_nodes, j) if !(get_boundary_nodes(__boundary_nodes, 1) isa DT.AbstractParametricCurve) n = DT.num_boundary_edges(__boundary_nodes) - for k in 1:(n+1) + for k in 1:(n + 1) push!(_points, get_point(points, get_boundary_nodes(__boundary_nodes, k))) end else @@ -1925,8 +1967,8 @@ end to_lines(rect::DT.BoundingBox) = [(rect.x.a, rect.y.a), (rect.x.b, rect.y.a), (rect.x.b, rect.y.b), (rect.x.a, rect.y.b), (rect.x.a, rect.y.a)] to_lines(rect::SI.Rect) = let a = rect.low[1], c = rect.low[2], b = rect.high[1], d = rect.high[2] - [(a, c), (b, c), (b, d), (a, d), (a, c)] - end + [(a, c), (b, c), (b, d), (a, d), (a, c)] +end to_lines(rect::DT.DiametralBoundingBox) = to_lines(DT.get_bounding_box(rect)) to_lines(rect::SI.SpatialElem) = to_lines(rect.mbr) to_edge(rect::DT.DiametralBoundingBox) = DT.get_edge(rect) @@ -1937,9 +1979,9 @@ function get_plot_data(tree, points) else bounding_rectangles, id_rectangles = get_si_rectangles(tree) end - _lines = NTuple{2,Float64}[] - id_rectangle_lines = NTuple{2,Float64}[] - bounding_rectangle_lines = NTuple{2,Float64}[] + _lines = NTuple{2, Float64}[] + id_rectangle_lines = NTuple{2, Float64}[] + bounding_rectangle_lines = NTuple{2, Float64}[] for rect in id_rectangles i, j = to_edge(rect) p, q = get_point(points, i, j) @@ -1955,9 +1997,9 @@ function get_plot_data(tree, points) end function plot_tree(tree, points) _lines, _id_rectangle_lines, _bounding_rectangle_lines = get_plot_data(tree, points) - fig, ax, sc = lines(_id_rectangle_lines, color=:blue) - linesegments!(ax, _lines, color=:black) - lines!(ax, _bounding_rectangle_lines, color=:red) + fig, ax, sc = lines(_id_rectangle_lines, color = :blue) + linesegments!(ax, _lines, color = :black) + lines!(ax, _bounding_rectangle_lines, color = :red) display(fig) return fig, ax, sc end @@ -1996,7 +2038,7 @@ function traverse_tree(tree::DT.PolygonTree) parent_index = DT.has_parent(tree) ? DT.get_index(DT.get_parent(tree)) : 0 tup = (height, index, parent_index) children = DT.get_children(tree) - schildren = sort(OrderedSet(children), by=x -> DT.get_index(x)) + schildren = sort(OrderedSet(children), by = x -> DT.get_index(x)) for child in schildren tup = (tup..., traverse_tree(child)) end @@ -2005,7 +2047,7 @@ end function traverse_tree(hierarchy::DT.PolygonHierarchy) dict = Dict() trees = DT.get_trees(hierarchy) - strees = sort(OrderedDict(trees), by=x -> x[1]) + strees = sort(OrderedDict(trees), by = x -> x[1]) for (index, tree) in strees dict[index] = traverse_tree(tree) end @@ -2020,7 +2062,7 @@ function compare_trees(hierarchy1::DT.PolygonHierarchy, hierarchy2::DT.PolygonHi return true end -function plot_boundary_and_diametral_circles(points, boundary_nodes, segments=nothing) +function plot_boundary_and_diametral_circles(points, boundary_nodes, segments = nothing) fpoints = flatten_boundary_nodes(points, boundary_nodes, segments) fig, ax, sc = lines(fpoints) scatter!(ax, points) @@ -2033,7 +2075,7 @@ function plot_boundary_and_diametral_circles(points, boundary_nodes, segments=no u, v = get_boundary_nodes(section_nodes, k), get_boundary_nodes(section_nodes, k + 1) p, q = get_point(points, u, v) c, r = DT.diametral_circle(p, q) - arc!(ax, c, r, 0, 2π, color=:red, linestyle=:dash) + arc!(ax, c, r, 0, 2π, color = :red, linestyle = :dash) end end end @@ -2044,7 +2086,7 @@ function plot_boundary_and_diametral_circles(points, boundary_nodes, segments=no u, v = get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, j + 1) p, q = get_point(points, u, v) c, r = DT.diametral_circle(p, q) - arc!(ax, c, r, 0, 2π, color=:red, linestyle=:dash) + arc!(ax, c, r, 0, 2π, color = :red, linestyle = :dash) end end else @@ -2052,7 +2094,7 @@ function plot_boundary_and_diametral_circles(points, boundary_nodes, segments=no u, v = get_boundary_nodes(boundary_nodes, i), get_boundary_nodes(boundary_nodes, i + 1) p, q = get_point(points, u, v) c, r = DT.diametral_circle(p, q) - arc!(ax, c, r, 0, 2π, color=:red, linestyle=:dash) + arc!(ax, c, r, 0, 2π, color = :red, linestyle = :dash) end end if !isnothing(segments) @@ -2060,7 +2102,7 @@ function plot_boundary_and_diametral_circles(points, boundary_nodes, segments=no i, j = DT.edge_vertices(e) p, q = get_point(points, i, j) c, r = DT.diametral_circle(p, q) - arc!(ax, c, r, 0, 2π, color=:red, linestyle=:dash) + arc!(ax, c, r, 0, 2π, color = :red, linestyle = :dash) end end display(fig) @@ -2069,7 +2111,7 @@ end plot_boundary_and_diametral_circles(enricher::DT.BoundaryEnricher) = plot_boundary_and_diametral_circles( get_points(enricher), get_boundary_nodes(enricher), - DT.get_segments(enricher) + DT.get_segments(enricher), ) function maximum_total_variation(points, boundary_nodes, boundary_curves) @@ -2183,7 +2225,7 @@ function all_points_are_inside(enricher::DT.BoundaryEnricher, orig_points, orig_ hierarchy = DT.get_polygon_hierarchy(enricher) for p in DT.each_point(points) δ = DT.distance_to_polygon(p, new_points, new_boundary_nodes) - δ < -1e-4 && return false + δ < -1.0e-4 && return false end return true end @@ -2191,7 +2233,7 @@ end function plot_small_angle_complexes(enricher) points, boundary_nodes, boundary_curves = get_points(enricher), get_boundary_nodes(enricher), DT.get_boundary_curves(enricher) complexes = DT.get_small_angle_complexes(points, boundary_nodes, boundary_curves) - _points, _boundary_nodes = DT.polygonise(points, boundary_nodes, boundary_curves; n=2^10) + _points, _boundary_nodes = DT.polygonise(points, boundary_nodes, boundary_curves; n = 2^10) fpoints = flatten_boundary_nodes(_points, _boundary_nodes) fig, ax, sc = lines(fpoints) colors = [:red, :green, :blue, :orange, :purple, :cyan, :magenta, :yellow] @@ -2204,18 +2246,18 @@ function plot_small_angle_complexes(enricher) curve = boundary_curves[parent_curve] p, q = get_point(points, apex, next_edge) if DT.is_piecewise_linear(curve) - lines!(ax, [p, q], linewidth=4, color=colors[color_ctr]) + lines!(ax, [p, q], linewidth = 4, color = colors[color_ctr]) else t₁ = DT.get_inverse(curve, p) t₂ = DT.get_inverse(curve, q) t = LinRange(t₁, t₂, 1000) - lines!(ax, curve.(t), linewidth=4, color=colors[color_ctr]) + lines!(ax, curve.(t), linewidth = 4, color = colors[color_ctr]) end end color_ctr = mod1(color_ctr + 1, length(colors)) end p = get_point(points, apex) - scatter!(ax, [p], color=colors[1], markersize=17) + scatter!(ax, [p], color = colors[1], markersize = 17) end display(fig) return fig @@ -2304,4 +2346,4 @@ export NUM_CWEGT export get_convex_polygon_weighted_example export rt export subtypes -end \ No newline at end of file +end diff --git a/test/interfaces/boundary_nodes.jl b/test/interfaces/boundary_nodes.jl index f8bdaeea8..418ff6e63 100644 --- a/test/interfaces/boundary_nodes.jl +++ b/test/interfaces/boundary_nodes.jl @@ -5,10 +5,11 @@ using DataStructures using StaticArraysCore - -global bn1 = [[[1, 2], [3, 4], [5, 6], [10, 12]], - [[13, 25, 50], [75, 17, 5, 10]], - [[17, 293, 101], [29, 23]]] +global bn1 = [ + [[1, 2], [3, 4], [5, 6], [10, 12]], + [[13, 25, 50], [75, 17, 5, 10]], + [[17, 293, 101], [29, 23]], +] global bn2 = [[13, 25, 50], [75, 17, 5, 10]] global bn3 = [17, 293, 101, 29, 23] global map1 = DT.construct_ghost_vertex_map(bn1) @@ -17,200 +18,212 @@ global map3 = DT.construct_ghost_vertex_map(bn3) global idx = DT.𝒢 @testset "Testing number of sections/curves" begin - @test DT.has_multiple_curves(bn1) - @test !DT.has_multiple_curves(bn2) - @test !DT.has_multiple_curves(bn3) - @test !DT.has_multiple_curves(Int[]) - @test !DT.has_multiple_sections(Int[]) - @test DT.has_multiple_sections(bn1) - @test DT.has_multiple_sections(bn2) - @test !DT.has_multiple_sections(bn3) + @test DT.has_multiple_curves(bn1) + @test !DT.has_multiple_curves(bn2) + @test !DT.has_multiple_curves(bn3) + @test !DT.has_multiple_curves(Int[]) + @test !DT.has_multiple_sections(Int[]) + @test DT.has_multiple_sections(bn1) + @test DT.has_multiple_sections(bn2) + @test !DT.has_multiple_sections(bn3) end @testset "Getting number of sections/curves" begin - @test DT.num_curves(bn1) == 3 - @test DT.num_curves(bn2) == 1 - @test DT.num_curves(bn3) == 1 - @test DT.num_sections(bn2) == 2 + @test DT.num_curves(bn1) == 3 + @test DT.num_curves(bn2) == 1 + @test DT.num_curves(bn3) == 1 + @test DT.num_sections(bn2) == 2 end @testset "Number of boundary edges" begin - @test DT.num_boundary_edges(bn3) == 4 - @test DT.num_boundary_edges(bn1[1][1]) == 1 - @test DT.num_boundary_edges(bn2[2]) == 3 - @test DT.num_boundary_edges(Int[]) == 0 + @test DT.num_boundary_edges(bn3) == 4 + @test DT.num_boundary_edges(bn1[1][1]) == 1 + @test DT.num_boundary_edges(bn2[2]) == 3 + @test DT.num_boundary_edges(Int[]) == 0 end @testset "Getting boundary nodes" begin - @test get_boundary_nodes(bn1, 1) == bn1[1] - @test get_boundary_nodes(bn1, 2) == bn1[2] - @test get_boundary_nodes(bn2, 2) == bn2[2] - @test get_boundary_nodes(bn3, 4) == bn3[4] - @test get_boundary_nodes(bn1, (1, 2)) == bn1[1][2] - @test get_boundary_nodes(bn3, bn3) == bn3 + @test get_boundary_nodes(bn1, 1) == bn1[1] + @test get_boundary_nodes(bn1, 2) == bn1[2] + @test get_boundary_nodes(bn2, 2) == bn2[2] + @test get_boundary_nodes(bn3, 4) == bn3[4] + @test get_boundary_nodes(bn1, (1, 2)) == bn1[1][2] + @test get_boundary_nodes(bn3, bn3) == bn3 end @testset "Getting each boundary node" begin - @test DT.each_boundary_node(bn3) == bn3 + @test DT.each_boundary_node(bn3) == bn3 end @testset "Constructing the ghost vertex map" begin - map1 = DT.construct_ghost_vertex_map(bn1) - map2 = DT.construct_ghost_vertex_map(bn2) - map3 = DT.construct_ghost_vertex_map(bn3) - idx = DT.𝒢 - @test map1 == - Dict(idx => (1, 1), idx - 1 => (1, 2), idx - 2 => (1, 3), idx - 3 => (1, 4), - idx - 4 => (2, 1), idx - 5 => (2, 2), - idx - 6 => (3, 1), idx - 7 => (3, 2)) - @test map2 == Dict(idx => 1, idx - 1 => 2) - @test map3 == Dict(idx => bn3) + map1 = DT.construct_ghost_vertex_map(bn1) + map2 = DT.construct_ghost_vertex_map(bn2) + map3 = DT.construct_ghost_vertex_map(bn3) + idx = DT.𝒢 + @test map1 == + Dict( + idx => (1, 1), idx - 1 => (1, 2), idx - 2 => (1, 3), idx - 3 => (1, 4), + idx - 4 => (2, 1), idx - 5 => (2, 2), + idx - 6 => (3, 1), idx - 7 => (3, 2), + ) + @test map2 == Dict(idx => 1, idx - 1 => 2) + @test map3 == Dict(idx => bn3) end @testset "Getting a curve index" begin - @test DT.get_curve_index(map1, idx - 4) == 2 - @test DT.get_curve_index(map2, idx - 1) == 1 - @test DT.get_curve_index(3) == 1 - @test DT.get_curve_index((5, 7)) == 5 - @test DT.get_curve_index(map3, idx) == 1 + @test DT.get_curve_index(map1, idx - 4) == 2 + @test DT.get_curve_index(map2, idx - 1) == 1 + @test DT.get_curve_index(3) == 1 + @test DT.get_curve_index((5, 7)) == 5 + @test DT.get_curve_index(map3, idx) == 1 end @testset "Getting a section index" begin - @test DT.get_section_index(map1, idx - 4) == 1 - @test DT.get_section_index(map2, idx - 1) == 2 - @test DT.get_section_index(3) == 3 - @test DT.get_section_index((5, 7)) == 7 - @test DT.get_section_index(map3, idx) == 1 + @test DT.get_section_index(map1, idx - 4) == 1 + @test DT.get_section_index(map2, idx - 1) == 2 + @test DT.get_section_index(3) == 3 + @test DT.get_section_index((5, 7)) == 7 + @test DT.get_section_index(map3, idx) == 1 end @testset "Getting ghost vertex ranges" begin - for r in 1:500 # this example used to StackOverflow randomly, so let's just be sure it doesn't come back - d1 = DT.construct_ghost_vertex_ranges(bn1) - d2 = DT.construct_ghost_vertex_ranges(bn2) - d3 = DT.construct_ghost_vertex_ranges(bn3) - boundary_nodes = [[[1, 2, 3, 4], [4, 5, 6, 1]], - [[18, 19, 20, 25, 26, 30]], - [[50, 51, 52, 53, 54, 55], [55, 56, 57, 58], - [58, 101, 103, 105, 107, 120], - [120, 121, 122, 50]]] - d4 = DT.construct_ghost_vertex_ranges(boundary_nodes) - @test d4 == Dict(-1 => -2:-1, - -2 => -2:-1, - -3 => -3:-3, - -4 => -7:-4, - -5 => -7:-4, - -6 => -7:-4, - -7 => -7:-4) - @test d1 == Dict(-1 => -4:-1, - -2 => -4:-1, - -3 => -4:-1, - -4 => -4:-1, - -5 => -6:-5, - -6 => -6:-5, - -7 => -8:-7, - -8 => -8:-7) - @test d2 == Dict(-1 => -2:-1, -2 => -2:-1) - @test d3 == Dict(-1 => -1:-1) - - x, y = complicated_geometry() - boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; boundary_nodes) - @test tri.ghost_vertex_ranges == Dict(-1 => -4:-1, - -2 => -4:-1, - -3 => -4:-1, - -4 => -4:-1, - -5 => -5:-5, - -6 => -6:-6, - -7 => -10:-7, - -8 => -10:-7, - -9 => -10:-7, - -10 => -10:-7, - -11 => -11:-11) - end + for r in 1:500 # this example used to StackOverflow randomly, so let's just be sure it doesn't come back + d1 = DT.construct_ghost_vertex_ranges(bn1) + d2 = DT.construct_ghost_vertex_ranges(bn2) + d3 = DT.construct_ghost_vertex_ranges(bn3) + boundary_nodes = [ + [[1, 2, 3, 4], [4, 5, 6, 1]], + [[18, 19, 20, 25, 26, 30]], + [ + [50, 51, 52, 53, 54, 55], [55, 56, 57, 58], + [58, 101, 103, 105, 107, 120], + [120, 121, 122, 50], + ], + ] + d4 = DT.construct_ghost_vertex_ranges(boundary_nodes) + @test d4 == Dict( + -1 => -2:-1, + -2 => -2:-1, + -3 => -3:-3, + -4 => -7:-4, + -5 => -7:-4, + -6 => -7:-4, + -7 => -7:-4, + ) + @test d1 == Dict( + -1 => -4:-1, + -2 => -4:-1, + -3 => -4:-1, + -4 => -4:-1, + -5 => -6:-5, + -6 => -6:-5, + -7 => -8:-7, + -8 => -8:-7, + ) + @test d2 == Dict(-1 => -2:-1, -2 => -2:-1) + @test d3 == Dict(-1 => -1:-1) + + x, y = complicated_geometry() + boundary_nodes, points = convert_boundary_points_to_indices(x, y) + tri = triangulate(points; boundary_nodes) + @test tri.ghost_vertex_ranges == Dict( + -1 => -4:-1, + -2 => -4:-1, + -3 => -4:-1, + -4 => -4:-1, + -5 => -5:-5, + -6 => -6:-6, + -7 => -10:-7, + -8 => -10:-7, + -9 => -10:-7, + -10 => -10:-7, + -11 => -11:-11, + ) + end end @testset "construct_boundary_edge_map" begin - bn = [1, 2, 3, 4, 5, 6, 7, 1] - bn_map = DT.construct_boundary_edge_map(bn) - for (ij, (index, k)) in bn_map - S = get_boundary_nodes(bn, index) - @test get_boundary_nodes(S, k) == ij[1] - @test get_boundary_nodes(S, k + 1) == ij[2] - end - bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] - bn_map = DT.construct_boundary_edge_map(bn) - for (ij, (index, k)) in bn_map - S = get_boundary_nodes(bn, index) - @test get_boundary_nodes(S, k) == ij[1] - @test get_boundary_nodes(S, k + 1) == ij[2] - end - bn = [ - [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], - [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]] - ] - bn_map = DT.construct_boundary_edge_map(bn) - for (ij, (index, k)) in bn_map - S = get_boundary_nodes(bn, index) - @test get_boundary_nodes(S, k) == ij[1] - @test get_boundary_nodes(S, k + 1) == ij[2] - end - bn = Int[] - bn_map = DT.construct_boundary_edge_map(bn) - @test bn_map == Dict{Tuple{Int32,Int32},Tuple{Vector{Int},Int}}() + bn = [1, 2, 3, 4, 5, 6, 7, 1] + bn_map = DT.construct_boundary_edge_map(bn) + for (ij, (index, k)) in bn_map + S = get_boundary_nodes(bn, index) + @test get_boundary_nodes(S, k) == ij[1] + @test get_boundary_nodes(S, k + 1) == ij[2] + end + bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] + bn_map = DT.construct_boundary_edge_map(bn) + for (ij, (index, k)) in bn_map + S = get_boundary_nodes(bn, index) + @test get_boundary_nodes(S, k) == ij[1] + @test get_boundary_nodes(S, k + 1) == ij[2] + end + bn = [ + [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], + [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]], + ] + bn_map = DT.construct_boundary_edge_map(bn) + for (ij, (index, k)) in bn_map + S = get_boundary_nodes(bn, index) + @test get_boundary_nodes(S, k) == ij[1] + @test get_boundary_nodes(S, k + 1) == ij[2] + end + bn = Int[] + bn_map = DT.construct_boundary_edge_map(bn) + @test bn_map == Dict{Tuple{Int32, Int32}, Tuple{Vector{Int}, Int}}() end @testset "insert_boundary_node!" begin - bn = [1, 2, 3, 4, 5, 6, 7, 1] - DT.insert_boundary_node!(bn, (bn, 5), 17) - DT.insert_boundary_node!(bn, (bn, 1), 13) - @test bn == [13, 1, 2, 3, 4, 17, 5, 6, 7, 1] - bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] - DT.insert_boundary_node!(bn, (1, 2), 9) - DT.insert_boundary_node!(bn, (1, 4), 18) - DT.insert_boundary_node!(bn, (2, 4), 23) - DT.insert_boundary_node!(bn, (3, 1), 5) - @test bn == [[1, 9, 2, 18, 3, 4], [4, 5, 6, 23, 7, 8], [5, 8, 9, 10, 1]] - bn = [ - [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], - [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]] - ] - DT.insert_boundary_node!(bn, ((1, 1), 1), 17) - DT.insert_boundary_node!(bn, ((1, 2), 3), 38) - DT.insert_boundary_node!(bn, ((1, 3), 2), 50) - DT.insert_boundary_node!(bn, ((1, 4), 3), 67) - DT.insert_boundary_node!(bn, ((2, 1), 3), 500) - DT.insert_boundary_node!(bn, ((2, 2), 3), 87) - DT.insert_boundary_node!(bn, ((2, 3), 2), 671) - @test bn == [ - [[17, 1, 2, 3, 4, 5], [5, 6, 38, 7], [7, 50, 8], [8, 9, 67, 10, 1]], - [[13, 14, 500, 15, 16, 17], [17, 18, 87, 19, 20], [20, 671, 13]] - ] + bn = [1, 2, 3, 4, 5, 6, 7, 1] + DT.insert_boundary_node!(bn, (bn, 5), 17) + DT.insert_boundary_node!(bn, (bn, 1), 13) + @test bn == [13, 1, 2, 3, 4, 17, 5, 6, 7, 1] + bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] + DT.insert_boundary_node!(bn, (1, 2), 9) + DT.insert_boundary_node!(bn, (1, 4), 18) + DT.insert_boundary_node!(bn, (2, 4), 23) + DT.insert_boundary_node!(bn, (3, 1), 5) + @test bn == [[1, 9, 2, 18, 3, 4], [4, 5, 6, 23, 7, 8], [5, 8, 9, 10, 1]] + bn = [ + [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], + [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]], + ] + DT.insert_boundary_node!(bn, ((1, 1), 1), 17) + DT.insert_boundary_node!(bn, ((1, 2), 3), 38) + DT.insert_boundary_node!(bn, ((1, 3), 2), 50) + DT.insert_boundary_node!(bn, ((1, 4), 3), 67) + DT.insert_boundary_node!(bn, ((2, 1), 3), 500) + DT.insert_boundary_node!(bn, ((2, 2), 3), 87) + DT.insert_boundary_node!(bn, ((2, 3), 2), 671) + @test bn == [ + [[17, 1, 2, 3, 4, 5], [5, 6, 38, 7], [7, 50, 8], [8, 9, 67, 10, 1]], + [[13, 14, 500, 15, 16, 17], [17, 18, 87, 19, 20], [20, 671, 13]], + ] end @testset "delete_boundary_node!" begin - bn = [1, 2, 3, 4, 5, 6, 7, 1] - DT.delete_boundary_node!(bn, (bn, 5)) - DT.delete_boundary_node!(bn, (bn, 1)) - @test bn == [2, 3, 4, 6, 7, 1] - bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] - DT.delete_boundary_node!(bn, (1, 2)) - DT.delete_boundary_node!(bn, (1, 2)) - DT.delete_boundary_node!(bn, (2, 4)) - DT.delete_boundary_node!(bn, (3, 1)) - @test bn == [[1, 4], [4, 5, 6, 8], [9, 10, 1]] - bn = [ - [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], - [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]] - ] - DT.delete_boundary_node!(bn, ((1, 1), 1)) - DT.delete_boundary_node!(bn, ((1, 2), 3)) - DT.delete_boundary_node!(bn, ((1, 3), 2)) - DT.delete_boundary_node!(bn, ((1, 4), 3)) - DT.delete_boundary_node!(bn, ((2, 1), 3)) - DT.delete_boundary_node!(bn, ((2, 2), 3)) - DT.delete_boundary_node!(bn, ((2, 3), 2)) - @test bn == [ - [[2, 3, 4, 5], [5, 6], [7], [8, 9, 1]], - [[13, 14, 16, 17], [17, 18, 20], [20]] - ] -end \ No newline at end of file + bn = [1, 2, 3, 4, 5, 6, 7, 1] + DT.delete_boundary_node!(bn, (bn, 5)) + DT.delete_boundary_node!(bn, (bn, 1)) + @test bn == [2, 3, 4, 6, 7, 1] + bn = [[1, 2, 3, 4], [4, 5, 6, 7, 8], [8, 9, 10, 1]] + DT.delete_boundary_node!(bn, (1, 2)) + DT.delete_boundary_node!(bn, (1, 2)) + DT.delete_boundary_node!(bn, (2, 4)) + DT.delete_boundary_node!(bn, (3, 1)) + @test bn == [[1, 4], [4, 5, 6, 8], [9, 10, 1]] + bn = [ + [[1, 2, 3, 4, 5], [5, 6, 7], [7, 8], [8, 9, 10, 1]], + [[13, 14, 15, 16, 17], [17, 18, 19, 20], [20, 13]], + ] + DT.delete_boundary_node!(bn, ((1, 1), 1)) + DT.delete_boundary_node!(bn, ((1, 2), 3)) + DT.delete_boundary_node!(bn, ((1, 3), 2)) + DT.delete_boundary_node!(bn, ((1, 4), 3)) + DT.delete_boundary_node!(bn, ((2, 1), 3)) + DT.delete_boundary_node!(bn, ((2, 2), 3)) + DT.delete_boundary_node!(bn, ((2, 3), 2)) + @test bn == [ + [[2, 3, 4, 5], [5, 6], [7], [8, 9, 1]], + [[13, 14, 16, 17], [17, 18, 20], [20]], + ] +end diff --git a/test/interfaces/edges.jl b/test/interfaces/edges.jl index 5e6404509..754391977 100644 --- a/test/interfaces/edges.jl +++ b/test/interfaces/edges.jl @@ -8,7 +8,7 @@ global i = 17 global j = 5 global e1 = (i, j) global e2 = [i, j] -global e3 = SVector{2,Int32}((i, j)) +global e3 = SVector{2, Int32}((i, j)) @testset "Individual edges" begin @testset "Constructing an edge" begin @@ -45,11 +45,15 @@ end global es1 = Set{typeof(e1)}(((1, 3), (4, 1), (10, 1), (3, 9), (5, 3))) global es2 = Set{typeof(e2)}(([1, 3], [4, 1], [10, 1], [3, 9], [5, 3])) -global es3 = Set{typeof(e3)}((SVector{2,Int32}((1, 3)), - SVector{2,Int32}((4, 1)), - SVector{2,Int32}((10, 1)), - SVector{2,Int32}((3, 9)), - SVector{2,Int32}((5, 3)))) +global es3 = Set{typeof(e3)}( + ( + SVector{2, Int32}((1, 3)), + SVector{2, Int32}((4, 1)), + SVector{2, Int32}((10, 1)), + SVector{2, Int32}((3, 9)), + SVector{2, Int32}((5, 3)), + ), +) @testset "Collection of edges" begin @testset "Getting the type of edges in a collection" begin @@ -57,7 +61,7 @@ global es3 = Set{typeof(e3)}((SVector{2,Int32}((1, 3)), F = eltype(es) @test DT.edge_type(typeof(es)) == F end - @test DT.edge_type(Vector{NTuple{2,Int}}) == NTuple{2,Int} + @test DT.edge_type(Vector{NTuple{2, Int}}) == NTuple{2, Int} end @testset "Number of edges" begin @@ -159,4 +163,4 @@ end @test !DT.edges_are_disjoint(e, e′) e′ = (3, 2) @test !DT.edges_are_disjoint(e, e′) -end \ No newline at end of file +end diff --git a/test/interfaces/points.jl b/test/interfaces/points.jl index 9f8a36613..b67d71f4a 100644 --- a/test/interfaces/points.jl +++ b/test/interfaces/points.jl @@ -7,7 +7,7 @@ import GeometryBasics: Point2f global p1 = [1.3, 2.5] global p2 = (1.3, 2.5) -global p3 = SVector{2,Float32}((1.3, 2.5)) +global p3 = SVector{2, Float32}((1.3, 2.5)) @testset "Individual points" begin @testset "Getting coordinates" begin @@ -52,9 +52,9 @@ global pts4 = ((2.0, 3.5), (1.7, 23.3), (-1.0, 0.0)) @test DT.get_point(pts, (2.0, 5.3), (17.0, 5.3)) == ((2.0, 5.3), (17.0, 5.3)) @inferred DT.get_point(pts, (2.0, 5.3), (17.0, 5.3)) == ((2.0, 5.3), (17.0, 5.3)) @test DT.get_point(pts, 1, 2, (17.0, -2.0), (57.0, 23.0)) == - ((2.0, 3.5), (1.7, 23.3), (17.0, -2.0), (57.0, 23.0)) + ((2.0, 3.5), (1.7, 23.3), (17.0, -2.0), (57.0, 23.0)) @inferred DT.get_point(pts, 1, 2, (17.0, -2.0), (57.0, 23.0)) == - ((2.0, 3.5), (1.7, 23.3), (17.0, -2.0), (57.0, 23.0)) + ((2.0, 3.5), (1.7, 23.3), (17.0, -2.0), (57.0, 23.0)) end end @@ -94,18 +94,22 @@ global pts4 = ((2.0, 3.5), (1.7, 23.3), (-1.0, 0.0)) end @testset "Sorting points lexicographically" begin - A = [2.0 5.0 1.0 10.0 17.0 23.0 5.0 5.0 - 7.0 2.0 0.0 7.5 2.0 -2.5 3.5 3.0] + A = [ + 2.0 5.0 1.0 10.0 17.0 23.0 5.0 5.0 + 7.0 2.0 0.0 7.5 2.0 -2.5 3.5 3.0 + ] idx = DT.lexicographic_order(A) @test idx == [3, 1, 2, 8, 7, 4, 5, 6] - A = [(2.0, 7.0), + A = [ + (2.0, 7.0), (5.0, 2.0), (1.0, 0.0), (10.0, 7.5), (17.0, 2.0), (23.0, -2.5), (5.0, 3.5), - (5.0, 3.0)] + (5.0, 3.0), + ] idx = DT.lexicographic_order(A) @test idx == [3, 1, 2, 8, 7, 4, 5, 6] end @@ -162,9 +166,9 @@ global pts4 = ((2.0, 3.5), (1.7, 23.3), (-1.0, 0.0)) DT.set_point!(points, 2, 3.4, 6.7) @test points == [[1.0, 5.0], [3.4, 6.7]] - points = [SVector{2,Float64}(1.0, 5.4), SVector{2,Float64}(6.5, 2.3)] + points = [SVector{2, Float64}(1.0, 5.4), SVector{2, Float64}(6.5, 2.3)] DT.set_point!(points, 2, 3.4, 6.7) - @test points == [SVector{2,Float64}(1.0, 5.4), SVector{2,Float64}(3.4, 6.7)] + @test points == [SVector{2, Float64}(1.0, 5.4), SVector{2, Float64}(3.4, 6.7)] points = [Float32[1.0, 5.0], Float32[2.3, -6.7]] DT.set_point!(points, 1, 2.3, 6.9) @@ -180,7 +184,7 @@ end points1 = [(1.0, 2.0), (5.0, 9.0), (3.0, 4.0)] points2 = [1.0 5.0 3.0; 2.0 9.0 4.0] points3 = rand(2, 75) - points4 = [SVector{2,Float32}((1.0, 2.0)), SVector{2,Float32}((5.0, 9.0)), SVector{2,Float32}((3.0, 4.0))] + points4 = [SVector{2, Float32}((1.0, 2.0)), SVector{2, Float32}((5.0, 9.0)), SVector{2, Float32}((3.0, 4.0))] points5 = [Point2f(1.0, 2.0), Point2f(5.0, 9.0), Point2f(3.0, 4.0)] points6 = [Float32[1.0, 2.0], Float32[5.0, 9.0], Float32[3.0, 4.0]] @test DT.find_point_index(points1, 1.0, 2.0) == 1 @@ -225,13 +229,13 @@ end (17.5, 17.5), (0.0, 0.0), (0.0, 0.0), - (20.0, 20.0) + (20.0, 20.0), ] dict = DT.find_duplicate_points(points) @test dict == Dict( (1.0, 2.0) => [1, 4], (17.5, 17.5) => [3, 6], - (0.0, 0.0) => [7, 8] + (0.0, 0.0) => [7, 8], ) end @@ -241,8 +245,8 @@ end r = [1.0f0, 4.0f0, 5.0f0] s = @SVector [3, 7, 5] t = [5.0, 13.0, -5.0] - - @test DT.getz(p) === 3.0 + + @test DT.getz(p) === 3.0 @test DT._getz(p) === 3.0 @test DT.getxyz(p) === (1.0, 2.0, 3.0) @test DT._getxyz(p) === (1.0, 2.0, 3.0) @@ -268,20 +272,19 @@ end @test DT._getxyz(t) === (5.0, 13.0, -5.0) end -@testset "is_point2/is_point3" begin - @test DT.is_point2((1.0,2.0)) - @test !DT.is_point2((1.0,2.0,3.0)) +@testset "is_point2/is_point3" begin + @test DT.is_point2((1.0, 2.0)) + @test !DT.is_point2((1.0, 2.0, 3.0)) @test !DT.is_point2((1.0,)) - @test DT.is_point2([1.0,2.0]) - @test !DT.is_point2([1.0,2.0,3.0]) - @test DT.is_point2(SVector{2,Float64}(1.0,2.0)) - @test DT.is_point2(Point2f(1.0,2.0)) - @test !DT.is_point2([[1.0,1.0]]) - @test !DT.is_point2([[1.0,2.0],[1.0,2.0]]) - - @test DT.is_point3((1.0,2.0,3.0)) - @test DT.is_point3([1.0,2.0,3.0]) - @test !DT.is_point3([[1.0,2.0,3.0],[3.0,4.0,5.0],[1.0,2.0,3.0]]) - @test DT.is_point3(SVector{3,Float64}(1.0,2.0,3.0)) -end + @test DT.is_point2([1.0, 2.0]) + @test !DT.is_point2([1.0, 2.0, 3.0]) + @test DT.is_point2(SVector{2, Float64}(1.0, 2.0)) + @test DT.is_point2(Point2f(1.0, 2.0)) + @test !DT.is_point2([[1.0, 1.0]]) + @test !DT.is_point2([[1.0, 2.0], [1.0, 2.0]]) + @test DT.is_point3((1.0, 2.0, 3.0)) + @test DT.is_point3([1.0, 2.0, 3.0]) + @test !DT.is_point3([[1.0, 2.0, 3.0], [3.0, 4.0, 5.0], [1.0, 2.0, 3.0]]) + @test DT.is_point3(SVector{3, Float64}(1.0, 2.0, 3.0)) +end diff --git a/test/interfaces/triangles.jl b/test/interfaces/triangles.jl index c00e45c83..c0626a106 100644 --- a/test/interfaces/triangles.jl +++ b/test/interfaces/triangles.jl @@ -8,15 +8,15 @@ global j = 5 global k = 10 global T1 = (i, j, k) global T2 = [i, j, k] -global T3 = SVector{3,Int32}((i, j, k)) +global T3 = SVector{3, Int32}((i, j, k)) @testset "Individual triangles" begin @testset "Constructing a triangle" begin @test_throws MethodError DT.construct_triangle(String, i, j, k) - @test DT.construct_triangle(NTuple{3,Int}, i, j, k) == T1 + @test DT.construct_triangle(NTuple{3, Int}, i, j, k) == T1 @test DT.construct_triangle(Vector{Int}, i, j, k) == T2 - @test DT.construct_triangle(SVector{3,Int32}, i, j, k) == T3 - @inferred DT.construct_triangle(NTuple{3,Int}, i, j, k) + @test DT.construct_triangle(SVector{3, Int32}, i, j, k) == T3 + @inferred DT.construct_triangle(NTuple{3, Int}, i, j, k) end @testset "Getting indices" begin @@ -42,10 +42,10 @@ global T3 = SVector{3,Int32}((i, j, k)) @testset "Edges of a triangle" begin @test DT.triangle_edges(T1) == - DT.triangle_edges(T2) == - DT.triangle_edges(T3) == - DT.triangle_edges(i, j, k) == - ((i, j), (j, k), (k, i)) + DT.triangle_edges(T2) == + DT.triangle_edges(T3) == + DT.triangle_edges(i, j, k) == + ((i, j), (j, k), (k, i)) @inferred DT.triangle_edges(T1) end @@ -53,7 +53,7 @@ global T3 = SVector{3,Int32}((i, j, k)) for T in (T1, T2, T3) for r in 0:2 @test DT.rotate_triangle(T, r) == - DT.construct_triangle(typeof(T), ((i, j, k), (j, k, i), (k, i, j))[r+1]...) + DT.construct_triangle(typeof(T), ((i, j, k), (j, k, i), (k, i, j))[r + 1]...) @inferred DT.rotate_triangle(T, r) end end @@ -84,10 +84,10 @@ global T3 = SVector{3,Int32}((i, j, k)) i = 1 j = (0.3, 0.5) k = 5 - P = NTuple{2,Float64} + P = NTuple{2, Float64} I = Int - types = Union{Tuple{I,I,P},Tuple{I,P,I},Tuple{P,I,I}} - types2 = Union{Tuple{P,P,I},Tuple{P,I,P},Tuple{P,P,I}} + types = Union{Tuple{I, I, P}, Tuple{I, P, I}, Tuple{P, I, I}} + types2 = Union{Tuple{P, P, I}, Tuple{P, I, P}, Tuple{P, P, I}} @test DT.sort_triangle(i, j, k) == (i, j, k) @inferred types DT.sort_triangle(i, j, k) @test DT.sort_triangle(5, 7, (0.9, 0.2)) == (5, 7, (0.9, 0.2)) @@ -105,19 +105,23 @@ end global Ts1 = Set{typeof(T1)}(((1, 2, 3), (4, 6, 1), (10, 6, 1), (3, 10, 9), (5, 10, 3))) global Ts2 = Set{typeof(T2)}(([1, 2, 3], [4, 6, 1], [10, 6, 1], [3, 10, 9], [5, 10, 3])) -global Ts3 = Set{typeof(T3)}((SVector{3,Int32}((1, 2, 3)), - SVector{3,Int32}((4, 6, 1)), - SVector{3,Int32}((10, 6, 1)), - SVector{3,Int32}((3, 10, 9)), - SVector{3,Int32}((5, 10, 3)))) +global Ts3 = Set{typeof(T3)}( + ( + SVector{3, Int32}((1, 2, 3)), + SVector{3, Int32}((4, 6, 1)), + SVector{3, Int32}((10, 6, 1)), + SVector{3, Int32}((3, 10, 9)), + SVector{3, Int32}((5, 10, 3)), + ), +) @testset "Collection of triangles" begin @testset "Getting the eltype of a collection of triangles" begin for (T, Ts) in zip((T1, T2, T3), (Ts1, Ts2, Ts3)) @test DT.triangle_type(typeof(Ts)) == typeof(T) end - @test DT.triangle_type(Vector{NTuple{3,Int}}) == NTuple{3,Int} - @inferred DT.triangle_type(Vector{NTuple{3,Int}}) + @test DT.triangle_type(Vector{NTuple{3, Int}}) == NTuple{3, Int} + @inferred DT.triangle_type(Vector{NTuple{3, Int}}) end @testset "Number of triangles" begin @@ -169,7 +173,7 @@ global Ts3 = Set{typeof(T3)}((SVector{3,Int32}((1, 2, 3)), V5 = DT.construct_triangle(V, 20, 25, 50) V6 = [17, 23, 507] V7 = (1, 100, 500) - V8 = SVector{3,Int32}(100, 50, 901) + V8 = SVector{3, Int32}(100, 50, 901) G6 = DT.construct_triangle(V, V6...) G7 = DT.construct_triangle(V, V7...) G8 = DT.construct_triangle(V, V8...) @@ -185,7 +189,7 @@ global Ts3 = Set{typeof(T3)}((SVector{3,Int32}((1, 2, 3)), end @test length(Ts) == 13 end - T = Vector{NTuple{3,Int}}() + T = Vector{NTuple{3, Int}}() DT.add_triangle!(T, (1, 2, 3)) DT.add_triangle!(T, (5, 6, 8), (9, 10, 12)) DT.add_triangle!(T, [13, 14, 15]) @@ -230,67 +234,91 @@ global Ts3 = Set{typeof(T3)}((SVector{3,Int32}((1, 2, 3)), @testset "Getting a positively oriented triangle" begin points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] - @test DT.construct_positively_oriented_triangle(NTuple{3,Int}, 1, 2, 3, points) == - (1, 2, 3) - @test DT.construct_positively_oriented_triangle(NTuple{3,Int}, 2, 1, 3, points) == - (1, 2, 3) - @inferred DT.construct_positively_oriented_triangle(NTuple{3,Int}, 2, 1, 3, points) + @test DT.construct_positively_oriented_triangle(NTuple{3, Int}, 1, 2, 3, points) == + (1, 2, 3) + @test DT.construct_positively_oriented_triangle(NTuple{3, Int}, 2, 1, 3, points) == + (1, 2, 3) + @inferred DT.construct_positively_oriented_triangle(NTuple{3, Int}, 2, 1, 3, points) end @testset "Comparing collections of triangles" begin - T = Set{NTuple{3,Int}}(((1, 2, 3), - (2, 3, 4), - (4, 5, 6), - (6, 9, 11))) - V = Set{NTuple{3,Int}}(((1, 2, 3), - (2, 3, 4), - (4, 5, 6), - (6, 9, 11))) + T = Set{NTuple{3, Int}}( + ( + (1, 2, 3), + (2, 3, 4), + (4, 5, 6), + (6, 9, 11), + ), + ) + V = Set{NTuple{3, Int}}( + ( + (1, 2, 3), + (2, 3, 4), + (4, 5, 6), + (6, 9, 11), + ), + ) @test DT.compare_triangle_collections(T, V) - V = Set{NTuple{3,Int}}(((1, 2, 3), - (2, 3, 4), - (4, 5, 6))) + V = Set{NTuple{3, Int}}( + ( + (1, 2, 3), + (2, 3, 4), + (4, 5, 6), + ), + ) @test !DT.compare_triangle_collections(T, V) - V = Set{NTuple{3,Int}}(((3, 1, 2), - (3, 4, 2), - (6, 4, 5), - (6, 9, 11))) + V = Set{NTuple{3, Int}}( + ( + (3, 1, 2), + (3, 4, 2), + (6, 4, 5), + (6, 9, 11), + ), + ) @test DT.compare_triangle_collections(T, V) - V = Set{NTuple{3,Int}}(((3, 1, 2), - (3, 4, 2), - (6, 4, 5), - (6, 11, 9))) + V = Set{NTuple{3, Int}}( + ( + (3, 1, 2), + (3, 4, 2), + (6, 4, 5), + (6, 11, 9), + ), + ) @test !DT.compare_triangle_collections(T, V) @inferred DT.compare_triangle_collections(T, V) end @testset "Sorting a collection of triangles" begin - T = Set{NTuple{3,Int}}([ - (1, 2, 3), - (10, 9, 3), - (11, 5, 1), - (193, 12, 10), - (5, 3, 1), - (19, 18, 17), - (17, 5, 23), - (20, 50, 72), - (30, 31, 32), - (20, 13, 37) - ]) + T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), + (10, 9, 3), + (11, 5, 1), + (193, 12, 10), + (5, 3, 1), + (19, 18, 17), + (17, 5, 23), + (20, 50, 72), + (30, 31, 32), + (20, 13, 37), + ], + ) V = DT.sort_triangles(T) @inferred DT.sort_triangles(T) - @test V == Set{NTuple{3,Int}}([ - (2, 3, 1), - (10, 9, 3), - (11, 5, 1), - (193, 12, 10), - (5, 3, 1), - (19, 18, 17), - (23, 17, 5), - (50, 72, 20), - (31, 32, 30), - (37, 20, 13) - ]) + @test V == Set{NTuple{3, Int}}( + [ + (2, 3, 1), + (10, 9, 3), + (11, 5, 1), + (193, 12, 10), + (5, 3, 1), + (19, 18, 17), + (23, 17, 5), + (50, 72, 20), + (31, 32, 30), + (37, 20, 13), + ], + ) @test DT.compare_triangle_collections(T, V) end -end \ No newline at end of file +end diff --git a/test/operations/add_ghost_triangles.jl b/test/operations/add_ghost_triangles.jl index acdc2e801..4d57282e3 100644 --- a/test/operations/add_ghost_triangles.jl +++ b/test/operations/add_ghost_triangles.jl @@ -7,24 +7,30 @@ using StaticArrays tri, label_map, index_map = simple_geometry() DT.add_ghost_triangles!(tri) - outer_edges = [("a", "b") => DT.𝒢, + outer_edges = [ + ("a", "b") => DT.𝒢, ("b", "c") => DT.𝒢, ("c", "d") => DT.𝒢, ("d", "e") => DT.𝒢, ("e", "f") => DT.𝒢, ("f", "g") => DT.𝒢, ("g", "h") => DT.𝒢, - ("h", "a") => DT.𝒢] - inner_edges_1 = [("k", "j") => DT.𝒢 - 1, + ("h", "a") => DT.𝒢, + ] + inner_edges_1 = [ + ("k", "j") => DT.𝒢 - 1, ("j", "i") => DT.𝒢 - 1, ("i", "ℓ") => DT.𝒢 - 1, - ("ℓ", "k") => DT.𝒢 - 1] - inner_edges_2 = [("r", "q") => DT.𝒢 - 2, + ("ℓ", "k") => DT.𝒢 - 1, + ] + inner_edges_2 = [ + ("r", "q") => DT.𝒢 - 2, ("q", "p") => DT.𝒢 - 2, ("p", "o") => DT.𝒢 - 3, ("o", "n") => DT.𝒢 - 3, ("n", "m") => DT.𝒢 - 3, - ("m", "r") => DT.𝒢 - 3] + ("m", "r") => DT.𝒢 - 3, + ] for ((a, b), k) in outer_edges i = index_map[a] @@ -39,4 +45,4 @@ using StaticArrays @test DT.contains_edge(i, k, DT.get_adjacent2vertex(tri, j)) @test DT.contains_edge(k, j, DT.get_adjacent2vertex(tri, i)) end -end \ No newline at end of file +end diff --git a/test/operations/add_point.jl b/test/operations/add_point.jl index 5f8bc3c8f..072bdea4f 100644 --- a/test/operations/add_point.jl +++ b/test/operations/add_point.jl @@ -10,13 +10,13 @@ rng = StableRNG(8888) @testset "Adding a point" begin for _ in 1:150 pts = tuple.(rand(50), rand(50)) - tri = DT.triangulate(pts, delete_ghosts=false, skip_points=4:50) + tri = DT.triangulate(pts, delete_ghosts = false, skip_points = 4:50) for i in setdiff(DT.each_point_index(pts), DT.get_vertices(tri)) - add_point!(tri, i; predicates=rt()) + add_point!(tri, i; predicates = rt()) @test validate_triangulation(tri) end @test num_solid_vertices(tri) == DT.num_points(tri) - DT.convex_hull!(tri; reconstruct=false) + DT.convex_hull!(tri; reconstruct = false) DT.clear_empty_features!(tri) _tri = triangulate(pts; rng) DT.compute_representative_points!(tri) @@ -45,7 +45,7 @@ end tri = triangulate(pts) _tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) - add_point!(tri, 0.4, 0.4, store_event_history=Val(true), event_history=history, peek=Val(true)) + add_point!(tri, 0.4, 0.4, store_event_history = Val(true), event_history = history, peek = Val(true)) @test DT.compare_triangle_collections(get_triangles(_tri), get_triangles(tri)) DT.clear_empty_features!(tri) @test get_adjacent(tri) == get_adjacent(_tri) @@ -62,20 +62,22 @@ end end @test get_points(tri) == get_points(_tri) - tri = triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 11, 6, delete_ghosts=false) + tri = triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 11, 6, delete_ghosts = false) _tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) - for (x, y) in [(0.0, 0.23), (0.0, 0.8), (1.0, 1.0), (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (0.39881, 0.0), (0.5, 1.0), (0.0, 0.4), (1.0, 0.881), - [(0.0, rand()) for _ in 1:50]..., [(rand(), 0.0) for _ in 1:50]..., [(rand(), 1.0) for _ in 1:50]..., [(1.0, rand()) for _ in 1:50]..., - [(rand(), rand()) for _ in 1:500]...] + for (x, y) in [ + (0.0, 0.23), (0.0, 0.8), (1.0, 1.0), (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (0.39881, 0.0), (0.5, 1.0), (0.0, 0.4), (1.0, 0.881), + [(0.0, rand()) for _ in 1:50]..., [(rand(), 0.0) for _ in 1:50]..., [(rand(), 1.0) for _ in 1:50]..., [(1.0, rand()) for _ in 1:50]..., + [(rand(), rand()) for _ in 1:500]..., + ] empty!(history) if rand() < 1 / 2 - add_point!(tri, x, y, store_event_history=Val(true), event_history=history, peek=Val(true)) + add_point!(tri, x, y, store_event_history = Val(true), event_history = history, peek = Val(true)) else - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history, peek=Val(true)) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history, peek = Val(true)) end DT.clear_empty_features!(tri) - @test tri ==_tri + @test tri == _tri @test length(history.added_triangles) > 0 @test length(history.deleted_triangles) > 0 for T in DT.each_added_triangle(history) @@ -91,10 +93,10 @@ end @testset "Peeking concurrency" begin pts = [(rand(), rand()) for _ in 1:50] - tri = triangulate(pts, delete_ghosts=false) + tri = triangulate(pts, delete_ghosts = false) Base.Threads.@threads for _ in 1:500 history = DT.InsertionEventHistory(tri) - add_point!(tri, rand(2), store_event_history=Val(true), event_history=history, peek=Val(true)) + add_point!(tri, rand(2), store_event_history = Val(true), event_history = history, peek = Val(true)) end @test DT.num_points(tri) == 50 end diff --git a/test/operations/add_triangle.jl b/test/operations/add_triangle.jl index 7c7936fe0..f1164250a 100644 --- a/test/operations/add_triangle.jl +++ b/test/operations/add_triangle.jl @@ -10,339 +10,370 @@ global x = _x global y = _y boundary_nodes, points = convert_boundary_points_to_indices(x, y) rng = StableRNG(9881) -global tri = triangulate(points; boundary_nodes, rng, delete_ghosts=false) +global tri = triangulate(points; boundary_nodes, rng, delete_ghosts = false) A = get_area(tri) -refine!(tri; max_area=1e-3A, rng, use_circumcenter=true) +refine!(tri; max_area = 1.0e-3A, rng, use_circumcenter = true) boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) rng = StableRNG(9881) -global tri_2 = triangulate(points; boundary_nodes, rng, delete_ghosts=false) +global tri_2 = triangulate(points; boundary_nodes, rng, delete_ghosts = false) A = get_area(tri_2) -refine!(tri_2; max_area=1e-3A, rng, use_circumcenter=true) +refine!(tri_2; max_area = 1.0e-3A, rng, use_circumcenter = true) global i, j, k = 451, 307, 227 global u, v, w = 420, 417, 418 global T = (u, v, w) @testset "Simple add, no connections" begin - DT.add_triangle!(tri, i, j, k) - DT.add_triangle!(tri, T) - for ((a, b, c)) in ((i, j, k), (u, v, w)) - @test DT.get_adjacent(tri, a, b) == c - @test DT.get_adjacent(tri, b, c) == a - @test DT.get_adjacent(tri, c, a) == b - @test (a, b) ∈ DT.get_adjacent2vertex(tri, c) - @test (b, c) ∈ DT.get_adjacent2vertex(tri, a) - @test (c, a) ∈ DT.get_adjacent2vertex(tri, b) - @test a ∈ DT.get_neighbours(tri, b) && a ∈ DT.get_neighbours(tri, c) - @test b ∈ DT.get_neighbours(tri, a) && b ∈ DT.get_neighbours(tri, c) - @test c ∈ DT.get_neighbours(tri, a) && c ∈ DT.get_neighbours(tri, b) - @test (a, b, c) ∈ tri.triangles - end + DT.add_triangle!(tri, i, j, k) + DT.add_triangle!(tri, T) + for ((a, b, c)) in ((i, j, k), (u, v, w)) + @test DT.get_adjacent(tri, a, b) == c + @test DT.get_adjacent(tri, b, c) == a + @test DT.get_adjacent(tri, c, a) == b + @test (a, b) ∈ DT.get_adjacent2vertex(tri, c) + @test (b, c) ∈ DT.get_adjacent2vertex(tri, a) + @test (c, a) ∈ DT.get_adjacent2vertex(tri, b) + @test a ∈ DT.get_neighbours(tri, b) && a ∈ DT.get_neighbours(tri, c) + @test b ∈ DT.get_neighbours(tri, a) && b ∈ DT.get_neighbours(tri, c) + @test c ∈ DT.get_neighbours(tri, a) && c ∈ DT.get_neighbours(tri, b) + @test (a, b, c) ∈ tri.triangles + end end @testset "Adding to empty triangulation, ghost edges included" begin - pts = rand(2, 500) - u, v, w = 37, 38, 73 - pts[:, u] .= 0.0 - pts[:, v] .= [1.0, 0.0] - pts[:, w] .= [0.0, 1.0] - tri = Triangulation(pts) - DT.add_triangle!(tri, (u, v, w); update_ghost_edges=true) - BI = DT.𝒢 - @test get_triangles(tri) == Set(((u, v, w), (w, v, BI), (v, u, BI), (u, w, BI))) - @test get_adjacent(get_adjacent(tri)) == Dict((u, v) => w, - (v, w) => u, - (w, u) => v, - (w, v) => BI, - (v, BI) => w, - (BI, w) => v, - (v, u) => BI, - (u, BI) => v, - (BI, v) => u, - (u, w) => BI, - (w, BI) => u, - (BI, u) => w) - @test get_adjacent2vertex(get_adjacent2vertex(tri)) == - Dict(BI => Set{NTuple{2,Int}}([(w, v), (v, u), (u, w)]), - u => Set{NTuple{2,Int}}([(v, w), (BI, v), (w, BI)]), - v => Set{NTuple{2,Int}}([(w, u), (BI, w), (u, BI)]), - w => Set{NTuple{2,Int}}([(u, v), (v, BI), (BI, u)])) - @test get_graph(tri).edges == - Set([(BI, v), (u, w), (u, v), (BI, w), (BI, u), (v, w)]) - @test get_graph(tri).vertices == Set([u, v, w, BI]) + pts = rand(2, 500) + u, v, w = 37, 38, 73 + pts[:, u] .= 0.0 + pts[:, v] .= [1.0, 0.0] + pts[:, w] .= [0.0, 1.0] + tri = Triangulation(pts) + DT.add_triangle!(tri, (u, v, w); update_ghost_edges = true) + BI = DT.𝒢 + @test get_triangles(tri) == Set(((u, v, w), (w, v, BI), (v, u, BI), (u, w, BI))) + @test get_adjacent(get_adjacent(tri)) == Dict( + (u, v) => w, + (v, w) => u, + (w, u) => v, + (w, v) => BI, + (v, BI) => w, + (BI, w) => v, + (v, u) => BI, + (u, BI) => v, + (BI, v) => u, + (u, w) => BI, + (w, BI) => u, + (BI, u) => w, + ) + @test get_adjacent2vertex(get_adjacent2vertex(tri)) == + Dict( + BI => Set{NTuple{2, Int}}([(w, v), (v, u), (u, w)]), + u => Set{NTuple{2, Int}}([(v, w), (BI, v), (w, BI)]), + v => Set{NTuple{2, Int}}([(w, u), (BI, w), (u, BI)]), + w => Set{NTuple{2, Int}}([(u, v), (v, BI), (BI, u)]), + ) + @test get_graph(tri).edges == + Set([(BI, v), (u, w), (u, v), (BI, w), (BI, u), (v, w)]) + @test get_graph(tri).vertices == Set([u, v, w, BI]) end @testset "Smaller example" begin - tri = example_triangulation() - i, j, k = 1, 3, 7 - DT.add_triangle!(tri, i, j, k) + tri = example_triangulation() + i, j, k = 1, 3, 7 + DT.add_triangle!(tri, i, j, k) - @testset "Adding an interior triangle" begin - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 3, 7), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3) - ]) + @testset "Adding an interior triangle" begin + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 3, 7), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + ], + ) + true_adj = + Dict( + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (4, 5) => DT.𝒢, (5, 2) => DT.𝒢, + (2, 3) => DT.𝒢, (3, 6) => DT.𝒢, + (6, 4) => DT.𝒢, + ) + true_adj2v = Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (7, 1), (1, 6)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 3)]), + ) + true_DG = [ + 0 0 1 1 1 1 1 0 + 0 0 0 1 1 1 1 1 + 1 0 0 1 0 1 0 0 + 1 1 1 0 0 1 1 1 + 1 1 0 0 0 1 1 0 + 1 1 1 1 1 0 0 0 + 1 1 0 1 1 0 0 0 + 0 1 0 1 0 0 0 0 + ] + true_DG = _make_graph_from_adjacency(true_DG, Dict(1:8 .=> [-1, (1:7)...])) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v + @test get_graph(tri) == true_DG + end + + @testset "Adding a boundary triangle with one boundary edge" begin + for (i, j, k) in ((5, 2, 8), (2, 8, 5), (8, 5, 2)) + local true_T, true_adj, true_adj2v, true_DG + _tri = deepcopy(tri) + DT.add_triangle!(_tri, i, j, k) + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 3, 7), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + (i, j, k), + ], + ) true_adj = - Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (4, 5) => DT.𝒢, (5, 2) => DT.𝒢, - (2, 3) => DT.𝒢, (3, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + Dict( + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, + (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, + (8, 2) => DT.𝒢, (2, 3) => DT.𝒢, + (3, 6) => DT.𝒢, (6, 4) => DT.𝒢, + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (7, 1), (1, 6)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 3)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 3), (3, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (8, 5)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (7, 1), (1, 6)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 3)]), + 8 => Set{NTuple{2, Int}}([(5, 2)]), ) - true_DG = [0 0 1 1 1 1 1 0 - 0 0 0 1 1 1 1 1 - 1 0 0 1 0 1 0 0 - 1 1 1 0 0 1 1 1 - 1 1 0 0 0 1 1 0 - 1 1 1 1 1 0 0 0 - 1 1 0 1 1 0 0 0 - 0 1 0 1 0 0 0 0] - true_DG = _make_graph_from_adjacency(true_DG, Dict(1:8 .=> [-1, (1:7)...])) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v - @test get_graph(tri) == true_DG - end - - @testset "Adding a boundary triangle with one boundary edge" begin - for (i, j, k) in ((5, 2, 8), (2, 8, 5), (8, 5, 2)) - local true_T, true_adj, true_adj2v, true_DG - _tri = deepcopy(tri) - DT.add_triangle!(_tri, i, j, k) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 3, 7), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3), - (i, j, k) - ]) - true_adj = - Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, - (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, - (8, 2) => DT.𝒢, (2, 3) => DT.𝒢, - (3, 6) => DT.𝒢, (6, 4) => DT.𝒢 - ) - true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 3), (3, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (8, 5)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (7, 1), (1, 6)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 3)]), - 8 => Set{NTuple{2,Int}}([(5, 2)]) - ) - true_DG = _make_graph_from_adjacency([ - 0 0 1 1 1 1 1 0 1 - 0 0 0 1 1 1 1 1 0 - 1 0 0 1 0 1 0 0 1 - 1 1 1 0 0 1 1 1 0 - 1 1 0 0 0 1 1 0 0 - 1 1 1 1 1 0 0 0 1 - 1 1 0 1 1 0 0 0 0 - 0 1 0 1 0 0 0 0 0 - 1 0 1 0 0 1 0 0 0 - ], Dict(1:9 .=> [-1, (1:8)...])) - DT.clear_empty_features!(_tri) - @test get_triangles(_tri) == true_T - @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(_tri) == true_adj2v - @test get_graph(_tri) == true_DG - end - DT.add_triangle!(tri, 5, 2, 8) # Get an actual copy for later, test is above - end + true_DG = _make_graph_from_adjacency( + [ + 0 0 1 1 1 1 1 0 1 + 0 0 0 1 1 1 1 1 0 + 1 0 0 1 0 1 0 0 1 + 1 1 1 0 0 1 1 1 0 + 1 1 0 0 0 1 1 0 0 + 1 1 1 1 1 0 0 0 1 + 1 1 0 1 1 0 0 0 0 + 0 1 0 1 0 0 0 0 0 + 1 0 1 0 0 1 0 0 0 + ], Dict(1:9 .=> [-1, (1:8)...]), + ) + DT.clear_empty_features!(_tri) + @test get_triangles(_tri) == true_T + @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(_tri) == true_adj2v + @test get_graph(_tri) == true_DG + end + DT.add_triangle!(tri, 5, 2, 8) # Get an actual copy for later, test is above + end - @testset "Adding a boundary triangle with two boundary edges" begin - for (i, j, k) in ((3, 6, 2), (6, 2, 3), (2, 3, 6)) - local true_T, true_adj, true_adj2v, true_DG - _tri = deepcopy(tri) - DT.add_triangle!(_tri, i, j, k) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 3, 7), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3), - (5, 2, 8), - (i, j, k) - ]) - true_adj = - Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, - (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, - (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, - (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) - true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (8, 5), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (7, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4), (2, 3)]), - 7 => Set{NTuple{2,Int}}([(1, 3)]), - 8 => Set{NTuple{2,Int}}([(5, 2)]) - ) - true_DG = _make_graph_from_adjacency([ - 0 0 1 0 1 1 1 0 1 - 0 0 0 1 1 1 1 1 0 - 1 0 0 1 0 1 1 0 1 - 0 1 1 0 0 1 1 1 0 - 1 1 0 0 0 1 1 0 0 - 1 1 1 1 1 0 0 0 1 - 1 1 1 1 1 0 0 0 0 - 0 1 0 1 0 0 0 0 0 - 1 0 1 0 0 1 0 0 0 - ], Dict(1:9 .=> [-1, (1:8)...])) - DT.clear_empty_features!(_tri) - @test get_triangles(_tri) == true_T - @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(_tri) == true_adj2v - @test get_graph(_tri) == true_DG - end - end + @testset "Adding a boundary triangle with two boundary edges" begin + for (i, j, k) in ((3, 6, 2), (6, 2, 3), (2, 3, 6)) + local true_T, true_adj, true_adj2v, true_DG + _tri = deepcopy(tri) + DT.add_triangle!(_tri, i, j, k) + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 3, 7), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + (5, 2, 8), + (i, j, k), + ], + ) + true_adj = + Dict( + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, + (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, + (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, + (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, + (6, 4) => DT.𝒢, + ) + true_adj2v = Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 7), (3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (8, 5), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (7, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4), (2, 3)]), + 7 => Set{NTuple{2, Int}}([(1, 3)]), + 8 => Set{NTuple{2, Int}}([(5, 2)]), + ) + true_DG = _make_graph_from_adjacency( + [ + 0 0 1 0 1 1 1 0 1 + 0 0 0 1 1 1 1 1 0 + 1 0 0 1 0 1 1 0 1 + 0 1 1 0 0 1 1 1 0 + 1 1 0 0 0 1 1 0 0 + 1 1 1 1 1 0 0 0 1 + 1 1 1 1 1 0 0 0 0 + 0 1 0 1 0 0 0 0 0 + 1 0 1 0 0 1 0 0 0 + ], Dict(1:9 .=> [-1, (1:8)...]), + ) + DT.clear_empty_features!(_tri) + @test get_triangles(_tri) == true_T + @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(_tri) == true_adj2v + @test get_graph(_tri) == true_DG + end + end end @testset "Empty triangulation" begin - tri = example_empty_triangulation() - true_T = Set{NTuple{3,Int}}([(1, 2, 3)]) - true_adj = - Dict((1, 2) => 3, (2, 3) => 1, (3, 1) => 2, - (3, 2) => DT.𝒢, (2, 1) => DT.𝒢, (1, 3) => DT.𝒢) - true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(3, 2), (2, 1), (1, 3)]), - 1 => Set{NTuple{2,Int}}([(2, 3)]), - 2 => Set{NTuple{2,Int}}([(3, 1)]), - 3 => Set{NTuple{2,Int}}([(1, 2)]) - ) - true_DG = _make_graph_from_adjacency([ - 0 1 1 1 - 1 0 1 1 - 1 1 0 1 - 1 1 1 0 - ], Dict(1:4 .=> [-1, 1, 2, 3])) - DT.add_triangle!(tri, 1, 2, 3) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v - @test get_graph(tri) == true_DG + tri = example_empty_triangulation() + true_T = Set{NTuple{3, Int}}([(1, 2, 3)]) + true_adj = + Dict( + (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, + (3, 2) => DT.𝒢, (2, 1) => DT.𝒢, (1, 3) => DT.𝒢, + ) + true_adj2v = Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(3, 2), (2, 1), (1, 3)]), + 1 => Set{NTuple{2, Int}}([(2, 3)]), + 2 => Set{NTuple{2, Int}}([(3, 1)]), + 3 => Set{NTuple{2, Int}}([(1, 2)]), + ) + true_DG = _make_graph_from_adjacency( + [ + 0 1 1 1 + 1 0 1 1 + 1 1 0 1 + 1 1 1 0 + ], Dict(1:4 .=> [-1, 1, 2, 3]), + ) + DT.add_triangle!(tri, 1, 2, 3) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v + @test get_graph(tri) == true_DG end @testset "Testing the boundary addition cases for updating ghost edges" begin - p1 = @SVector[0.0, 0.0] - p2 = @SVector[1.0, 0.0] - p3 = @SVector[0.0, 1.0] - pts = [p1, p2, p3] - tri = Triangulation(pts) - DT.add_triangle!(tri, 1, 2, 3; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([(1, 2, 3), + p1 = @SVector[0.0, 0.0] + p2 = @SVector[1.0, 0.0] + p3 = @SVector[0.0, 1.0] + pts = [p1, p2, p3] + tri = Triangulation(pts) + DT.add_triangle!(tri, 1, 2, 3; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), (2, 1, DT.𝒢), (1, 3, DT.𝒢), - (3, 2, DT.𝒢)]) - true_adj = DT.Adjacent( - Dict( - (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, - (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, - (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, - (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2 - )) - true_adj2v = DT.Adjacent2Vertex( - Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(2, 1), (1, 3), (3, 2)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 3)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (DT.𝒢, 1), (2, DT.𝒢)]) - ) - ) - true_DG = DT.Graph{Int}() - DT.add_neighbour!(true_DG, DT.𝒢, [1, 2, 3]...) - DT.add_neighbour!(true_DG, 1, [2, 3]...) - DT.add_neighbour!(true_DG, 2, [1, 3]...) - DT.add_neighbour!(true_DG, 3, [1, 2]...) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex - @test get_graph(tri) == true_DG - p4 = @SVector[1.7, 1.7] - push!(pts, p4) - DT.add_triangle!(tri, 3, 2, 4; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([(1, 2, 3), + (3, 2, DT.𝒢), + ], + ) + true_adj = DT.Adjacent( + Dict( + (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, + (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, + (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, + (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2, + ), + ) + true_adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(2, 1), (1, 3), (3, 2)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 3)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (DT.𝒢, 1), (2, DT.𝒢)]), + ), + ) + true_DG = DT.Graph{Int}() + DT.add_neighbour!(true_DG, DT.𝒢, [1, 2, 3]...) + DT.add_neighbour!(true_DG, 1, [2, 3]...) + DT.add_neighbour!(true_DG, 2, [1, 3]...) + DT.add_neighbour!(true_DG, 3, [1, 2]...) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex + @test get_graph(tri) == true_DG + p4 = @SVector[1.7, 1.7] + push!(pts, p4) + DT.add_triangle!(tri, 3, 2, 4; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), (2, 1, DT.𝒢), (1, 3, DT.𝒢), (3, 4, DT.𝒢), (4, 2, DT.𝒢), - (3, 2, 4)]) - true_adj = DT.Adjacent( - Dict( - (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, - (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, - (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, - (3, 4) => DT.𝒢, (4, DT.𝒢) => 3, (DT.𝒢, 3) => 4, - (4, 2) => DT.𝒢, (2, DT.𝒢) => 4, (DT.𝒢, 4) => 2, - (3, 2) => 4, (2, 4) => 3, (4, 3) => 2 - )) - true_adj2v = DT.Adjacent2Vertex( - Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(2, 1), (1, 3), (3, 4), (4, 2)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 4), (4, 3)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (DT.𝒢, 1), (4, DT.𝒢), (2, 4)]), - 4 => Set{NTuple{2,Int}}([(DT.𝒢, 3), (2, DT.𝒢), (3, 2)]) - ) - ) - true_DG = DT.Graph{Int}() - DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 4, 2]...) - DT.add_neighbour!(true_DG, 1, [2, 3]...) - DT.add_neighbour!(true_DG, 2, [1, 3, 4]...) - DT.add_neighbour!(true_DG, 3, [1, 2, 4]...) - DT.add_neighbour!(true_DG, 4, [2, 3]...) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex - @test get_graph(tri) == true_DG - p5 = @SVector[1.0, 3.0] - p6 = @SVector[3.0, 1.0] - push!(pts, p5, p6) - DT.add_triangle!(tri, 3, 4, 5; update_ghost_edges=true) - DT.add_triangle!(tri, 4, 2, 6; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([ + (3, 2, 4), + ], + ) + true_adj = DT.Adjacent( + Dict( + (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, + (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, + (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, + (3, 4) => DT.𝒢, (4, DT.𝒢) => 3, (DT.𝒢, 3) => 4, + (4, 2) => DT.𝒢, (2, DT.𝒢) => 4, (DT.𝒢, 4) => 2, + (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, + ), + ) + true_adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(2, 1), (1, 3), (3, 4), (4, 2)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 4), (4, 3)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (DT.𝒢, 1), (4, DT.𝒢), (2, 4)]), + 4 => Set{NTuple{2, Int}}([(DT.𝒢, 3), (2, DT.𝒢), (3, 2)]), + ), + ) + true_DG = DT.Graph{Int}() + DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 4, 2]...) + DT.add_neighbour!(true_DG, 1, [2, 3]...) + DT.add_neighbour!(true_DG, 2, [1, 3, 4]...) + DT.add_neighbour!(true_DG, 3, [1, 2, 4]...) + DT.add_neighbour!(true_DG, 4, [2, 3]...) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex + @test get_graph(tri) == true_DG + p5 = @SVector[1.0, 3.0] + p6 = @SVector[3.0, 1.0] + push!(pts, p5, p6) + DT.add_triangle!(tri, 3, 4, 5; update_ghost_edges = true) + DT.add_triangle!(tri, 4, 2, 6; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ (1, 2, 3), (3, 2, 4), (3, 4, 5), @@ -352,46 +383,49 @@ end (3, 5, DT.𝒢), (5, 4, DT.𝒢), (4, 6, DT.𝒢), - (6, 2, DT.𝒢) - ]) - true_adj = DT.Adjacent( - Dict( - (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, - (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, - (3, 4) => 5, (4, 5) => 3, (5, 3) => 4, - (4, 2) => 6, (2, 6) => 4, (6, 4) => 2, - (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, - (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, - (3, 5) => DT.𝒢, (5, DT.𝒢) => 3, (DT.𝒢, 3) => 5, - (5, 4) => DT.𝒢, (4, DT.𝒢) => 5, (DT.𝒢, 5) => 4, - (4, 6) => DT.𝒢, (6, DT.𝒢) => 4, (DT.𝒢, 4) => 6, - (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2 - )) - true_adj2v = DT.Adjacent2Vertex( - Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 4), (4, 6), (6, 2), (2, 1)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), - 4 => Set{NTuple{2,Int}}([(3, 2), (5, 3), (2, 6), (DT.𝒢, 5), (6, DT.𝒢)]), - 5 => Set{NTuple{2,Int}}([(3, 4), (DT.𝒢, 3), (4, DT.𝒢)]), - 6 => Set{NTuple{2,Int}}([(4, 2), (DT.𝒢, 4), (2, DT.𝒢)]) - ) - ) - true_DG = DT.Graph{Int}() - DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 5, 4, 6, 2]...) - DT.add_neighbour!(true_DG, 1, [2, 3]...) - DT.add_neighbour!(true_DG, 2, [1, 3, 4, 6]...) - DT.add_neighbour!(true_DG, 3, [1, 2, 4, 5]...) - DT.add_neighbour!(true_DG, 4, [2, 3, 5, 6]...) - DT.add_neighbour!(true_DG, 5, [3, 4]...) - DT.add_neighbour!(true_DG, 6, [2, 4]...) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex - @test get_graph(tri) == true_DG - DT.add_triangle!(tri, 5, 4, 6; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([ + (6, 2, DT.𝒢), + ], + ) + true_adj = DT.Adjacent( + Dict( + (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, + (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, + (3, 4) => 5, (4, 5) => 3, (5, 3) => 4, + (4, 2) => 6, (2, 6) => 4, (6, 4) => 2, + (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, + (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, + (3, 5) => DT.𝒢, (5, DT.𝒢) => 3, (DT.𝒢, 3) => 5, + (5, 4) => DT.𝒢, (4, DT.𝒢) => 5, (DT.𝒢, 5) => 4, + (4, 6) => DT.𝒢, (6, DT.𝒢) => 4, (DT.𝒢, 4) => 6, + (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2, + ), + ) + true_adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 4), (4, 6), (6, 2), (2, 1)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), + 4 => Set{NTuple{2, Int}}([(3, 2), (5, 3), (2, 6), (DT.𝒢, 5), (6, DT.𝒢)]), + 5 => Set{NTuple{2, Int}}([(3, 4), (DT.𝒢, 3), (4, DT.𝒢)]), + 6 => Set{NTuple{2, Int}}([(4, 2), (DT.𝒢, 4), (2, DT.𝒢)]), + ), + ) + true_DG = DT.Graph{Int}() + DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 5, 4, 6, 2]...) + DT.add_neighbour!(true_DG, 1, [2, 3]...) + DT.add_neighbour!(true_DG, 2, [1, 3, 4, 6]...) + DT.add_neighbour!(true_DG, 3, [1, 2, 4, 5]...) + DT.add_neighbour!(true_DG, 4, [2, 3, 5, 6]...) + DT.add_neighbour!(true_DG, 5, [3, 4]...) + DT.add_neighbour!(true_DG, 6, [2, 4]...) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex + @test get_graph(tri) == true_DG + DT.add_triangle!(tri, 5, 4, 6; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ (1, 2, 3), (3, 2, 4), (3, 4, 5), @@ -401,64 +435,66 @@ end (1, 3, DT.𝒢), (3, 5, DT.𝒢), (5, 6, DT.𝒢), - (6, 2, DT.𝒢) - ]) - true_adj = DT.Adjacent( - Dict( - (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, - (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, - (3, 4) => 5, (4, 5) => 3, (5, 3) => 4, - (4, 2) => 6, (2, 6) => 4, (6, 4) => 2, - (5, 4) => 6, (4, 6) => 5, (6, 5) => 4, - (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, - (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, - (3, 5) => DT.𝒢, (5, DT.𝒢) => 3, (DT.𝒢, 3) => 5, - (5, 6) => DT.𝒢, (6, DT.𝒢) => 5, (DT.𝒢, 5) => 6, - (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2 - )) - true_adj2v = DT.Adjacent2Vertex( - Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 6), (6, 2), (2, 1)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), - 4 => Set{NTuple{2,Int}}([(3, 2), (2, 6), (6, 5), (5, 3)]), - 5 => Set{NTuple{2,Int}}([(3, 4), (4, 6), (6, DT.𝒢), (DT.𝒢, 3)]), - 6 => Set{NTuple{2,Int}}([(4, 2), (5, 4), (DT.𝒢, 5), (2, DT.𝒢)]) - ) - ) - true_DG = DT.Graph{Int}() - DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 5, 6, 2]...) - DT.add_neighbour!(true_DG, 1, [2, 3]...) - DT.add_neighbour!(true_DG, 2, [1, 3, 4, 6]...) - DT.add_neighbour!(true_DG, 3, [1, 2, 4, 5]...) - DT.add_neighbour!(true_DG, 4, [2, 3, 5, 6]...) - DT.add_neighbour!(true_DG, 5, [3, 4, 6]...) - DT.add_neighbour!(true_DG, 6, [2, 4, 5]...) - @test get_triangles(tri) == true_T - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex - @test get_graph(tri) == true_DG - DT.convex_hull!(tri; reconstruct=false) - DT.compute_representative_points!(tri) - @test validate_triangulation(tri) + (6, 2, DT.𝒢), + ], + ) + true_adj = DT.Adjacent( + Dict( + (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, + (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, + (3, 4) => 5, (4, 5) => 3, (5, 3) => 4, + (4, 2) => 6, (2, 6) => 4, (6, 4) => 2, + (5, 4) => 6, (4, 6) => 5, (6, 5) => 4, + (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, + (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, + (3, 5) => DT.𝒢, (5, DT.𝒢) => 3, (DT.𝒢, 3) => 5, + (5, 6) => DT.𝒢, (6, DT.𝒢) => 5, (DT.𝒢, 5) => 6, + (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2, + ), + ) + true_adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 6), (6, 2), (2, 1)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), + 4 => Set{NTuple{2, Int}}([(3, 2), (2, 6), (6, 5), (5, 3)]), + 5 => Set{NTuple{2, Int}}([(3, 4), (4, 6), (6, DT.𝒢), (DT.𝒢, 3)]), + 6 => Set{NTuple{2, Int}}([(4, 2), (5, 4), (DT.𝒢, 5), (2, DT.𝒢)]), + ), + ) + true_DG = DT.Graph{Int}() + DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 5, 6, 2]...) + DT.add_neighbour!(true_DG, 1, [2, 3]...) + DT.add_neighbour!(true_DG, 2, [1, 3, 4, 6]...) + DT.add_neighbour!(true_DG, 3, [1, 2, 4, 5]...) + DT.add_neighbour!(true_DG, 4, [2, 3, 5, 6]...) + DT.add_neighbour!(true_DG, 5, [3, 4, 6]...) + DT.add_neighbour!(true_DG, 6, [2, 4, 5]...) + @test get_triangles(tri) == true_T + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex + @test get_graph(tri) == true_DG + DT.convex_hull!(tri; reconstruct = false) + DT.compute_representative_points!(tri) + @test validate_triangulation(tri) end @testset "Larger example" begin - p1 = @SVector[-3.32, 3.53] - p2 = @SVector[-5.98, 2.17] - p3 = @SVector[-6.36, -1.55] - p4 = @SVector[-2.26, -4.31] - p5 = @SVector[6.34, -3.23] - p6 = @SVector[-3.24, 1.01] - p7 = @SVector[0.14, -1.51] - p8 = @SVector[0.2, 1.25] - p9 = @SVector[1.0, 4.0] - p10 = @SVector[4.74, 2.21] - p11 = @SVector[2.32, -0.27] - pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] - tri = Triangulation(pts) - for (i, j, k) in ( + p1 = @SVector[-3.32, 3.53] + p2 = @SVector[-5.98, 2.17] + p3 = @SVector[-6.36, -1.55] + p4 = @SVector[-2.26, -4.31] + p5 = @SVector[6.34, -3.23] + p6 = @SVector[-3.24, 1.01] + p7 = @SVector[0.14, -1.51] + p8 = @SVector[0.2, 1.25] + p9 = @SVector[1.0, 4.0] + p10 = @SVector[4.74, 2.21] + p11 = @SVector[2.32, -0.27] + pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] + tri = Triangulation(pts) + for (i, j, k) in ( (1, 2, 6), (1, 6, 8), (9, 1, 8), @@ -471,11 +507,12 @@ end (6, 4, 7), (7, 4, 5), (11, 7, 5), - (10, 11, 5) - ) - DT.add_triangle!(tri, i, j, k; update_ghost_edges=true) - end - true_T = Set{NTuple{3,Int}}([ + (10, 11, 5), + ) + DT.add_triangle!(tri, i, j, k; update_ghost_edges = true) + end + true_T = Set{NTuple{3, Int}}( + [ (1, 6, 8), (1, 8, 9), (9, 8, 10), @@ -495,54 +532,55 @@ end (10, 5, DT.𝒢), (5, 4, DT.𝒢), (4, 3, DT.𝒢), - (3, 2, DT.𝒢) - ]) - true_adj = DT.Adjacent( - Dict( - (1, 6) => 8, (6, 8) => 1, (8, 1) => 6, - (1, 8) => 9, (8, 9) => 1, (9, 1) => 8, - (9, 8) => 10, (8, 10) => 9, (10, 9) => 8, - (10, 8) => 11, (8, 11) => 10, (11, 10) => 8, - (10, 11) => 5, (11, 5) => 10, (5, 10) => 11, - (11, 7) => 5, (7, 5) => 11, (5, 11) => 7, - (7, 4) => 5, (4, 5) => 7, (5, 7) => 4, - (7, 6) => 4, (6, 4) => 7, (4, 7) => 6, - (6, 3) => 4, (3, 4) => 6, (4, 6) => 3, - (6, 2) => 3, (2, 3) => 6, (3, 6) => 2, - (1, 2) => 6, (2, 6) => 1, (6, 1) => 2, - (8, 6) => 7, (6, 7) => 8, (7, 8) => 6, - (8, 7) => 11, (7, 11) => 8, (11, 8) => 7, - (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, - (1, 9) => DT.𝒢, (9, DT.𝒢) => 1, (DT.𝒢, 1) => 9, - (9, 10) => DT.𝒢, (10, DT.𝒢) => 9, (DT.𝒢, 9) => 10, - (10, 5) => DT.𝒢, (5, DT.𝒢) => 10, (DT.𝒢, 10) => 5, - (5, 4) => DT.𝒢, (4, DT.𝒢) => 5, (DT.𝒢, 5) => 4, - (4, 3) => DT.𝒢, (3, DT.𝒢) => 4, (DT.𝒢, 4) => 3, - (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2 - ) - ) - true_adj2v = DT.Adjacent2Vertex{Int,Set{NTuple{2,Int}}}() - for (ij, k) in true_adj.adjacent - DT.add_adjacent2vertex!(true_adj2v, k, ij) - end - true_DG = DT.Graph{Int}() - DT.add_neighbour!(true_DG, DT.𝒢, 1, 9, 10, 5, 4, 3, 2) - DT.add_neighbour!(true_DG, 1, 2, 6, 8, 9) - DT.add_neighbour!(true_DG, 2, 1, 6, 3) - DT.add_neighbour!(true_DG, 3, 2, 6, 4) - DT.add_neighbour!(true_DG, 4, 6, 3, 7, 5) - DT.add_neighbour!(true_DG, 5, 10, 11, 7, 4) - DT.add_neighbour!(true_DG, 6, 1, 2, 3, 4, 7, 8) - DT.add_neighbour!(true_DG, 7, 8, 6, 4, 5, 11) - DT.add_neighbour!(true_DG, 8, 1, 6, 7, 11, 10, 9) - DT.add_neighbour!(true_DG, 9, 1, 8, 10) - DT.add_neighbour!(true_DG, 10, 9, 8, 11, 5) - DT.add_neighbour!(true_DG, 11, 10, 8, 7, 5) - @test DT.compare_triangle_collections(get_triangles(tri), true_T) - @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent - @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex - @test get_graph(tri) == true_DG - DT.convex_hull!(tri; reconstruct=false) - DT.compute_representative_points!(tri) - @test validate_triangulation(tri) -end \ No newline at end of file + (3, 2, DT.𝒢), + ], + ) + true_adj = DT.Adjacent( + Dict( + (1, 6) => 8, (6, 8) => 1, (8, 1) => 6, + (1, 8) => 9, (8, 9) => 1, (9, 1) => 8, + (9, 8) => 10, (8, 10) => 9, (10, 9) => 8, + (10, 8) => 11, (8, 11) => 10, (11, 10) => 8, + (10, 11) => 5, (11, 5) => 10, (5, 10) => 11, + (11, 7) => 5, (7, 5) => 11, (5, 11) => 7, + (7, 4) => 5, (4, 5) => 7, (5, 7) => 4, + (7, 6) => 4, (6, 4) => 7, (4, 7) => 6, + (6, 3) => 4, (3, 4) => 6, (4, 6) => 3, + (6, 2) => 3, (2, 3) => 6, (3, 6) => 2, + (1, 2) => 6, (2, 6) => 1, (6, 1) => 2, + (8, 6) => 7, (6, 7) => 8, (7, 8) => 6, + (8, 7) => 11, (7, 11) => 8, (11, 8) => 7, + (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, + (1, 9) => DT.𝒢, (9, DT.𝒢) => 1, (DT.𝒢, 1) => 9, + (9, 10) => DT.𝒢, (10, DT.𝒢) => 9, (DT.𝒢, 9) => 10, + (10, 5) => DT.𝒢, (5, DT.𝒢) => 10, (DT.𝒢, 10) => 5, + (5, 4) => DT.𝒢, (4, DT.𝒢) => 5, (DT.𝒢, 5) => 4, + (4, 3) => DT.𝒢, (3, DT.𝒢) => 4, (DT.𝒢, 4) => 3, + (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2, + ), + ) + true_adj2v = DT.Adjacent2Vertex{Int, Set{NTuple{2, Int}}}() + for (ij, k) in true_adj.adjacent + DT.add_adjacent2vertex!(true_adj2v, k, ij) + end + true_DG = DT.Graph{Int}() + DT.add_neighbour!(true_DG, DT.𝒢, 1, 9, 10, 5, 4, 3, 2) + DT.add_neighbour!(true_DG, 1, 2, 6, 8, 9) + DT.add_neighbour!(true_DG, 2, 1, 6, 3) + DT.add_neighbour!(true_DG, 3, 2, 6, 4) + DT.add_neighbour!(true_DG, 4, 6, 3, 7, 5) + DT.add_neighbour!(true_DG, 5, 10, 11, 7, 4) + DT.add_neighbour!(true_DG, 6, 1, 2, 3, 4, 7, 8) + DT.add_neighbour!(true_DG, 7, 8, 6, 4, 5, 11) + DT.add_neighbour!(true_DG, 8, 1, 6, 7, 11, 10, 9) + DT.add_neighbour!(true_DG, 9, 1, 8, 10) + DT.add_neighbour!(true_DG, 10, 9, 8, 11, 5) + DT.add_neighbour!(true_DG, 11, 10, 8, 7, 5) + @test DT.compare_triangle_collections(get_triangles(tri), true_T) + @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent + @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex + @test get_graph(tri) == true_DG + DT.convex_hull!(tri; reconstruct = false) + DT.compute_representative_points!(tri) + @test validate_triangulation(tri) +end diff --git a/test/operations/delete_ghost_triangles.jl b/test/operations/delete_ghost_triangles.jl index f158db9db..ac8890b3e 100644 --- a/test/operations/delete_ghost_triangles.jl +++ b/test/operations/delete_ghost_triangles.jl @@ -17,19 +17,19 @@ end @testset "Making sure the ghost triangles are correctly adjusted on disjoint sets" begin θ = LinRange(0, 2π, 100) |> collect θ[end] = 0 - xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() + xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() cx = 0.0 for i in 1:2 - push!(xy, [[(cx + cos(θ) + 1e-3rand(), sin(θ) + 1e-3rand()) for θ in θ]]) # use perturbations to also do this check without ExactPredicates loaded. iszero makes the boundary closed - push!(xy, [[(cx + 0.5cos(θ) + 1e-3rand(), 0.5sin(θ) + 1e-3rand()) for θ in reverse(θ)]]) + push!(xy, [[(cx + cos(θ) + 1.0e-3rand(), sin(θ) + 1.0e-3rand()) for θ in θ]]) # use perturbations to also do this check without ExactPredicates loaded. iszero makes the boundary closed + push!(xy, [[(cx + 0.5cos(θ) + 1.0e-3rand(), 0.5sin(θ) + 1.0e-3rand()) for θ in reverse(θ)]]) cx += 3.0 end xy[1][1][end] = xy[1][1][1] - xy[2][1][end] = xy[2][1][1] + xy[2][1][end] = xy[2][1][1] xy[3][1][end] = xy[3][1][1] - xy[4][1][end] = xy[4][1][1] + xy[4][1][end] = xy[4][1][1] boundary_nodes, points = convert_boundary_points_to_indices(xy) - tri = triangulate(points; boundary_nodes=boundary_nodes) + tri = triangulate(points; boundary_nodes = boundary_nodes) @test validate_triangulation(tri) validate_statistics(tri) -end \ No newline at end of file +end diff --git a/test/operations/delete_holes.jl b/test/operations/delete_holes.jl index 2da7e11de..f323a3308 100644 --- a/test/operations/delete_holes.jl +++ b/test/operations/delete_holes.jl @@ -13,43 +13,45 @@ using StaticArrays rng = StableRNG(1919) existing_pts = [(rand(rng), rand(rng)) for _ in 1:15] push!(existing_pts, (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0)) - nodes, points = convert_boundary_points_to_indices([p1, p2, p3, p4, p1], existing_points=existing_pts) - tri = triangulate(points; boundary_nodes=nodes, delete_holes=false, delete_ghosts=false, rng) + nodes, points = convert_boundary_points_to_indices([p1, p2, p3, p4, p1], existing_points = existing_pts) + tri = triangulate(points; boundary_nodes = nodes, delete_holes = false, delete_ghosts = false, rng) points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((17, 1, DT.𝒢, 19, 12, 3, 8, 16, 15, 5, 11, 18, 9, 4)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - true_triangles_to_delete = Set(( - (1, 22, 4), - (1, 4, 19), - (1, 19, 17), - (1, 17, 12), - (1, 12, 22), - (3, 8, 23), - (3, 23, 17), - (3, 17, 8), - (4, 11, 19), - (4, 22, 21), - (4, 21, 11), - (5, 18, 11), - (5, 11, 21), - (5, 21, 9), - (5, 9, 15), - (5, 15, 16), - (8, 16, 20), - (8, 17, 16), - (8, 20, 23), - (9, 20, 15), - (9, 21, 20), - (5, 16, 18), - (11, 18, 19), - (12, 23, 22), - (12, 17, 23), - (15, 20, 16), - (17, 19, DT.𝒢), - (19, 18, DT.𝒢), - (18, 16, DT.𝒢), - (16, 17, DT.𝒢) - )) + true_triangles_to_delete = Set( + ( + (1, 22, 4), + (1, 4, 19), + (1, 19, 17), + (1, 17, 12), + (1, 12, 22), + (3, 8, 23), + (3, 23, 17), + (3, 17, 8), + (4, 11, 19), + (4, 22, 21), + (4, 21, 11), + (5, 18, 11), + (5, 11, 21), + (5, 21, 9), + (5, 9, 15), + (5, 15, 16), + (8, 16, 20), + (8, 17, 16), + (8, 20, 23), + (9, 20, 15), + (9, 21, 20), + (5, 16, 18), + (11, 18, 19), + (12, 23, 22), + (12, 17, 23), + (15, 20, 16), + (17, 19, DT.𝒢), + (19, 18, DT.𝒢), + (18, 16, DT.𝒢), + (16, 17, DT.𝒢), + ), + ) @test DT.compare_triangle_collections(triangles_to_delete, true_triangles_to_delete) p1 = (0.2, 0.2) @@ -59,8 +61,8 @@ using StaticArrays rng = StableRNG(1919) existing_pts = [(rand(rng), rand(rng)) for _ in 1:15] push!(existing_pts, (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0)) - nodes, points = convert_boundary_points_to_indices([p1, p2, p3, p4, p1], existing_points=existing_pts) - tri = triangulate(points; boundary_nodes=nodes, rng) + nodes, points = convert_boundary_points_to_indices([p1, p2, p3, p4, p1], existing_points = existing_pts) + tri = triangulate(points; boundary_nodes = nodes, rng) @test validate_triangulation(tri) validate_statistics(tri) end @@ -98,46 +100,48 @@ end f1 = (5.0, 4.3) pts = [[[d, e, f, a, b, f1, e1, c1, d1, c, d]], [[g, h, i, ℓ, k, j, g]]] existing_points = [m, n, o, p, q, r, s, t, u, v, w, z, a1, b1] - nodes, points = convert_boundary_points_to_indices(pts; existing_points=existing_points) - tri = triangulate(points; boundary_nodes=nodes, delete_holes=false, delete_ghosts=false) + nodes, points = convert_boundary_points_to_indices(pts; existing_points = existing_points) + tri = triangulate(points; boundary_nodes = nodes, delete_holes = false, delete_ghosts = false) points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((12, 11, 14, 3, 13, 4, 6, 7, DT.𝒢)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - true_triangles_to_delete = Set(( - (15, 17, 12), - (12, 17, 11), - (12, 11, 16), - (11, 17, 16), - (25, 30, 29), - (29, 28, 6), - (25, 29, 6), - (25, 6, 26), - (6, 7, 26), - (6, 28, 7), - (7, 28, 27), - (26, 7, 27), - (20, 19, 13), - (13, 19, 14), - (13, 14, 3), - (20, 13, 3), - (20, 3, 4), - (21, 20, 4), - (24, 23, 22), - (24, 22, 21), - (24, 21, 4), - (15, 24, DT.𝒢), - (24, 4, DT.𝒢), - (4, 3, DT.𝒢), - (3, 14, DT.𝒢), - (14, 19, DT.𝒢), - (19, 18, DT.𝒢), - (18, 17, DT.𝒢), - (17, 15, DT.𝒢), - (12, 16, 15) - )) + true_triangles_to_delete = Set( + ( + (15, 17, 12), + (12, 17, 11), + (12, 11, 16), + (11, 17, 16), + (25, 30, 29), + (29, 28, 6), + (25, 29, 6), + (25, 6, 26), + (6, 7, 26), + (6, 28, 7), + (7, 28, 27), + (26, 7, 27), + (20, 19, 13), + (13, 19, 14), + (13, 14, 3), + (20, 13, 3), + (20, 3, 4), + (21, 20, 4), + (24, 23, 22), + (24, 22, 21), + (24, 21, 4), + (15, 24, DT.𝒢), + (24, 4, DT.𝒢), + (4, 3, DT.𝒢), + (3, 14, DT.𝒢), + (14, 19, DT.𝒢), + (19, 18, DT.𝒢), + (18, 17, DT.𝒢), + (17, 15, DT.𝒢), + (12, 16, 15), + ), + ) @test DT.compare_triangle_collections(triangles_to_delete, true_triangles_to_delete) - tri = triangulate(points; boundary_nodes=nodes) + tri = triangulate(points; boundary_nodes = nodes) @test validate_triangulation(tri) validate_statistics(tri) end @@ -152,51 +156,63 @@ end p6 = (0.8, 0.2) p7 = (0.8, 0.8) pts = [p1, p2, p3, p4, p5, p6, p7] - tri = triangulate(pts, boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], delete_holes=false, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts, boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], delete_holes = false, delete_ghosts = false, predicates = PT()) @test num_ghost_triangles(tri) == 4 @test num_ghost_edges(tri) == 4 points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((DT.𝒢,)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - @test DT.compare_triangle_collections(triangles_to_delete, Set(( - (1, 4, DT.𝒢), - (4, 3, DT.𝒢), - (3, 2, DT.𝒢), - (2, 1, DT.𝒢), - (5, 6, 7) - ))) - tri = triangulate(pts; boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + @test DT.compare_triangle_collections( + triangles_to_delete, Set( + ( + (1, 4, DT.𝒢), + (4, 3, DT.𝒢), + (3, 2, DT.𝒢), + (2, 1, DT.𝒢), + (5, 6, 7), + ), + ), + ) + tri = triangulate(pts; boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) validate_statistics(tri) - tri = triangulate(pts, boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7], [7, 6, 5]]], delete_holes=false, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts, boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7], [7, 6, 5]]], delete_holes = false, delete_ghosts = false, predicates = PT()) points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((DT.𝒢,)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - @test DT.compare_triangle_collections(triangles_to_delete, Set(( - (1, 4, DT.𝒢), - (4, 3, DT.𝒢), - (3, 2, DT.𝒢), - (2, 1, DT.𝒢), - (5, 6, 7) - ))) - tri = triangulate(pts; boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7], [7, 6, 5]]], predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + @test DT.compare_triangle_collections( + triangles_to_delete, Set( + ( + (1, 4, DT.𝒢), + (4, 3, DT.𝒢), + (3, 2, DT.𝒢), + (2, 1, DT.𝒢), + (5, 6, 7), + ), + ), + ) + tri = triangulate(pts; boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7], [7, 6, 5]]], predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) validate_statistics(tri) - tri = triangulate(pts, boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], delete_holes=false, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts, boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], delete_holes = false, delete_ghosts = false, predicates = PT()) points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((DT.𝒢,)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - @test DT.compare_triangle_collections(triangles_to_delete, Set(( - (1, 4, DT.𝒢), - (4, 3, DT.𝒢), - (3, 2, DT.𝒢), - (2, 1, DT.𝒢), - (5, 6, 7) - ))) - tri = triangulate(pts; boundary_nodes=[[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + @test DT.compare_triangle_collections( + triangles_to_delete, Set( + ( + (1, 4, DT.𝒢), + (4, 3, DT.𝒢), + (3, 2, DT.𝒢), + (2, 1, DT.𝒢), + (5, 6, 7), + ), + ), + ) + tri = triangulate(pts; boundary_nodes = [[[1, 2, 3, 4, 1]], [[5, 7, 6, 5]]], predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) validate_statistics(tri) end end @@ -209,21 +225,23 @@ end y = @. a * (2sin(t) - sin(2t)) points = [2.4 -0.152786404500042 -1.047213595499958 -1.047213595499958 -0.1527864045000426; 0.0 1.051462224238267 1.70130161670408 -1.70130161670408 -1.051462224238268] bn_nodes = [1, 2, 3, 4, 5, 1] - tri = triangulate(points; boundary_nodes=bn_nodes, delete_ghosts=false, delete_holes=false, predicates=PT()) + tri = triangulate(points; boundary_nodes = bn_nodes, delete_ghosts = false, delete_holes = false, predicates = PT()) points_to_process = DT.find_all_points_to_delete(tri) @test points_to_process == Set((DT.𝒢,)) triangles_to_delete = DT.find_all_triangles_to_delete(tri, points_to_process) - true_triangles_to_delete = Set(( - (3, 2, 1), - (4, 1, 5), - (3, 1, DT.𝒢), - (1, 4, DT.𝒢), - (4, 3, DT.𝒢) - )) + true_triangles_to_delete = Set( + ( + (3, 2, 1), + (4, 1, 5), + (3, 1, DT.𝒢), + (1, 4, DT.𝒢), + (4, 3, DT.𝒢), + ), + ) @test DT.compare_triangle_collections(triangles_to_delete, true_triangles_to_delete) - tri = triangulate(points; boundary_nodes=bn_nodes, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + tri = triangulate(points; boundary_nodes = bn_nodes, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) validate_statistics(tri) a = 4 / 5 @@ -232,8 +250,8 @@ end y = @. a * (2sin(t) - sin(2t)) points = [2.4 2.390342532619651 2.361486661646358 2.313780262033189 2.247797423889998 2.16432999441036 2.064375923309772 1.949124594926212 1.819939377400058 1.678337662931399 1.525968712312314 1.364589651123909 1.196039993627106 1.022215093005981 0.8450389328830836 0.6664366846599798 0.4883074580921845 0.3124976685434042 0.1407754336467903 -0.02519360519360872 -0.1838686646186263 -0.333854062108855 -0.473917012361638 -0.6030027096667079 -0.7202464727404799 -0.824982776042241 -0.9167510419119772 -0.9952981201288541 -1.060577434849961 -1.112744832492037 -1.152151217102105 -1.179332111274063 -1.194994329879372 -1.2 -1.19534820274028 -1.182154550372295 -1.161629044931084 -1.13505259139796 -1.103752559560399 -1.069077803180918 -1.032373553014235 -0.994956601357817 -0.958091190190919 -0.9229660026456057 -0.8906726387622712 -0.8621859315182511 -0.8383464283873544 -0.8198453276894746 -0.8072121183067701 -0.8008051266355886 -0.8008051266355887 -0.8072121183067701 -0.8198453276894746 -0.8383464283873544 -0.8621859315182508 -0.890672638762271 -0.9229660026456055 -0.9580911901909194 -0.9949566013578169 -1.032373553014235 -1.069077803180918 -1.103752559560399 -1.135052591397961 -1.161629044931084 -1.182154550372295 -1.19534820274028 -1.2 -1.194994329879372 -1.179332111274063 -1.152151217102105 -1.112744832492038 -1.060577434849961 -0.9952981201288543 -0.9167510419119774 -0.8249827760422405 -0.7202464727404799 -0.6030027096667084 -0.473917012361639 -0.3338540621088567 -0.1838686646186263 -0.02519360519360934 0.1407754336467914 0.3124976685434047 0.4883074580921845 0.6664366846599791 0.8450389328830821 1.022215093005981 1.196039993627106 1.364589651123908 1.525968712312312 1.678337662931397 1.819939377400058 1.949124594926211 2.064375923309773 2.16432999441036 2.247797423889998 2.313780262033188 2.361486661646357 2.390342532619651 0.3170611563256605 0.3222593190661471 -0.6183519451946706 -0.6497375598908914 -0.03601883360826612 0.6813132651727021 -0.6442990922286358 0.677301056434819 -0.03212472989883586 1.049402030184789 -0.6932272745230642 -0.3561747556617257 1.050855112561903 -0.3586613134669976 -0.6921937990949052 -0.7738275096391242 1.420372082515759 -0.6465445728766354 -0.7401785386842585 -0.8130282799705698 1.553206818654827 -0.4939148325245979 -0.5486837455157717 -0.3610262116797264 -0.73633174592415 -0.5446205627063301 -0.5160523518705824 1.230246578448748 1.093304308222101 0.8980444010246713 1.226019949979472 -0.4997667391156656 -0.726253210863807 -0.6697924507551998 -0.4891744968539103 -0.4634488008923348 -0.301600826224346 -0.2783275986241442 -0.1177692287900377 -0.09393337228059367 -0.2546427830837441 -0.0703514373220399 0.08836743861011277 -0.2313237479039875 0.1137973151090641 0.2724811315356115 0.2996278178466897 0.4682688930880384 0.1380153936605681 0.406551246715369 0.6046552182453121 -0.426784127732563 -0.3923263038801806 -0.208465408072328 -0.3607313375439971 -0.1857892526190982 0.4960419968524275 -0.1415763437967015 0.03591030790050782 0.8685411342185969 -0.1926902902309472 -0.8592155035553608 1.716817787430798 -0.8576022838754369 -0.1921452564055306 -0.6683334786985783 0.8654953794762578 0.6952267131341282 -0.6287806122165458 0.4999252549098672 0.3218569037134379 -0.5986272435711641 0.1449039324769594 2.203335189185611 -1.101667594592808 -1.101667594592807 -0.0286998603756622 -0.3499716813694415 -0.4450559779573338 -0.04783795748406422 0.09480479796065325 2.114352958860066 -1.054192316972474 -1.054192316972475 -0.3317870997991825 1.39665732177026 -0.6206155967973439 -0.7760417249729167 0.4988340023743217 0.1461550962121355 0.3242397406248529 0.9036042833648704 -0.5300851339677813 -0.3652221764727946 -0.9373851776825108 1.875039225311675 -0.9376540476291644 -0.5066666554551625 0.2368123037070368 -0.02440461564986861 0.150646683235148 1.991415825682697 -0.9957149117466657 -0.9957009139360333 0.5336878756578392 0.7210970221965526 -0.1928809320498361 0.7689122343492278 -0.6467071096582683 1.285560087566004 -0.6388529779077368 -0.1969978949942105 0.1875732054682595 -0.4975220279896986 -0.7186754363850769 1.577166091039188 -0.8584906546541111; 0.0 0.000204308591503799 0.001629535973135443 0.005472026448394285 0.01287939060935179 0.02492716987386698 0.04259671987083449 0.06675468790926908 0.09813443380113843 0.1373197116453414 0.1847308933321656 0.2406139730886964 0.3050325470249727 0.3778629130904994 0.4587923858949879 0.5473208683088024 0.6427656684861544 0.7442694978083142 0.8508115330838226 0.9612213760111374 1.074195695220302 1.188317291935738 1.302076290158998 1.413893116908774 1.522142908049466 1.625180951076655 1.721368758301788 1.809100352482636 1.886828342268937 1.953089366954632 2.006528498919954 2.04592220767042 2.070199511290803 2.078460969082653 2.069995202699299 2.044292671697285 2.001056472471559 1.94020997634528 1.86190117239507 1.766503632611802 1.654614070392519 1.527046517275516 1.384823196404126 1.229162223576608 1.061462317070302 0.8832847449107668 0.6963327821298029 0.5024289901161495 0.3034906647750211 0.1015038293221599 -0.1015038293221605 -0.3034906647750203 -0.50242899011615 -0.6963327821298022 -0.8832847449107647 -1.061462317070301 -1.229162223576608 -1.384823196404126 -1.527046517275515 -1.654614070392518 -1.766503632611802 -1.86190117239507 -1.940209976345281 -2.001056472471559 -2.044292671697285 -2.069995202699299 -2.078460969082653 -2.070199511290803 -2.04592220767042 -2.006528498919954 -1.953089366954633 -1.886828342268938 -1.809100352482636 -1.721368758301788 -1.625180951076654 -1.522142908049467 -1.413893116908775 -1.302076290158999 -1.18831729193574 -1.074195695220302 -0.9612213760111378 -0.8508115330838222 -0.7442694978083139 -0.6427656684861544 -0.5473208683088027 -0.4587923858949887 -0.3778629130904991 -0.3050325470249729 -0.2406139730886968 -0.184730893332166 -0.137319711645342 -0.09813443380113851 -0.06675468790926926 -0.04259671987083431 -0.02492716987386698 -0.01287939060935179 -0.005472026448394374 -0.001629535973135488 -0.000204308591503799 -0.5473096449852685 0.5447620596126443 0.01428450391194042 -0.4309321583994598 0.7536074241825893 0.3536290172290472 0.4171992061645116 -0.354274248521617 -0.7697113089269275 0.1945973624956351 0.8115101356751746 -1.00610749817081 -0.1925650703607583 1.006349758355742 -0.8137846879949843 1.19333488738332 0.07348683780306886 -1.266821725186389 1.366146471157314 -1.324086653415268 -0.04174935346989145 1.135404524959176 0.9456563651429131 0.8229544359251958 -0.995445054751826 -0.9480022448317108 -0.741992356781049 -0.13995947020735 0.002345879688797254 -0.08111410706343182 0.130762025431598 -1.127145434944549 0.9963834095129508 0.6153059195085407 0.5329795234649529 0.3351323238863241 0.4528041803207281 0.2552428653861011 0.3751002341424148 0.1760741054849401 0.05622243244883154 -0.02310920543998908 0.0916097709503603 -0.1431517599572751 -0.1033611549989752 0.01112539166303821 -0.1796378655622734 -0.06423821903495724 -0.2933071885887684 0.1346998725151015 0.06389662809144629 -0.06697977586584479 -0.263147702667072 -0.3418086892373844 -0.4602230597841197 -0.5395791962871652 -0.260267079463506 0.5739282454666178 0.5007002518322551 0.2757413735876992 -0.8939205770864943 -1.486342121175829 0.0009313928164653013 1.487273513992295 0.8909822595409715 -0.6270118467477362 -0.2692763527002932 -0.1472140205276644 0.2179450297267495 0.4510351900656056 0.3329413377177828 -0.2182665505265999 -0.6631900778915942 0.0 1.908144246886934 -1.908144246886936 -0.4106426344765784 -0.6482825657476072 0.1353078965823503 -0.2192301054498285 0.3004465131589842 4.336808689942018e-17 1.825914653945082 -1.825914653945081 0.6415639095768699 -0.08968357289590935 1.254408379505216 -1.164673062563948 -0.4517076066327135 0.6541117112279523 -0.36426907951982 0.09997393244042915 0.731016147780223 -0.8325312305826258 1.623909218280243 0.0001552321360775167 -1.623753986144165 -0.5474230356714256 0.1741645772010534 -0.5950229828132197 -0.4758032489975526 8.081639737527319e-6 -1.724612653719712 1.724620735359448 0.2655807939077015 0.1867114129881211 -0.717357771233564 0.01594342553679897 -1.111060401383298 -0.004534585080420719 1.115594986463718 0.7308601982314702 0.4541306336569979 -0.3789760643386818 -1.406227077779554 0.08072235390443261 1.325504723875121] bn_nodes = [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, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 1] - tri = triangulate(points; boundary_nodes=bn_nodes, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + tri = triangulate(points; boundary_nodes = bn_nodes, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) validate_statistics(tri) end -end \ No newline at end of file +end diff --git a/test/operations/delete_point.jl b/test/operations/delete_point.jl index 9d1e57bee..323215733 100644 --- a/test/operations/delete_point.jl +++ b/test/operations/delete_point.jl @@ -11,24 +11,24 @@ using StaticArrays rng1 = StableRNG(j) n = rand(rng1, 50:1000) points = 20randn(rng1, 2, n) - tri = triangulate(points; delete_ghosts=false, rng=rng1, predicates=PT()) + tri = triangulate(points; delete_ghosts = false, rng = rng1, predicates = PT()) deleted_pts = Int[] - for k in 1:(n÷10) + for k in 1:(n ÷ 10) rng2 = StableRNG(j + k * n) i = rand(rng2, each_solid_vertex(tri) |> collect) while DT.is_boundary_node(tri, i)[1] i = rand(rng2, each_solid_vertex(tri) |> collect) end - delete_point!(tri, i; rng=rng2, predicates=PT()) + delete_point!(tri, i; rng = rng2, predicates = PT()) push!(deleted_pts, i) - _tri = triangulate(points; delete_ghosts=false, skip_points=deleted_pts, rng=rng2, predicates=PT()) + _tri = triangulate(points; delete_ghosts = false, skip_points = deleted_pts, rng = rng2, predicates = PT()) DT.clear_empty_features!(tri) DT.clear_empty_features!(_tri) @test DT.compare_triangle_collections(get_triangles(_tri), get_triangles(tri)) @test get_adjacent(tri) == get_adjacent(_tri) @test get_adjacent2vertex(tri) == get_adjacent2vertex(_tri) @test get_graph(tri) == get_graph(_tri) - DT.convex_hull!(tri, predicates=PT()) + DT.convex_hull!(tri, predicates = PT()) @test validate_triangulation(tri) end end @@ -36,14 +36,14 @@ using StaticArrays for j in 1:50 rng = StableRNG(j) points = rand(rng, 2, 500) - tri = triangulate(points; rng, predicates=PT()) + tri = triangulate(points; rng, predicates = PT()) for k in 1:25 rng = StableRNG(k) i = rand(rng, each_solid_vertex(tri)) while DT.is_boundary_node(tri, i)[1] i = rand(rng, each_solid_vertex(tri)) end - delete_point!(tri, i, rng=rng, predicates=PT()) + delete_point!(tri, i, rng = rng, predicates = PT()) @test validate_triangulation(tri) end end @@ -58,25 +58,25 @@ using StaticArrays c, d = sort(15randn(rng1, 2)) nx = rand(rng1, 5:25) ny = rand(rng1, 5:25) - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) points = get_points(tri) n = nx * ny - for k in 1:(n÷10) + for k in 1:(n ÷ 10) rng2 = StableRNG(j + k * n) i = rand(rng2, each_solid_vertex(tri) |> collect) while DT.is_boundary_node(tri, i)[1] i = rand(rng2, each_solid_vertex(tri) |> collect) end - delete_point!(tri, i; rng=rng2, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + delete_point!(tri, i; rng = rng2, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end - tri = triangulate_rectangle(0, 1, 0, 1, 25, 25; delete_ghosts=false, single_boundary=true, predicates=PT()) - add_segment!(tri, 7, 7 + 25, predicates=PT()) - @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 2, predicates=PT()) - @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 7, predicates=PT()) - @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 7 + 25, predicates=PT()) - @test_throws DT.InvalidVertexDeletionError delete_point!(tri, -1, predicates=PT()) + tri = triangulate_rectangle(0, 1, 0, 1, 25, 25; delete_ghosts = false, single_boundary = true, predicates = PT()) + add_segment!(tri, 7, 7 + 25, predicates = PT()) + @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 2, predicates = PT()) + @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 7, predicates = PT()) + @test_throws DT.InvalidVertexDeletionError delete_point!(tri, 7 + 25, predicates = PT()) + @test_throws DT.InvalidVertexDeletionError delete_point!(tri, -1, predicates = PT()) end end @testset "Lattice with multiple boundary indices" begin @@ -87,17 +87,17 @@ using StaticArrays c, d = sort(15randn(rng1, 2)) nx = rand(rng1, 5:25) ny = rand(rng1, 5:25) - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=false, predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = false, predicates = PT()) points = get_points(tri) n = nx * ny - for k in 1:(n÷10) + for k in 1:(n ÷ 10) rng2 = StableRNG(j + k * n) i = rand(rng2, each_solid_vertex(tri) |> collect) while DT.is_boundary_node(tri, i)[1] i = rand(rng2, each_solid_vertex(tri) |> collect) end - delete_point!(tri, i; rng=rng2, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + delete_point!(tri, i; rng = rng2, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end end @@ -137,7 +137,7 @@ end 5 4 1 ] for T in eachrow(true_T) - add_triangle!(_tri, T; update_ghost_edges=true) + add_triangle!(_tri, T; update_ghost_edges = true) end convex_hull!(tri) DT.compute_representative_points!(tri) @@ -147,7 +147,7 @@ end @test get_adjacent(tri) == get_adjacent(_tri) @test get_adjacent2vertex(tri) == get_adjacent2vertex(_tri) @test get_graph(tri) == get_graph(_tri) - _tri = triangulate(get_points(tri); skip_points=16, delete_ghosts=false) + _tri = triangulate(get_points(tri); skip_points = 16, delete_ghosts = false) DT.clear_empty_features!(_tri) @test DT.compare_triangle_collections(get_triangles(_tri), get_triangles(tri)) @test get_adjacent(tri) == get_adjacent(_tri) @@ -178,7 +178,7 @@ end delete_point!(tri, point; rng) convex_hull!(tri) DT.compute_representative_points!(tri) - _tri = triangulate(get_points(tri); skip_points=_deleted_points, delete_ghosts=false, rng) + _tri = triangulate(get_points(tri); skip_points = _deleted_points, delete_ghosts = false, rng) @test validate_triangulation(tri) rng = StableRNG(ctr) ctr += 1 @@ -195,17 +195,17 @@ end @testset "Issue #96" begin for PT in subtypes(DT.AbstractPredicateKernel) - j = 96 - rng = StableRNG(j) - points = rand(rng, 2, 500) - tri = triangulate(points; rng, predicates=PT()) - orig_tri = deepcopy(tri) - k = 19 - rng = StableRNG(k) - i = 183 - delete_point!(tri, i, rng=rng, predicates=PT()) - @test validate_triangulation(tri) - add_point!(tri, i, rng=rng, predicates=PT()) - @test tri == orig_tri - @test validate_triangulation(tri) -end end \ No newline at end of file + j = 96 + rng = StableRNG(j) + points = rand(rng, 2, 500) + tri = triangulate(points; rng, predicates = PT()) + orig_tri = deepcopy(tri) + k = 19 + rng = StableRNG(k) + i = 183 + delete_point!(tri, i, rng = rng, predicates = PT()) + @test validate_triangulation(tri) + add_point!(tri, i, rng = rng, predicates = PT()) + @test tri == orig_tri + @test validate_triangulation(tri) + end end diff --git a/test/operations/delete_triangle.jl b/test/operations/delete_triangle.jl index e4e8edea0..9a72a92ff 100644 --- a/test/operations/delete_triangle.jl +++ b/test/operations/delete_triangle.jl @@ -10,17 +10,19 @@ global tri, label_map, index_map = simple_geometry() add_ghost_triangles!(tri) @testset "Deleting a triangle" begin - all_i = Set{NTuple{3,Int}}() - for (a, b, c) in [("a1", "f", "g"), - ("a1", "g", "i"), - ("a1", "i", "f"), - ("f", "i", "ℓ"), - ("f", "v", "e"), - ("f", "w", "v"), - ("e", "v", "z")] + all_i = Set{NTuple{3, Int}}() + for (a, b, c) in [ + ("a1", "f", "g"), + ("a1", "g", "i"), + ("a1", "i", "f"), + ("f", "i", "ℓ"), + ("f", "v", "e"), + ("f", "w", "v"), + ("e", "v", "z"), + ] i, j, k = index_map[a], index_map[b], index_map[c] push!(all_i, (i, j, k)) - DT.delete_triangle!(tri, i, j, k; protect_boundary=true, update_ghost_edges=false) + DT.delete_triangle!(tri, i, j, k; protect_boundary = true, update_ghost_edges = false) @test !DT.contains_triangle(tri, i, j, k)[2] @test !DT.contains_triangle(tri, j, k, i)[2] @test !DT.contains_triangle(tri, k, i, j)[2] @@ -56,38 +58,40 @@ end @testset "Deleting an interior triangle" begin i, j, k = 1, 3, 7 DT.delete_triangle!(tri, i, j, k) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3), - (5, 2, 8), - (6, 2, 3) - ]) + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + (5, 2, 8), + (6, 2, 3), + ], + ) true_adj = Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, - (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, - (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, - (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (5, 2) => 8, (2, 8) => 5, (8, 5) => 2, + (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, + (4, 5) => DT.𝒢, (5, 8) => DT.𝒢, + (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, + (6, 4) => DT.𝒢, + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (8, 5), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4), (2, 3)]), - 7 => Set{NTuple{2,Int}}([]), - 8 => Set{NTuple{2,Int}}([(5, 2)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (8, 5), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2), (2, 8)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4), (2, 3)]), + 7 => Set{NTuple{2, Int}}([]), + 8 => Set{NTuple{2, Int}}([(5, 2)]), ) true_DG = _make_graph_from_adjacency( [ @@ -100,7 +104,8 @@ end 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 - ], Dict(1:9 .=> [-1, (1:8)...])) + ], Dict(1:9 .=> [-1, (1:8)...]), + ) @test get_triangles(tri) == true_T @test (get_adjacent ∘ get_adjacent)(tri) == true_adj @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v @@ -112,34 +117,36 @@ end local true_T, true_adj, true_adj2v, true_DG _tri = deepcopy(tri) DT.delete_triangle!(_tri, i, j, k) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3), - (6, 2, 3) - ]) + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + (6, 2, 3), + ], + ) true_adj = Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, - (4, 5) => DT.𝒢, - (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (2, 3) => 6, (3, 6) => 2, (6, 2) => 3, + (4, 5) => DT.𝒢, + (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, + (6, 4) => DT.𝒢, + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4), (2, 3)]), + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4), (2, 3)]), ) true_DG = _make_graph_from_adjacency( [ @@ -150,7 +157,8 @@ end 1 1 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 1 1 0 0 - ], Dict(1:7 .=> [-1, (1:6)...])) + ], Dict(1:7 .=> [-1, (1:6)...]), + ) DT.clear_empty_features!(_tri) @test get_triangles(_tri) == true_T @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj @@ -166,33 +174,35 @@ end local true_T, true_adj, true_adj2v, true_DG _tri = deepcopy(tri) DT.delete_triangle!(_tri, i, j, k) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (6, 3, 1), - (4, 6, 1), - (5, 1, 3), - ]) + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (6, 3, 1), + (4, 6, 1), + (5, 1, 3), + ], + ) true_adj = Dict( - (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, - (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, - (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, - (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, - (5, 1) => 3, (3, 5) => 1, - (4, 5) => DT.𝒢, - (5, 2) => DT.𝒢, - (6, 4) => DT.𝒢, - (2, 3) => DT.𝒢, (3, 6) => DT.𝒢, - ) + (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, + (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, + (6, 3) => 1, (3, 1) => 6, (1, 6) => 3, + (4, 6) => 1, (6, 1) => 4, (1, 4) => 6, + (5, 1) => 3, (3, 5) => 1, + (4, 5) => DT.𝒢, + (5, 2) => DT.𝒢, + (6, 4) => DT.𝒢, + (2, 3) => DT.𝒢, (3, 6) => DT.𝒢, + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 1), (1, 6)]), - 4 => Set{NTuple{2,Int}}([(1, 5), (6, 1)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(3, 1), (1, 4)]), + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 3), (3, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(3, 5), (6, 3), (5, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 1), (1, 6)]), + 4 => Set{NTuple{2, Int}}([(1, 5), (6, 1)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(3, 1), (1, 4)]), ) true_DG = _make_graph_from_adjacency( [ @@ -203,7 +213,8 @@ end 1 1 0 0 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 - ], Dict(1:7 .=> [-1, (1:6)...])) + ], Dict(1:7 .=> [-1, (1:6)...]), + ) DT.clear_empty_features!(_tri) @test get_triangles(_tri) == true_T @test (get_adjacent ∘ get_adjacent)(_tri) == true_adj @@ -216,13 +227,13 @@ end @testset "Deleting the only triangle of a triangulation" begin tri = example_empty_triangulation() DT.add_triangle!(tri, 1, 2, 3) - true_T = Set{NTuple{3,Int}}([]) + true_T = Set{NTuple{3, Int}}([]) true_adj = DefaultDict(DT.∅, Dict()) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}(), - 1 => Set{NTuple{2,Int}}(), - 2 => Set{NTuple{2,Int}}(), - 3 => Set{NTuple{2,Int}}() + DT.𝒢 => Set{NTuple{2, Int}}(), + 1 => Set{NTuple{2, Int}}(), + 2 => Set{NTuple{2, Int}}(), + 3 => Set{NTuple{2, Int}}(), ) true_DG = _make_graph_from_adjacency([0 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0], Dict(1:4 .=> [-1, 1, 2, 3])) DT.delete_triangle!(tri, 1, 2, 3) @@ -238,29 +249,31 @@ end p3 = @SVector[0.0, 1.0] pts = [p1, p2, p3] tri = Triangulation(pts) - DT.add_triangle!(tri, 1, 2, 3; update_ghost_edges=true) + DT.add_triangle!(tri, 1, 2, 3; update_ghost_edges = true) p4 = @SVector[1.7, 1.7] push!(pts, p4) - DT.add_triangle!(tri, 3, 2, 4; update_ghost_edges=true) + DT.add_triangle!(tri, 3, 2, 4; update_ghost_edges = true) p5 = @SVector[1.0, 3.0] p6 = @SVector[3.0, 1.0] push!(pts, p5, p6) - DT.add_triangle!(tri, 3, 4, 5; update_ghost_edges=true) - DT.add_triangle!(tri, 4, 2, 6; update_ghost_edges=true) - DT.add_triangle!(tri, 5, 4, 6; update_ghost_edges=true) - DT.delete_triangle!(tri, 5, 4, 6; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([ - (1, 2, 3), - (3, 2, 4), - (3, 4, 5), - (4, 2, 6), - (2, 1, DT.𝒢), - (1, 3, DT.𝒢), - (3, 5, DT.𝒢), - (5, 4, DT.𝒢), - (4, 6, DT.𝒢), - (6, 2, DT.𝒢) - ]) + DT.add_triangle!(tri, 3, 4, 5; update_ghost_edges = true) + DT.add_triangle!(tri, 4, 2, 6; update_ghost_edges = true) + DT.add_triangle!(tri, 5, 4, 6; update_ghost_edges = true) + DT.delete_triangle!(tri, 5, 4, 6; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), + (3, 2, 4), + (3, 4, 5), + (4, 2, 6), + (2, 1, DT.𝒢), + (1, 3, DT.𝒢), + (3, 5, DT.𝒢), + (5, 4, DT.𝒢), + (4, 6, DT.𝒢), + (6, 2, DT.𝒢), + ], + ) true_adj = DT.Adjacent( Dict( (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, @@ -272,18 +285,19 @@ end (3, 5) => DT.𝒢, (5, DT.𝒢) => 3, (DT.𝒢, 3) => 5, (5, 4) => DT.𝒢, (4, DT.𝒢) => 5, (DT.𝒢, 5) => 4, (4, 6) => DT.𝒢, (6, DT.𝒢) => 4, (DT.𝒢, 4) => 6, - (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2 - )) + (6, 2) => DT.𝒢, (2, DT.𝒢) => 6, (DT.𝒢, 6) => 2, + ), + ) true_adj2v = DT.Adjacent2Vertex( Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 4), (4, 6), (6, 2), (2, 1)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), - 4 => Set{NTuple{2,Int}}([(3, 2), (5, 3), (2, 6), (DT.𝒢, 5), (6, DT.𝒢)]), - 5 => Set{NTuple{2,Int}}([(3, 4), (DT.𝒢, 3), (4, DT.𝒢)]), - 6 => Set{NTuple{2,Int}}([(4, 2), (DT.𝒢, 4), (2, DT.𝒢)]) - ) + DT.𝒢 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 4), (4, 6), (6, 2), (2, 1)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (3, DT.𝒢), (DT.𝒢, 2)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (4, 3), (6, 4), (1, DT.𝒢), (DT.𝒢, 6)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (2, 4), (4, 5), (DT.𝒢, 1), (5, DT.𝒢)]), + 4 => Set{NTuple{2, Int}}([(3, 2), (5, 3), (2, 6), (DT.𝒢, 5), (6, DT.𝒢)]), + 5 => Set{NTuple{2, Int}}([(3, 4), (DT.𝒢, 3), (4, DT.𝒢)]), + 6 => Set{NTuple{2, Int}}([(4, 2), (DT.𝒢, 4), (2, DT.𝒢)]), + ), ) true_DG = DT.Graph{Int}() DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 5, 4, 6, 2]...) @@ -297,14 +311,18 @@ end @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex @test get_graph(tri) == true_DG - DT.delete_triangle!(tri, 4, 2, 6; update_ghost_edges=true) - DT.delete_triangle!(tri, 3, 4, 5; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([(1, 2, 3), - (2, 1, DT.𝒢), - (1, 3, DT.𝒢), - (3, 4, DT.𝒢), - (4, 2, DT.𝒢), - (3, 2, 4)]) + DT.delete_triangle!(tri, 4, 2, 6; update_ghost_edges = true) + DT.delete_triangle!(tri, 3, 4, 5; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), + (2, 1, DT.𝒢), + (1, 3, DT.𝒢), + (3, 4, DT.𝒢), + (4, 2, DT.𝒢), + (3, 2, 4), + ], + ) true_adj = DT.Adjacent( Dict( (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, @@ -312,16 +330,17 @@ end (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, (3, 4) => DT.𝒢, (4, DT.𝒢) => 3, (DT.𝒢, 3) => 4, (4, 2) => DT.𝒢, (2, DT.𝒢) => 4, (DT.𝒢, 4) => 2, - (3, 2) => 4, (2, 4) => 3, (4, 3) => 2 - )) + (3, 2) => 4, (2, 4) => 3, (4, 3) => 2, + ), + ) true_adj2v = DT.Adjacent2Vertex( Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(2, 1), (1, 3), (3, 4), (4, 2)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 4), (4, 3)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (DT.𝒢, 1), (4, DT.𝒢), (2, 4)]), - 4 => Set{NTuple{2,Int}}([(DT.𝒢, 3), (2, DT.𝒢), (3, 2)]) - ) + DT.𝒢 => Set{NTuple{2, Int}}([(2, 1), (1, 3), (3, 4), (4, 2)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 4), (4, 3)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (DT.𝒢, 1), (4, DT.𝒢), (2, 4)]), + 4 => Set{NTuple{2, Int}}([(DT.𝒢, 3), (2, DT.𝒢), (3, 2)]), + ), ) true_DG = DT.Graph{Int}() DT.add_neighbour!(true_DG, DT.𝒢, [1, 3, 4, 2]...) @@ -334,25 +353,30 @@ end @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex @test get_graph(tri) == true_DG - DT.delete_triangle!(tri, 3, 2, 4; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}([(1, 2, 3), - (2, 1, DT.𝒢), - (1, 3, DT.𝒢), - (3, 2, DT.𝒢)]) + DT.delete_triangle!(tri, 3, 2, 4; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}( + [ + (1, 2, 3), + (2, 1, DT.𝒢), + (1, 3, DT.𝒢), + (3, 2, DT.𝒢), + ], + ) true_adj = DT.Adjacent( Dict( (1, 2) => 3, (2, 3) => 1, (3, 1) => 2, (2, 1) => DT.𝒢, (1, DT.𝒢) => 2, (DT.𝒢, 2) => 1, (1, 3) => DT.𝒢, (3, DT.𝒢) => 1, (DT.𝒢, 1) => 3, - (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2 - )) + (3, 2) => DT.𝒢, (2, DT.𝒢) => 3, (DT.𝒢, 3) => 2, + ), + ) true_adj2v = DT.Adjacent2Vertex( Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(2, 1), (1, 3), (3, 2)]), - 1 => Set{NTuple{2,Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), - 2 => Set{NTuple{2,Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 3)]), - 3 => Set{NTuple{2,Int}}([(1, 2), (DT.𝒢, 1), (2, DT.𝒢)]) - ) + DT.𝒢 => Set{NTuple{2, Int}}([(2, 1), (1, 3), (3, 2)]), + 1 => Set{NTuple{2, Int}}([(2, 3), (DT.𝒢, 2), (3, DT.𝒢)]), + 2 => Set{NTuple{2, Int}}([(3, 1), (1, DT.𝒢), (DT.𝒢, 3)]), + 3 => Set{NTuple{2, Int}}([(1, 2), (DT.𝒢, 1), (2, DT.𝒢)]), + ), ) true_DG = DT.Graph{Int}() DT.add_neighbour!(true_DG, DT.𝒢, [1, 2, 3]...) @@ -364,10 +388,10 @@ end @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex @test get_graph(tri) == true_DG - DT.delete_triangle!(tri, 1, 2, 3; update_ghost_edges=true) - true_T = Set{NTuple{3,Int}}() - true_adj = DT.Adjacent{Int,NTuple{2,Int}}() - true_adj2v = DT.Adjacent2Vertex{Int,Set{NTuple{2,Int}}}() + DT.delete_triangle!(tri, 1, 2, 3; update_ghost_edges = true) + true_T = Set{NTuple{3, Int}}() + true_adj = DT.Adjacent{Int, NTuple{2, Int}}() + true_adj2v = DT.Adjacent2Vertex{Int, Set{NTuple{2, Int}}}() true_DG = DT.Graph{Int}() DT.clear_empty_features!(tri) @test DT.compare_triangle_collections(get_triangles(tri), true_T) @@ -391,41 +415,45 @@ end pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] tri = Triangulation(pts) for (i, j, k) in ( - (1, 2, 6), - (1, 6, 8), - (9, 1, 8), - (9, 8, 10), - (10, 8, 11), - (8, 7, 11), - (8, 6, 7), - (6, 2, 3), - (6, 3, 4), - (6, 4, 7), - (7, 4, 5), - (11, 7, 5), - (10, 11, 5) - ) - DT.add_triangle!(tri, i, j, k; update_ghost_edges=true) + (1, 2, 6), + (1, 6, 8), + (9, 1, 8), + (9, 8, 10), + (10, 8, 11), + (8, 7, 11), + (8, 6, 7), + (6, 2, 3), + (6, 3, 4), + (6, 4, 7), + (7, 4, 5), + (11, 7, 5), + (10, 11, 5), + ) + DT.add_triangle!(tri, i, j, k; update_ghost_edges = true) end - [DT.delete_triangle!(tri, i, j, k; update_ghost_edges=true) for (i, j, k) in ( - (1, 8, 9), (9, 8, 10), (10, 11, 5), (5, 7, 4), (4, 6, 3), (3, 6, 2), (2, 6, 1) - )] - true_T = Set{NTuple{3,Int}}([ - (1, 6, 8), - (6, 7, 8), - (6, 4, 7), - (8, 7, 11), - (11, 7, 5), - (10, 8, 11), - (1, 8, DT.𝒢), - (8, 10, DT.𝒢), - (10, 11, DT.𝒢), - (11, 5, DT.𝒢), - (5, 7, DT.𝒢), - (7, 4, DT.𝒢), - (4, 6, DT.𝒢), - (6, 1, DT.𝒢) - ]) + [ + DT.delete_triangle!(tri, i, j, k; update_ghost_edges = true) for (i, j, k) in ( + (1, 8, 9), (9, 8, 10), (10, 11, 5), (5, 7, 4), (4, 6, 3), (3, 6, 2), (2, 6, 1), + ) + ] + true_T = Set{NTuple{3, Int}}( + [ + (1, 6, 8), + (6, 7, 8), + (6, 4, 7), + (8, 7, 11), + (11, 7, 5), + (10, 8, 11), + (1, 8, DT.𝒢), + (8, 10, DT.𝒢), + (10, 11, DT.𝒢), + (11, 5, DT.𝒢), + (5, 7, DT.𝒢), + (7, 4, DT.𝒢), + (4, 6, DT.𝒢), + (6, 1, DT.𝒢), + ], + ) true_adj = DT.Adjacent( Dict( (1, 6) => 8, (6, 8) => 1, (8, 1) => 6, @@ -441,10 +469,10 @@ end (5, 7) => DT.𝒢, (7, DT.𝒢) => 5, (DT.𝒢, 5) => 7, (7, 4) => DT.𝒢, (4, DT.𝒢) => 7, (DT.𝒢, 7) => 4, (4, 6) => DT.𝒢, (6, DT.𝒢) => 4, (DT.𝒢, 4) => 6, - (6, 1) => DT.𝒢, (1, DT.𝒢) => 6, (DT.𝒢, 6) => 1 - ) + (6, 1) => DT.𝒢, (1, DT.𝒢) => 6, (DT.𝒢, 6) => 1, + ), ) - true_adj2v = DT.Adjacent2Vertex{Int,Set{NTuple{2,Int}}}() + true_adj2v = DT.Adjacent2Vertex{Int, Set{NTuple{2, Int}}}() for (ij, k) in true_adj.adjacent DT.add_adjacent2vertex!(true_adj2v, k, ij) end @@ -463,4 +491,4 @@ end @test (get_adjacent ∘ get_adjacent)(tri) == true_adj.adjacent @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v.adjacent2vertex @test get_graph(tri) == true_DG -end \ No newline at end of file +end diff --git a/test/operations/flip_edge.jl b/test/operations/flip_edge.jl index 1ec056949..e7ef3df75 100644 --- a/test/operations/flip_edge.jl +++ b/test/operations/flip_edge.jl @@ -10,19 +10,22 @@ using StaticArrays DT.split_triangle!(tri, 4, 6, 1, 8) DT.split_triangle!(tri, 1, 5, 4, 7) @testset "First flip" begin - true_T = Set{NTuple{3,Int}}([ - (5, 6, 3), - (3, 2, 5), - (4, 1, 7), - (5, 4, 7), - (5, 1, 6), - (1, 5, 7), - (6, 2, 3), - (6, 1, 8), - (4, 6, 8), - (1, 4, 8) - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (5, 6, 3), + (3, 2, 5), + (4, 1, 7), + (5, 4, 7), + (5, 1, 6), + (1, 5, 7), + (6, 2, 3), + (6, 1, 8), + (4, 6, 8), + (1, 4, 8), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (5, 6) => 3, (6, 3) => 5, (3, 5) => 6, (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, @@ -38,18 +41,18 @@ using StaticArrays (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - ) + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(6, 5), (5, 7), (7, 4), (4, 8), (8, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(5, 6), (6, 2), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(6, 8), (8, 1), (1, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 1), (1, 6), (6, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 5), (5, 1), (1, 8), (8, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 5), (5, 4), (4, 1)]), - 8 => Set{NTuple{2,Int}}([(1, 4), (4, 6), (6, 1)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(6, 5), (5, 7), (7, 4), (4, 8), (8, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(5, 6), (6, 2), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(6, 8), (8, 1), (1, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 1), (1, 6), (6, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 5), (5, 1), (1, 8), (8, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 5), (5, 4), (4, 1)]), + 8 => Set{NTuple{2, Int}}([(1, 4), (4, 6), (6, 1)]), ) true_DG = _make_graph_from_adjacency( [ @@ -62,7 +65,8 @@ using StaticArrays 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 0 1 0 0 1 0 1 0 0 - ], Dict(1:9 .=> [-1, 1, 2, 3, 4, 5, 6, 7, 8])) + ], Dict(1:9 .=> [-1, 1, 2, 3, 4, 5, 6, 7, 8]), + ) DT.flip_edge!(tri, 1, 3) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @@ -72,19 +76,22 @@ using StaticArrays end @testset "Second flip" begin - true_T = Set{NTuple{3,Int}}([ - (5, 6, 3), - (3, 2, 5), - (5, 4, 7), - (5, 1, 6), - (1, 5, 7), - (6, 2, 3), - (6, 1, 8), - (4, 6, 8), - (8, 1, 7), - (8, 7, 4) - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (5, 6, 3), + (3, 2, 5), + (5, 4, 7), + (5, 1, 6), + (1, 5, 7), + (6, 2, 3), + (6, 1, 8), + (4, 6, 8), + (8, 1, 7), + (8, 7, 4), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (5, 6) => 3, (6, 3) => 5, (3, 5) => 6, (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, @@ -100,18 +107,18 @@ using StaticArrays (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - ) + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(6, 5), (5, 7), (7, 8), (8, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(5, 6), (6, 2), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(6, 8), (8, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 1), (1, 6), (6, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 5), (5, 1), (1, 8), (8, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 5), (5, 4), (4, 8), (8, 1)]), - 8 => Set{NTuple{2,Int}}([(1, 7), (7, 4), (4, 6), (6, 1)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(6, 5), (5, 7), (7, 8), (8, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(5, 6), (6, 2), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(6, 8), (8, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 1), (1, 6), (6, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 5), (5, 1), (1, 8), (8, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 5), (5, 4), (4, 8), (8, 1)]), + 8 => Set{NTuple{2, Int}}([(1, 7), (7, 4), (4, 6), (6, 1)]), ) true_DG = _make_graph_from_adjacency( [ @@ -124,7 +131,8 @@ using StaticArrays 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 1 1 0 - ], Dict(1:9 .=> [-1, 1, 2, 3, 4, 5, 6, 7, 8])) + ], Dict(1:9 .=> [-1, 1, 2, 3, 4, 5, 6, 7, 8]), + ) DT.flip_edge!(tri, 1, 4) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @@ -142,17 +150,20 @@ end r = 7 e = DT.get_adjacent(tri, j, i) DT.flip_edge!(tri, i, j) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 3, 7), - (3, 5, 7), - (6, 3, 1), - (4, 6, 1), - (6, 2, 3), - (7, 5, 4), - (7, 4, 1) - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 3, 7), + (3, 5, 7), + (6, 3, 1), + (4, 6, 1), + (6, 2, 3), + (7, 5, 4), + (7, 4, 1), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, @@ -166,19 +177,20 @@ end (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - ) + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(6, 3), (3, 7), (7, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 7), (7, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(6, 1), (1, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(3, 5), (5, 4), (4, 1), (1, 3)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(6, 3), (3, 7), (7, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 7), (7, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(6, 1), (1, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(3, 5), (5, 4), (4, 1), (1, 3)]), ) - true_DG = _make_graph_from_adjacency([ + true_DG = _make_graph_from_adjacency( + [ 0 0 1 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 0 1 1 0 @@ -187,11 +199,12 @@ end 1 0 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 1 0 1 1 1 0 0 - ], Dict(1:8 .=> [-1, (1:7)...])) + ], Dict(1:8 .=> [-1, (1:7)...]), + ) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @test (get_adjacent ∘ get_adjacent)(tri) == true_adj @test (get_adjacent2vertex ∘ get_adjacent2vertex)(tri) == true_adj2v @test (get_graph)(tri) == true_DG @test all(DT.is_positively_oriented(DT.triangle_orientation(tri, T...)) for T in each_triangle(tri)) -end \ No newline at end of file +end diff --git a/test/operations/legalise_edge.jl b/test/operations/legalise_edge.jl index fd10a320b..77a1ac708 100644 --- a/test/operations/legalise_edge.jl +++ b/test/operations/legalise_edge.jl @@ -13,17 +13,20 @@ using StaticArrays i, j, r = 5, 1, 7 e = DT.get_adjacent(tri, j, i) DT.legalise_edge!(tri, i, j, r) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 3, 7), - (3, 5, 7), - (6, 3, 1), - (4, 6, 1), - (6, 2, 3), - (7, 5, 4), - (7, 4, 1) - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 3, 7), + (3, 5, 7), + (6, 3, 1), + (4, 6, 1), + (6, 2, 3), + (7, 5, 4), + (7, 4, 1), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (1, 3) => 7, (3, 7) => 1, (7, 1) => 3, @@ -37,19 +40,20 @@ using StaticArrays (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - ) + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(6, 3), (3, 7), (7, 4), (4, 6)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 5), (5, 7), (7, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(6, 1), (1, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(3, 5), (5, 4), (4, 1), (1, 3)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(6, 3), (3, 7), (7, 4), (4, 6)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 5), (5, 7), (7, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(6, 1), (1, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(3, 5), (5, 4), (4, 1), (1, 3)]), ) - true_DG = _make_graph_from_adjacency([ + true_DG = _make_graph_from_adjacency( + [ 0 0 1 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 0 1 1 0 @@ -58,7 +62,8 @@ using StaticArrays 1 0 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 1 0 1 1 1 0 0 - ], Dict(1:8 .=> [-1, (1:7)...])) + ], Dict(1:8 .=> [-1, (1:7)...]), + ) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @test (get_adjacent ∘ get_adjacent)(tri) == true_adj @@ -68,4 +73,4 @@ using StaticArrays for ((i, j), v) in get_adjacent(tri).adjacent @test DT.is_legal(tri, i, j) |> DT.is_legal end -end \ No newline at end of file +end diff --git a/test/operations/lock_convex_hull.jl b/test/operations/lock_convex_hull.jl index 4aa922a43..fb178d61c 100644 --- a/test/operations/lock_convex_hull.jl +++ b/test/operations/lock_convex_hull.jl @@ -29,7 +29,7 @@ using StaticArrays add_segment!(tri, e) end lock_convex_hull!(tri2) - tri3 = triangulate(pts; boundary_nodes=bn) + tri3 = triangulate(pts; boundary_nodes = bn) @test tri2.boundary_nodes == tri3.boundary_nodes == bn @test tri2.ghost_vertex_map == tri3.ghost_vertex_map == bn_map @test tri2.boundary_edge_map == tri3.boundary_edge_map == bnn_map @@ -42,7 +42,7 @@ using StaticArrays p3 = (1.0, 1.0) p4 = (0.0, 1.0) pts = [p1, p2, p3, p4] - tri = triangulate(pts; boundary_nodes=[1, 2, 3, 4, 1]) + tri = triangulate(pts; boundary_nodes = [1, 2, 3, 4, 1]) @test_throws ArgumentError("Cannot lock the convex hull of a triangulation with boundary nodes.") lock_convex_hull!(tri) end @@ -77,7 +77,7 @@ end @testset "Fixing interior segments that happen to be on the convex hull" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.25, 0.5), (0.75, 0.5)] - tri = triangulate(points; segments=Set([(1, 2), (2, 3), (5, 6)])) + tri = triangulate(points; segments = Set([(1, 2), (2, 3), (5, 6)])) lock_convex_hull!(tri) @test DT.compare_unoriented_edge_collections(get_interior_segments(tri), Set([(5, 6)])) @test DT.compare_unoriented_edge_collections(tri.cache.interior_segments_on_hull, Set([(1, 2), (2, 3)])) @@ -88,7 +88,7 @@ end DT.complete_split_edge_and_legalise!(tri, 7, 2, 8) DT.complete_split_edge_and_legalise!(tri, 7, 8, 9) @test validate_triangulation(tri) - unlock_convex_hull!(tri; reconstruct=true) + unlock_convex_hull!(tri; reconstruct = true) @test validate_triangulation(tri) @test DT.compare_unoriented_edge_collections(get_interior_segments(tri), Set([(5, 6), (1, 7), (7, 9), (9, 8), (8, 2), (2, 3)])) @test isempty(tri.cache.interior_segments_on_hull) @@ -97,7 +97,7 @@ end validate_statistics(tri) points = [(0.0, 0.0), (9.0, 0.0), (9.0, 7.0)] - tri = triangulate(points; segments=Set([(1, 2), (1, 3)])) + tri = triangulate(points; segments = Set([(1, 2), (1, 3)])) lock_convex_hull!(tri) orig_tri = deepcopy(tri) orig_points = copy(orig_tri.points) @@ -105,7 +105,7 @@ end DT.complete_split_edge_and_legalise!(tri, 1, 2, 4) @test validate_triangulation(tri) @test collect(get_point(tri, 4)) ≈ [4.5, 0.0] - unlock_convex_hull!(tri; reconstruct=true) - @test tri == triangulate([orig_points; get_point(tri, 4)]; segments=Set([(1, 4), (4, 2), (1, 3)])) + unlock_convex_hull!(tri; reconstruct = true) + @test tri == triangulate([orig_points; get_point(tri, 4)]; segments = Set([(1, 4), (4, 2), (1, 3)])) end -end \ No newline at end of file +end diff --git a/test/operations/split_edge.jl b/test/operations/split_edge.jl index dcab3e40d..9441a3caf 100644 --- a/test/operations/split_edge.jl +++ b/test/operations/split_edge.jl @@ -18,19 +18,22 @@ using StaticArrays i, j, r = 1, 7, 8 DT.split_edge!(tri, i, j, r) DT.split_edge!(tri, j, i, r) - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (1, 8, 4), - (7, 8, 3), - (3, 5, 7), - (6, 3, 1), - (4, 6, 1), - (4, 7, 5), - (6, 2, 3), - (8, 7, 4), - (8, 1, 3), - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (1, 8, 4), + (7, 8, 3), + (3, 5, 7), + (6, 3, 1), + (4, 6, 1), + (4, 7, 5), + (6, 2, 3), + (8, 7, 4), + (8, 1, 3), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (1, 8) => 4, (8, 4) => 1, (4, 1) => 8, @@ -46,17 +49,18 @@ using StaticArrays (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - )) + ), + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(4, 6), (6, 3), (3, 8), (8, 4)]), - 2 => Set{NTuple{2,Int}}([(5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(6, 2), (2, 5), (5, 7), (7, 8), (8, 1), (1, 6)]), - 4 => Set{NTuple{2,Int}}([(6, 1), (1, 8), (8, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 3), (3, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(3, 5), (5, 4), (4, 8), (8, 3)]), - 8 => Set{NTuple{2,Int}}([(1, 3), (3, 7), (7, 4), (4, 1)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(4, 6), (6, 3), (3, 8), (8, 4)]), + 2 => Set{NTuple{2, Int}}([(5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(6, 2), (2, 5), (5, 7), (7, 8), (8, 1), (1, 6)]), + 4 => Set{NTuple{2, Int}}([(6, 1), (1, 8), (8, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 3), (3, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(3, 5), (5, 4), (4, 8), (8, 3)]), + 8 => Set{NTuple{2, Int}}([(1, 3), (3, 7), (7, 4), (4, 1)]), ) true_DG = _make_graph_from_adjacency( [ @@ -69,7 +73,8 @@ using StaticArrays 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 1 1 0 0 1 0 - ], Dict(1:9 .=> [-1, (1:8)...])) + ], Dict(1:9 .=> [-1, (1:8)...]), + ) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @test (get_adjacent ∘ get_adjacent)(tri) == true_adj @@ -80,21 +85,24 @@ using StaticArrays i, j, r = 5, 3, 9 DT.split_edge!(tri, i, j, r) DT.split_edge!(tri, j, i, r) - true_T = Set{NTuple{3,Int}}([ - (1, 8, 4), - (7, 8, 3), - (6, 3, 1), - (4, 6, 1), - (4, 7, 5), - (6, 2, 3), - (8, 7, 4), - (8, 1, 3), - (9, 5, 7), - (3, 9, 7), - (9, 3, 2), - (5, 9, 2) - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (1, 8, 4), + (7, 8, 3), + (6, 3, 1), + (4, 6, 1), + (4, 7, 5), + (6, 2, 3), + (8, 7, 4), + (8, 1, 3), + (9, 5, 7), + (3, 9, 7), + (9, 3, 2), + (5, 9, 2), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (1, 8) => 4, (8, 4) => 1, (4, 1) => 8, (7, 8) => 3, (8, 3) => 7, (3, 7) => 8, @@ -112,18 +120,19 @@ using StaticArrays (5, 2) => DT.𝒢, (2, 6) => DT.𝒢, (6, 4) => DT.𝒢, - )) + ), + ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(4, 6), (6, 3), (3, 8), (8, 4)]), - 2 => Set{NTuple{2,Int}}([(5, 9), (9, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(2, 9), (9, 7), (7, 8), (8, 1), (1, 6), (6, 2)]), - 4 => Set{NTuple{2,Int}}([(6, 1), (1, 8), (8, 7), (7, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 7), (7, 9), (9, 2)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(9, 5), (5, 4), (4, 8), (8, 3), (3, 9)]), - 8 => Set{NTuple{2,Int}}([(1, 3), (3, 7), (7, 4), (4, 1)]), - 9 => Set{NTuple{2,Int}}([(2, 5), (5, 7), (7, 3), (3, 2)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(4, 6), (6, 3), (3, 8), (8, 4)]), + 2 => Set{NTuple{2, Int}}([(5, 9), (9, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(2, 9), (9, 7), (7, 8), (8, 1), (1, 6), (6, 2)]), + 4 => Set{NTuple{2, Int}}([(6, 1), (1, 8), (8, 7), (7, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 7), (7, 9), (9, 2)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(9, 5), (5, 4), (4, 8), (8, 3), (3, 9)]), + 8 => Set{NTuple{2, Int}}([(1, 3), (3, 7), (7, 4), (4, 1)]), + 9 => Set{NTuple{2, Int}}([(2, 5), (5, 7), (7, 3), (3, 2)]), ) true_DG = _make_graph_from_adjacency( [ @@ -137,7 +146,8 @@ using StaticArrays 0 0 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 0 0 0 1 1 0 1 0 1 0 0 - ], Dict(1:10 .=> [-1, (1:9)...])) + ], Dict(1:10 .=> [-1, (1:9)...]), + ) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @test (get_adjacent ∘ get_adjacent)(tri) == true_adj @@ -157,7 +167,7 @@ end DT.push_point!(tri, 4.0, 1.3) DT.complete_split_edge_and_legalise!(tri, 12, 9, DT.num_points(tri)) validate_triangulation(tri) - DT.push_point!(tri, 4.0 + 1e-13, 2.2 - 1e-9) + DT.push_point!(tri, 4.0 + 1.0e-13, 2.2 - 1.0e-9) DT.complete_split_edge_and_legalise!(tri, 12, 10, DT.num_points(tri)) validate_triangulation(tri) DT.push_point!(tri, 4.0, 0.0) @@ -187,19 +197,23 @@ end @testset "Boundary segments" begin for i in 1:100 - curve_1 = [[ - (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), - (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), - (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), - (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), - (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), - (-4.0, 0.0), (0.0, 0.0), - ]] - curve_2 = [[ - (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), - (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ]] + curve_1 = [ + [ + (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), + (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), + (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), + (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), + (-4.0, 0.0), (0.0, 0.0), + ], + ] + curve_2 = [ + [ + (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), + (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], + ] curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] curves = [curve_1, curve_2, curve_3, curve_4] @@ -214,10 +228,11 @@ end (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] - boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) + (7.0, 7.8), (7.0, 7.4), + ] + boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) uncons_tri = triangulate(points) - cons_tri = triangulate(points; boundary_nodes=boundary_nodes) + cons_tri = triangulate(points; boundary_nodes = boundary_nodes) tri = cons_tri @test validate_triangulation(tri) validate_statistics(tri) @@ -251,22 +266,30 @@ end @test get_adjacent(tri, 102, 96) == DT.𝒢 - 3 flag = validate_triangulation(tri) @test flag - @test get_adjacent2vertex(tri, DT.𝒢) == Set(( - (70, 69), (69, 68), (68, 67), (67, 66), (66, 65), (65, 64), (64, 63), - (63, 62), (62, 61), (61, 60), (60, 59), (59, 58), (58, 57), - (57, 56), (56, 55), (55, 78), (78, 77), (77, 76), (76, 75), - (75, 74), (74, 73), (73, 72), (72, 71), (71, 70), - )) - @test get_adjacent2vertex(tri, DT.𝒢 - 1) == Set(( - (79, 89), (89, 88), (88, 87), (87, 86), (86, 85), (85, 84), - (84, 83), (83, 82), (82, 81), (81, 80), (80, 79) - )) - @test get_adjacent2vertex(tri, DT.𝒢 - 2) == Set(( - (90, 93), (93, 92), (92, 91), (91, 90) - )) - @test get_adjacent2vertex(tri, DT.𝒢 - 3) == Set(( - (94, 97), (97, 102), (102, 96), (96, 95), (95, 94) - )) + @test get_adjacent2vertex(tri, DT.𝒢) == Set( + ( + (70, 69), (69, 68), (68, 67), (67, 66), (66, 65), (65, 64), (64, 63), + (63, 62), (62, 61), (61, 60), (60, 59), (59, 58), (58, 57), + (57, 56), (56, 55), (55, 78), (78, 77), (77, 76), (76, 75), + (75, 74), (74, 73), (73, 72), (72, 71), (71, 70), + ), + ) + @test get_adjacent2vertex(tri, DT.𝒢 - 1) == Set( + ( + (79, 89), (89, 88), (88, 87), (87, 86), (86, 85), (85, 84), + (84, 83), (83, 82), (82, 81), (81, 80), (80, 79), + ), + ) + @test get_adjacent2vertex(tri, DT.𝒢 - 2) == Set( + ( + (90, 93), (93, 92), (92, 91), (91, 90), + ), + ) + @test get_adjacent2vertex(tri, DT.𝒢 - 3) == Set( + ( + (94, 97), (97, 102), (102, 96), (96, 95), (95, 94), + ), + ) validate_statistics(tri) @test test_fnc(tri, 87, 86) @@ -290,4 +313,4 @@ end @test test_fnc(tri, 78, 77) end end -end \ No newline at end of file +end diff --git a/test/operations/split_triangle.jl b/test/operations/split_triangle.jl index 4794c3b30..2abdca023 100644 --- a/test/operations/split_triangle.jl +++ b/test/operations/split_triangle.jl @@ -13,16 +13,19 @@ using StaticArrays DT.add_triangle!(tri, 6, 2, 3) @testset "Interior splitting" begin - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (5, 2, 8), - (6, 3, 1), - (4, 6, 1), - (1, 3, 7), (3, 5, 7), (5, 1, 7), - (6, 2, 3), - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (5, 2, 8), + (6, 3, 1), + (4, 6, 1), + (1, 3, 7), (3, 5, 7), (5, 1, 7), + (6, 2, 3), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, @@ -37,21 +40,22 @@ using StaticArrays (5, 8) => DT.𝒢, (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (6, 4) => DT.𝒢, + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(5, 4), (4, 6), (6, 3), (3, 7), (7, 5)]), - 2 => Set{NTuple{2,Int}}([(8, 5), (5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(6, 1), (1, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 8)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 1)]), - 8 => Set{NTuple{2,Int}}([(5, 2)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(5, 4), (4, 6), (6, 3), (3, 7), (7, 5)]), + 2 => Set{NTuple{2, Int}}([(8, 5), (5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(6, 1), (1, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 8)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 1)]), + 8 => Set{NTuple{2, Int}}([(5, 2)]), ) - true_DG = _make_graph_from_adjacency([ + true_DG = _make_graph_from_adjacency( + [ 0 0 1 0 1 1 1 0 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0 1 1 0 1 @@ -61,7 +65,8 @@ using StaticArrays 1 1 1 1 1 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 0 - ], Dict(1:9 .=> [-1, (1:8)...])) + ], Dict(1:9 .=> [-1, (1:8)...]), + ) DT.split_triangle!(tri, 1, 3, 5, 7) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @@ -71,16 +76,19 @@ using StaticArrays end @testset "Splitting a triangle with one boundary edge" begin - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (5, 2, 8), - (6, 3, 1), - (4, 6, 9), (6, 1, 9), (1, 4, 9), - (1, 3, 7), (3, 5, 7), (5, 1, 7), - (6, 2, 3), - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (5, 2, 8), + (6, 3, 1), + (4, 6, 9), (6, 1, 9), (1, 4, 9), + (1, 3, 7), (3, 5, 7), (5, 1, 7), + (6, 2, 3), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, @@ -97,22 +105,23 @@ using StaticArrays (5, 8) => DT.𝒢, (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (6, 4) => DT.𝒢, + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(5, 4), (4, 9), (9, 6), (6, 3), (3, 7), (7, 5)]), - 2 => Set{NTuple{2,Int}}([(8, 5), (5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(6, 9), (9, 1), (1, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 8)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 9), (9, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 1)]), - 8 => Set{NTuple{2,Int}}([(5, 2)]), - 9 => Set{NTuple{2,Int}}([(6, 1), (1, 4), (4, 6)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(5, 4), (4, 9), (9, 6), (6, 3), (3, 7), (7, 5)]), + 2 => Set{NTuple{2, Int}}([(8, 5), (5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(6, 9), (9, 1), (1, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 8)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 9), (9, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 1)]), + 8 => Set{NTuple{2, Int}}([(5, 2)]), + 9 => Set{NTuple{2, Int}}([(6, 1), (1, 4), (4, 6)]), ) - true_DG = _make_graph_from_adjacency([ + true_DG = _make_graph_from_adjacency( + [ 0 0 1 0 1 1 1 0 1 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1 0 1 1 0 1 0 @@ -123,7 +132,8 @@ using StaticArrays 0 1 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 1 0 0 0 - ], Dict(1:10 .=> [-1, (1:9)...])) + ], Dict(1:10 .=> [-1, (1:9)...]), + ) DT.split_triangle!(tri, 4, 6, 1, 9) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @@ -133,16 +143,19 @@ using StaticArrays end @testset "Splitting two boundary edges" begin - true_T = Set{NTuple{3,Int}}([ - (3, 2, 5), - (4, 1, 5), - (5, 2, 10), (2, 8, 10), (8, 5, 10), - (6, 3, 1), - (4, 6, 9), (6, 1, 9), (1, 4, 9), - (1, 3, 7), (3, 5, 7), (5, 1, 7), - (6, 2, 3), - ]) - true_adj = DefaultDict(DT.∅, + true_T = Set{NTuple{3, Int}}( + [ + (3, 2, 5), + (4, 1, 5), + (5, 2, 10), (2, 8, 10), (8, 5, 10), + (6, 3, 1), + (4, 6, 9), (6, 1, 9), (1, 4, 9), + (1, 3, 7), (3, 5, 7), (5, 1, 7), + (6, 2, 3), + ], + ) + true_adj = DefaultDict( + DT.∅, Dict( (3, 2) => 5, (2, 5) => 3, (5, 3) => 2, (4, 1) => 5, (1, 5) => 4, (5, 4) => 1, @@ -161,23 +174,24 @@ using StaticArrays (5, 8) => DT.𝒢, (8, 2) => DT.𝒢, (2, 6) => DT.𝒢, - (6, 4) => DT.𝒢 - ) + (6, 4) => DT.𝒢, + ), ) true_adj2v = Dict( - DT.𝒢 => Set{NTuple{2,Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), - 1 => Set{NTuple{2,Int}}([(5, 4), (4, 9), (9, 6), (6, 3), (3, 7), (7, 5)]), - 2 => Set{NTuple{2,Int}}([(8, 10), (10, 5), (5, 3), (3, 6)]), - 3 => Set{NTuple{2,Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), - 4 => Set{NTuple{2,Int}}([(6, 9), (9, 1), (1, 5)]), - 5 => Set{NTuple{2,Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 10), (10, 8)]), - 6 => Set{NTuple{2,Int}}([(2, 3), (3, 1), (1, 9), (9, 4)]), - 7 => Set{NTuple{2,Int}}([(1, 3), (3, 5), (5, 1)]), - 8 => Set{NTuple{2,Int}}([(5, 10), (10, 2)]), - 9 => Set{NTuple{2,Int}}([(6, 1), (1, 4), (4, 6)]), - 10 => Set{NTuple{2,Int}}([(5, 2), (2, 8), (8, 5)]) + DT.𝒢 => Set{NTuple{2, Int}}([(4, 5), (5, 8), (8, 2), (2, 6), (6, 4)]), + 1 => Set{NTuple{2, Int}}([(5, 4), (4, 9), (9, 6), (6, 3), (3, 7), (7, 5)]), + 2 => Set{NTuple{2, Int}}([(8, 10), (10, 5), (5, 3), (3, 6)]), + 3 => Set{NTuple{2, Int}}([(5, 7), (7, 1), (1, 6), (6, 2), (2, 5)]), + 4 => Set{NTuple{2, Int}}([(6, 9), (9, 1), (1, 5)]), + 5 => Set{NTuple{2, Int}}([(4, 1), (1, 7), (7, 3), (3, 2), (2, 10), (10, 8)]), + 6 => Set{NTuple{2, Int}}([(2, 3), (3, 1), (1, 9), (9, 4)]), + 7 => Set{NTuple{2, Int}}([(1, 3), (3, 5), (5, 1)]), + 8 => Set{NTuple{2, Int}}([(5, 10), (10, 2)]), + 9 => Set{NTuple{2, Int}}([(6, 1), (1, 4), (4, 6)]), + 10 => Set{NTuple{2, Int}}([(5, 2), (2, 8), (8, 5)]), ) - true_DG = _make_graph_from_adjacency([ + true_DG = _make_graph_from_adjacency( + [ 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 0 1 1 0 1 0 1 @@ -189,7 +203,8 @@ using StaticArrays 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 - ], Dict(1:11 .=> [-1, (1:10)...])) + ], Dict(1:11 .=> [-1, (1:10)...]), + ) DT.split_triangle!(tri, 5, 2, 8, 10) DT.clear_empty_features!(tri) @test get_triangles(tri) == true_T @@ -245,4 +260,4 @@ end @test DT.contains_segment(tri, 1, 11) @test DT.edge_exists(tri, 1, 11) && DT.edge_exists(tri, 11, 1) end -end \ No newline at end of file +end diff --git a/test/point_location/brute_force.jl b/test/point_location/brute_force.jl index 1e9670807..a9b665202 100644 --- a/test/point_location/brute_force.jl +++ b/test/point_location/brute_force.jl @@ -3,7 +3,6 @@ const DT = DelaunayTriangulation using StatsBase - global tri, label_map, index_map = simple_geometry() @testset "Finding points in ghost triangles" begin @@ -33,15 +32,15 @@ global tri, label_map, index_map = simple_geometry() d1_i = length(pts) - 4 c1_i = length(pts) - 5 for pred in (DT.FastKernel(), DT.ExactKernel(), DT.AdaptiveKernel()) - @test DT.compare_triangles(DT.brute_force_search(tri, c1_i; predicates=pred), (index_map["g"], index_map["f"], DT.𝒢)) - @test DT.compare_triangles(DT.brute_force_search(tri, d1_i; predicates=pred), (index_map["f"], index_map["e"], DT.𝒢)) + @test DT.compare_triangles(DT.brute_force_search(tri, c1_i; predicates = pred), (index_map["g"], index_map["f"], DT.𝒢)) + @test DT.compare_triangles(DT.brute_force_search(tri, d1_i; predicates = pred), (index_map["f"], index_map["e"], DT.𝒢)) @test DT.compare_triangles(DT.brute_force_search(tri, e1_i), (index_map["k"], index_map["ℓ"], DT.𝒢 - 1)) @test DT.compare_triangles(DT.brute_force_search(tri, f1_i), (index_map["ℓ"], index_map["k"], index_map["w"])) - @test DT.compare_triangles(DT.brute_force_search(tri, g1_i; predicates=pred), (index_map["b"], index_map["c"], index_map["p"])) - @test DT.compare_triangles(DT.brute_force_search(tri, h1_i; predicates=pred), (index_map["m"], index_map["n"], DT.𝒢 - 3)) - @inferred DT.brute_force_search(tri, c1_i; predicates=pred) - @inferred DT.brute_force_search(tri, d1_i; predicates=pred) - @inferred DT.brute_force_search(tri, e1_i; predicates=pred) + @test DT.compare_triangles(DT.brute_force_search(tri, g1_i; predicates = pred), (index_map["b"], index_map["c"], index_map["p"])) + @test DT.compare_triangles(DT.brute_force_search(tri, h1_i; predicates = pred), (index_map["m"], index_map["n"], DT.𝒢 - 3)) + @inferred DT.brute_force_search(tri, c1_i; predicates = pred) + @inferred DT.brute_force_search(tri, d1_i; predicates = pred) + @inferred DT.brute_force_search(tri, e1_i; predicates = pred) end end @@ -65,7 +64,7 @@ end for i in triangle_vertices(T) if i ≠ DT.𝒢 p = get_point(tri, i) - V = DT.brute_force_search(tri, p; predicates=rt()) + V = DT.brute_force_search(tri, p; predicates = rt()) @inferred DT.brute_force_search(tri, p) if !DT.is_ghost_triangle(T) @test i ∈ V @@ -75,4 +74,4 @@ end end end end -end \ No newline at end of file +end diff --git a/test/point_location/find_polygon.jl b/test/point_location/find_polygon.jl index 0699b3c65..2d0591b86 100644 --- a/test/point_location/find_polygon.jl +++ b/test/point_location/find_polygon.jl @@ -4,40 +4,40 @@ const DT = DelaunayTriangulation curve = [ [ - [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])] + [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] -tri = triangulate(points; boundary_nodes=curve) -refine!(tri; max_area=1e-2) +tri = triangulate(points; boundary_nodes = curve) +refine!(tri; max_area = 1.0e-2) q = (-1.0, -4.0) idx = find_polygon(tri, q) -@test idx == 3 +@test idx == 3 q = (-1.0, 0.2) idx = find_polygon(tri, q) -@test idx == 1 -q = (-1/2, -3.0) +@test idx == 1 +q = (-1 / 2, -3.0) idx = find_polygon(tri, q) -@test idx == 4 +@test idx == 4 q = (0.0, -4.05) idx = find_polygon(tri, q) -@test idx == 6 +@test idx == 6 q = (0.0, -5.0) idx = find_polygon(tri, q) -@test idx == 0 \ No newline at end of file +@test idx == 0 diff --git a/test/point_location/ghost_search.jl b/test/point_location/ghost_search.jl index 0f205fab1..d14eca3a1 100644 --- a/test/point_location/ghost_search.jl +++ b/test/point_location/ghost_search.jl @@ -5,7 +5,6 @@ using Random using StatsBase - tri, label_map, index_map = simple_geometry() add_ghost_triangles!(tri) DT.compute_representative_points!(tri) @@ -122,8 +121,8 @@ end if DT.is_exterior_boundary_node(tri, k) i, j = DT.exterior_find_triangle(tri, k, get_point(tri, k)) @test k ∈ (i, j) && - DT.is_exterior_ghost_triangle(tri, i, j, get_adjacent(tri, i, j)) + DT.is_exterior_ghost_triangle(tri, i, j, get_adjacent(tri, i, j)) @test DT.is_on(DT.point_position_relative_to_triangle(tri, i, j, k, k)) end end -end \ No newline at end of file +end diff --git a/test/point_location/interior_edge_intersections.jl b/test/point_location/interior_edge_intersections.jl index 854550ae4..8141d9b87 100644 --- a/test/point_location/interior_edge_intersections.jl +++ b/test/point_location/interior_edge_intersections.jl @@ -6,7 +6,6 @@ using Random using ..DelaunayTriangulation: Certificate - tri, label_map, index_map = simple_geometry() add_ghost_triangles!(tri) pts = get_points(tri) @@ -28,331 +27,331 @@ rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) graph = get_graph(tri) @testset "check_for_intersections_with_adjacent_boundary_edges" begin - @testset "General positions" begin - k = index_map["a"] - q = (6.0, 0.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Right && dir_cert == Certificate.On && id == index_map["b"] - @inferred DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q = (14.0, 0.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Right && dir_cert == Certificate.Right && id == index_map["b"] - q = (0.0, 4.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Left && dir_cert == Certificate.On && id == index_map["h"] - q = (0.0, 14.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Left && dir_cert == Certificate.Left && id == index_map["h"] - q = (-2.0, 0.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k - q = (0.0, -2.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k - q = (2.0, -2.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k - q = (4.0, 4.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k - k = index_map["d"] - q = (20.0, 2.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Left && dir_cert == Certificate.On && id == index_map["c"] - q = (20.0, 17.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Right && dir_cert == Certificate.On && id == index_map["e"] - q = (20.0, -5.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Left && dir_cert == Certificate.Left && id == index_map["c"] - q = (20.0, 30.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Right && dir_cert == Certificate.Right && id == index_map["e"] - q = (10.0, 10.0) - dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @inferred DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k - end + @testset "General positions" begin + k = index_map["a"] + q = (6.0, 0.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Right && dir_cert == Certificate.On && id == index_map["b"] + @inferred DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q = (14.0, 0.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Right && dir_cert == Certificate.Right && id == index_map["b"] + q = (0.0, 4.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Left && dir_cert == Certificate.On && id == index_map["h"] + q = (0.0, 14.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Left && dir_cert == Certificate.Left && id == index_map["h"] + q = (-2.0, 0.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k + q = (0.0, -2.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k + q = (2.0, -2.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k + q = (4.0, 4.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k + k = index_map["d"] + q = (20.0, 2.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Left && dir_cert == Certificate.On && id == index_map["c"] + q = (20.0, 17.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Right && dir_cert == Certificate.On && id == index_map["e"] + q = (20.0, -5.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Left && dir_cert == Certificate.Left && id == index_map["c"] + q = (20.0, 30.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Right && dir_cert == Certificate.Right && id == index_map["e"] + q = (10.0, 10.0) + dir, dir_cert, id = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @inferred DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test dir == Certificate.Outside && dir_cert == Certificate.Outside && id == k + end - @testset "Stepping down edges" begin - k = index_map["a"] - q = (6.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) - q = (10.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test DT.is_degenerate(q_pos) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) - q = (12.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @inferred DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["b"], index_map["c"], index_map["p"]) - q = (20.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["b"], index_map["c"], index_map["p"]) - q = (22.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_outside(q_cert) && - (u, v, w) == (index_map["d"], index_map["c"], DT.𝒢) - q = (0.0, 2.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["h"], index_map["a"], index_map["s"]) - q = (0.0, 10.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["h"], index_map["a"], index_map["s"]) - q = (0.0, 12.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["g"], index_map["h"], index_map["b1"]) - q = (0.0, 20.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["g"], index_map["h"], index_map["b1"]) - q = (0.0, 22.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_outside(q_cert) && - (u, v, w) == (index_map["g"], index_map["f"], DT.𝒢) - @inferred DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - q = (0.0, 0.0) - direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) - @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) - end + @testset "Stepping down edges" begin + k = index_map["a"] + q = (6.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) + q = (10.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test DT.is_degenerate(q_pos) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) + q = (12.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @inferred DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["b"], index_map["c"], index_map["p"]) + q = (20.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["b"], index_map["c"], index_map["p"]) + q = (22.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_outside(q_cert) && + (u, v, w) == (index_map["d"], index_map["c"], DT.𝒢) + q = (0.0, 2.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["h"], index_map["a"], index_map["s"]) + q = (0.0, 10.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["h"], index_map["a"], index_map["s"]) + q = (0.0, 12.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["g"], index_map["h"], index_map["b1"]) + q = (0.0, 20.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["g"], index_map["h"], index_map["b1"]) + q = (0.0, 22.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_outside(q_cert) && + (u, v, w) == (index_map["g"], index_map["f"], DT.𝒢) + @inferred DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + q = (0.0, 0.0) + direction, q_pos, next_vertex = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + q_cert, u, v, w = DT.search_down_adjacent_boundary_edges(tri, k, q, direction, q_pos, next_vertex) + @test DT.is_on(q_cert) && (u, v, w) == (index_map["a"], index_map["b"], index_map["t"]) + end - @testset "Outside" begin - k = index_map["b"] - q = [2.0, 4.0] - direction, q_pos, next_vertex, right_cert, left_cert = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test DT.is_outside(direction) - i, j, edge_cert, triangle_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test i == index_map["a"] && - j == index_map["t"] && - DT.has_one_intersection(edge_cert) && - DT.is_outside(triangle_cert) - end + @testset "Outside" begin + k = index_map["b"] + q = [2.0, 4.0] + direction, q_pos, next_vertex, right_cert, left_cert = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test DT.is_outside(direction) + i, j, edge_cert, triangle_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test i == index_map["a"] && + j == index_map["t"] && + DT.has_one_intersection(edge_cert) && + DT.is_outside(triangle_cert) + end - @testset "Testing for points already on the boundary" begin - for k in DT.each_point_index(pts) - local dir, rc, ℓc - if DT.is_exterior_boundary_node(tri, k) - dir, qp, _k, rc, ℓc = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, get_point(tri, k)) - @test DT.is_degenerate(qp) - end + @testset "Testing for points already on the boundary" begin + for k in DT.each_point_index(pts) + local dir, rc, ℓc + if DT.is_exterior_boundary_node(tri, k) + dir, qp, _k, rc, ℓc = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, get_point(tri, k)) + @test DT.is_degenerate(qp) end - end + end + end end @testset "check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex" begin - @testset "General" begin - k = index_map["g"] - right = index_map["h"] - left = index_map["f"] - q = (3.8544234210286, 19.2195032844691) - p = pts[k] - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - dir, dir_cert, id, rc, ℓc = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - @test rc == right_cert && ℓc == left_cert - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) && k == k - q = (6.0, 18.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["f"], index_map["a1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) && k == k - q = (4.2913632954055, 16.864882850327) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a1"], index_map["i"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) && k == k - q = (3.368934671721, 17.3989204745654) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) && k == k - q = (4.0, 17.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) && k == k - q = (5.0, 15.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (j, i, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_right(edge_cert) && DT.is_outside(tri_cert) - @test DT.is_positively_oriented(DT.triangle_orientation(tri, i, j, q)) - q = (5.0, 12.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (3.0, 12.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (3.0, 14.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (2.0, 14.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - q = (0.5, 14.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["h"], index_map["b1"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - q = (1.0, 16.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["h"], index_map["b1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (1.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (2.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (3.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - q = (18.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["f"], index_map["a1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (4.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - q = (4.0, 12.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (-1.0, 19.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (-1.0, 20.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) &&DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (0.0, 21.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (-1.0, 21.0) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) &&DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (3.0, 21.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (-2.0, -2.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - k = index_map["b"] - right = index_map["c"] - left = index_map["a"] - q = (10.0, 1.0) - p = pts[k] - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["p"], index_map["t"], index_map["b"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (16.27931, 0.4487) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["c"], index_map["p"], index_map["b"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - q = (17.0, 1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["c"], index_map["p"], index_map["b"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) - q = (15.0, -1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (23.0, -1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (10.0, -1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (8.0, -1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) - q = (18.0, 3.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["p"], index_map["c"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (11.4965, 2.53) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["t"], index_map["p"], index_map["b"]) &&DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (5.0, 2.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a"], index_map["t"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (4.0, 1.0) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["a"], index_map["t"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) - q = (5.2, 0.6) - right_cert = DT.point_position_relative_to_line(p, pts[right], q) - left_cert = DT.point_position_relative_to_line(p, pts[left], q) - i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test (i, j, k) == (index_map["t"], index_map["a"], index_map["b"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) - @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - end + @testset "General" begin + k = index_map["g"] + right = index_map["h"] + left = index_map["f"] + q = (3.8544234210286, 19.2195032844691) + p = pts[k] + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + dir, dir_cert, id, rc, ℓc = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + @test rc == right_cert && ℓc == left_cert + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) && k == k + q = (6.0, 18.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["f"], index_map["a1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) && k == k + q = (4.2913632954055, 16.864882850327) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a1"], index_map["i"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) && k == k + q = (3.368934671721, 17.3989204745654) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) && k == k + q = (4.0, 17.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) && k == k + q = (5.0, 15.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (j, i, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_right(edge_cert) && DT.is_outside(tri_cert) + @test DT.is_positively_oriented(DT.triangle_orientation(tri, i, j, q)) + q = (5.0, 12.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (3.0, 12.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (3.0, 14.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (2.0, 14.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + q = (0.5, 14.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["h"], index_map["b1"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + q = (1.0, 16.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["h"], index_map["b1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (1.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["b1"], index_map["i"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (2.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["a1"], index_map["g"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (3.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + q = (18.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["f"], index_map["a1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (4.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a1"], index_map["f"], index_map["g"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + q = (4.0, 12.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["i"], index_map["b1"], index_map["g"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (-1.0, 19.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (-1.0, 20.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) &&DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (0.0, 21.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (-1.0, 21.0) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) &&DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (3.0, 21.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (-2.0, -2.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["g"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + k = index_map["b"] + right = index_map["c"] + left = index_map["a"] + q = (10.0, 1.0) + p = pts[k] + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["p"], index_map["t"], index_map["b"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (16.27931, 0.4487) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["c"], index_map["p"], index_map["b"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + q = (17.0, 1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["c"], index_map["p"], index_map["b"]) && DT.is_on(edge_cert) && DT.is_inside(tri_cert) + q = (15.0, -1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (23.0, -1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (10.0, -1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (8.0, -1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (0, 0, index_map["b"]) && DT.is_none(edge_cert) && DT.is_outside(tri_cert) + q = (18.0, 3.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["p"], index_map["c"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (11.4965, 2.53) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["t"], index_map["p"], index_map["b"]) &&DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (5.0, 2.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a"], index_map["t"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (4.0, 1.0) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["a"], index_map["t"], index_map["b"]) && DT.is_single(edge_cert) && DT.is_outside(tri_cert) + q = (5.2, 0.6) + right_cert = DT.point_position_relative_to_line(p, pts[right], q) + left_cert = DT.point_position_relative_to_line(p, pts[left], q) + i, j, edge_cert, tri_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test (i, j, k) == (index_map["t"], index_map["a"], index_map["b"]) && DT.is_none(edge_cert) && DT.is_inside(tri_cert) + @inferred DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + end - @testset "Specific example" begin - k = 6 - q = get_point(pts, 9) - direction, q_pos, next_vertex, right_cert, left_cert = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) - i, j, edge_cert, triangle_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) - @test i == 25 && j == 9 && DT.is_on(edge_cert) && DT.is_inside(triangle_cert) - end -end \ No newline at end of file + @testset "Specific example" begin + k = 6 + q = get_point(pts, 9) + direction, q_pos, next_vertex, right_cert, left_cert = DT.check_for_intersections_with_adjacent_boundary_edges(tri, k, q) + i, j, edge_cert, triangle_cert = DT.check_for_intersections_with_interior_edges_adjacent_to_boundary_vertex(tri, k, q, right_cert, left_cert) + @test i == 25 && j == 9 && DT.is_on(edge_cert) && DT.is_inside(triangle_cert) + end +end diff --git a/test/point_location/jump_and_march.jl b/test/point_location/jump_and_march.jl index f1b56b580..b94a1ee9f 100644 --- a/test/point_location/jump_and_march.jl +++ b/test/point_location/jump_and_march.jl @@ -27,47 +27,61 @@ boundary_nodes = get_boundary_nodes(tri) q3 = (14.2726546767168, 18.7727571005127) V3 = [(index_map["f"], index_map["v"], index_map["e"])] q4 = (12.0, 2.0) - V4 = [(index_map["t"], index_map["p"], index_map["o"]), - (index_map["t"], index_map["b"], index_map["p"])] + V4 = [ + (index_map["t"], index_map["p"], index_map["o"]), + (index_map["t"], index_map["b"], index_map["p"]), + ] q5 = (13.0, 0.0) - V5 = [(index_map["b"], index_map["c"], index_map["p"]), - (index_map["c"], index_map["b"], DT.𝒢)] + V5 = [ + (index_map["b"], index_map["c"], index_map["p"]), + (index_map["c"], index_map["b"], DT.𝒢), + ] q6 = (6.0819947177817, 8.90410894457) V6 = [(index_map["j"], index_map["k"], DT.𝒢 - 1)] q7 = (15.8, 9.2) - V7 = [(index_map["m"], DT.𝒢 - 2, index_map["r"]), - (index_map["m"], DT.𝒢 - 3, index_map["r"])] + V7 = [ + (index_map["m"], DT.𝒢 - 2, index_map["r"]), + (index_map["m"], DT.𝒢 - 3, index_map["r"]), + ] q8 = (14.5391680629781, 8.5135910023477) - V8 = [(index_map["m"], index_map["n"], DT.𝒢 - 2), - (index_map["m"], index_map["n"], DT.𝒢 - 3)] + V8 = [ + (index_map["m"], index_map["n"], DT.𝒢 - 2), + (index_map["m"], index_map["n"], DT.𝒢 - 3), + ] q9 = (22.0, 8.0) V9 = [(index_map["d"], index_map["c"], DT.𝒢)] q10 = (6.0, 11.0) - V10 = [(index_map["j"], index_map["k"], DT.𝒢 - 1), + V10 = [ + (index_map["j"], index_map["k"], DT.𝒢 - 1), (index_map["k"], index_map["ℓ"], DT.𝒢 - 1), (index_map["ℓ"], index_map["i"], DT.𝒢 - 1), - (index_map["i"], index_map["j"], DT.𝒢 - 1)] + (index_map["i"], index_map["j"], DT.𝒢 - 1), + ] q11 = (6.0819947177817, 8.90410894457) V11 = [(index_map["j"], index_map["k"], DT.𝒢 - 1)] q12 = (-6.6465702688004, 19.4798146355492) V12 = [(index_map["h"], index_map["g"], DT.𝒢)] q13 = (-20.0, 10.0) - V13 = [(index_map["h"], index_map["g"], DT.𝒢), - (index_map["a"], index_map["h"], DT.𝒢)] + V13 = [ + (index_map["h"], index_map["g"], DT.𝒢), + (index_map["a"], index_map["h"], DT.𝒢), + ] q14 = (20.0, 6.0) - V14 = [(index_map["c"], index_map["d"], index_map["q"]), - (index_map["c"], index_map["d"], DT.𝒢)] + V14 = [ + (index_map["c"], index_map["d"], index_map["q"]), + (index_map["c"], index_map["d"], DT.𝒢), + ] allq = [q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14] allV = [V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14] for _ in 1:36 for k in DT.each_point_index(pts) for i in eachindex(allq) - T1 = jump_and_march(tri, allq[i]; k, predicates=rt()) + T1 = jump_and_march(tri, allq[i]; k, predicates = rt()) T2 = jump_and_march(tri, allq[i]) @test DT.is_positively_oriented(DT.triangle_orientation(rt(), tri, T1)) @test DT.is_positively_oriented(DT.triangle_orientation(tri, T2)) - @inferred jump_and_march(tri, allq[i]; k, predicates=rt()) - @inferred jump_and_march(tri, allq[i]; predicates=rt()) + @inferred jump_and_march(tri, allq[i]; k, predicates = rt()) + @inferred jump_and_march(tri, allq[i]; predicates = rt()) for V in [T1, T2] if length(allV[i]) == 1 @test DT.compare_triangles(V, allV[i][1]) && DT.is_inside(DT.point_position_relative_to_triangle(tri, V, allq[i])) @@ -97,14 +111,14 @@ rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) x, y = complicated_geometry() rng = StableRNG(919191919) boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri2 = triangulate(points; rng, boundary_nodes, delete_ghosts=false) + tri2 = triangulate(points; rng, boundary_nodes, delete_ghosts = false) A = get_area(tri2) - refine!(tri2; max_area=1e-2A, use_circumcenter=true) + refine!(tri2; max_area = 1.0e-2A, use_circumcenter = true) a, b, c, d = 2.0, 10.0, -5.0, 7.5 nx = 20 ny = 10 - tri3 = DT.triangulate_rectangle(a, b, c, d, nx, ny, delete_ghosts=false) + tri3 = DT.triangulate_rectangle(a, b, c, d, nx, ny, delete_ghosts = false) for (tri_idx, tri) in enumerate((tri, tri2, tri3)) DT.compute_representative_points!(tri) @@ -132,7 +146,7 @@ rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) local c c = (p .+ q .+ r) ./ 3 for k in DT.each_solid_vertex(tri) - _V = find_triangle(tri, c; k, concavity_protection=true, predicates=PT()) + _V = find_triangle(tri, c; k, concavity_protection = true, predicates = PT()) @test DT.is_positively_oriented(DT.triangle_orientation(PT(), tri, _V)) if !DT.is_ghost_triangle(_V...) @test DT.compare_triangles(_V, V) && DT.is_inside(DT.point_position_relative_to_triangle(PT(), tri, _V, c)) @@ -150,7 +164,7 @@ rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) end _V = DT.construct_triangle(typeof(V), i1, DT.getj(V1), DT.getk(V1)) @test DT.compare_triangles(_V, V) && - DT.is_inside(DT.point_position_relative_to_triangle(PT(), tri, _V, c)) + DT.is_inside(DT.point_position_relative_to_triangle(PT(), tri, _V, c)) end end end @@ -166,7 +180,7 @@ rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) for k in DT.each_solid_vertex(tri) rand() < 1 / 3 && continue for j in DT.each_solid_vertex(tri) - _V = find_triangle(tri, get_point(tri, k); k=j, predicates=PT()) + _V = find_triangle(tri, get_point(tri, k); k = j, predicates = PT()) @test k ∈ triangle_vertices(_V) @test DT.is_positively_oriented(DT.triangle_orientation(PT(), tri, _V)) end @@ -203,7 +217,7 @@ end k = [8.0, 4.0] pts = [a, b, c, d, e, f, g, h, i, j, k] rng = StableRNG(213) - tri = triangulate(pts; rng, delete_ghosts=false, randomise=false) + tri = triangulate(pts; rng, delete_ghosts = false, randomise = false) for qi in each_solid_vertex(tri) for k in each_solid_vertex(tri) q = get_point(tri, qi) @@ -215,9 +229,9 @@ end end @testset "History structure" begin - history = DT.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}() - @test history.triangles == NTuple{3,Int}[] - @test history.collinear_segments == NTuple{2,Int}[] + history = DT.PointLocationHistory{NTuple{3, Int}, NTuple{2, Int}, Int}() + @test history.triangles == NTuple{3, Int}[] + @test history.collinear_segments == NTuple{2, Int}[] @test history.left_vertices == Int[] @test history.right_vertices == Int[] @test history.collinear_point_indices == Int[] @@ -278,13 +292,13 @@ end f1 = (5.0, 4.3) pts = [[[d, e, f, a, b, f1, e1, c1, d1, c, d]], [[g, h, i, ℓ, k, j, g]]] existing_points = [m, n, o, p, q, r, s, t, u, v, w, z, a1, b1] - nodes, points = convert_boundary_points_to_indices(pts; existing_points=existing_points) - tri = triangulate(points; boundary_nodes=nodes, delete_ghosts=false) + nodes, points = convert_boundary_points_to_indices(pts; existing_points = existing_points) + tri = triangulate(points; boundary_nodes = nodes, delete_ghosts = false) i, j, k = 2, 25, 8 T = (i, j, k) r = 5 for i in 1:10000 - V = find_triangle(tri, get_point(tri, k); point_indices=nothing, m=nothing, try_points=nothing, k=r, concavity_protection=true) + V = find_triangle(tri, get_point(tri, k); point_indices = nothing, m = nothing, try_points = nothing, k = r, concavity_protection = true) @test !DT.is_outside(DT.point_position_relative_to_triangle(tri, V, get_point(tri, k))) end end @@ -302,17 +316,17 @@ end inner = [[r, z, v, u, w, t, s, r]] boundary_nodes, points = convert_boundary_points_to_indices([outer, inner]) rng = StableRNG(123) - tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) - refine!(tri; max_area=0.01get_area(tri), rng, use_circumcenter=true) + tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) + refine!(tri; max_area = 0.01get_area(tri), rng, use_circumcenter = true) qs = [ (4.0, 5.0), (1.0, 5.6), (0.2, 5.0), (0.0, -1.0), (0.5, 3.5), (2.5, 1.5), (1.0, 2.0), (4.5, 1.0), (6.0, 1.5), - (0.5, 8.5), (1.0, 7.5), (1.2, 1.6) + (0.5, 8.5), (1.0, 7.5), (1.2, 1.6), ] δs = [DelaunayTriangulation.distance_to_polygon(q, get_points(tri), get_boundary_nodes(tri)) for q in qs] for i in 1:1000 - Vs = [find_triangle(tri, q, concavity_protection=true, rng=StableRNG(i + j)) for (j, q) in enumerate(qs)] + Vs = [find_triangle(tri, q, concavity_protection = true, rng = StableRNG(i + j)) for (j, q) in enumerate(qs)] for (q, δ, V) in zip(qs, δs, Vs) cert = DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) if δ ≥ 0.0 @@ -329,7 +343,7 @@ end rng = StableRNG(i) qs = [((b - a) * rand(rng) + a, (d - c) * rand(rng) + c) for _ in 1:1000] δs = [DelaunayTriangulation.distance_to_polygon(q, get_points(tri), get_boundary_nodes(tri)) for q in qs] - Vs = [find_triangle(tri, q, concavity_protection=true, rng=StableRNG(i + j)) for (j, q) in enumerate(qs)] + Vs = [find_triangle(tri, q, concavity_protection = true, rng = StableRNG(i + j)) for (j, q) in enumerate(qs)] for (q, δ, V) in zip(qs, δs, Vs) cert = DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) if δ ≥ 0.0 @@ -362,21 +376,21 @@ end new_domain₂ = [[t₁, w₁, v₁, u₁, t₁]] boundary_nodes, points = convert_boundary_points_to_indices([outer, inner, new_domain₁, new_domain₂]) rng = StableRNG(125123) - tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) + tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) @test DT.is_disjoint(tri) - refine!(tri; max_area=0.001get_area(tri), rng, use_circumcenter=true) + refine!(tri; max_area = 0.001get_area(tri), rng, use_circumcenter = true) qs = [ (0.6, 6.4), (1.4, 0.8), (3.1, 2.9), (6.3, 4.9), (4.6, 3.5), (7.0, 7.0), (8.9, 5.1), (5.8, 0.8), (1.0, 1.5), - (1.5, 2.0), (8.15, 6.0) + (1.5, 2.0), (8.15, 6.0), ] q = (7.0, 7.0) # When you have a point that is exactly the same as a representative point, you need to be careful of (1) the point being exactly collinear with a ghost edge, and (2) the algorithm mistakenly regarding q as if it were equal to a triangle's vertices (since this is where the ghost vertices map). This is now fixed, but we need this isolated to avoid regressions. - V = find_triangle(tri, q, rng=StableRNG(268), k=31, concavity_protection=true) + V = find_triangle(tri, q, rng = StableRNG(268), k = 31, concavity_protection = true) @test !DT.is_outside(DT.point_position_relative_to_triangle(tri, V, q)) δs = [DelaunayTriangulation.distance_to_polygon(q, get_points(tri), get_boundary_nodes(tri)) for q in qs] for i in 1:1000 - Vs = [find_triangle(tri, q; concavity_protection=true, rng=StableRNG(i)) for q in qs] + Vs = [find_triangle(tri, q; concavity_protection = true, rng = StableRNG(i)) for q in qs] for (q, δ, V) in zip(qs, δs, Vs) cert = DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) if δ > 0.0 @@ -395,7 +409,7 @@ end rng = StableRNG(i) qs = [((b - a) * rand(rng) + a, (d - c) * rand(rng) + c) for _ in 1:100] δs = [DelaunayTriangulation.distance_to_polygon(q, get_points(tri), get_boundary_nodes(tri)) for q in qs] - Vs = [find_triangle(tri, q, concavity_protection=true, rng=StableRNG(i + j)) for (j, q) in enumerate(qs)] + Vs = [find_triangle(tri, q, concavity_protection = true, rng = StableRNG(i + j)) for (j, q) in enumerate(qs)] for (q, δ, V) in zip(qs, δs, Vs) cert = DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q) if δ ≥ 0.0 @@ -413,20 +427,20 @@ end @testset "A simple boundary" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], randomise=false) - V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers=Val(true), k=4) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], randomise = false) + V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers = Val(true), k = 4) @test invisible_flag && DT.is_invisible(DT.test_visibility(tri, (1 / 2, -1.0), 4)) - @inferred find_triangle(tri, (1 / 2, -1.0), use_barriers=Val(true), k=4) + @inferred find_triangle(tri, (1 / 2, -1.0), use_barriers = Val(true), k = 4) @test V == (1, 2, 3) @test DT.is_positively_oriented(DT.triangle_orientation(tri, V)) - V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers=Val(true), k=3) + V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers = Val(true), k = 3) @test invisible_flag && DT.is_invisible(DT.test_visibility(tri, (1 / 2, -1.0), 3)) @test V == (1, 2, 3) @test DT.is_positively_oriented(DT.triangle_orientation(tri, V)) - V, invisible_flag = jump_and_march(tri, (1 / 2, -1.0), use_barriers=Val(true), k=1) + V, invisible_flag = jump_and_march(tri, (1 / 2, -1.0), use_barriers = Val(true), k = 1) @test invisible_flag && DT.is_invisible(DT.test_visibility(tri, (1 / 2, -1.0), 1)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V, (1 / 2, -1, 0))) # starting at a boundary edge right next to the query point - V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers=Val(true), k=2) + V, invisible_flag = find_triangle(tri, (1 / 2, -1.0), use_barriers = Val(true), k = 2) @test invisible_flag && DT.is_invisible(DT.test_visibility(tri, (1 / 2, -1.0), 2)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V, (1 / 2, -1.0))) end @@ -434,17 +448,19 @@ end @testset "An unconstrained triangulation with a segment inside it" begin for _ in 1:1000 - points = [(-8.0, 6.0), (-10.0, 1.0), (-2.0, -2.0), (1.38, 2.05), - (2.0, 1.0), (4.78, 3.23), (0.0, 6.0), (-3.0, 4.0), (-3.0, 2.0)] + points = [ + (-8.0, 6.0), (-10.0, 1.0), (-2.0, -2.0), (1.38, 2.05), + (2.0, 1.0), (4.78, 3.23), (0.0, 6.0), (-3.0, 4.0), (-3.0, 2.0), + ] segments = Set([(8, 9)]) - tri = triangulate(points; segments, randomise=false) + tri = triangulate(points; segments, randomise = false) q1 = (-1.0, 1.0) q2 = (-4.0, 1.0) q3 = (-8.0, 2.0) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=1) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=1) - @inferred find_triangle(tri, q1, use_barriers=Val(true), k=1) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=1) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 1) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 1) + @inferred find_triangle(tri, q1, use_barriers = Val(true), k = 1) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 1) @test DT.compare_triangles(V1, (9, 8, 1)) @test DT.is_positively_oriented(DT.triangle_orientation(tri, V1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -454,9 +470,9 @@ end @test invisible_flag1 && DT.is_invisible(DT.test_visibility(tri, q1, 1)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 1)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 1)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=2) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=2) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=2) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 2) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 2) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 2) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -466,9 +482,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 2)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 2)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 2)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=3) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=3) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=3) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 3) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 3) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 3) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -478,9 +494,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 3)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 3)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 3)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=4) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=4) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=4) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 4) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 4) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 4) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -490,9 +506,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 4)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 4)) @test invisible_flag3 && DT.is_invisible(DT.test_visibility(tri, q3, 4)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=5) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=5) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=5) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 5) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 5) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 5) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -502,9 +518,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 5)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 5)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 5)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=6) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=6) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=6) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 6) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 6) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 6) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -514,9 +530,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 6)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 6)) @test invisible_flag3 && DT.is_invisible(DT.test_visibility(tri, q3, 6)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=7) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=7) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=7) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 7) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 7) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 7) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (8, 9, 4)) @@ -526,9 +542,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 7)) @test invisible_flag2 && DT.is_invisible(DT.test_visibility(tri, q2, 7)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 7)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=8) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=8) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=8) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 8) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 8) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 8) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -538,9 +554,9 @@ end @test !invisible_flag1 && DT.is_visible(DT.test_visibility(tri, q1, 8)) @test !invisible_flag2 && DT.is_visible(DT.test_visibility(tri, q2, 8)) @test !invisible_flag3 && DT.is_visible(DT.test_visibility(tri, q3, 8)) - V1, invisible_flag1 = find_triangle(tri, q1, use_barriers=Val(true), k=9) - V2, invisible_flag2 = find_triangle(tri, q2, use_barriers=Val(true), k=9) - V3, invisible_flag3 = find_triangle(tri, q3, use_barriers=Val(true), k=9) + V1, invisible_flag1 = find_triangle(tri, q1, use_barriers = Val(true), k = 9) + V2, invisible_flag2 = find_triangle(tri, q2, use_barriers = Val(true), k = 9) + V3, invisible_flag3 = find_triangle(tri, q3, use_barriers = Val(true), k = 9) @test DT.compare_triangles(V1, (9, 3, 4)) @test DT.is_inside(DT.point_position_relative_to_triangle(tri, V1, q1)) @test DT.compare_triangles(V2, (2, 3, 9)) @@ -575,7 +591,7 @@ end boundary_nodes, points = convert_boundary_points_to_indices(boundary) q1, r1 = (5.0, 6.0), (3.0, 1.0) push!(points, q1, r1) - tri = triangulate(points; boundary_nodes, rng=StableRNG(123)) + tri = triangulate(points; boundary_nodes, rng = StableRNG(123)) K1, L1, M1, N1, O1, P1, S1 = (2.0, 6.0), (6.0, 1.0), (5.2, 2.4), (9.0, 4.0), (5.0, -2.0), (3.0, 13.0), (0.5, 4.0) all_q = [K1, L1, M1, N1, O1, P1, S1] blocked_test(Vfound, Vtrue) = begin @@ -587,14 +603,14 @@ end visible_test(Vfound, Vtrue, q) = begin _p, _q, _r = Vtrue _i, _j, __k = !(_p isa Integer) ? findfirst(==(_p), points) : _p, # check for ghost vertices - !(_q isa Integer) ? findfirst(==(_q), points) : _q, - !(_r isa Integer) ? findfirst(==(_r), points) : _r + !(_q isa Integer) ? findfirst(==(_q), points) : _q, + !(_r isa Integer) ? findfirst(==(_r), points) : _r _Vtrue = (_i, _j, __k) return DT.compare_triangles(Vfound, _Vtrue) && !DT.is_outside(DT.point_position_relative_to_triangle(tri, Vfound, q)) end _k = findfirst(==(a), points) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) #@test blocked_test(VK, (u, f, v)) #@test visible_test(VL, (f1, g1, k), L1) || visible_test(VL, (f1, k, ℓ), L1) # on (f1, k) #@test blocked_test(VM, (d1, r1, g1)) @@ -610,7 +626,7 @@ end @test flagVP && DT.is_invisible(DT.test_visibility(tri, P1, _k)) @test !flagVS && DT.is_visible(DT.test_visibility(tri, S1, _k)) _k = findfirst(==(q), points) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) #@test blocked_test(VK, (q, u, z)) #@test blocked_test(VL, (h1, z, a1)) #@test blocked_test(VM, (z, a1, h1)) @@ -626,7 +642,7 @@ end @test flagVP && DT.is_invisible(DT.test_visibility(tri, P1, _k)) @test flagVS && DT.is_invisible(DT.test_visibility(tri, S1, _k)) _k = findfirst(==(q1), points) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) #@test blocked_test(VK, (a1, w, d1)) #@test blocked_test(VL, (e1, d1, f1)) #@test blocked_test(VM, (e1, d1, f1)) @@ -642,7 +658,7 @@ end @test flagVP && DT.is_invisible(DT.test_visibility(tri, P1, _k)) @test flagVS && DT.is_invisible(DT.test_visibility(tri, S1, _k)) _k = findfirst(==(p), points) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) #@test blocked_test(VK, (a1, w, d1)) #@test visible_test(VL, (f1, g1, k), L1) || visible_test(VL, (f1, k, ℓ), L1) # on (f1, k) #@test blocked_test(VM, (c1, b1, o)) @@ -658,7 +674,7 @@ end @test flagVP && DT.is_invisible(DT.test_visibility(tri, P1, _k)) @test flagVS && DT.is_invisible(DT.test_visibility(tri, S1, _k)) _k = findfirst(==(b), points) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) @test blocked_test(VK, (b1, e1, f1)) || blocked_test(VK, (a1, w, d1)) @test visible_test(VL, (f1, g1, k), L1) || visible_test(VL, (f1, k, ℓ), L1) # on (f1, k) @test blocked_test(VM, (f1, g1, k)) @@ -675,7 +691,7 @@ end @test flagVS && DT.is_invisible(DT.test_visibility(tri, S1, _k)) add_segment!(tri, findfirst(==(m), points), findfirst(==(ℓ), points)) push!(all_q, (9.0, 1.0), (9.5, 0.5), (8.9, 1.1)) - (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS), (VH4, flagVH4), (VK9, flagVK9), (VH5, flagVH5) = find_triangle.(Ref(tri), all_q; k=_k, use_barriers=Val(true)) + (VK, flagVK), (VL, flagVL), (VM, flagVM), (VN, flagVN), (VO, flagVO), (VP, flagVP), (VS, flagVS), (VH4, flagVH4), (VK9, flagVK9), (VH5, flagVH5) = find_triangle.(Ref(tri), all_q; k = _k, use_barriers = Val(true)) @test blocked_test(VK, (m, ℓ, b)) @test blocked_test(VL, (m, ℓ, b)) @test blocked_test(VM, (m, ℓ, b)) @@ -706,7 +722,7 @@ end tri = triangulate(points) for _ in 1:20000 q = rand(2) - V, flag = find_triangle(tri, q; use_barriers=Val(true)) + V, flag = find_triangle(tri, q; use_barriers = Val(true)) @test !DT.is_outside(DT.point_position_relative_to_triangle(tri, V, q)) @test !flag end @@ -719,15 +735,15 @@ end q = (0.19 + 0.19) * rand(2) .- 0.19 push!(points, Tuple(q)) end - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1]) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1]) for _ in 1:20000 q = 2randn(2) k = rand(each_solid_vertex(tri)) while DT.is_boundary_node(tri, k)[1] k = rand(each_solid_vertex(tri)) end - V, flag = find_triangle(tri, q; k, use_barriers=Val(true)) + V, flag = find_triangle(tri, q; k, use_barriers = Val(true)) @test !DT.is_ghost_triangle(V) end end -end \ No newline at end of file +end diff --git a/test/point_location/select_initial_point.jl b/test/point_location/select_initial_point.jl index bc740bca0..ffb73ff4a 100644 --- a/test/point_location/select_initial_point.jl +++ b/test/point_location/select_initial_point.jl @@ -5,7 +5,6 @@ using Random using StableRNGs - global tri, label_map, index_map = simple_geometry() add_ghost_triangles!(tri) DT.compute_representative_points!(tri) @@ -35,12 +34,18 @@ end current_idx = 1 for i in DT.each_point_index(pts) if i ≠ 5 - current_dist, current_idx = DT.compare_distance(current_dist, current_idx, tri, i, - qx, qy) - @inferred DT.compare_distance(current_dist, current_idx, tri, i, - qx, qy) - @inferred DT.compare_distance(current_dist, current_idx, pts, i, - qx, qy) + current_dist, current_idx = DT.compare_distance( + current_dist, current_idx, tri, i, + qx, qy, + ) + @inferred DT.compare_distance( + current_dist, current_idx, tri, i, + qx, qy, + ) + @inferred DT.compare_distance( + current_dist, current_idx, pts, i, + qx, qy, + ) end end cd, ci = findmin([[norm(p .- (qx, qy))^2 + (p == pts[5]) * Inf] for p in pts]) @@ -83,14 +88,14 @@ end q = (20rand(rng), 20rand(rng)) ci = tried_idx[argmin([norm(pts[i] .- q) for i in tried_idx])] rng = StableRNG(s) - ci2 = DT.select_initial_point(tri, q; m, rng, point_indices=(1, 5, 8, 19, 20)) - @inferred DT.select_initial_point(tri, q; m, rng, point_indices=(1, 5, 8, 19, 20)) + ci2 = DT.select_initial_point(tri, q; m, rng, point_indices = (1, 5, 8, 19, 20)) + @inferred DT.select_initial_point(tri, q; m, rng, point_indices = (1, 5, 8, 19, 20)) @test ci == ci2 @test ci2 ∈ (1, 5, 8, 19, 20) end for k in DT.each_point_index(pts) - @test DT.select_initial_point(tri, k; try_points=k) == k + @test DT.select_initial_point(tri, k; try_points = k) == k end end end diff --git a/test/point_location/select_initial_triangle_interior_node.jl b/test/point_location/select_initial_triangle_interior_node.jl index bfc981b3c..5c3e56fd0 100644 --- a/test/point_location/select_initial_triangle_interior_node.jl +++ b/test/point_location/select_initial_triangle_interior_node.jl @@ -6,7 +6,6 @@ using StableRNGs using StatsBase - tri, label_map, index_map = simple_geometry() add_ghost_triangles!(tri) pts = get_points(tri) @@ -28,176 +27,192 @@ rep[3].x = mean([18.0, 18.0, 14.0, 12.0, 14.0, 14.0]) rep[3].y = mean([12.0, 6.0, 2.0, 4.0, 6.0, 10.0]) @testset "Selecting a random edge" begin - k = 7 - edges = DT.get_adjacent2vertex(tri, k) - Random.seed!(2992881) - rng = StableRNG(2992881) - i, j = rand(rng, edges) - pᵢ, pⱼ = pts[i], pts[j] - rng = StableRNG(2992881) - u, v, qᵢ, qⱼ = DT.select_random_edge(tri, edges, rng) - @test u == i && v == j && qᵢ == pᵢ && pⱼ == qⱼ - @inferred DT.select_random_edge(tri, edges, rng) + k = 7 + edges = DT.get_adjacent2vertex(tri, k) + Random.seed!(2992881) + rng = StableRNG(2992881) + i, j = rand(rng, edges) + pᵢ, pⱼ = pts[i], pts[j] + rng = StableRNG(2992881) + u, v, qᵢ, qⱼ = DT.select_random_edge(tri, edges, rng) + @test u == i && v == j && qᵢ == pᵢ && pⱼ == qⱼ + @inferred DT.select_random_edge(tri, edges, rng) end @testset "Testing for a non-exterior-boundary node" begin - for _ in 1:350 - local i, j, pᵢ, pⱼ, line_cert_i, line_cert_j, k - k = index_map["m"] # This point is on the boundary of an interior hole - # Close - q = (16.4445425, 19.8427) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["v"] && - _j == index_map["z"] && - _pᵢ == get_point(pts, index_map["v"]) && - _pⱼ == get_point(pts, index_map["z"]) + for _ in 1:350 + local i, j, pᵢ, pⱼ, line_cert_i, line_cert_j, k + k = index_map["m"] # This point is on the boundary of an interior hole + # Close + q = (16.4445425, 19.8427) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["v"] && + _j == index_map["z"] && + _pᵢ == get_point(pts, index_map["v"]) && + _pⱼ == get_point(pts, index_map["z"]) - # Further away - q = (4.008184, 1.077) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _j == index_map["w"] && - _i == index_map["u"] && - _pⱼ == get_point(pts, index_map["w"]) && - _pᵢ == get_point(pts, index_map["u"]) + # Further away + q = (4.008184, 1.077) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _j == index_map["w"] && + _i == index_map["u"] && + _pⱼ == get_point(pts, index_map["w"]) && + _pᵢ == get_point(pts, index_map["u"]) - # How are collinearities handled? - q = (14.0, 0.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test (_p == get_point(pts, k) && - (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && - _j == index_map["n"] && - _pᵢ == get_point(tri, DT.𝒢 - 2) && - _pⱼ == get_point(pts, index_map["n"])) || - (_p == get_point(pts, k) && - _i == index_map["n"] && - _j == index_map["u"] && - _pᵢ == get_point(tri, index_map["n"]) && - _pⱼ == get_point(pts, index_map["u"])) + # How are collinearities handled? + q = (14.0, 0.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test ( + _p == get_point(pts, k) && + (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && + _j == index_map["n"] && + _pᵢ == get_point(tri, DT.𝒢 - 2) && + _pⱼ == get_point(pts, index_map["n"]) + ) || + ( + _p == get_point(pts, k) && + _i == index_map["n"] && + _j == index_map["u"] && + _pᵢ == get_point(tri, index_map["n"]) && + _pⱼ == get_point(pts, index_map["u"]) + ) - # Now do the same test, but put the point above p - q = (14.0, 19.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test (_p == get_point(pts, k) && - _i == index_map["w"] && - _j == index_map["v"] && - _pᵢ == get_point(tri, index_map["w"]) && - _pⱼ == get_point(pts, index_map["v"])) || - (_p == get_point(pts, k) && - _i == index_map["v"] && - _j == index_map["z"] && - _pᵢ == get_point(tri, index_map["v"]) && - _pⱼ == get_point(pts, index_map["z"])) + # Now do the same test, but put the point above p + q = (14.0, 19.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test ( + _p == get_point(pts, k) && + _i == index_map["w"] && + _j == index_map["v"] && + _pᵢ == get_point(tri, index_map["w"]) && + _pⱼ == get_point(pts, index_map["v"]) + ) || + ( + _p == get_point(pts, k) && + _i == index_map["v"] && + _j == index_map["z"] && + _pᵢ == get_point(tri, index_map["v"]) && + _pⱼ == get_point(pts, index_map["z"]) + ) - # What happens if the point is on an edge? - q = (14.0, 7.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test (_p == get_point(pts, k) && - (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && - _j == index_map["n"] && - _pᵢ == get_point(tri, DT.𝒢 - 2) && - _pⱼ == get_point(pts, index_map["n"])) || - (_p == get_point(pts, k) && - _i == index_map["n"] && - _j == index_map["u"] && - _pᵢ == get_point(tri, index_map["n"]) && - _pⱼ == get_point(pts, index_map["u"])) + # What happens if the point is on an edge? + q = (14.0, 7.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test ( + _p == get_point(pts, k) && + (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && + _j == index_map["n"] && + _pᵢ == get_point(tri, DT.𝒢 - 2) && + _pⱼ == get_point(pts, index_map["n"]) + ) || + ( + _p == get_point(pts, k) && + _i == index_map["n"] && + _j == index_map["u"] && + _pᵢ == get_point(tri, index_map["n"]) && + _pⱼ == get_point(pts, index_map["u"]) + ) - # Now do the same test, but put the point above p - q = (14.0, 14.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test (_p == get_point(pts, k) && - _i == index_map["w"] && - _j == index_map["v"] && - _pᵢ == get_point(tri, index_map["w"]) && - _pⱼ == get_point(pts, index_map["v"])) || - (_p == get_point(pts, k) && - _i == index_map["v"] && - _j == index_map["z"] && - _pᵢ == get_point(tri, index_map["v"]) && - _pⱼ == get_point(pts, index_map["z"])) + # Now do the same test, but put the point above p + q = (14.0, 14.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test ( + _p == get_point(pts, k) && + _i == index_map["w"] && + _j == index_map["v"] && + _pᵢ == get_point(tri, index_map["w"]) && + _pⱼ == get_point(pts, index_map["v"]) + ) || + ( + _p == get_point(pts, k) && + _i == index_map["v"] && + _j == index_map["z"] && + _pᵢ == get_point(tri, index_map["v"]) && + _pⱼ == get_point(pts, index_map["z"]) + ) - # What if it is an existing triangle? - q = (12.0, 6.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["n"] && - _j == index_map["u"] && - _pᵢ == get_point(tri, index_map["n"]) && - _pⱼ == get_point(pts, index_map["u"]) + # What if it is an existing triangle? + q = (12.0, 6.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["n"] && + _j == index_map["u"] && + _pᵢ == get_point(tri, index_map["n"]) && + _pⱼ == get_point(pts, index_map["u"]) - # Now do the same test, but put the point above p - q = (13.288, 15.01) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["w"] && - _j == index_map["v"] && - _pᵢ == get_point(tri, index_map["w"]) && - _pⱼ == get_point(pts, index_map["v"]) - q = (16.437, 15.42) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["v"] && - _j == index_map["z"] && - _pᵢ == get_point(tri, index_map["v"]) && - _pⱼ == get_point(pts, index_map["z"]) - q = (17.46287, 13.111) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["z"] && - _j == index_map["r"] && - _pᵢ == get_point(tri, index_map["z"]) && - _pⱼ == get_point(pts, index_map["r"]) + # Now do the same test, but put the point above p + q = (13.288, 15.01) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["w"] && + _j == index_map["v"] && + _pᵢ == get_point(tri, index_map["w"]) && + _pⱼ == get_point(pts, index_map["v"]) + q = (16.437, 15.42) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["v"] && + _j == index_map["z"] && + _pᵢ == get_point(tri, index_map["v"]) && + _pⱼ == get_point(pts, index_map["z"]) + q = (17.46287, 13.111) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["z"] && + _j == index_map["r"] && + _pᵢ == get_point(tri, index_map["z"]) && + _pⱼ == get_point(pts, index_map["r"]) - # Check that everything is fine when the point is outside - q = (23.068, 6.92) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @inferred DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["r"] && - (_j == DT.𝒢 - 2 || _j == DT.𝒢 - 3) && - _pᵢ == get_point(tri, index_map["r"]) && - _pⱼ == get_point(tri, DT.𝒢 - 3) + # Check that everything is fine when the point is outside + q = (23.068, 6.92) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @inferred DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["r"] && + (_j == DT.𝒢 - 2 || _j == DT.𝒢 - 3) && + _pᵢ == get_point(tri, index_map["r"]) && + _pⱼ == get_point(tri, DT.𝒢 - 3) - # Can interior ghost edges be handled correctly? - q = (15.5, 9.0) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _i == index_map["r"] && - (_j == DT.𝒢 - 2 || _j == DT.𝒢 - 3) && - _pᵢ == get_point(tri, index_map["r"]) && - _pⱼ == get_point(tri, DT.𝒢 - 3) - q = (14.87, 4.01) - _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) - @test _p == get_point(pts, k) && - _j == index_map["n"] && - (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && - _pⱼ == get_point(tri, index_map["n"]) && - _pᵢ == get_point(tri, DT.𝒢 - 3) - end + # Can interior ghost edges be handled correctly? + q = (15.5, 9.0) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _i == index_map["r"] && + (_j == DT.𝒢 - 2 || _j == DT.𝒢 - 3) && + _pᵢ == get_point(tri, index_map["r"]) && + _pⱼ == get_point(tri, DT.𝒢 - 3) + q = (14.87, 4.01) + _p, _i, _j, _pᵢ, _pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, q) + @test _p == get_point(pts, k) && + _j == index_map["n"] && + (_i == DT.𝒢 - 2 || _i == DT.𝒢 - 3) && + _pⱼ == get_point(tri, index_map["n"]) && + _pᵢ == get_point(tri, DT.𝒢 - 3) + end end @testset "Testing points that are already in the triangulation" begin - for k in DT.each_point_index(pts) - local i, j, pᵢ, pⱼ - if !DT.is_exterior_boundary_node(tri, k) - for (i, j) in get_adjacent2vertex(tri, k) - p1, i1, j1, pᵢ1, pⱼ1 = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, i)) - p2, i2, j2, pᵢ2, pⱼ2 = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, j)) - if DT.is_ghost_vertex(i) - @test i ∈ (i1, j1) || i - 1 ∈ (i1, j1) || i + 1 ∈ (i1, j1) - else - @test i ∈ (i1, j1) - end - if DT.is_ghost_vertex(j) - @test j ∈ (i2, j2) || j - 1 ∈ (i2, j2) || j + 1 ∈ (i2, j2) - else - @test j ∈ (i2, j2) - end - end + for k in DT.each_point_index(pts) + local i, j, pᵢ, pⱼ + if !DT.is_exterior_boundary_node(tri, k) + for (i, j) in get_adjacent2vertex(tri, k) + p1, i1, j1, pᵢ1, pⱼ1 = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, i)) + p2, i2, j2, pᵢ2, pⱼ2 = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, j)) + if DT.is_ghost_vertex(i) + @test i ∈ (i1, j1) || i - 1 ∈ (i1, j1) || i + 1 ∈ (i1, j1) + else + @test i ∈ (i1, j1) + end + if DT.is_ghost_vertex(j) + @test j ∈ (i2, j2) || j - 1 ∈ (i2, j2) || j + 1 ∈ (i2, j2) + else + @test j ∈ (i2, j2) + end end - p, i, j, pᵢ, pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, k)) - @test get_adjacent(tri.adjacent, j, i) == k - end -end \ No newline at end of file + end + p, i, j, pᵢ, pⱼ = DT.select_initial_triangle_interior_vertex(tri, k, get_point(tri, k)) + @test get_adjacent(tri.adjacent, j, i) == k + end +end diff --git a/test/predicates/boundaries_and_ghosts.jl b/test/predicates/boundaries_and_ghosts.jl index 111252b64..b406e8708 100644 --- a/test/predicates/boundaries_and_ghosts.jl +++ b/test/predicates/boundaries_and_ghosts.jl @@ -7,13 +7,12 @@ const GV = DT.𝒢 using ..DelaunayTriangulation: Certificate - x, y = complicated_geometry() rng = StableRNG(99988) boundary_nodes, points = convert_boundary_points_to_indices(x, y) -tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) +tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) A = get_area(tri) -refine!(tri; max_area=1e-2A, rng, use_circumcenter=true) +refine!(tri; max_area = 1.0e-2A, rng, use_circumcenter = true) tri2, label_map, index_map = simple_geometry() add_ghost_triangles!(tri2) @@ -198,7 +197,7 @@ end @testset "has_boundary_nodes and is_constrained" begin @test DT.has_boundary_nodes(tri) @test DT.has_boundary_nodes(tri2) - _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary=true) + _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary = true) @test DT.has_boundary_nodes(_tri) __tri = triangulate(_tri.points) @test !DT.has_boundary_nodes(__tri) @@ -213,7 +212,7 @@ end p2 = @SVector[-5.98, 2.17] p3 = @SVector[-6.36, -1.55] pts = [p1, p2, p3] - tri = triangulate(pts; delete_ghosts=false) + tri = triangulate(pts; delete_ghosts = false) @test all(DT.is_positively_oriented(DT.triangle_orientation(tri, T)) for T in each_triangle(tri)) DT.add_triangle!(get_triangles(tri), (2, 3, -1)) @test !all(DT.is_positively_oriented(DT.triangle_orientation(tri, T)) for T in each_triangle(tri)) @@ -223,7 +222,7 @@ end x, y = complicated_geometry() rng = StableRNG(99988) boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri = triangulate(points; rng, boundary_nodes, delete_ghosts=false) + tri = triangulate(points; rng, boundary_nodes, delete_ghosts = false) for (ghost_vertex, segment_index) in get_ghost_vertex_map(tri) nodes = get_boundary_nodes(tri, segment_index) for node in nodes @@ -271,4 +270,4 @@ end @test !flag2 && res2 == DT.∅ end end -end \ No newline at end of file +end diff --git a/test/predicates/certificate.jl b/test/predicates/certificate.jl index 034b54250..4801f464a 100644 --- a/test/predicates/certificate.jl +++ b/test/predicates/certificate.jl @@ -2,7 +2,8 @@ using ..DelaunayTriangulation const DT = DelaunayTriangulation using ..DelaunayTriangulation: Certificate -global i = [Certificate.Inside, +global i = [ + Certificate.Inside, Certificate.Degenerate, Certificate.Outside, Certificate.On, @@ -20,7 +21,7 @@ global i = [Certificate.Inside, Certificate.Closer, Certificate.Further, Certificate.Equidistant, - Certificate.Above, + Certificate.Above, Certificate.Below, Certificate.EncroachmentFailure, Certificate.PrecisionFailure, @@ -28,8 +29,10 @@ global i = [Certificate.Inside, Certificate.Acute, Certificate.FailedInsertion, Certificate.Visible, - Certificate.Invisible] -global j = [DT.is_inside, + Certificate.Invisible, +] +global j = [ + DT.is_inside, DT.is_degenerate, DT.is_outside, DT.is_on, @@ -47,7 +50,7 @@ global j = [DT.is_inside, DT.is_closer, DT.is_further, DT.is_equidistant, - DT.is_above, + DT.is_above, DT.is_below, DT.is_encroachment_failure, DT.is_precision_failure, @@ -55,7 +58,8 @@ global j = [DT.is_inside, DT.is_acute, DT.is_failed_insertion, DT.is_visible, - DT.is_invisible] + DT.is_invisible, +] @testset "Classifiers" begin for a in eachindex(i) diff --git a/test/predicates/general.jl b/test/predicates/general.jl index 043231b5c..ca6c035e6 100644 --- a/test/predicates/general.jl +++ b/test/predicates/general.jl @@ -61,14 +61,14 @@ end @test DT.orient_predicate(DT.FastKernel(), p, q, r) === Int(sign(AdaptivePredicates.orient2fast(p, q, r))) === ExactPredicates.orient(p, q, r) @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r) === AdaptivePredicates.orient2p(p, q, r) === ExactPredicates.orient(p, q, r) @inferred DT.orient_predicate(rt(), p, q, r) - @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r) === DT.orient_predicate(p, q, r) + @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r) === DT.orient_predicate(p, q, r) p, q, r, s = eachcol(rand(3, 4)) @test DT.orient_predicate(DT.ExactKernel(), p, q, r, s) === ExactPredicates.orient(p, q, r, s) @test DT.orient_predicate(DT.FastKernel(), p, q, r, s) === Int(sign(AdaptivePredicates.orient3fast(p, q, r, s))) === ExactPredicates.orient(p, q, r, s) @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r, s) === AdaptivePredicates.orient3p(p, q, r, s) === ExactPredicates.orient(p, q, r, s) @inferred DT.orient_predicate(rt(), p, q, r, s) - @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r) === DT.orient_predicate(p, q, r) + @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r) === DT.orient_predicate(p, q, r) a, b, c, p = eachcol(rand(2, 4)) @test DT.incircle_predicate(DT.ExactKernel(), a, b, c, p) === ExactPredicates.incircle(a, b, c, p) @@ -82,7 +82,7 @@ end @test DT.parallelorder_predicate(DT.FastKernel(), a, b, p, q) === DT.parallelorder(DT.FastKernel(), a, b, p, q) === ExactPredicates.parallelorder(a, b, p, q) @test DT.parallelorder_predicate(DT.AdaptiveKernel(), a, b, p, q) === ExactPredicates.parallelorder(a, b, p, q) === ExactPredicates.parallelorder(a, b, p, q) @inferred DT.parallelorder_predicate(rt(), a, b, p, q) - @test DT.parallelorder_predicate(DT.AdaptiveKernel(), a, b, p, q) ===DT.parallelorder_predicate(a, b, p, q) + @test DT.parallelorder_predicate(DT.AdaptiveKernel(), a, b, p, q) === DT.parallelorder_predicate(a, b, p, q) p, a, b = eachcol(rand(2, 3)) @test DT.sameside_predicate(a, b, p) === ExactPredicates.sameside(p, a, b) @@ -120,7 +120,7 @@ end r = (rand(x), rand(y), rand(z)) s = (rand(x), rand(y), rand(z)) @test DT.orient_predicate(DT.ExactKernel(), p, q, r, s) == ExactPredicates.orient(p, q, r, s) === DT.orient_predicate(DT.AdaptiveKernel(), p, q, r, s) === DT.orient_predicate(DT.FastKernel(), p, q, r, s) - @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r, s) == DT.orient_predicate(p, q, r, s) + @test DT.orient_predicate(DT.AdaptiveKernel(), p, q, r, s) == DT.orient_predicate(p, q, r, s) end end @@ -147,17 +147,21 @@ global p3, q3, r3 = (2.8, 1.4), (2.8, 2.4), (4.6, 1.4) # - global p4, q4, r4 = (2.8, 1.4), (3.8, 1.4), (4.6, 1.4) # 0 global p5, q5, r5 = (5.0, 1.4), (3.8, 1.4), (4.6, 1.4) # 0 global p6, q6, r6 = (5.0, 1.4), (3.8, 1.4), (4.4, 0.8) # + -global pqr = ((p1, q1, r1), (p2, q2, r2), (p3, q3, r3), +global pqr = ( + (p1, q1, r1), (p2, q2, r2), (p3, q3, r3), (p4, q4, r4), (p5, q5, r5), (p6, q6, r6), - (p4, q4, r4), (p5, q5, r5), (p6, q6, r6)) + (p4, q4, r4), (p5, q5, r5), (p6, q6, r6), +) @testset "triangle_orientation" begin - results = [Certificate.PositivelyOriented, + results = [ + Certificate.PositivelyOriented, Certificate.NegativelyOriented, Certificate.NegativelyOriented, Certificate.Degenerate, Certificate.Degenerate, - Certificate.PositivelyOriented] + Certificate.PositivelyOriented, + ] for T in subtypes(DT.AbstractPredicateKernel) for ((p, q, r), result) in zip(pqr, results) @test DT.triangle_orientation(T(), p, q, r) == result @@ -174,11 +178,13 @@ end for T in subtypes(DT.AbstractPredicateKernel) R = 5 a, b, c = (0.0, 5.0), (-3.0, -4.0), (3.0, 4.0) - p1, p2, p3, p4, p5 = [(0.0, -5.0), + p1, p2, p3, p4, p5 = [ + (0.0, -5.0), (5.0, 0.0), (-5.0, 0.0), (-3.0, 4.0), - (3.0, -4.0)] + (3.0, -4.0), + ] for p in (p1, p2, p3, p4, p5) cert = DT.point_position_relative_to_circle(T(), a, b, c, p) @test DT.is_on(cert) @@ -245,12 +251,14 @@ end @testset "point_position_relative_to_line" begin for T in subtypes(DT.AbstractPredicateKernel) - results = [Certificate.Left, + results = [ + Certificate.Left, Certificate.Right, Certificate.Right, Certificate.Collinear, Certificate.Collinear, - Certificate.Left] + Certificate.Left, + ] for ((p, q, r), result) in zip(pqr, results) @test DT.point_position_relative_to_line(T(), p, q, r) == result @inferred DT.point_position_relative_to_line(T(), p, q, r) @@ -309,9 +317,9 @@ end @inferred DT.is_right(DT.point_position_on_line_segment(p, q, c3)) @test DT.is_degenerate(DT.point_position_on_line_segment(p, q, p)) @test DT.is_degenerate(DT.point_position_on_line_segment(p, q, q)) - p, q = (4.0, 5.0), (4.0, 1.50) + p, q = (4.0, 5.0), (4.0, 1.5) c1, c2, c3, c4, c5, c6, c7, c8 = (4.0, 3.0), (4.0, 2.5), (4.0, 4.0), (4.0, 4.5), (4.0, 1.0), - (4.0, 6.0), (4.0, 6.5), (4.0, 0.5) + (4.0, 6.0), (4.0, 6.5), (4.0, 0.5) (4.0, 6.0), (4.0, 6.5), (4.0, 0.5) @test DT.is_on(DT.point_position_on_line_segment(p, q, c1)) @test DT.is_on(DT.point_position_on_line_segment(p, q, c2)) @@ -342,7 +350,8 @@ end p11, q11, a11, b11 = (6.0, 6.5), (8.0, 5.5), (8.0, 5.0), (8.0, 7.5) # on point p12, q12, a12, b12 = (6.0, 6.5), (9.947, 8.137), (8.0, 5.0), (8.0, 7.5) # one point p13, q13, a13, b13 = (6.0, 6.5), (9.947, 8.137), (8.0, 5.0), (6.0, 7.0) # one point - results = [Certificate.Single, + results = [ + Certificate.Single, Certificate.None, Certificate.None, Certificate.Multiple, @@ -354,11 +363,14 @@ end Certificate.Touching, Certificate.Touching, Certificate.Single, - Certificate.Single] - pqab = ((p1, q1, a1, b1), (p2, q2, a2, b2), (p3, q3, a3, b3), (p4, q4, a4, b4), + Certificate.Single, + ] + pqab = ( + (p1, q1, a1, b1), (p2, q2, a2, b2), (p3, q3, a3, b3), (p4, q4, a4, b4), (p5, q5, a5, b5), (p6, q6, a6, b6), (p7, q7, a7, b7), (p8, q8, a8, b8), (p9, q9, a9, b9), (p10, q10, a10, b10), (p11, q11, a11, b11), (p12, q12, a12, b12), - (p13, q13, a13, b13)) + (p13, q13, a13, b13), + ) for ((p, q, a, b), result) in zip(pqab, results) @test DT.line_segment_intersection_type(T(), p, q, a, b) == result @inferred DT.line_segment_intersection_type(T(), p, q, a, b) @@ -372,18 +384,18 @@ end p, q, r = (2.0, 1.0), (5.0, 1.0), (2.0, 5.0) c1, c2, c3, c4 = (2.57, 3.35), (2.45, 2.51), (3.11, 2.43), (3.33, 1.83) # inside d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12 = (1.76, 4.06), (1.24, 4.109), + (2.589, 0.505), (3.19, -0.186), + (3.875, 4.53), (4.8, 2.698), (2.0, 6.5), + (2.0, 0.0), + (0.5, 1.0), (6.0, 1.0), (6.0, 0.0), + (1.0, 6.0) # outside (2.589, 0.505), (3.19, -0.186), - (3.875, 4.53), (4.8, 2.698), (2.0, 6.5), - (2.0, 0.0), - (0.5, 1.0), (6.0, 1.0), (6.0, 0.0), - (1.0, 6.0) # outside - (2.589, 0.505), (3.19, -0.186), - (3.875, 4.53), (4.8, 2.698), (2.0, 6.5), - (2.0, 0.0), - (0.5, 1.0), (6.0, 1.0), (6.0, 0.0), - (1.0, 6.0) # outside + (3.875, 4.53), (4.8, 2.698), (2.0, 6.5), + (2.0, 0.0), + (0.5, 1.0), (6.0, 1.0), (6.0, 0.0), + (1.0, 6.0) # outside e1, e2, e3, e4, e5, e6, e7, e8, e9, e10 = (2.0, 3.0), (2.0, 2.5), (2.0, 4.5), (2.0, 1.5), - (2.5, 1.0), (3.5, 1.0), (4.5, 1.0), p, q, r # on + (2.5, 1.0), (3.5, 1.0), (4.5, 1.0), p, q, r # on (2.5, 1.0), (3.5, 1.0), (4.5, 1.0), p, q, r # on for c in (c1, c2, c3, c4) @test DT.point_position_relative_to_triangle(PT(), p, q, r, c) == Certificate.Inside @@ -408,126 +420,126 @@ end p8 = Float64[4, -1] p9 = Float64[-1, 4] pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9] - T1 = DT.construct_triangle(NTuple{3,Int}, 4, 1, 6) - T2 = DT.construct_triangle(NTuple{3,Int}, 4, 2, 1) - T3 = DT.construct_triangle(NTuple{3,Int}, 3, 2, 4) - T4 = DT.construct_triangle(NTuple{3,Int}, 8, 1, 2) - T5 = DT.construct_triangle(NTuple{3,Int}, 8, 2, 3) - T6 = DT.construct_triangle(NTuple{3,Int}, 8, 3, 5) - T7 = DT.construct_triangle(NTuple{3,Int}, 5, 3, 7) - T8 = DT.construct_triangle(NTuple{3,Int}, 3, 4, 7) - T9 = DT.construct_triangle(NTuple{3,Int}, 5, 7, 9) - T10 = DT.construct_triangle(NTuple{3,Int}, 7, 6, 9) - T11 = DT.construct_triangle(NTuple{3,Int}, 7, 4, 6) + T1 = DT.construct_triangle(NTuple{3, Int}, 4, 1, 6) + T2 = DT.construct_triangle(NTuple{3, Int}, 4, 2, 1) + T3 = DT.construct_triangle(NTuple{3, Int}, 3, 2, 4) + T4 = DT.construct_triangle(NTuple{3, Int}, 8, 1, 2) + T5 = DT.construct_triangle(NTuple{3, Int}, 8, 2, 3) + T6 = DT.construct_triangle(NTuple{3, Int}, 8, 3, 5) + T7 = DT.construct_triangle(NTuple{3, Int}, 5, 3, 7) + T8 = DT.construct_triangle(NTuple{3, Int}, 3, 4, 7) + T9 = DT.construct_triangle(NTuple{3, Int}, 5, 7, 9) + T10 = DT.construct_triangle(NTuple{3, Int}, 7, 6, 9) + T11 = DT.construct_triangle(NTuple{3, Int}, 7, 4, 6) T = [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] pt1 = ( - A=(3.9551298987095, 4.7489988803935), - B=(3.2585303811361, 4.3003415639903), - C=(2.69180534989, 4.4066025073489), - D=(3.2231100666833, 4.6781582514877), - E=(2.0424329182538, 4.8198395092992) + A = (3.9551298987095, 4.7489988803935), + B = (3.2585303811361, 4.3003415639903), + C = (2.69180534989, 4.4066025073489), + D = (3.2231100666833, 4.6781582514877), + E = (2.0424329182538, 4.8198395092992), ) pt2 = ( - A=(3.5, 3.5), - B=(3.8384340736083, 3.2777159548861), - C=(4.173119090818, 3.0606229707501), - D=(4.0736181397556, 3.8475850382431), - E=(4.390212074954, 3.6938108411468), - F=(4.390212074954, 4.2546343834981), - G=(4.7520337151806, 4.2998620885264), - H=(4.7520337151806, 4.661683728753) + A = (3.5, 3.5), + B = (3.8384340736083, 3.2777159548861), + C = (4.173119090818, 3.0606229707501), + D = (4.0736181397556, 3.8475850382431), + E = (4.390212074954, 3.6938108411468), + F = (4.390212074954, 4.2546343834981), + G = (4.7520337151806, 4.2998620885264), + H = (4.7520337151806, 4.661683728753), ) pt3 = ( - A=(3.114790793155, 2.9520764786821), - B=(3.3952025643307, 2.8163933635972), - C=(3.3137926952797, 2.4545717233705), - D=(2.951971055053, 2.3098430672799), - E=(2.9157888910304, 2.4726628053818), - F=(3.0786086291324, 2.6535736254952), - G=(3.901752860648, 2.6626191665008), - H=(3.0, 2.0), - I=(2.7258325299114, 1.8213838529739) + A = (3.114790793155, 2.9520764786821), + B = (3.3952025643307, 2.8163933635972), + C = (3.3137926952797, 2.4545717233705), + D = (2.951971055053, 2.3098430672799), + E = (2.9157888910304, 2.4726628053818), + F = (3.0786086291324, 2.6535736254952), + G = (3.901752860648, 2.6626191665008), + H = (3.0, 2.0), + I = (2.7258325299114, 1.8213838529739), ) pt4 = ( - A=(4.5781396673455, 2.7004728027825), - B=(4.6264236360138, 2.9231155471972), - C=(4.6693427192745, 3.1618529478347), - D=(4.70153203172, 3.3871781349531), - E=(4.5325381413811, 2.437593417811), - F=(4.4708419591939, 2.1988560171735), - G=(4.4520648602673, 2.0352270122422), - H=(4.3501320375233, 1.3082850395147) + A = (4.5781396673455, 2.7004728027825), + B = (4.6264236360138, 2.9231155471972), + C = (4.6693427192745, 3.1618529478347), + D = (4.70153203172, 3.3871781349531), + E = (4.5325381413811, 2.437593417811), + F = (4.4708419591939, 2.1988560171735), + G = (4.4520648602673, 2.0352270122422), + H = (4.3501320375233, 1.3082850395147), ) pt5 = ( - A=(3.433718968984, 1.1294534677817), - B=(3.7382811110409, 1.4137114670348), - C=(3.8499538964617, 0.9162599683419), - D=(3.6875207540314, 0.5304812550699), - E=(3.0377881843101, 1.2614303960064), - F=(3.7484331824428, -0.0481868148381), - G=(4.0, 2.0) + A = (3.433718968984, 1.1294534677817), + B = (3.7382811110409, 1.4137114670348), + C = (3.8499538964617, 0.9162599683419), + D = (3.6875207540314, 0.5304812550699), + E = (3.0377881843101, 1.2614303960064), + F = (3.7484331824428, -0.0481868148381), + G = (4.0, 2.0), ) pt6 = ( - A=(2.8956591846836, 0.4086563982472), - B=(2.4286639001964, 0.90610789694), - C=(2.0936455439339, 1.2309741818007), - D=(1.5149774740259, 1.4035593956329), - E=(0.824636618697, 1.586296680867), - F=(1.3322401887918, 1.2715824674082), - G=(1.6063461166429, 1.0177806823609), - H=(2.0225810441206, 0.713218540304), - I=(2.3169911147756, 0.4391126124529), - J=(2.6317053282343, 0.1954628988074), - K=(3.1697651125348, -0.1395554574552) + A = (2.8956591846836, 0.4086563982472), + B = (2.4286639001964, 0.90610789694), + C = (2.0936455439339, 1.2309741818007), + D = (1.5149774740259, 1.4035593956329), + E = (0.824636618697, 1.586296680867), + F = (1.3322401887918, 1.2715824674082), + G = (1.6063461166429, 1.0177806823609), + H = (2.0225810441206, 0.713218540304), + I = (2.3169911147756, 0.4391126124529), + J = (2.6317053282343, 0.1954628988074), + K = (3.1697651125348, -0.1395554574552), ) pt7 = ( - A=(1.0581342609406, 2.2766375361959), - B=(0.9363094041178, 2.550743464047), - C=(1.2916319031842, 2.3070937504015), - D=(1.7281709734657, 1.9923795369428), - E=(1.0, 2.0), - F=(0.5809869050515, 2.1142043937655) + A = (1.0581342609406, 2.2766375361959), + B = (0.9363094041178, 2.550743464047), + C = (1.2916319031842, 2.3070937504015), + D = (1.7281709734657, 1.9923795369428), + E = (1.0, 2.0), + F = (0.5809869050515, 2.1142043937655), ) pt8 = ( - A=(1.5454336882315, 2.845153534702), - B=(1.9921248299149, 2.5405913926451), - C=(2.1545579723453, 2.936522177319), - D=(2.1951662579528, 2.4187665358224), - E=(2.4185118287945, 2.8756097489077), - F=(2.4185118287945, 2.5101351784394), - G=(2.4489680430002, 2.0431398939523), - H=(2.6317053282343, 2.9162180345153) + A = (1.5454336882315, 2.845153534702), + B = (1.9921248299149, 2.5405913926451), + C = (2.1545579723453, 2.936522177319), + D = (2.1951662579528, 2.4187665358224), + E = (2.4185118287945, 2.8756097489077), + F = (2.4185118287945, 2.5101351784394), + G = (2.4489680430002, 2.0431398939523), + H = (2.6317053282343, 2.9162180345153), ) pt9 = ( - A=(-0.5458930205588, 3.5557985328346), - B=(0.0733833349568, 3.2512363907778), - C=(0.3170330486022, 2.9771304629266), - D=(0.0835354063587, 2.6421121066641), - E=(0.0, 2.4187665358224), - F=(0.3576413342098, 2.4695268928319), - G=(-0.2210267356982, 2.9872825343285), - H=(-0.4849805921475, 3.2410843193759), - I=(0.5099224052383, 2.9162180345153) + A = (-0.5458930205588, 3.5557985328346), + B = (0.0733833349568, 3.2512363907778), + C = (0.3170330486022, 2.9771304629266), + D = (0.0835354063587, 2.6421121066641), + E = (0.0, 2.4187665358224), + F = (0.3576413342098, 2.4695268928319), + G = (-0.2210267356982, 2.9872825343285), + H = (-0.4849805921475, 3.2410843193759), + I = (0.5099224052383, 2.9162180345153), ) pt10 = ( - A=(0.3576413342098, 4.1649228169483), - B=(0.0, 4.0), - C=(0.4794661910326, 3.6573192468536), - D=(0.7028117618743, 3.3527571047967), - E=(0.6520514048648, 4.4796370304071), - F=(-0.3530036639228, 4.1243145313408), - G=(0.0, 3.7689920322744) + A = (0.3576413342098, 4.1649228169483), + B = (0.0, 4.0), + C = (0.4794661910326, 3.6573192468536), + D = (0.7028117618743, 3.3527571047967), + E = (0.6520514048648, 4.4796370304071), + F = (-0.3530036639228, 4.1243145313408), + G = (0.0, 3.7689920322744), ) pt11 = ( - A=(1.3931526172031, 4.0735541743313), - B=(2.0022769013168, 3.718231675265), - C=(1.3931526172031, 3.5354943900309), - D=(2.1444059009434, 3.4339736760119), - E=(1.3017839745861, 4.3172038879768), - F=(1.3017839745861, 4.5507015302204), - G=(1.7992354732789, 3.9923376031161), - H=(1.6875626878581, 3.5151902472271), - I=(1.4337609028107, 3.809600317882) + A = (1.3931526172031, 4.0735541743313), + B = (2.0022769013168, 3.718231675265), + C = (1.3931526172031, 3.5354943900309), + D = (2.1444059009434, 3.4339736760119), + E = (1.3017839745861, 4.3172038879768), + F = (1.3017839745861, 4.5507015302204), + G = (1.7992354732789, 3.9923376031161), + H = (1.6875626878581, 3.5151902472271), + I = (1.4337609028107, 3.809600317882), ) test_pts = [pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, pt9, pt10, pt11] for i in eachindex(T) @@ -554,9 +566,9 @@ end @test DT.is_outside(DT.point_position_relative_to_triangle(PT(), get_point(pts, i, j, k, ℓ)...)) p1, p2, p3 = ([2.858866215272096, -2.220975375945989], [0.25559192484080395, -0.37340906332046214], [1.3855904656897817, -2.47947044705479]) pts = [p1, p2, p3] - τ1 = DT.construct_triangle(NTuple{3,Int}, 1, 2, 3) - τ2 = DT.construct_triangle(NTuple{3,Int}, 2, 3, 1) - τ3 = DT.construct_triangle(NTuple{3,Int}, 3, 1, 2) + τ1 = DT.construct_triangle(NTuple{3, Int}, 1, 2, 3) + τ2 = DT.construct_triangle(NTuple{3, Int}, 2, 3, 1) + τ3 = DT.construct_triangle(NTuple{3, Int}, 3, 1, 2) e = Vector{Any}(undef, 9) e[1] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ1..., 1)...) e[2] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ2..., 2)...) @@ -571,17 +583,17 @@ end for _ in 1:5000 local pts, i, j, k n = rand(3:5000) - pts = rand(SVector{2,Float64}, n) + pts = rand(SVector{2, Float64}, n) i, j, k = rand(1:n, 3) while length(unique((i, j, k))) < 3 i, j, k = rand(1:n, 3) end local τ1, τ2, τ3, e - τ = DT.construct_positively_oriented_triangle(NTuple{3,Int}, i, j, k, pts, PT()) + τ = DT.construct_positively_oriented_triangle(NTuple{3, Int}, i, j, k, pts, PT()) i, j, k = triangle_vertices(τ) - τ1 = DT.construct_triangle(NTuple{3,Int}, i, j, k) - τ2 = DT.construct_triangle(NTuple{3,Int}, j, k, i) - τ3 = DT.construct_triangle(NTuple{3,Int}, k, i, j) + τ1 = DT.construct_triangle(NTuple{3, Int}, i, j, k) + τ2 = DT.construct_triangle(NTuple{3, Int}, j, k, i) + τ3 = DT.construct_triangle(NTuple{3, Int}, k, i, j) e = Vector{Any}(undef, 9) e[1] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ1..., i)...) e[2] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ2..., i)...) @@ -606,11 +618,11 @@ end while length(unique((i, j, k))) < 3 i, j, k = rand(1:n, 3) end - τ = DT.construct_positively_oriented_triangle(NTuple{3,Int}, i, j, k, pts, PT()) + τ = DT.construct_positively_oriented_triangle(NTuple{3, Int}, i, j, k, pts, PT()) i, j, k = triangle_vertices(τ) - τ1 = DT.construct_triangle(NTuple{3,Int}, i, j, k) - τ2 = DT.construct_triangle(NTuple{3,Int}, j, k, i) - τ3 = DT.construct_triangle(NTuple{3,Int}, k, i, j) + τ1 = DT.construct_triangle(NTuple{3, Int}, i, j, k) + τ2 = DT.construct_triangle(NTuple{3, Int}, j, k, i) + τ3 = DT.construct_triangle(NTuple{3, Int}, k, i, j) e = Vector{Any}(undef, 9) e[1] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ1..., i)...) e[2] = DT.point_position_relative_to_triangle(PT(), get_point(pts, τ2..., i)...) @@ -642,10 +654,10 @@ end for PT in subtypes(DT.AbstractPredicateKernel) p, q = (3.0, 4.0), (6.0, 4.0) c, d, e, f, g, h, i, j, k, ℓ = (2.0, 4.0), (7.0, 4.0), (5.0, 5.0), + (4.0, 6.0), (6.0, 7.0), (4.0, 4.0), (5.0, 4.0), + (3.0, 2.0), (5.0, 3.0), (6.0, 1.0) (4.0, 6.0), (6.0, 7.0), (4.0, 4.0), (5.0, 4.0), - (3.0, 2.0), (5.0, 3.0), (6.0, 1.0) - (4.0, 6.0), (6.0, 7.0), (4.0, 4.0), (5.0, 4.0), - (3.0, 2.0), (5.0, 3.0), (6.0, 1.0) + (3.0, 2.0), (5.0, 3.0), (6.0, 1.0) @test DT.is_outside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, c)) @test DT.is_outside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, d)) @test DT.is_inside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, e)) @@ -662,12 +674,12 @@ end @inferred DT.is_outside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, ℓ)) p, q = (3.0, 4.0), (6.0, 7.0) c, d, e, f, g, h, i, j, k, ℓ = (3.0, 5.0), (3.0, 7.0), (4.0, 8.0), + (2.0, 3.0), (5.787, 3.774), (4.128, 1.626), + (6.95784, 7.715), (4.0, 5.0), (5.0, 6.0), + (4.143, 6.57) (2.0, 3.0), (5.787, 3.774), (4.128, 1.626), - (6.95784, 7.715), (4.0, 5.0), (5.0, 6.0), - (4.143, 6.57) - (2.0, 3.0), (5.787, 3.774), (4.128, 1.626), - (6.95784, 7.715), (4.0, 5.0), (5.0, 6.0), - (4.143, 6.57) + (6.95784, 7.715), (4.0, 5.0), (5.0, 6.0), + (4.143, 6.57) @test DT.is_inside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, c)) @test DT.is_inside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, d)) @test DT.is_inside(DT.point_position_relative_to_oriented_outer_halfplane(PT(), p, q, e)) @@ -700,7 +712,7 @@ end p9 = [31.7813088302274, -22.9759380718838] pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9] for PT in subtypes(DT.AbstractPredicateKernel) - tri = triangulate(pts; predicates=PT()) + tri = triangulate(pts; predicates = PT()) for (i, j) in ((1, 3), (3, 2), (2, 1), (1, 4), (4, 3), (3, 1), (3, 4), (4, 5), (5, 3), (3, 5), (5, 2), (2, 3)) @test DT.is_legal(AdaptiveKernel(), tri, i, j) == DT.is_legal(tri, i, j) @test DT.is_legal(DT.is_legal(PT(), tri, i, j)) @@ -730,7 +742,7 @@ end @testset "Constrained triangulations" begin for PT in subtypes(DT.AbstractPredicateKernel) tri = fixed_shewchuk_example_constrained() - add_segment!(tri, 2, 7; predicates=PT()) + add_segment!(tri, 2, 7; predicates = PT()) for e in each_edge(tri) i, j = DT.edge_vertices(e) @test DT.is_legal(DT.is_legal(PT(), tri, i, j)) @@ -772,7 +784,7 @@ end (a11, b11), (a12, b12), (a13, b13), - (a14, b14) + (a14, b14), ] flags = [DT.triangle_line_segment_intersection(PT(), p, q, r, a, b) for (a, b) in ab] true_flags = [ @@ -789,18 +801,18 @@ end Certificate.Touching, Certificate.Inside, Certificate.Outside, - Certificate.Inside + Certificate.Inside, ] @test isempty(findall(flags .≠ true_flags)) for i in eachindex(flags) a, b = ab[i] @test DT.triangle_line_segment_intersection(PT(), p, q, r, a, b) == - DT.triangle_line_segment_intersection(PT(), p, q, r, b, a) == - DT.triangle_line_segment_intersection(PT(), q, r, p, a, b) == - DT.triangle_line_segment_intersection(PT(), q, r, p, b, a) == - DT.triangle_line_segment_intersection(PT(), r, p, q, a, b) == - DT.triangle_line_segment_intersection(PT(), r, p, q, b, a) == - true_flags[i] + DT.triangle_line_segment_intersection(PT(), p, q, r, b, a) == + DT.triangle_line_segment_intersection(PT(), q, r, p, a, b) == + DT.triangle_line_segment_intersection(PT(), q, r, p, b, a) == + DT.triangle_line_segment_intersection(PT(), r, p, q, a, b) == + DT.triangle_line_segment_intersection(PT(), r, p, q, b, a) == + true_flags[i] @test DT.triangle_line_segment_intersection(AdaptiveKernel(), p, q, r, a, b) == DT.triangle_line_segment_intersection(p, q, r, a, b) end end @@ -925,7 +937,7 @@ end cert = DT.point_position_relative_to_witness_plane(PT(), tri, 1, 2, 3, 4) @test DT.is_above(cert) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, 2, 3, 4)) - tri = Triangulation(points; weights=zeros(4)) + tri = Triangulation(points; weights = zeros(4)) cert = DT.point_position_relative_to_witness_plane(PT(), tri, 1, 2, 3, 4) @test DT.is_above(cert) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, 2, 3, 4)) @@ -936,7 +948,7 @@ end points = [(2.0, 0.0), (1.0, 1.0), (0.0, 0.0), (1.0, 0.0)] weights = [2.0, -1.0, -1.0, -1 / 2] - tri = Triangulation(points; weights=weights) + tri = Triangulation(points; weights = weights) cert = DT.point_position_relative_to_witness_plane(PT(), tri, 1, 2, 3, 4) @test DT.point_position_relative_to_witness_plane(tri, 1, 2, 3, 4) == DT.point_position_relative_to_witness_plane(AdaptiveKernel(), tri, 1, 2, 3, 4) @test DT.is_on(cert) @@ -946,7 +958,7 @@ end a, b, c = (0.0, -6.0), (6.0, 2.0), (-7.0, 7.0) points = [a, b, c] weights = DT.ZeroWeight() - tri = triangulate(points; weights, predicates=PT()) + tri = triangulate(points; weights, predicates = PT()) d = (3.18, 7.62) push!(points, d) cert = DT.point_position_relative_to_circumcircle(PT(), tri, 3, 1, 2, 4) @@ -1021,4 +1033,4 @@ end flag1 && flag2 end end -end \ No newline at end of file +end diff --git a/test/predicates/index_and_ghost_handling.jl b/test/predicates/index_and_ghost_handling.jl index e9fbb4ade..f8466919b 100644 --- a/test/predicates/index_and_ghost_handling.jl +++ b/test/predicates/index_and_ghost_handling.jl @@ -9,15 +9,17 @@ using ..DelaunayTriangulation: Certificate for PT in subtypes(DT.AbstractPredicateKernel) global x, y = complicated_geometry() - boundary_nodes, points = convert_boundary_points_to_indices(x, y; existing_points=ElasticMatrix{Float64}(undef, 2, 0)) - _tri = triangulate(points; boundary_nodes, delete_ghosts=false, predicates=PT()) + boundary_nodes, points = convert_boundary_points_to_indices(x, y; existing_points = ElasticMatrix{Float64}(undef, 2, 0)) + _tri = triangulate(points; boundary_nodes, delete_ghosts = false, predicates = PT()) A = get_area(_tri) - refine!(_tri; max_area=1e-2A, use_circumcenter=true, predicates=PT()) + refine!(_tri; max_area = 1.0e-2A, use_circumcenter = true, predicates = PT()) _pts = ElasticMatrix(get_points(_tri)) - global tri = DT.Triangulation(_pts, _tri.triangles, _tri.boundary_nodes, _tri.interior_segments, + global tri = DT.Triangulation( + _pts, _tri.triangles, _tri.boundary_nodes, _tri.interior_segments, _tri.all_segments, _tri.weights, _tri.adjacent, _tri.adjacent2vertex, _tri.graph, _tri.boundary_curves, _tri.boundary_edge_map, _tri.ghost_vertex_map, _tri.ghost_vertex_ranges, DT.ConvexHull(_pts, _tri.convex_hull.vertices), _tri.representative_point_list, - _tri.polygon_hierarchy, _tri.boundary_enricher, _tri.cache) + _tri.polygon_hierarchy, _tri.boundary_enricher, _tri.cache, + ) DT.compute_representative_points!(tri) global rep = DT.get_representative_point_list(tri) global ghost_vertex_map = DT.get_ghost_vertex_map(tri) @@ -46,7 +48,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) p7 = Float64[4, -1] p8 = Float64[-1, 4] points = [p0, p1, p2, p3, p4, p5, p6, p7, p8] - temptri = triangulate(points; predicates=PT()) + temptri = triangulate(points; predicates = PT()) @test DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (4, 6, 7))) @test DT.is_negatively_oriented(DT.triangle_orientation(PT(), temptri, (4, 7, 6))) @test DT.is_negatively_oriented(DT.triangle_orientation(PT(), temptri, (4, 2, 3))) @@ -55,13 +57,13 @@ for PT in subtypes(DT.AbstractPredicateKernel) @test DT.is_negatively_oriented(DT.triangle_orientation(PT(), temptri, (5, 9, 7))) @test DT.is_negatively_oriented(DT.triangle_orientation(PT(), temptri, (3, 8, 5))) points = [[1.0, 2.0], [1.0, 5.0], [1.0, 8.0]] - temptrit = triangulate(points; predicates=PT()) + temptrit = triangulate(points; predicates = PT()) @test DT.is_degenerate(DT.triangle_orientation(PT(), tri, (1, 2, 3))) points = [[0, -3.0], [3.0, 0.0], [0.0, 3.0], [-3.0, 0.0]] - temptri = triangulate(points; predicates=PT()) + temptri = triangulate(points; predicates = PT()) @test DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (1, 2, 3))) && - DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (2, 3, 4))) && - DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (4, 1, 2))) + DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (2, 3, 4))) && + DT.is_positively_oriented(DT.triangle_orientation(PT(), temptri, (4, 1, 2))) end @testset "point_position_relative_to_circumcircle" begin @@ -71,14 +73,18 @@ for PT in subtypes(DT.AbstractPredicateKernel) for ℓ in (i, j, k) cert3 = DT.point_position_relative_to_circumcircle(PT(), tri, T, ℓ) cert4 = DT.point_position_relative_to_circumcircle(PT(), tri, i, j, k, ℓ) - cert5 = DT.point_position_relative_to_circumcircle(PT(), tri, pts[:, i], j, k, - pts[:, ℓ]) + cert5 = DT.point_position_relative_to_circumcircle( + PT(), tri, pts[:, i], j, k, + pts[:, ℓ], + ) cert6 = DT.point_position_relative_to_circumcircle(PT(), tri, i, pts[:, j], k, ℓ) @test all(DT.is_on, (cert3, cert4, cert5, cert6)) @inferred DT.point_position_relative_to_circumcircle(PT(), tri, T, ℓ) @inferred DT.point_position_relative_to_circumcircle(PT(), tri, i, j, k, ℓ) - @inferred DT.point_position_relative_to_circumcircle(PT(), tri, pts[:, i], j, k, - pts[:, ℓ]) + @inferred DT.point_position_relative_to_circumcircle( + PT(), tri, pts[:, i], j, k, + pts[:, ℓ], + ) @inferred DT.point_position_relative_to_circumcircle(PT(), tri, i, pts[:, j], k, ℓ) end q = (pts[:, i] .+ pts[:, j] .+ pts[:, k]) ./ 3 @@ -104,7 +110,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) p10 = @SVector[4.74, 2.21] p11 = @SVector[2.32, -0.27] pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] - tri = triangulate(pts; delete_ghosts=false,predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, predicates = PT()) p12 = @SVector[-1.86, 5.99] push!(pts, p12) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, 9, DT.𝒢, 12)) @@ -171,7 +177,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 4, 3, DT.𝒢, 23)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 3, DT.𝒢, 4, 23)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, DT.𝒢, 4, 3, 23)) - p24 = @SVector[-5.04821, -2.54880] + p24 = @SVector[-5.04821, -2.5488] push!(pts, p24) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 4, 3, DT.𝒢, 24)) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 3, DT.𝒢, 4, 24)) @@ -192,14 +198,14 @@ for PT in subtypes(DT.AbstractPredicateKernel) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 3, 2, DT.𝒢, 26)) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 2, DT.𝒢, 3, 26)) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, DT.𝒢, 3, 2, 26)) - p27 = @SVector[-5.310, 2.87596] + p27 = @SVector[-5.31, 2.87596] push!(pts, p27) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 2, 1, DT.𝒢, 27)) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, DT.𝒢, 2, 27)) @test DT.is_inside(DT.point_position_relative_to_circumcircle(PT(), tri, DT.𝒢, 2, 1, 27)) p28 = @SVector[-5.247746, 0.905588] push!(pts, p28) - @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(),tri, 2, 1, DT.𝒢, 28)) + @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 2, 1, DT.𝒢, 28)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, DT.𝒢, 2, 28)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, DT.𝒢, 2, 1, 28)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 8, 7, 11, 28)) @@ -213,7 +219,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) p13 = (8.0, 2.0) p14 = (0.0, 0.0) pts = [p8, p9, p13, p14] - tri = triangulate(pts; delete_ghosts=false, predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, predicates = PT()) @test DT.is_on(DT.point_position_relative_to_circumcircle(PT(), tri, 1, 2, DT.𝒢, 3)) push!(pts, (2.0, 14.0)) @test DT.is_outside(DT.point_position_relative_to_circumcircle(PT(), tri, 1, 2, DT.𝒢, 5)) @@ -238,7 +244,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) p10 = @SVector[4.74, 2.21] p11 = @SVector[2.32, -0.27] pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] - tri = triangulate(pts; delete_ghosts=false, randomise=false) + tri = triangulate(pts; delete_ghosts = false, randomise = false) p12 = @SVector[3.538447, 3.99844] push!(pts, p12) @test DT.is_left(DT.point_position_relative_to_line(PT(), tri, 9, 10, 12)) @@ -257,7 +263,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) @test DT.point_position_relative_to_triangle(PT(), tri, 9, DT.𝒢, 1, 13) |> DT.is_inside @test DT.point_position_relative_to_triangle(PT(), tri, DT.𝒢, 1, 9, 13) |> DT.is_inside @test DT.point_position_relative_to_triangle(PT(), tri, 1, 6, 8, 13) |> DT.is_outside - @test DT.brute_force_search(tri, 13; predicates=PT()) == (9, DT.𝒢, 1) + @test DT.brute_force_search(tri, 13; predicates = PT()) == (9, DT.𝒢, 1) p14 = @SVector[-4.85877, 3.086] push!(pts, p14) @test DT.point_position_relative_to_line(PT(), tri, 2, 1, 14) |> DT.is_left @@ -296,7 +302,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) @test DT.point_position_relative_to_triangle(PT(), tri, 2, 6, 3, 16) |> DT.is_outside @test DT.point_position_relative_to_triangle(PT(), tri, 3, 2, DT.𝒢, 16) |> DT.is_outside @test DT.point_position_relative_to_line(tri, 10, DT.𝒢, 16) |> DT.is_right - @test brute_force_search(tri, 16; predicates=PT()) == (10, 5, DT.𝒢) + @test brute_force_search(tri, 16; predicates = PT()) == (10, 5, DT.𝒢) end @testset "Detailed tests for a simple geometry" begin @@ -305,21 +311,57 @@ for PT in subtypes(DT.AbstractPredicateKernel) orig_length = length(pts) DT.compute_representative_points!(tri) rep = DT.get_representative_point_list(tri) - rep[1] = DT.RepresentativeCoordinates(mean(reinterpret(reshape, + rep[1] = DT.RepresentativeCoordinates( + mean( + reinterpret( + reshape, Float64, - pts[unique(reduce(vcat, - tri.boundary_nodes[1]))]); - dims=2)..., 0) - rep[2] = DT.RepresentativeCoordinates(mean(reinterpret(reshape, + pts[ + unique( + reduce( + vcat, + tri.boundary_nodes[1], + ), + ), + ], + ); + dims = 2, + )..., 0, + ) + rep[2] = DT.RepresentativeCoordinates( + mean( + reinterpret( + reshape, Float64, - pts[unique(reduce(vcat, - tri.boundary_nodes[2]))]); - dims=2)..., 0) - rep[3] = DT.RepresentativeCoordinates(mean(reinterpret(reshape, + pts[ + unique( + reduce( + vcat, + tri.boundary_nodes[2], + ), + ), + ], + ); + dims = 2, + )..., 0, + ) + rep[3] = DT.RepresentativeCoordinates( + mean( + reinterpret( + reshape, Float64, - pts[unique(reduce(vcat, - tri.boundary_nodes[3]))]); - dims=2)..., 0) + pts[ + unique( + reduce( + vcat, + tri.boundary_nodes[3], + ), + ), + ], + ); + dims = 2, + )..., 0, + ) ghost_vertex_map = DT.get_ghost_vertex_map(tri) @testset "point_position_relative_to_circumcircle" begin @@ -342,7 +384,7 @@ for PT in subtypes(DT.AbstractPredicateKernel) f1_i = length(pts) - 1 g1_i = length(pts) h1 = (21.517785930112, 22.1693108196262) - i1 = (22.0683240766855, 21.526199282940) + i1 = (22.0683240766855, 21.52619928294) push!(pts, h1, i1) h1_i = length(pts) - 1 i1_i = length(pts) @@ -368,7 +410,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) q1_i = length(pts) - 2 r1_i = length(pts) - 1 s1_i = length(pts) - certs = [("w", "v", "f") => Certificate.Left, + certs = [ + ("w", "v", "f") => Certificate.Left, ("c", "d", "k") => Certificate.Left, ("r", "q", "j") => Certificate.Right, ("r", "q", "d") => Certificate.Left, @@ -402,7 +445,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) ("m", DT.𝒢 - 2, s1_i) => Certificate.Right, (DT.𝒢 - 2, "m", s1_i) => Certificate.Left, (DT.𝒢 - 2, "p", r1_i) => Certificate.Left, - ("p", DT.𝒢 - 2, r1_i) => Certificate.Right] + ("p", DT.𝒢 - 2, r1_i) => Certificate.Right, + ] for ((i, j, u), cert) in certs i = i isa String ? index_map[i] : i j = j isa String ? index_map[j] : j @@ -430,9 +474,9 @@ for PT in subtypes(DT.AbstractPredicateKernel) cert7 = DT.point_position_on_line_segment(tri, j, i, i) cert8 = DT.point_position_on_line_segment(tri, j, i, j) cert9 = DT.point_position_on_line_segment(tri, i, j, i) - cert10 = DT.point_position_on_line_segment( tri, i, j, j) - cert11 = DT.point_position_on_line_segment( tri, i, j, pts[j]) - cert12 = DT.point_position_on_line_segment( tri, pts[i], j, i) + cert10 = DT.point_position_on_line_segment(tri, i, j, j) + cert11 = DT.point_position_on_line_segment(tri, i, j, pts[j]) + cert12 = DT.point_position_on_line_segment(tri, pts[i], j, i) @test all(DT.is_on, (cert1, cert4)) @test all(DT.is_left, (cert3, cert5)) @test all(DT.is_right, (cert2, cert6)) @@ -474,11 +518,11 @@ for PT in subtypes(DT.AbstractPredicateKernel) a2_i = length(pts) - 2 b2_i = length(pts) - 1 d2_i = length(pts) - @test DT.is_single(DT.line_segment_intersection_type(PT(),tri, z1_i, a2_i, b2_i, d2_i)) - @test DT.is_single(DT.line_segment_intersection_type(PT(),tri, b2_i, d2_i, z1_i, a2_i)) - @test DT.is_single(DT.line_segment_intersection_type(PT(),tri, b2_i, d2, z1_i, a2)) - @inferred DT.line_segment_intersection_type(PT(),tri, z1_i, a2_i, b2_i, d2_i) - @inferred DT.line_segment_intersection_type(PT(),tri, z1, a2, b2_i, d2_i) + @test DT.is_single(DT.line_segment_intersection_type(PT(), tri, z1_i, a2_i, b2_i, d2_i)) + @test DT.is_single(DT.line_segment_intersection_type(PT(), tri, b2_i, d2_i, z1_i, a2_i)) + @test DT.is_single(DT.line_segment_intersection_type(PT(), tri, b2_i, d2, z1_i, a2)) + @inferred DT.line_segment_intersection_type(PT(), tri, z1_i, a2_i, b2_i, d2_i) + @inferred DT.line_segment_intersection_type(PT(), tri, z1, a2, b2_i, d2_i) e2 = (48.0, 6.0) f2 = (54.0, 6.0) g2 = (52.0, 8.0) @@ -488,11 +532,11 @@ for PT in subtypes(DT.AbstractPredicateKernel) f2_i = length(pts) - 2 g2_i = length(pts) - 1 h2_i = length(pts) - @test DT.is_touching(DT.line_segment_intersection_type(PT(),tri, e2_i, f2_i, g2_i, h2_i)) - @test DT.is_touching(DT.line_segment_intersection_type(PT(),tri, g2_i, h2_i, e2_i, f2_i)) - @test DT.is_touching(DT.line_segment_intersection_type(PT(),tri, e2_i, h2_i, h2_i, g2_i)) - @test DT.is_touching(DT.line_segment_intersection_type(PT(),tri, g2_i, h2_i, h2_i, e2_i)) - @inferred DT.line_segment_intersection_type(PT(),tri, g2_i, h2_i, e2_i, f2_i) + @test DT.is_touching(DT.line_segment_intersection_type(PT(), tri, e2_i, f2_i, g2_i, h2_i)) + @test DT.is_touching(DT.line_segment_intersection_type(PT(), tri, g2_i, h2_i, e2_i, f2_i)) + @test DT.is_touching(DT.line_segment_intersection_type(PT(), tri, e2_i, h2_i, h2_i, g2_i)) + @test DT.is_touching(DT.line_segment_intersection_type(PT(), tri, g2_i, h2_i, h2_i, e2_i)) + @inferred DT.line_segment_intersection_type(PT(), tri, g2_i, h2_i, e2_i, f2_i) i2 = (53.58, 35.45) j2 = (57.11, 27.3) k2 = (49.61, 37.12) @@ -502,8 +546,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) j2_i = length(pts) - 2 k2_i = length(pts) - 1 ℓ2_i = length(pts) - @test DT.is_none(DT.line_segment_intersection_type(PT(),tri, i2_i, j2_i, k2_i, ℓ2_i)) - @test DT.is_none(DT.line_segment_intersection_type(PT(),tri, k2_i, ℓ2_i, i2_i, j2_i)) + @test DT.is_none(DT.line_segment_intersection_type(PT(), tri, i2_i, j2_i, k2_i, ℓ2_i)) + @test DT.is_none(DT.line_segment_intersection_type(PT(), tri, k2_i, ℓ2_i, i2_i, j2_i)) m2 = (50.0, 30.0) n2 = (50.0, 24.0) o2 = (50.0, 28.0) @@ -513,10 +557,10 @@ for PT in subtypes(DT.AbstractPredicateKernel) n2_i = length(pts) - 2 o2_i = length(pts) - 1 p2_i = length(pts) - @test DT.is_multiple(DT.line_segment_intersection_type(PT(),tri, m2_i, n2_i, o2_i, p2_i)) - @test DT.is_multiple(DT.line_segment_intersection_type(PT(),tri, n2_i, o2_i, m2_i, p2_i)) - @test DT.is_multiple(DT.line_segment_intersection_type(PT(),tri, o2_i, p2_i, m2_i, n2_i)) - @test DT.is_none(DT.line_segment_intersection_type(PT(),tri, p2_i, n2_i, o2_i, m2_i)) + @test DT.is_multiple(DT.line_segment_intersection_type(PT(), tri, m2_i, n2_i, o2_i, p2_i)) + @test DT.is_multiple(DT.line_segment_intersection_type(PT(), tri, n2_i, o2_i, m2_i, p2_i)) + @test DT.is_multiple(DT.line_segment_intersection_type(PT(), tri, o2_i, p2_i, m2_i, n2_i)) + @test DT.is_none(DT.line_segment_intersection_type(PT(), tri, p2_i, n2_i, o2_i, m2_i)) end @testset "point_position_relative_to_triangle" begin @@ -548,7 +592,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) h1_i = length(pts) - 10 g1_i = length(pts) - 11 f1_i = length(pts) - 12 - certs = [("g", "h", "b1", f1_i) => Certificate.Inside, + certs = [ + ("g", "h", "b1", f1_i) => Certificate.Inside, ("b1", "i", "g", f1_i) => Certificate.Outside, ("b1", "h", "j", g1_i) => Certificate.Inside, ("i", "b1", "j", h1_i) => Certificate.Inside, @@ -566,7 +611,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) ("a1", "f", "g", o1_i) => Certificate.On, ("h", "a", "s", q1_i) => Certificate.On, ("a1", "f", "g", p1_i) => Certificate.On, - ("b1", "j", "i", "v") => Certificate.Outside] + ("b1", "j", "i", "v") => Certificate.Outside, + ] for ((i, j, k, u), cert) in certs local cert1, cert2, cert3, cert4, cert5, cert6 i = i isa String ? index_map[i] : i @@ -576,21 +622,21 @@ for PT in subtypes(DT.AbstractPredicateKernel) T1 = (i, j, k) T2 = [i, j, k] if !DT.is_ghost_vertex(i) - cert1 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) + cert1 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) else - cert1 = DT.point_position_relative_to_triangle(PT(),tri, pts[i], j, pts[k], u, pts) - @inferred DT.point_position_relative_to_triangle(PT(),tri, pts[i], j, pts[k], u) + cert1 = DT.point_position_relative_to_triangle(PT(), tri, pts[i], j, pts[k], u, pts) + @inferred DT.point_position_relative_to_triangle(PT(), tri, pts[i], j, pts[k], u) end - cert2 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert3 = DT.point_position_relative_to_triangle(PT(),tri, T2, u) - cert4 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - cert5 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert6 = DT.point_position_relative_to_triangle(PT(),tri, T2, pts[u]) + cert2 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert3 = DT.point_position_relative_to_triangle(PT(), tri, T2, u) + cert4 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + cert5 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert6 = DT.point_position_relative_to_triangle(PT(), tri, T2, pts[u]) @test all(==(cert), (cert1, cert2, cert3, cert4, cert5, cert6)) - @inferred DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - @inferred DT.point_position_relative_to_triangle(PT(),tri, T1, u) - @inferred DT.point_position_relative_to_triangle(PT(),tri, T2, u) - @inferred DT.point_position_relative_to_triangle(PT(),tri, T2, pts[u]) + @inferred DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, T1, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, T2, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, T2, pts[u]) end resize!(pts, orig_length) f1 = (-4.0, 20.0) @@ -616,7 +662,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) h1_i = length(pts) - 8 g1_i = length(pts) - 9 f1_i = length(pts) - 10 - certs = [("h", "g", DT.𝒢, f1_i) => Certificate.Inside, + certs = [ + ("h", "g", DT.𝒢, f1_i) => Certificate.Inside, ("h", "g", DT.𝒢, g1_i) => Certificate.Inside, ("h", "g", DT.𝒢, h1_i) => Certificate.Inside, (DT.𝒢, "h", "g", i1_i) => Certificate.Inside, @@ -627,7 +674,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) ("h", "g", DT.𝒢, n1_i) => Certificate.Outside, ("h", "g", DT.𝒢, o1_i) => Certificate.Outside, ("h", "g", DT.𝒢, p1_i) => Certificate.Outside, - ("h", "g", DT.𝒢, "b1") => Certificate.Outside] + ("h", "g", DT.𝒢, "b1") => Certificate.Outside, + ] rep[1].x = 10.0 rep[1].y = 10.0 for ((i, j, k, u), cert) in certs @@ -638,20 +686,20 @@ for PT in subtypes(DT.AbstractPredicateKernel) u = u isa String ? index_map[u] : u T1 = (i, j, k) T2 = [i, j, k] - cert4 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - cert5 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert6 = DT.point_position_relative_to_triangle(PT(),tri, T2, u) + cert4 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + cert5 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert6 = DT.point_position_relative_to_triangle(PT(), tri, T2, u) @test all(==(cert), (cert4, cert5, cert6)) - @inferred DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - @inferred DT.point_position_relative_to_triangle(PT(),tri, T1, u) - @inferred DT.point_position_relative_to_triangle(PT(),tri, T2, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, T1, u) + @inferred DT.point_position_relative_to_triangle(PT(), tri, T2, u) end resize!(pts, orig_length) f1 = (2.98004, 22.706) g1 = (6.449, 23.343) h1 = (10.0, 24.0) i1 = (12.4666, 22.777) - j1 = (18.555, 22.600) + j1 = (18.555, 22.6) k1 = (24.0, 24.0) push!(pts, f1, g1, h1, i1, j1, k1) f1_i = length(pts) - 5 @@ -660,7 +708,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) i1_i = length(pts) - 2 j1_i = length(pts) - 1 k1_i = length(pts) - certs = [("g", "f", DT.𝒢, f1_i) => Certificate.Inside, + certs = [ + ("g", "f", DT.𝒢, f1_i) => Certificate.Inside, ("f", "e", DT.𝒢, f1_i) => Certificate.Outside, ("g", "f", DT.𝒢, g1_i) => Certificate.Inside, ("e", DT.𝒢, "f", h1_i) => Certificate.Inside, @@ -670,7 +719,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) (DT.𝒢, "f", "e", k1_i) => Certificate.Inside, ("e", "d", DT.𝒢, k1_i) => Certificate.Inside, ("b", "a", DT.𝒢, "s") => Certificate.Outside, - (DT.𝒢, "b", "a", "v") => Certificate.Outside] + (DT.𝒢, "b", "a", "v") => Certificate.Outside, + ] for ((i, j, k, u), cert) in certs local cert1, cert2, cert3, cert4, cert5, cert6 i = i isa String ? index_map[i] : i @@ -679,9 +729,9 @@ for PT in subtypes(DT.AbstractPredicateKernel) u = u isa String ? index_map[u] : u T1 = (i, j, k) T2 = [i, j, k] - cert4 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - cert5 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert6 = DT.point_position_relative_to_triangle(PT(),tri, T2, u) + cert4 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + cert5 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert6 = DT.point_position_relative_to_triangle(PT(), tri, T2, u) @test all(==(cert), (cert4, cert5, cert6)) end resize!(pts, orig_length) @@ -707,7 +757,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) h1_i = length(pts) - 8 g1_i = length(pts) - 9 f1_i = length(pts) - 10 - certs = [("ℓ", "i", DT.𝒢 - 1, f1_i) => Certificate.Inside, + certs = [ + ("ℓ", "i", DT.𝒢 - 1, f1_i) => Certificate.Inside, ("i", DT.𝒢 - 1, "ℓ", g1_i) => Certificate.Inside, (DT.𝒢 - 1, "ℓ", "i", k1_i) => Certificate.Outside, ("i", "j", DT.𝒢 - 1, k1_i) => Certificate.Inside, @@ -722,7 +773,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) ("k", "ℓ", DT.𝒢 - 1, h1_i) => Certificate.Inside, ("ℓ", DT.𝒢 - 1, "k", m1_i) => Certificate.On, ("ℓ", DT.𝒢 - 1, "k", "b1") => Certificate.Outside, - ("j", "k", DT.𝒢 - 1, "s") => Certificate.Outside] + ("j", "k", DT.𝒢 - 1, "s") => Certificate.Outside, + ] for ((i, j, k, u), cert) in certs local cert4, cert5, cert6 i = i isa String ? index_map[i] : i @@ -731,9 +783,9 @@ for PT in subtypes(DT.AbstractPredicateKernel) u = u isa String ? index_map[u] : u T1 = (i, j, k) T2 = [i, j, k] - cert4 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - cert5 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert6 = DT.point_position_relative_to_triangle(PT(),tri, T2, u) + cert4 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + cert5 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert6 = DT.point_position_relative_to_triangle(PT(), tri, T2, u) @test all(==(cert), (cert4, cert5, cert6)) end resize!(pts, orig_length) @@ -768,7 +820,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) h1_i = length(pts) - 12 g1_i = length(pts) - 13 f1_i = length(pts) - 14 - certs = [("o", "p", DT.𝒢 - 2, o1_i) => Certificate.On, + certs = [ + ("o", "p", DT.𝒢 - 2, o1_i) => Certificate.On, ("p", DT.𝒢 - 2, "o", n1_i) => Certificate.On, (DT.𝒢 - 2, "o", "p", q1_i) => Certificate.Inside, (DT.𝒢 - 3, "o", "p", t1_i) => Certificate.Outside, @@ -788,7 +841,8 @@ for PT in subtypes(DT.AbstractPredicateKernel) ("m", DT.𝒢 - 3, "r", r1_i) => Certificate.Outside, ("m", DT.𝒢 - 3, "r", h1_i) => Certificate.Inside, ("m", "n", DT.𝒢 - 2, p1_i) => Certificate.Inside, - (DT.𝒢 - 2, "m", "n", s1_i) => Certificate.Outside] + (DT.𝒢 - 2, "m", "n", s1_i) => Certificate.Outside, + ] for ((i, j, k, u), cert) in certs local cert4, cert5, cert6 i = i isa String ? index_map[i] : i @@ -797,11 +851,11 @@ for PT in subtypes(DT.AbstractPredicateKernel) u = u isa String ? index_map[u] : u T1 = (i, j, k) T2 = [i, j, k] - cert4 = DT.point_position_relative_to_triangle(PT(),tri, i, j, k, u) - cert5 = DT.point_position_relative_to_triangle(PT(),tri, T1, u) - cert6 = DT.point_position_relative_to_triangle(PT(),tri, T2, u) + cert4 = DT.point_position_relative_to_triangle(PT(), tri, i, j, k, u) + cert5 = DT.point_position_relative_to_triangle(PT(), tri, T1, u) + cert6 = DT.point_position_relative_to_triangle(PT(), tri, T2, u) @test all(==(cert), (cert4, cert5, cert6)) end end end -end \ No newline at end of file +end diff --git a/test/readme_example.jl b/test/readme_example.jl index 3fd60590a..4638cd868 100644 --- a/test/readme_example.jl +++ b/test/readme_example.jl @@ -9,58 +9,66 @@ tri1 = triangulate(points; rng) # default predicate kernel is AdaptiveKernel() vorn2 = voronoi(tri1; rng) # Clipped Voronoi -vorn3 = voronoi(tri1, clip=true; rng, predicates = ExactKernel()) # you can change the predicate kernel +vorn3 = voronoi(tri1, clip = true; rng, predicates = ExactKernel()) # you can change the predicate kernel # Smoothed Voronoi vorn4 = centroidal_smooth(vorn3; rng, predicates = FastKernel()) # Constrained example with refinement -boundary_points = [(0.0, 0.0), (1.0, 0.0), (1.0, 0.3), (0.5, 0.3), - (0.3, 0.7), (0.1, 1.0), (0.0, 1.0), (0.0, 0.0)] +boundary_points = [ + (0.0, 0.0), (1.0, 0.0), (1.0, 0.3), (0.5, 0.3), + (0.3, 0.7), (0.1, 1.0), (0.0, 1.0), (0.0, 0.0), +] boundary_nodes, points = convert_boundary_points_to_indices(boundary_points) tri5 = triangulate(points; boundary_nodes, rng) -refine!(tri5; max_area=1e-2get_area(tri5), rng) +refine!(tri5; max_area = 1.0e-2get_area(tri5), rng) # Disjoint constrained example with refinement boundary_points = [ [[(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)]], [[(0.3, 0.3), (0.3, 0.7), (0.7, 0.7), (0.7, 0.3), (0.3, 0.3)]], - [[(1.2, 0.0), (1.4, 0.0), (1.4, 1.2), (0.0, 1.2), (0.0, 1.1), - (1.1, 1.1), (1.1, 0.0), (1.2, 0.0)]] + [ + [ + (1.2, 0.0), (1.4, 0.0), (1.4, 1.2), (0.0, 1.2), (0.0, 1.1), + (1.1, 1.1), (1.1, 0.0), (1.2, 0.0), + ], + ], ] boundary_nodes, points = convert_boundary_points_to_indices(boundary_points) tri6 = triangulate(points; boundary_nodes, rng) -refine!(tri6; max_area=1e-2get_area(tri6), rng) +refine!(tri6; max_area = 1.0e-2get_area(tri6), rng) # Curve-bounded example using DelaunayTriangulation: EllipticalArc ellipse = EllipticalArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0), 1.0, 2.0, 0.0) -tri7 = triangulate(NTuple{2,Float64}[]; boundary_nodes=[ellipse], rng) -refine!(tri7; max_area=1e-2get_area(tri7), rng) +tri7 = triangulate(NTuple{2, Float64}[]; boundary_nodes = [ellipse], rng) +refine!(tri7; max_area = 1.0e-2get_area(tri7), rng) # Disjoint curve-bounded example ellipse = EllipticalArc((7.0, 3.5), (7.0, 3.5), (0.0, 3.5), 7.0, 10.0, 0.0) -catmull_cp = [(0.0, 0.0), (-2.0, -1.0), (-4.0, 0.0), (-5.0, 2.0), (-1.0, 4.0), (0.0, 3.0), - (1.0, 4.0), (5.0, 2.0), (4.0, 0.0), (2.0, -1.0), (0.0, 0.0)] +catmull_cp = [ + (0.0, 0.0), (-2.0, -1.0), (-4.0, 0.0), (-5.0, 2.0), (-1.0, 4.0), (0.0, 3.0), + (1.0, 4.0), (5.0, 2.0), (4.0, 0.0), (2.0, -1.0), (0.0, 0.0), +] catmull_spl = CatmullRomSpline(catmull_cp) circle = CircularArc((0.5, 1.5), (0.5, 1.5), (0.0, 1.0)) -circle2 = CircularArc((0.1, 1.5), (0.1, 1.5), (0.0, 1.0), positive=false) +circle2 = CircularArc((0.1, 1.5), (0.1, 1.5), (0.0, 1.0), positive = false) points = [(-4.0, -10.0), (4.0, -10.0), (4.0, -7.0), (-4.0, -7.0)] square = [1, 2, 3, 4, 1] boundary_nodes = [[square], [[ellipse]], [[catmull_spl]], [[circle]], [[circle2]]] tri8 = triangulate(points; boundary_nodes, rng) -refine!(tri8; max_area=1e-2get_area(tri8), rng) # could also use find_polygon to help define a custom refinement function for each shape +refine!(tri8; max_area = 1.0e-2get_area(tri8), rng) # could also use find_polygon to help define a custom refinement function for each shape # Plotting fig = Figure(fontsize = 42, size = (2800, 1480)) -ax = Axis(fig[1, 1], title="Unconstrained", width=600,height=600); triplot!(ax, tri1) -ax = Axis(fig[1, 2], title="Voronoi", width=600,height=600); voronoiplot!(ax, vorn2) -ax = Axis(fig[1, 3], title="Clipped Voronoi", width=600,height=600); voronoiplot!(ax, vorn3) -ax = Axis(fig[1, 4], title="Centroidal Voronoi", width=600,height=600); voronoiplot!(ax, vorn4) -ax = Axis(fig[2, 1], title="Constrained", width=600,height=600); triplot!(ax, tri5) -ax = Axis(fig[2, 2], title="Disjoint Constrained", width=600,height=600); triplot!(ax, tri6) -ax = Axis(fig[2, 3], title="Curve-Bounded", width=600,height=600); triplot!(ax, tri7) -ax = Axis(fig[2, 4], title="Disjoint Curve-Bounded", width=600,height=600); triplot!(ax, tri8) +ax = Axis(fig[1, 1], title = "Unconstrained", width = 600, height = 600); triplot!(ax, tri1) +ax = Axis(fig[1, 2], title = "Voronoi", width = 600, height = 600); voronoiplot!(ax, vorn2) +ax = Axis(fig[1, 3], title = "Clipped Voronoi", width = 600, height = 600); voronoiplot!(ax, vorn3) +ax = Axis(fig[1, 4], title = "Centroidal Voronoi", width = 600, height = 600); voronoiplot!(ax, vorn4) +ax = Axis(fig[2, 1], title = "Constrained", width = 600, height = 600); triplot!(ax, tri5) +ax = Axis(fig[2, 2], title = "Disjoint Constrained", width = 600, height = 600); triplot!(ax, tri6) +ax = Axis(fig[2, 3], title = "Curve-Bounded", width = 600, height = 600); triplot!(ax, tri7) +ax = Axis(fig[2, 4], title = "Disjoint Curve-Bounded", width = 600, height = 600); triplot!(ax, tri8) readme_img = joinpath(dirname(dirname(pathof(DelaunayTriangulation))), "readme.png") -@test_reference readme_img fig by=psnr_equality(10) +@test_reference readme_img fig by = psnr_equality(10) diff --git a/test/refinement/curve_bounded.jl b/test/refinement/curve_bounded.jl index 9774ab969..6aeae46a4 100644 --- a/test/refinement/curve_bounded.jl +++ b/test/refinement/curve_bounded.jl @@ -39,7 +39,7 @@ names = ( "multiply_connected_piecewise_linear_interior_circle", "multiply_connected_piecewise_linear_elliptical_bspline_piecewise_linear", "multiply_connected_piecewise_linear_elliptical_bspline_piecewise_linear_catmull_bezier_piecewise_linear_circle", - "multiply_connected_intersecting" + "multiply_connected_intersecting", ) curve_I = [1, 2, 3, 4, 1] @@ -60,7 +60,7 @@ curve_II = [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 1]] points_II = [ (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), - (0.75, 0.75), (0.25, 0.25) + (0.75, 0.75), (0.25, 0.25), ] fpoints_II = flatten_boundary_nodes(points_II, curve_II) points_II_extra = copy(points_II) @@ -77,7 +77,7 @@ points_III = [ (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), (0.0, 1.0), (0.0, 0.5), - (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75) + (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75), ] fpoints_III = flatten_boundary_nodes(points_III, curve_III) points_III_extra = copy(points_III) @@ -90,7 +90,7 @@ segments_III = Set([(n + 2, n + 1)]) fpoints_III_extra_segments = flatten_boundary_nodes(points_III_extra_segments, curve_III, segments_III) curve_IV = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0))] -points_IV = NTuple{2,Float64}[] +points_IV = NTuple{2, Float64}[] fpoints_IV = flatten_boundary_nodes(points_IV, curve_IV) points_IV_extra = copy(points_IV) push!(points_IV_extra, (0.99, 0.14), (0.0, 0.99), (-0.99, 0.0), (0.99, 0.0), (0.0, -0.99), (0.0, 0.0), (0.5, -0.5)) @@ -110,7 +110,7 @@ push!(points_V_extra, (0.01, 0.01), (0.25, 0.25), (0.5, 0.5), (0.25, 0.55), (0.5 curve_VI = [ [CircularArc((1.0, 0.0), (0.0, 1.0), (0.0, 0.0))], [BSpline([(0.0, 1.0), (-1.0, 2.0), (-2.0, 0.0), (-2.0, -1.0), (0.0, -2.0)])], - [5, 6, 10] + [5, 6, 10], ] points_VI = [(0.1, 0.1), (0.15, 0.15), (0.23, 0.23), (0.009, 0.11), (0.0, -2.0), (0.2, -1.7), (0.000591, 0.00019), (0.111, -0.005), (-0.0001, -0.00991), (1.0, 0.0)] fpoints_VI = flatten_boundary_nodes(points_VI, curve_VI) @@ -119,7 +119,7 @@ push!(points_VI_extra, (0.0, 0.0), (0.999, 0.0), (-1.0, -1.0), (0.5, 0.0), (-1.0 curve_VII = [ [CircularArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0))], - [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])] + [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])], ] points_VII = [(2.0, 0.0), (0.0, 0.5)] fpoints_VII = flatten_boundary_nodes(points_VII, curve_VII) @@ -130,23 +130,25 @@ curve_VIII = [ [1, 2, 3, 4, 5], [DT.EllipticalArc((0.0, 0.0), (2.0, -2.0), (1.0, -1.0), sqrt(2), sqrt(2), 45.0)], [6, 7, 8, 9, 10], - [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)], lookup_steps=5000)] + [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)], lookup_steps = 5000)], +] +points_VIII = [ + (10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), + (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, -0.2), (14.0, -0.05), ] -points_VIII = [(10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), - (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, -0.2), (14.0, -0.05)] fpoints_VIII = flatten_boundary_nodes(points_VIII, curve_VIII) points_VIII_extra = copy(points_VIII) push!(points_VIII_extra, (5.0, -0.01), (10.0, -1.0), (15.0, -1.95), (0.0, -1.0), (2.0, -1.5), (1.0, 0.5), (10.0, -2.0)) curve_IX = [ - [ - [1, 2, 3, 4, 5, 6, 7, 1] - ], - [ - [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive=false)] - ], - ] + [ + [1, 2, 3, 4, 5, 6, 7, 1], + ], + [ + [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive = false)], + ], +] points_IX = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.5), (0.0, 1.0), (0.0, 0.5), (0.0, 0.2)] fpoints_IX = flatten_boundary_nodes(points_IX, curve_IX) points_IX_extra = copy(points_IX) @@ -154,14 +156,14 @@ push!(points_IX_extra, (0.5, 0.01), (0.01, 0.01), (0.01, 0.5), (0.01, 1.0), (0.5 curve_X = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]) - ] + [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]), + ], ] points_X = [ - (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2) + (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2), ] fpoints_X = flatten_boundary_nodes(points_X, curve_X) points_X_extra = copy(points_X) @@ -169,23 +171,23 @@ push!(points_X_extra, (0.0, 0.01), (-0.5, 0.27), (1.0, 0.275), (1.5, 0.2), (0.0, curve_XI = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))] + [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points_XI = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] fpoints_XI = flatten_boundary_nodes(points_XI, curve_XI) @@ -196,15 +198,15 @@ ctrl = [ (0.0, 0.0), (2.0, 0.0), (1.6, -0.1), (0.3, -0.2), (-0.31, -0.35), (-0.2, 1.0), (0.0, 0.8), (0.2, 0.6), (0.4, 0.4), - (2.0, 0.4), (0.0, 0.0) + (2.0, 0.4), (0.0, 0.0), ] reverse!(ctrl) points_XII = [ (-0.1, 0.8), (-0.15, -0.15), (0.3, -0.1), (0.0, -0.1), (-0.1, 0.0), - (0.4, 0.2), (0.2, 0.4), (0.0, 0.6) + (0.4, 0.2), (0.2, 0.4), (0.0, 0.6), ] -curve_XII = [[[BSpline(ctrl, lookup_steps=25000)]], [[1, 8, 7, 6, 5, 4, 3, 2, 1]]] +curve_XII = [[[BSpline(ctrl, lookup_steps = 25000)]], [[1, 8, 7, 6, 5, 4, 3, 2, 1]]] fpoints_XII = flatten_boundary_nodes(points_XII, curve_XII) points_XII_extra = copy(points_XII) push!(points_XII_extra, (0.5, -0.15), (1.0, -0.1), (1.0, 0.25), (0.0, 0.75), (-0.01, 0.0)) @@ -287,8 +289,10 @@ end @test curves_X_tuple == (DT.PiecewiseLinear(points_X, curve_X[1][1]), curve_X[1][2][1], curve_X[2][1][1], DT.PiecewiseLinear(points_X, curve_X[2][2])) curves_XI_tuple = DT.to_boundary_curves(points_XI, curve_XI) - @test curves_XI_tuple == (DT.PiecewiseLinear(points_XI, curve_XI[1][1]), curve_XI[1][2][1], curve_XI[2][1][1], DT.PiecewiseLinear(points_XI, curve_XI[3][1]), curve_XI[4][1][1], curve_XI[4][2][1], - DT.PiecewiseLinear(points_XI, curve_XI[5][1]), curve_XI[6][1][1]) + @test curves_XI_tuple == ( + DT.PiecewiseLinear(points_XI, curve_XI[1][1]), curve_XI[1][2][1], curve_XI[2][1][1], DT.PiecewiseLinear(points_XI, curve_XI[3][1]), curve_XI[4][1][1], curve_XI[4][2][1], + DT.PiecewiseLinear(points_XI, curve_XI[5][1]), curve_XI[6][1][1], + ) end @testset "get_skeleton" begin @@ -360,51 +364,53 @@ end boundary_nodes = deepcopy(curve_VI) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[10, 11], [11, 5], [5, 6, 10]] && - points == [(0.1, 0.1), (0.15, 0.15), (0.23, 0.23), (0.009, 0.11), (0.0, -2.0), (0.2, -1.7), (0.000591, 0.00019), (0.111, -0.005), (-0.0001, -0.00991), (1.0, 0.0), (0.0, 1.0)] + new_boundary_nodes == [[10, 11], [11, 5], [5, 6, 10]] && + points == [(0.1, 0.1), (0.15, 0.15), (0.23, 0.23), (0.009, 0.11), (0.0, -2.0), (0.2, -1.7), (0.000591, 0.00019), (0.111, -0.005), (-0.0001, -0.00991), (1.0, 0.0), (0.0, 1.0)] points = deepcopy(points_VII) boundary_nodes = deepcopy(curve_VII) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[1, 3], [3, 1]] && - points == [(2.0, 0.0), (0.0, 0.5), (-2.0, 0.0)] + new_boundary_nodes == [[1, 3], [3, 1]] && + points == [(2.0, 0.0), (0.0, 0.5), (-2.0, 0.0)] points = deepcopy(points_VIII) boundary_nodes = deepcopy(curve_VIII) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[1, 2, 3, 4, 5], [5, 6], [6, 7, 8, 9, 10], [10, 1]] && - points == [(10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), - (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, -0.2), (14.0, -0.05)] + new_boundary_nodes == [[1, 2, 3, 4, 5], [5, 6], [6, 7, 8, 9, 10], [10, 1]] && + points == [ + (10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), + (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, -0.2), (14.0, -0.05), + ] points = deepcopy(points_IX) boundary_nodes = deepcopy(curve_IX) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[[1, 2, 3, 4, 5, 6, 7, 1]], [[8, 8]]] && - points == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.5), (0.0, 1.0), (0.0, 0.5), (0.0, 0.2), (0.6, 0.5)] + new_boundary_nodes == [[[1, 2, 3, 4, 5, 6, 7, 1]], [[8, 8]]] && + points == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.5), (0.0, 1.0), (0.0, 0.5), (0.0, 0.2), (0.6, 0.5)] points = deepcopy(points_X) boundary_nodes = deepcopy(curve_X) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[[1, 2, 3], [3, 1]], [[4, 8], [8, 7, 6, 5, 4]]] && - points == [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2)] + new_boundary_nodes == [[[1, 2, 3], [3, 1]], [[4, 8], [8, 7, 6, 5, 4]]] && + points == [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2)] points = deepcopy(points_XI) boundary_nodes = deepcopy(curve_XI) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) @test boundary_curves == DT.to_boundary_curves(points, boundary_nodes) && - new_boundary_nodes == [[[1, 2, 3], [3, 1]], [[13, 13]], [[4, 5, 6, 7, 4]], [[14, 8], [8, 14]], [[12, 11, 10, 12]], [[15, 15]]] && - points == [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0), (0.0, 0.4), (0.0, -2.0), (1.1, -3.0)] + new_boundary_nodes == [[[1, 2, 3], [3, 1]], [[13, 13]], [[4, 5, 6, 7, 4]], [[14, 8], [8, 14]], [[12, 11, 10, 12]], [[15, 15]]] && + points == [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0), (0.0, 0.4), (0.0, -2.0), (1.1, -3.0)] end @testset "BoundaryEnricher" begin all_points = deepcopy.((points_I, points_II, points_III, points_IV, points_V, points_VI, points_VII, points_VIII, points_IX, points_X, points_XI)) all_boundary_nodes = deepcopy.((curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI)) for (points, boundary_nodes) in zip(all_points, all_boundary_nodes) - enricher = DT.BoundaryEnricher(points, boundary_nodes; IntegerType=Int) + enricher = DT.BoundaryEnricher(points, boundary_nodes; IntegerType = Int) @test get_points(enricher) == enricher.points == points @test get_boundary_nodes(enricher) == enricher.boundary_nodes @test DT.get_boundary_curves(enricher) == enricher.boundary_curves @@ -422,7 +428,7 @@ end @test DT.get_queue(enricher) ⊢ DT.Queue{Int}() @test DT.get_boundary_edge_map(enricher) == enricher.boundary_edge_map == DT.construct_boundary_edge_map(DT.get_boundary_nodes(enricher)) @test !DT.has_segments(enricher) - @test DT.get_segments(enricher) == Set{NTuple{2,Int}}() + @test DT.get_segments(enricher) == Set{NTuple{2, Int}}() @test !DT.is_segment(enricher, 1, 2) end points, boundary_nodes, segments = deepcopy(points_I_extra_segments), deepcopy(curve_I), deepcopy(segments_I) @@ -449,7 +455,7 @@ end (8, 9) => 2, (9, 10) => 3, (10, 11) => 3, - (11, 1) => 3 + (11, 1) => 3, ) @test length(DT.get_parent_map(enricher)) == 11 curve_index_map = DT.get_curve_index_map(enricher) @@ -481,7 +487,7 @@ end 5 => 4, 6 => 4, 7 => 5, - 8 => 6 + 8 => 6, ) @test DT.map_curve_index(enricher, 1) == 1 @test DT.map_curve_index(enricher, 7) == 5 @@ -552,14 +558,14 @@ end points = deepcopy(points_V) boundary_nodes = deepcopy(curve_V) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n=5) # 5 gets mapped to 8 + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n = 5) # 5 gets mapped to 8 @test length(points) == 9 all_t = DT.get_inverse.(Ref(curve_V[1]), get_point(points, new_boundary_nodes...)) |> collect all_t[end] = 1.0 @test issorted(all_t) boundary_nodes = new_boundary_nodes @test DT.num_boundary_edges(boundary_nodes) == 8 - for i in 1:(num_boundary_edges(boundary_nodes)-1) + for i in 1:(num_boundary_edges(boundary_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(boundary_nodes, i), get_boundary_nodes(boundary_nodes, j), get_boundary_nodes(boundary_nodes, k) @@ -574,14 +580,14 @@ end end Tθ₁ = slow_total_absolute_curvature(curve_V[1], t₁, t₂) Tθ₂ = slow_total_absolute_curvature(curve_V[1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-2 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-2 end # VI points = deepcopy(points_VI) boundary_nodes = deepcopy(curve_VI) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n=64) + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n = 64) @test length(points) == 137 all_t = DT.get_inverse.(Ref(curve_VI[1][1]), get_point(points, get_boundary_nodes(new_boundary_nodes, 1)...)) |> collect @test issorted(all_t) @@ -593,7 +599,7 @@ end @test DT.num_boundary_edges(boundary_nodes[2]) == 64 for idx in 1:2 section_nodes = get_boundary_nodes(boundary_nodes, idx) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -601,7 +607,7 @@ end t₁, t₂, t₃ = DT.get_inverse(curve_VI[idx][1], p), DT.get_inverse(curve_VI[idx][1], q), DT.get_inverse(curve_VI[idx][1], r) Tθ₁ = DT.total_variation(curve_VI[idx][1], t₁, t₂) Tθ₂ = DT.total_variation(curve_VI[idx][1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-2 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-2 end end @@ -609,7 +615,7 @@ end points = deepcopy(points_VII) boundary_nodes = deepcopy(curve_VII) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n=512) + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n = 512) @test length(points) == 1025 all_t = DT.get_inverse.(Ref(curve_VII[1][1]), get_point(points, get_boundary_nodes(new_boundary_nodes, 1)...)) |> collect @test issorted(all_t) @@ -620,7 +626,7 @@ end @test DT.num_boundary_edges(boundary_nodes[2]) == 512 for idx in 1:2 section_nodes = get_boundary_nodes(boundary_nodes, idx) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -628,7 +634,7 @@ end t₁, t₂, t₃ = DT.get_inverse(curve_VII[idx][1], p), DT.get_inverse(curve_VII[idx][1], q), DT.get_inverse(curve_VII[idx][1], r) Tθ₁ = DT.total_variation(curve_VII[idx][1], t₁, t₂) Tθ₂ = DT.total_variation(curve_VII[idx][1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-1 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-1 end end @@ -651,7 +657,7 @@ end @test boundary_nodes[3] == [6, 7, 8, 9, 10] for idx in [2, 4] section_nodes = get_boundary_nodes(boundary_nodes, idx) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -659,7 +665,7 @@ end t₁, t₂, t₃ = DT.get_inverse(curve_VIII[idx][1], p), DT.get_inverse(curve_VIII[idx][1], q), DT.get_inverse(curve_VIII[idx][1], r) Tθ₁ = DT.total_variation(curve_VIII[idx][1], t₁, t₂) Tθ₂ = DT.total_variation(curve_VIII[idx][1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-2 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-2 end end @@ -667,7 +673,7 @@ end points = deepcopy(points_IX) boundary_nodes = deepcopy(curve_IX) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves, n=1) # check that 1 becomes 4 + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves, n = 1) # check that 1 becomes 4 @test length(points) == 11 # 1 gets ignored because it's a piecewise linear curve all_t = DT.get_inverse.(Ref(curve_IX[2][1][1]), get_point(points, new_boundary_nodes[2][1]...)) |> collect @@ -679,7 +685,7 @@ end for idx in (2,) curve_nodes = get_boundary_nodes(boundary_nodes, idx) section_nodes = get_boundary_nodes(curve_nodes, 1) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -702,7 +708,7 @@ end points = deepcopy(points_X) boundary_nodes = deepcopy(curve_X) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n=32) + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n = 32) @test length(points) == 70 # 1 and 4 are piecewise linear curves all_t = DT.get_inverse.(Ref(curve_X[1][2][1]), get_point(points, new_boundary_nodes[1][2]...)) |> collect @@ -717,7 +723,7 @@ end for (idx, idx2) in zip((1, 2), (2, 1)) curve_nodes = get_boundary_nodes(boundary_nodes, idx) section_nodes = get_boundary_nodes(curve_nodes, idx2) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -725,7 +731,7 @@ end t₁, t₂, t₃ = DT.get_inverse(curve_X[idx][idx2][1], p), DT.get_inverse(curve_X[idx][idx2][1], q), DT.get_inverse(curve_X[idx][idx2][1], r) Tθ₁ = DT.total_variation(curve_X[idx][idx2][1], t₁, t₂) Tθ₂ = DT.total_variation(curve_X[idx][idx2][1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-1 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-1 end end @@ -733,7 +739,7 @@ end points = deepcopy(points_XI) boundary_nodes = deepcopy(curve_XI) boundary_curves, new_boundary_nodes = DT.convert_boundary_curves!(points, boundary_nodes, Int32) - DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n=128) + DT.coarse_discretisation!(points, new_boundary_nodes, boundary_curves; n = 128) @test length(points) == 650 # (1, 1), (3, 1), and (5, 1) are piecewise linear # (2, 1) and (6, 1) are periodic @@ -758,7 +764,7 @@ end for (idx, idx2) in zip((1, 2, 4, 4, 6), (2, 1, 1, 2, 1)) curve_nodes = get_boundary_nodes(boundary_nodes, idx) section_nodes = get_boundary_nodes(curve_nodes, idx2) - for i in 1:(num_boundary_edges(section_nodes)-1) + for i in 1:(num_boundary_edges(section_nodes) - 1) j = i + 1 k = j + 1 u, v, w = get_boundary_nodes(section_nodes, i), get_boundary_nodes(section_nodes, j), get_boundary_nodes(section_nodes, k) @@ -773,7 +779,7 @@ end end Tθ₁ = DT.total_variation(curve_XI[idx][idx2][1], t₁, t₂) Tθ₂ = DT.total_variation(curve_XI[idx][idx2][1], t₂, t₃) - @test Tθ₁ ≈ Tθ₂ rtol = 1e-2 + @test Tθ₁ ≈ Tθ₂ rtol = 1.0e-2 end end end @@ -796,8 +802,8 @@ end @test DT.is_piecewise_linear(enricher_III, 1) @test !DT.is_piecewise_linear(enricher_IV, 1) @test DT.is_piecewise_linear(enricher_XI, 1) && !DT.is_piecewise_linear(enricher_XI, 2) && - !DT.is_piecewise_linear(enricher_XI, 3) && DT.is_piecewise_linear(enricher_XI, 4) && !DT.is_piecewise_linear(enricher_XI, 5) && - !DT.is_piecewise_linear(enricher_XI, 6) && DT.is_piecewise_linear(enricher_XI, 7) && !DT.is_piecewise_linear(enricher_XI, 8) + !DT.is_piecewise_linear(enricher_XI, 3) && DT.is_piecewise_linear(enricher_XI, 4) && !DT.is_piecewise_linear(enricher_XI, 5) && + !DT.is_piecewise_linear(enricher_XI, 6) && DT.is_piecewise_linear(enricher_XI, 7) && !DT.is_piecewise_linear(enricher_XI, 8) @inferred DT.is_piecewise_linear(enricher_I, 1) @inferred DT.is_piecewise_linear(enricher_II, 3) @inferred DT.is_piecewise_linear(enricher_III, 3) @@ -930,7 +936,7 @@ end (3.4, -0.2), (3.4, 0.0) geo1 = [[g, m, h, ℓ, a, ii, b, jj, c, kk, d, p, e, o, f, n, g]] geo2 = [[a1, z, w, v, u, t, s, a1]] - boundary_nodes, points = convert_boundary_points_to_indices([geo1, geo2]; existing_points=[r, c1, b1, d1, e1, f1, g1]) + boundary_nodes, points = convert_boundary_points_to_indices([geo1, geo2]; existing_points = [r, c1, b1, d1, e1, f1, g1]) enricher = DT.BoundaryEnricher(points, boundary_nodes) i, j, k = findfirst(==(ii), points), findfirst(==(b), points), findfirst(==(r), points) @test DT.is_invisible(DT.test_visibility(PT(), enricher, i, j, k)) @@ -1002,7 +1008,7 @@ end DT.split_edge!(enricher, 1, 2, length(enricher.points)) vis = DT.test_visibility(PT(), enricher, length(enricher.points), 2, length(enricher.points) - 1) @test DT.is_invisible(vis) - enricher.points[end-1] = (0.5, 0.49) + enricher.points[end - 1] = (0.5, 0.49) vis = DT.test_visibility(PT(), enricher, length(enricher.points), 2, length(enricher.points) - 1) @test DT.is_visible(vis) end @@ -1027,7 +1033,7 @@ end complexes = DT.get_small_angle_complexes(points, boundary_nodes, boundary_curves) _complexes = Dict( 9 => [SAC(9, [SACM(2, 8), SACM(3, 10)])], - 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])] + 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])], ) @test complexes == _complexes @test DT.get_small_angle_complexes(enricher) == complexes @@ -1049,14 +1055,14 @@ end DT.replace_next_edge!(enricher, 9, 1, 2, 17) _complexes = Dict( 9 => [SAC(9, [SACM(2, 8), SACM(3, 17)])], - 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])] + 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])], ) @test DT.get_small_angle_complexes(enricher) == _complexes A, B, C, D, E, F, G, H, I, J, K = (0.0, 0.0), (0.2, 1.4), (0.6, 1.2), - (1.2, 0.2), (1.2, -0.2), (-1.4, -0.2), - (-1.0, -0.6), (0.6, 1.0), (0.8, 0.6), - (0.6, 0.4), (0.6, 0.2) + (1.2, 0.2), (1.2, -0.2), (-1.4, -0.2), + (-1.0, -0.6), (0.6, 1.0), (0.8, 0.6), + (0.6, 0.4), (0.6, 0.2) points = [A, B, C, D, E, F, G, H, I, J, K] boundary_nodes = [[[1, 3, 2, 1]], [[1, 9, 8, 1]], [[1, 11, 10, 1]], [[1, 5, 4, 1]], [[1, 6, 7, 1]]] enricher = DT.BoundaryEnricher(points, boundary_nodes) @@ -1065,8 +1071,8 @@ end _complexes = Dict( 1 => [ SAC(1, [SACM(1, 2), SACM(1, 3), SACM(2, 8), SACM(2, 9), SACM(3, 10), SACM(3, 11), SACM(4, 4), SACM(4, 5)]), - SAC(1, [SACM(5, 7), SACM(5, 6)]) - ] + SAC(1, [SACM(5, 7), SACM(5, 6)]), + ], ) @test complexes == _complexes @test DT.get_small_angle_complexes(enricher) == complexes @@ -1120,8 +1126,8 @@ end _complexes = Dict( 1 => [ SAC(1, [SACM(1, 2), SACM(1, 3), SACM(2, 8), SACM(2, 9), SACM(3, 10), SACM(3, 11), SACM(4, 4), SACM(4, 5)]), - SAC(1, [SACM(5, 7), SACM(5, 20)]) - ] + SAC(1, [SACM(5, 7), SACM(5, 20)]), + ], ) @test DT.get_small_angle_complexes(enricher) == _complexes @@ -1165,7 +1171,7 @@ end 19 => [16], 20 => [16], 21 => [16], - 22 => [16] + 22 => [16], ) end @@ -1176,7 +1182,7 @@ end _complexes = Dict( 9 => [SAC(9, [SACM(2, 8), SACM(3, 10)])], 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])], - 16 => [SAC(16, [SACM(0, 18), SACM(0, 17), SACM(0, 19), SACM(0, 22)]), SAC(16, [SACM(0, 21), SACM(0, 20)])] + 16 => [SAC(16, [SACM(0, 18), SACM(0, 17), SACM(0, 19), SACM(0, 22)]), SAC(16, [SACM(0, 21), SACM(0, 20)])], ) @test complexes == _complexes @@ -1225,9 +1231,9 @@ end ctr = 1 for i in eachindex(enricher_III.boundary_nodes) for j in eachindex(enricher_III.boundary_nodes[i]) - for k in 1:(length(enricher_III.boundary_nodes[i])-1) + for k in 1:(length(enricher_III.boundary_nodes[i]) - 1) u = enricher_III.boundary_nodes[i][j][k] - v = enricher_III.boundary_nodes[i][j][k+1] + v = enricher_III.boundary_nodes[i][j][k + 1] p = enricher_III.parent_map[(u, v)] @test p == ctr end @@ -1237,7 +1243,7 @@ end rects, els = get_dt_rectangles(enricher_III.spatial_tree.tree) all_edges = Set(DT.get_edge(el) for el in els) @test (ii, jj) ∉ all_edges && (jj, ii) ∉ all_edges && - (ii, rr) ∈ all_edges && (jj, rr) ∈ all_edges + (ii, rr) ∈ all_edges && (jj, rr) ∈ all_edges end @testset "split_subcurve! (standard)" begin @@ -1271,7 +1277,7 @@ end enricher_V = DT.BoundaryEnricher(deepcopy(points_V), deepcopy(curve_V)) t, Δθ, ct = DT.compute_split_position(enricher_V, 3, 5, PT()) origθ = DT.total_variation(curve_V[1], DT.get_inverse(curve_V[1], get_point(enricher_V.points, 3)), DT.get_inverse(curve_V[1], get_point(enricher_V.points, 5))) - @test Δθ ≈ origθ / 2 rtol = 1e-3 + @test Δθ ≈ origθ / 2 rtol = 1.0e-3 @test 0.4999 ≤ t ≤ 0.708 && t ≈ 0.5994483483424031 && ct ⪧ curve_V[1](t) DT.split_subcurve!(enricher_V, 3, 5, PT()) @test enricher_V.points[end] ⪧ ct @@ -1279,7 +1285,7 @@ end enricher_VI = DT.BoundaryEnricher(deepcopy(points_VI), deepcopy(curve_VI)) t, Δθ, ct = DT.compute_split_position(enricher_VI, 12, 14, PT()) origθ = DT.total_variation(curve_VI[1][1], DT.get_inverse(curve_VI[1][1], get_point(enricher_VI.points, 12)), DT.get_inverse(curve_VI[1][1], get_point(enricher_VI.points, 14))) - @test Δθ ≈ origθ / 2 rtol = 1e-3 + @test Δθ ≈ origθ / 2 rtol = 1.0e-3 @test 0.5 ≤ t ≤ 0.75 && t ≈ 0.625 && ct ⪧ curve_VI[1][1](t) DT.split_subcurve!(enricher_VI, 12, 14, PT()) @test enricher_VI.points[end] ⪧ ct @@ -1287,8 +1293,8 @@ end enricher_VII = DT.BoundaryEnricher(deepcopy(points_VII), deepcopy(curve_VII)) t, Δθ, ct = DT.compute_split_position(enricher_VII, 8, 7, PT()) origθ = DT.total_variation(curve_VII[2][1], DT.get_inverse(curve_VII[2][1], get_point(enricher_VII.points, 8)), DT.get_inverse(curve_VII[2][1], get_point(enricher_VII.points, 7))) - @test Δθ ≈ origθ / 2 rtol = 1e-3 - @test 0.10 ≤ t ≤ 0.501 && t ≈ 0.1599962634542922 && ct ⪧ curve_VII[2][1](t) + @test Δθ ≈ origθ / 2 rtol = 1.0e-3 + @test 0.1 ≤ t ≤ 0.501 && t ≈ 0.1599962634542922 && ct ⪧ curve_VII[2][1](t) DT.split_subcurve!(enricher_VII, 8, 7, PT()) @test enricher_VII.points[end] ⪧ ct @@ -1310,14 +1316,14 @@ end @test DT.dist(enricher.points[9], enricher.points[13]) ≈ DT.dist(enricher.points[9], enricher.points[12]) ≈ ℓ _complexes = Dict( 9 => [SAC(9, [SACM(2, 12), SACM(3, 13)])], - 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])] + 1 => [SAC(1, [SACM(3, 11), SACM(1, 2)])], ) @test DT.get_small_angle_complexes(enricher) == _complexes A, B, C, D, E, F, G, H, I, J, K = (0.0, 0.0), (0.2, 1.4), (0.6, 1.2), - (1.2, 0.2), (1.2, -0.2), (-1.4, -0.2), - (-1.0, -0.6), (0.6, 1.0), (0.8, 0.6), - (0.6, 0.4), (0.6, 0.2) + (1.2, 0.2), (1.2, -0.2), (-1.4, -0.2), + (-1.0, -0.6), (0.6, 1.0), (0.8, 0.6), + (0.6, 0.4), (0.6, 0.2) points = [A, B, C, D, E, F, G, H, I, J, K] boundary_nodes = [[[1, 3, 2, 1]], [[1, 9, 8, 1]], [[1, 11, 10, 1]], [[1, 5, 4, 1]], [[1, 6, 7, 1]]] enricher = DT.BoundaryEnricher(points, boundary_nodes) @@ -1327,8 +1333,8 @@ end _complexes = Dict( 1 => [ SAC(1, [SACM(1, 12), SACM(1, 13), SACM(2, 14), SACM(2, 15), SACM(3, 16), SACM(3, 17), SACM(4, 18), SACM(4, 19)]), - SAC(1, [SACM(5, 7), SACM(5, 6)]) - ] + SAC(1, [SACM(5, 7), SACM(5, 6)]), + ], ) @test DT.get_small_angle_complexes(enricher) == _complexes DT.split_subcurve!(enricher, 1, 6, PT()) @@ -1336,8 +1342,8 @@ end _complexes = Dict( 1 => [ SAC(1, [SACM(1, 12), SACM(1, 13), SACM(2, 14), SACM(2, 15), SACM(3, 16), SACM(3, 17), SACM(4, 18), SACM(4, 19)]), - SAC(1, [SACM(5, 20), SACM(5, 21)]) - ] + SAC(1, [SACM(5, 20), SACM(5, 21)]), + ], ) @test DT.get_small_angle_complexes(enricher) == _complexes end @@ -1345,8 +1351,8 @@ end @testset "has_acute_neighbouring_angles and splitting small angles" begin A, B, C, D, E, F, G, H, I, J, K = (0.0, 0.0), (7.0, 0.0), (-0.2, 1.0), (1.0, 0.0), - (2.0, 0.0), (3.0, 0.0), (4.0, 0.0), (4.5, 0.5), (3.0, 0.8), - (1.6, 0.8), (0.4, 0.2) + (2.0, 0.0), (3.0, 0.0), (4.0, 0.0), (4.5, 0.5), (3.0, 0.8), + (1.6, 0.8), (0.4, 0.2) points = [E, F, G, B, H, I, C, A, D, E] boundary_nodes, points = convert_boundary_points_to_indices(points) enricher = DT.BoundaryEnricher(points, boundary_nodes) @@ -1410,19 +1416,19 @@ end curve_sets = [curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI, curve_XII] for (points, curve) in zip(point_sets, curve_sets) enricher = DT.BoundaryEnricher(deepcopy(points), deepcopy(curve)) - DT.enrich_boundary!(enricher; predicates=rt()) + DT.enrich_boundary!(enricher; predicates = rt()) @test all_diametral_circles_are_empty(enricher) == 1 @test allunique(get_points(enricher)) @test all_points_are_inside(enricher, points, curve) end A, B, C, D, E, F, G, H, I, J, K = (0.0, 0.0), (7.0, 0.0), (2.0, 1.0), (1.0, 0.0), - (2.0, 0.0), (3.0, 0.0), (4.0, 0.0), (4.5, 0.5), (3.0, 0.8), - (1.6, 0.8), (0.4, 0.2) + (2.0, 0.0), (3.0, 0.0), (4.0, 0.0), (4.5, 0.5), (3.0, 0.8), + (1.6, 0.8), (0.4, 0.2) points = [E, F, G, B, H, I, C, J, K, A, D, E] boundary_nodes, points = convert_boundary_points_to_indices(points) enricher = DT.BoundaryEnricher(points, boundary_nodes) - DT.enrich_boundary!(enricher; predicates=rt()) + DT.enrich_boundary!(enricher; predicates = rt()) @test all_diametral_circles_are_empty(enricher) == 1 @test all_points_are_inside(enricher, points, boundary_nodes) end @@ -1432,7 +1438,7 @@ end curve_sets = [curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI, curve_XII] for (points, curve) in zip(point_sets, curve_sets) enricher = DT.BoundaryEnricher(deepcopy(points), deepcopy(curve)) - DT.enrich_boundary!(enricher; predicates=rt()) + DT.enrich_boundary!(enricher; predicates = rt()) @test all_diametral_circles_are_empty(enricher) == 1 @test allunique(get_points(enricher)) @test all_points_are_inside(enricher, points, curve) @@ -1446,7 +1452,7 @@ end segment_sets = [segments_I, segments_II, segments_III, segments_IV] for i in eachindex(point_sets) enricher = DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i]), deepcopy(segment_sets[i])) - DT.enrich_boundary!(enricher; predicates=PT()) + DT.enrich_boundary!(enricher; predicates = PT()) @test all_diametral_circles_are_empty(enricher) == 1 @test allunique(get_points(enricher)) @test all_points_are_inside(enricher, point_sets[i], curve_sets[i]) @@ -1462,10 +1468,10 @@ end curve_sets = deepcopy.([curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI, curve_XII]) for i in eachindex(point_sets, curve_sets) points, curve = deepcopy(point_sets[i]), deepcopy(curve_sets[i]) - tri = triangulate(points; boundary_nodes=curve, enrich=i ≤ 3, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, enrich = i ≤ 3, predicates = PT()) @test validate_triangulation(tri) - @test is_conformal(tri; predicates=PT()) - @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i])), predicates=PT()) + @test is_conformal(tri; predicates = PT()) + @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i])), predicates = PT()) i > 3 && @test DT.is_curve_bounded(tri) i ≤ 3 && @test !DT.is_curve_bounded(tri) end @@ -1478,10 +1484,10 @@ end curve_sets = deepcopy.([curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI, curve_XII]) for i in eachindex(point_sets, curve_sets) points, curve = deepcopy(point_sets[i]), deepcopy(curve_sets[i]) - tri = triangulate(points; boundary_nodes=curve, enrich=i ≤ 3, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, enrich = i ≤ 3, predicates = PT()) @test validate_triangulation(tri) - @test is_conformal(tri; predicates=PT()) - i ∉ (2, 11) && @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i])), predicates=PT()) # i ≠ 2 since we deliberately included some boundary points in the extra points, which triangulate then sees and mutates + @test is_conformal(tri; predicates = PT()) + i ∉ (2, 11) && @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i])), predicates = PT()) # i ≠ 2 since we deliberately included some boundary points in the extra points, which triangulate then sees and mutates i > 3 && @test DT.is_curve_bounded(tri) i ≤ 3 && @test !DT.is_curve_bounded(tri) end @@ -1495,10 +1501,10 @@ end segment_sets = deepcopy.([segments_I, segments_II, segments_III, segments_IV]) for i in eachindex(point_sets, curve_sets, segment_sets) points, curve, segments = deepcopy(point_sets[i]), deepcopy(curve_sets[i]), deepcopy(segment_sets[i]) - tri = triangulate(points; boundary_nodes=curve, segments=segments, enrich=i ≤ 3, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, segments = segments, enrich = i ≤ 3, predicates = PT()) @test validate_triangulation(tri) - @test is_conformal(tri; predicates=PT()) - i ≠ 2 && @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i]), deepcopy(segment_sets[i])), predicates=PT()) + @test is_conformal(tri; predicates = PT()) + i ≠ 2 && @test DT.get_boundary_enricher(tri) == DT.enrich_boundary!(DT.BoundaryEnricher(deepcopy(point_sets[i]), deepcopy(curve_sets[i]), deepcopy(segment_sets[i])), predicates = PT()) i > 3 && @test DT.is_curve_bounded(tri) i ≤ 3 && @test !DT.is_curve_bounded(tri) end @@ -1514,52 +1520,54 @@ end point_sets = (point_sets_no_extra, point_sets_extra_points, point_sets_extra_segments) curve_sets = deepcopy.([curve_I, curve_II, curve_III, curve_IV, curve_V, curve_VI, curve_VII, curve_VIII, curve_IX, curve_X, curve_XI, curve_XII]) point_names = ("default", "extra_points", "extra_segments") - _rng_num(idx1, - idx2, idx3, idx4, idx5, curve_idx, point_idx) = 2^idx1 * 3^idx2 * 5^idx3 * 7^idx4 * 11^idx5 * 13^curve_idx * 17^point_idx + _rng_num( + idx1, + idx2, idx3, idx4, idx5, curve_idx, point_idx, + ) = 2^idx1 * 3^idx2 * 5^idx3 * 7^idx4 * 11^idx5 * 13^curve_idx * 17^point_idx @testset "all_examples" begin for PT in (DT.ExactKernel, DT.AdaptiveKernel) max_area_opts = [ - (1e-2, 1e-3), - (1e-2, 1e-3), - (1e-2, 1e-3), - (1e-2, 1e-3), - (1e-2, 1e-3), - (1e-1, 1e-2), - (1e-1, 1e-2), - (1e-1, 1e-2), - (1e-2, 1e-3), - (1e-1, 1e-2), - (1e-1, 1e-2), - (1e-1, 1e-2) + (1.0e-2, 1.0e-3), + (1.0e-2, 1.0e-3), + (1.0e-2, 1.0e-3), + (1.0e-2, 1.0e-3), + (1.0e-2, 1.0e-3), + (1.0e-1, 1.0e-2), + (1.0e-1, 1.0e-2), + (1.0e-1, 1.0e-2), + (1.0e-2, 1.0e-3), + (1.0e-1, 1.0e-2), + (1.0e-1, 1.0e-2), + (1.0e-1, 1.0e-2), ] for curve_idx in 4:lastindex(curve_sets) for point_idx in 1:3 point_idx == 3 && curve_idx ≥ 5 && continue # no extra segments for curves ≥ 5 for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((20.0, 27.5, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) + for (idx3, min_area) in enumerate((1.0e-12,)) for (idx4, max_area) in enumerate(max_area_opts[curve_idx]) for (idx5, seditious_angle) in enumerate((10.0, 20.0)) @info "Testing curve-bounded refinement with circumcenters. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle; curve: $curve_idx; point set: $point_idx" rng = StableRNG(abs(_rng_num(idx1, idx2, idx3, idx4, idx5, curve_idx, point_idx))) points, curve = deepcopy(point_sets[point_idx][curve_idx]), deepcopy(curve_sets[curve_idx]) if point_idx ≤ 2 - tri = triangulate(points; boundary_nodes=curve, enrich=curve_idx ≤ 3, rng, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, enrich = curve_idx ≤ 3, rng, predicates = PT()) else segments = deepcopy(segment_sets[curve_idx]) - tri = triangulate(points; boundary_nodes=curve, segments=segments, enrich=curve_idx ≤ 3, rng, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, segments = segments, enrich = curve_idx ≤ 3, rng, predicates = PT()) end custom_constraint = (_tri, T) -> curve_idx ≠ 5 ? false : begin - i, j, k = triangle_vertices(T) - p, q, r = get_point(_tri, i, j, k) - c = (p .+ q .+ r) ./ 3 - x, y = getxy(c) - return (x + y^2 < 1 / 4) && DT.triangle_area(p, q, r) > 1e-4 / 2 - end - refine!(tri; min_angle, min_area, max_area, custom_constraint, seditious_angle, use_circumcenter=true, use_lens, rng, predicates=PT()) - args = DT.RefinementArguments(tri; min_angle, min_area, max_area, seditious_angle, custom_constraint, use_circumcenter=true, use_lens, predicates=PT()) - @test validate_refinement(tri, args, warn=false) + i, j, k = triangle_vertices(T) + p, q, r = get_point(_tri, i, j, k) + c = (p .+ q .+ r) ./ 3 + x, y = getxy(c) + return (x + y^2 < 1 / 4) && DT.triangle_area(p, q, r) > 1.0e-4 / 2 + end + refine!(tri; min_angle, min_area, max_area, custom_constraint, seditious_angle, use_circumcenter = true, use_lens, rng, predicates = PT()) + args = DT.RefinementArguments(tri; min_angle, min_area, max_area, seditious_angle, custom_constraint, use_circumcenter = true, use_lens, predicates = PT()) + @test validate_refinement(tri, args, warn = false) if _rng_num(idx1, idx2, idx3, idx4, idx5, curve_idx, point_idx) == _rng_num(1, 3, 1, 2, 2, curve_idx, point_idx) fig, ax, sc = triplot(tri) @test_reference "refine_curve_bounded_example_$(curve_idx)_$(names[curve_idx])_$(point_names[point_idx])_$(abs(_rng_num(1, 3, 1, 2, 2, curve_idx, point_idx))).png" fig by = psnr_equality(7) @@ -1583,11 +1591,11 @@ end curve_idx = 12 point_idx = 2 points, curve = deepcopy(point_sets[point_idx][curve_idx]), deepcopy(curve_sets[curve_idx]) - tri = triangulate(points; boundary_nodes=curve, predicates=PT()) - refine!(tri; max_area=1e-3, max_points=500, use_circumcenter=true, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, predicates = PT()) + refine!(tri; max_area = 1.0e-3, max_points = 500, use_circumcenter = true, predicates = PT()) @test DT.num_solid_vertices(tri) == 500 @test validate_triangulation(tri) - @test !validate_refinement(tri; max_area=1e-3, max_points=500, use_circumcenter=true, warn=false) + @test !validate_refinement(tri; max_area = 1.0e-3, max_points = 500, use_circumcenter = true, warn = false) end end end @@ -1596,35 +1604,35 @@ end for PT in subtypes(DT.AbstractPredicateKernel) curve = [ [ - [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])] + [BezierCurve([(0.0, -2.0), (0.0, -2.5), (-1.0, -2.5), (-1.0, -3.0)])], [CatmullRomSpline([(-1.0, -3.0), (0.0, -4.0), (1.0, -3.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] rng = StableRNG(123) - tri = triangulate(points; boundary_nodes=curve, rng, predicates=PT()) - refine!(tri; max_area=1e-2, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + tri = triangulate(points; boundary_nodes = curve, rng, predicates = PT()) + refine!(tri; max_area = 1.0e-2, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) r = DT.num_points(tri) - add_point!(tri, -3 / 2, -4.0, concavity_protection=true, predicates=PT()) - add_point!(tri, -3 / 2, -1.0, concavity_protection=true, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_segment!(tri, r + 1, r + 2, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + add_point!(tri, -3 / 2, -4.0, concavity_protection = true, predicates = PT()) + add_point!(tri, -3 / 2, -1.0, concavity_protection = true, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_segment!(tri, r + 1, r + 2, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) @test tri.boundary_enricher.segments ∈ (Set(((r + 1, r + 2),)), Set(((r + 2, r + 1),))) end -end \ No newline at end of file +end diff --git a/test/refinement/refine.jl b/test/refinement/refine.jl index 3f1240241..75b96b7c5 100644 --- a/test/refinement/refine.jl +++ b/test/refinement/refine.jl @@ -34,10 +34,10 @@ const pT = (1, 2, 3) end @testset "Setting some values" begin - constraints = DT.RefinementConstraints(min_area=1e-9, max_area=13.7, max_points=505, seditious_angle=60.0) + constraints = DT.RefinementConstraints(min_area = 1.0e-9, max_area = 13.7, max_points = 505, seditious_angle = 60.0) @test constraints.min_angle == 0.0 @test constraints.max_angle == 180.0 - @test constraints.min_area == 1e-9 + @test constraints.min_area == 1.0e-9 @test constraints.max_area == 13.7 @test constraints.max_radius_edge_ratio == Inf @test constraints.max_points == 505 @@ -48,8 +48,8 @@ const pT = (1, 2, 3) end @testset "Constraints and setting min_angle" begin - constraints = DT.RefinementConstraints(min_angle=30.0, custom_constraint=(tri, T) -> T == (1, 2, 3)) - @inferred DT.RefinementConstraints(min_angle=30.0, custom_constraint=(tri, T) -> T == (1, 2, 3)) + constraints = DT.RefinementConstraints(min_angle = 30.0, custom_constraint = (tri, T) -> T == (1, 2, 3)) + @inferred DT.RefinementConstraints(min_angle = 30.0, custom_constraint = (tri, T) -> T == (1, 2, 3)) @test constraints.min_angle == 30.0 @test constraints.max_angle == 180.0 @test constraints.min_area == 0.0 @@ -65,10 +65,10 @@ const pT = (1, 2, 3) end @testset "Setting a maximum angle constraint and a non-30 min_angle" begin - constraints = DT.RefinementConstraints(max_angle=179.9, min_angle=27.59, min_area=1e-9) + constraints = DT.RefinementConstraints(max_angle = 179.9, min_angle = 27.59, min_area = 1.0e-9) @test constraints.min_angle == 27.59 @test constraints.max_angle == 179.9 - @test constraints.min_area == 1e-9 + @test constraints.min_area == 1.0e-9 @test constraints.max_area == Inf @test constraints.max_radius_edge_ratio == cscd(27.59) / 2 @test constraints.max_points == typemax(Int) @@ -81,19 +81,19 @@ const pT = (1, 2, 3) end @testset verbose = true "RefinementQueue" begin - T = NTuple{3,Int} - E = NTuple{2,Int} + T = NTuple{3, Int} + E = NTuple{2, Int} F = Float64 @testset "Initialisation" begin - queue1 = DT.RefinementQueue{T,E,F}() + queue1 = DT.RefinementQueue{T, E, F}() queue2 = DT.RefinementQueue(ptri) @inferred DT.RefinementQueue(ptri) for queue in (queue1, queue2) - @test queue.segments == DT.MaxPriorityQueue{E,F}() - @test typeof(queue.segments) == DT.MaxPriorityQueue{E,F} - @test queue.triangles == DT.MaxPriorityQueue{T,F}() - @test typeof(queue.triangles) == DT.MaxPriorityQueue{T,F} + @test queue.segments == DT.MaxPriorityQueue{E, F}() + @test typeof(queue.segments) == DT.MaxPriorityQueue{E, F} + @test queue.triangles == DT.MaxPriorityQueue{T, F}() + @test typeof(queue.triangles) == DT.MaxPriorityQueue{T, F} @test isempty(queue.segments) @test isempty(queue.triangles) @test !DT.has_segments(queue) @@ -119,16 +119,17 @@ end queue[(27, 25)] = 150.0 queue[(17, 13)] = 23.5 queue[(13, 17)] = 109.591 - @test queue.segments == PriorityQueue(Base.Order.Reverse, + @test queue.segments == PriorityQueue( + Base.Order.Reverse, (1, 2) => 1.0, (5, 7) => 5.6, (10, 3) => 1.881, (11, 12) => 0.0, (27, 25) => 150.0, - (17, 13) => 109.591 + (17, 13) => 109.591, ) @test sprint(show, MIME"text/plain"(), queue) == "RefinementQueue\n 6 segments: DelaunayTriangulation.MaxPriorityQueue((27, 25) => 150.0, (17, 13) => 109.591, (5, 7) => 5.6, (10, 3) => 1.881, (1, 2) => 1.0, (11, 12) => 0.0)\n 0 triangles: DelaunayTriangulation.MaxPriorityQueue{Tuple{Int64, Int64, Int64}, Float64}()" - res = Pair{NTuple{2,Int},Float64}[] + res = Pair{NTuple{2, Int}, Float64}[] while DT.has_segments(queue) push!(res, DT.popfirst_segment!(queue)) end @@ -138,7 +139,7 @@ end (5, 7) => 5.6, (10, 3) => 1.881, (1, 2) => 1.0, - (11, 12) => 0.0 + (11, 12) => 0.0, ] @test isempty(queue) @test !DT.has_segments(queue) @@ -158,15 +159,16 @@ end queue[(7, 9, 5)] = 18.375 queue[(10, 15, 20)] = 0.0 queue[(10, 17, 21)] = 13818.5 - @test queue.triangles == PriorityQueue(Base.Order.Reverse, + @test queue.triangles == PriorityQueue( + Base.Order.Reverse, (1, 2, 3) => 1.0, (5, 7, 9) => 18.375, (10, 3, 4) => 1.881, (10, 17, 21) => 13818.5, - (10, 15, 20) => 0.0 + (10, 15, 20) => 0.0, ) @test sprint(show, MIME"text/plain"(), queue) == "RefinementQueue\n 0 segments: DelaunayTriangulation.MaxPriorityQueue{Tuple{Int64, Int64}, Float64}()\n 5 triangles: DelaunayTriangulation.MaxPriorityQueue((10, 17, 21) => 13818.5, (5, 7, 9) => 18.375, (10, 3, 4) => 1.881, (1, 2, 3) => 1.0, (10, 15, 20) => 0.0)" - res = Pair{NTuple{3,Int},Float64}[] + res = Pair{NTuple{3, Int}, Float64}[] while DT.has_triangles(queue) push!(res, DT.popfirst_triangle!(queue)) end @@ -175,7 +177,7 @@ end (5, 7, 9) => 18.375, (10, 3, 4) => 1.881, (1, 2, 3) => 1.0, - (10, 15, 20) => 0.0 + (10, 15, 20) => 0.0, ] @test isempty(queue) @test !DT.has_triangles(queue) @@ -183,8 +185,8 @@ end @testset "Pushing and popping both segments and triangles / haskey" begin queue = DT.RefinementQueue(ptri) - true_triangle_queue = PriorityQueue{NTuple{3,Int},Float64}(Base.Order.Reverse) - true_segment_queue = PriorityQueue{NTuple{2,Int},Float64}(Base.Order.Reverse) + true_triangle_queue = PriorityQueue{NTuple{3, Int}, Float64}(Base.Order.Reverse) + true_segment_queue = PriorityQueue{NTuple{2, Int}, Float64}(Base.Order.Reverse) for T in each_solid_triangle(ptri) _i, _j, _k = triangle_vertices(T) ρ = DT.triangle_radius_edge_ratio(get_point(ptri, T...)...) @@ -225,10 +227,10 @@ end @test !isempty(queue) @test DT.has_segments(queue) @test DT.has_triangles(queue) - triangle_res = Pair{NTuple{3,Int},Float64}[] - segment_res = Pair{NTuple{2,Int},Float64}[] - true_triangle_res = Pair{NTuple{3,Int},Float64}[] - true_segment_res = Pair{NTuple{2,Int},Float64}[] + triangle_res = Pair{NTuple{3, Int}, Float64}[] + segment_res = Pair{NTuple{2, Int}, Float64}[] + true_triangle_res = Pair{NTuple{3, Int}, Float64}[] + true_segment_res = Pair{NTuple{2, Int}, Float64}[] for i in 1:length(true_triangle_queue) T, ρ = DT.popfirst_triangle!(queue) push!(triangle_res, DT.sort_triangle(T) => ρ) @@ -253,8 +255,8 @@ end @testset verbose = true "InsertionEventHistory" begin @testset "Initialisation" begin - T = NTuple{3,Int} - E = NTuple{2,Int} + T = NTuple{3, Int} + E = NTuple{2, Int} F = Float64 history = DT.InsertionEventHistory(ptri) @inferred DT.InsertionEventHistory(ptri) @@ -268,8 +270,8 @@ end end @testset "Mutating" begin - T = NTuple{3,Int} - E = NTuple{2,Int} + T = NTuple{3, Int} + E = NTuple{2, Int} F = Float64 history = DT.InsertionEventHistory(ptri) @test !DT.has_segment_changes(history) @@ -306,11 +308,11 @@ end @testset "Adding some points inside" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; randomise=false) + tri = triangulate(points; randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = 0.9, 0.9 - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) @test DT.compare_triangle_collections(history.added_triangles, Set([(2, 3, 5), (5, 3, 4), (1, 5, 4), (1, 2, 5)])) @test DT.compare_triangle_collections(history.deleted_triangles, Set([(1, 2, 3), (1, 3, 4)])) @test !DT.has_segment_changes(history) @@ -322,12 +324,12 @@ end validate_insertion_event_history(tri, orig_tri, history) DT.undo_insertion!(tri, history) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) new_points = [(0.5, 0.5), (0.2, 0.2), (0.5, 0.75), (0.236, 0.987)] for (x, y) in new_points empty!(history) - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) @test tri ≠ orig_tri # make sure == isn't lying for later validate_insertion_event_history(tri, orig_tri, history) @test !DT.has_segment_changes(history) @@ -335,14 +337,14 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) end - @test tri == triangulate(points; randomise=false) + @test tri == triangulate(points; randomise = false) new_points = [Tuple(rand(2)) for _ in 1:100] for (x, y) in new_points empty!(history) - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) @test tri ≠ orig_tri # make sure == isn't lying for later validate_insertion_event_history(tri, orig_tri, history) @test !DT.has_segment_changes(history) @@ -350,21 +352,21 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) end - @test tri == triangulate(points; randomise=false) + @test tri == triangulate(points; randomise = false) end end @testset "Testing how add_point! handles segments" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.5, 0.0), (0.5, 1.0)] - tri = triangulate(points; segments=Set(((5, 6),)), randomise=false) + tri = triangulate(points; segments = Set(((5, 6),)), randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = 0.5, 0.5 - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) @test DT.compare_triangle_collections(history.added_triangles, Set([(1, 5, 7), (7, 5, 2), (7, 2, 3), (6, 7, 3), (4, 7, 6), (4, 1, 7)])) @test DT.compare_triangle_collections(history.deleted_triangles, Set([(1, 5, 4), (5, 2, 3), (5, 3, 6), (4, 5, 6)])) @test DT.compare_unoriented_edge_collections(history.added_segments, Set([(5, 7), (7, 6)])) @@ -376,14 +378,14 @@ end validate_insertion_event_history(tri, orig_tri, history) DT.undo_insertion!(tri, history) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) new_points = LinRange(0.0001, 0.9999, 25) |> collect setdiff!(new_points, 0.5) x = 0.5 for y in new_points empty!(history) - add_point!(tri, x, y, store_event_history=Val(true), event_history=history) + add_point!(tri, x, y, store_event_history = Val(true), event_history = history) @test tri ≠ orig_tri # make sure == isn't lying for later validate_insertion_event_history(tri, orig_tri, history) @test DT.has_segment_changes(history) @@ -391,7 +393,7 @@ end @test tri == orig_tri validate_statistics(tri) @test validate_triangulation(tri) - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) end end @@ -401,12 +403,12 @@ end for PT in (DT.ExactKernel, DT.AdaptiveKernel) for _ in 1:5 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], randomise=false, predicates=PT()) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], randomise = false, predicates = PT()) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = 0.5, 0.0 - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) @test DT.compare_triangle_collections(history.added_triangles, Set([(1, 5, 4), (5, 2, 3), (4, 5, 3), (5, 1, -1), (2, 5, -1)])) @test DT.compare_triangle_collections(history.deleted_triangles, Set([(1, 2, 3), (1, 3, 4), (2, 1, -1)])) @test isempty(history.added_segments) @@ -420,7 +422,7 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history, predicates=PT()) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history, predicates = PT()) orig_tri = deepcopy(tri) new_points = LinRange(0.0001, 0.9999, 10) |> collect setdiff!(new_points, 0.5) @@ -428,7 +430,7 @@ end for r in new_points for p in ((r, 0.0), (1.0, r), (r, 1.0), (0.0, r)) empty!(history) - add_point!(tri, p, store_event_history=Val(true), event_history=history, predicates=PT()) + add_point!(tri, p, store_event_history = Val(true), event_history = history, predicates = PT()) @test tri ≠ orig_tri # make sure == isn't lying for later validate_insertion_event_history(tri, orig_tri, history) @test DT.has_segment_changes(history) @@ -438,7 +440,7 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, p, store_event_history=Val(true), event_history=history, predicates=PT()) + add_point!(tri, p, store_event_history = Val(true), event_history = history, predicates = PT()) orig_tri = deepcopy(tri) end end @@ -450,11 +452,11 @@ end for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.3, 0.3), (0.7, 0.3), (0.5, 0.7)] boundary_nodes = [[[1, 2], [2, 3], [3, 4], [4, 1]], [[5, 7], [7, 6], [6, 5]]] - tri = triangulate(points; boundary_nodes, randomise=false) + tri = triangulate(points; boundary_nodes, randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = (0.5, 0.3) - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) @test validate_triangulation(tri) @test DT.compare_triangle_collections(history.added_triangles, Set([(1, 8, 5), (1, 2, 8), (8, 2, 6), (8, 6, -7), (5, 8, -7)])) @test DT.compare_triangle_collections(history.deleted_triangles, Set([(1, 6, 5), (1, 2, 6), (5, 6, -7)])) @@ -469,7 +471,7 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, (x, y), store_event_history=Val(true), event_history=history) + add_point!(tri, (x, y), store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) new_points = LinRange(0.31, 0.69, 15) |> collect @test validate_triangulation(tri) @@ -477,7 +479,7 @@ end for r in new_points for p in ((r, 0.3), (r, 0.0)) empty!(history) - add_point!(tri, p, store_event_history=Val(true), event_history=history) + add_point!(tri, p, store_event_history = Val(true), event_history = history) @test tri ≠ orig_tri # make sure == isn't lying for later validate_insertion_event_history(tri, orig_tri, history) @test DT.has_segment_changes(history) @@ -487,7 +489,7 @@ end validate_statistics(tri) @test validate_triangulation(tri) @test tri == orig_tri - add_point!(tri, p, store_event_history=Val(true), event_history=history) + add_point!(tri, p, store_event_history = Val(true), event_history = history) orig_tri = deepcopy(tri) end end @@ -497,7 +499,7 @@ end @testset "Testing how split_edge! is handled on non-segments" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.25, 0.25), (0.75, 0.75)] - tri = triangulate(points; randomise=false) + tri = triangulate(points; randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = (0.5, 0.5) @@ -546,7 +548,7 @@ end @testset "Testing how split_edge! is handled on segments" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; randomise=false, segments=Set([(1, 3)])) + tri = triangulate(points; randomise = false, segments = Set([(1, 3)])) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = (0.5, 0.5) @@ -595,7 +597,7 @@ end @testset "Testing how split_edge! is handled on boundary segments" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], randomise=false) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) x, y = (0.5, 0.0) @@ -645,7 +647,7 @@ end @testset "Testing how flip_edge! is handled" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; randomise=false) + tri = triangulate(points; randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) flip_edge!(tri, 1, 3, Val(true), history) @@ -668,7 +670,7 @@ end @testset "Testing how complete_split_edge_and_legalise! is handled for non-segments" begin for _ in 1:100 points = [(0.01, 0.0), (0.99, 0.00027), (1.0, 1.00025), (0.0, 0.994)] - tri = triangulate(points; randomise=false) + tri = triangulate(points; randomise = false) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) push!(points, (0.5, 0.5)) @@ -712,14 +714,14 @@ end DT.complete_split_edge_and_legalise!(tri, DT.num_points(tri) - 1, 3, DT.num_points(tri), Val(true), history) orig_tri = deepcopy(tri) end - @test tri == triangulate(points; randomise=false) + @test tri == triangulate(points; randomise = false) end end @testset "Testing how complete_split_edge_and_legalise! is handled for segments" begin for _ in 1:10 points = [(0.01, 0.0), (0.99, 0.00027), (1.0, 1.00025), (0.0, 0.994), (0.5, 0.1), (0.5, 0.9)] - tri = triangulate(points; randomise=false, segments=Set([(5, 6)])) + tri = triangulate(points; randomise = false, segments = Set([(5, 6)])) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) push!(points, (0.5, 0.5)) @@ -767,7 +769,7 @@ end @testset "Testing how complete_split_edge_and_legalise! is handled for boundary segments" begin for _ in 1:10 points = [(0.01, 0.0), (0.99, 0.00027), (1.0, 1.00025), (0.0, 0.994), (0.5, 0.1), (0.5, 0.9)] - tri = triangulate(points; randomise=false, boundary_nodes=[1, 2, 3, 4, 1]) + tri = triangulate(points; randomise = false, boundary_nodes = [1, 2, 3, 4, 1]) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) push!(points, (0.1, 0.0)) @@ -810,7 +812,7 @@ end orig_tri = deepcopy(tri) end convex_hull!(tri) - @test tri == triangulate(points; randomise=false, boundary_nodes=tri.boundary_nodes) + @test tri == triangulate(points; randomise = false, boundary_nodes = tri.boundary_nodes) end end @@ -820,7 +822,7 @@ end tri = triangulate(points) orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) - delete_point!(tri, 5, store_event_history=Val(true), event_history=history) + delete_point!(tri, 5, store_event_history = Val(true), event_history = history) validate_insertion_event_history(tri, orig_tri, history) DT.undo_insertion!(tri, history, Val(false)) validate_statistics(tri) @@ -840,7 +842,7 @@ end end orig_tri = deepcopy(tri) history = DT.InsertionEventHistory(tri) - delete_point!(tri, i, rng=rng, store_event_history=Val(true), event_history=history) + delete_point!(tri, i, rng = rng, store_event_history = Val(true), event_history = history) @test validate_triangulation(tri) validate_insertion_event_history(tri, orig_tri, history) DT.undo_insertion!(tri, history, Val(false)) @@ -857,7 +859,7 @@ end p4 = (1.0, 1.0) pts = [p1, p2, p3, p4] rng = StableRNG(123) - tri = triangulate(pts; boundary_nodes=[1, 2, 4, 3, 1], rng, delete_ghosts=false) + tri = triangulate(pts; boundary_nodes = [1, 2, 4, 3, 1], rng, delete_ghosts = false) _tri = deepcopy(tri) push!(pts, (0.5, 0.5)) events = DT.InsertionEventHistory(tri) @@ -900,7 +902,7 @@ end @inferred DT.RefinementArguments(tri) @test args.constraints.min_angle == 30.0 @test args.constraints.max_angle == 180.0 - @test args.constraints.min_area == get_area(tri) / 1e9 + @test args.constraints.min_area == get_area(tri) / 1.0e9 @test args.constraints.max_area == Inf @test args.constraints.max_points == 1000^2 @test args.constraints.seditious_angle == 20.0 @@ -916,11 +918,11 @@ end @test DT.has_ghost_triangles(tri) @test DT.has_boundary_nodes(tri) # convex hull @test args.min_steiner_vertex == 51 - segment_list = Set{NTuple{2,Int}}() + segment_list = Set{NTuple{2, Int}}() segment_vertices = Set{Int}() - for i in 1:(length(tri.convex_hull.vertices)-1) + for i in 1:(length(tri.convex_hull.vertices) - 1) u = tri.convex_hull.vertices[i] - v = tri.convex_hull.vertices[i+1] + v = tri.convex_hull.vertices[i + 1] push!(segment_list, (u, v)) push!(segment_vertices, u, v) @test !DT.is_subsegment(args, (u, v)) && !DT.is_subsegment(args, (v, u)) @@ -936,19 +938,20 @@ end @testset "Setting values" begin tri = triangulate(rand(2, 50)) - args = DT.RefinementArguments(tri; - min_angle=30.5, - max_angle=90.5, - min_area=0.2, - max_area=0.9, - max_points=573, - custom_constraint=(tri, T) -> T == (1, 2, 3), - use_circumcenter=true, - use_lens=false, - steiner_scale=0.95, - seditious_angle=25.3, - rng=StableRNG(123), - concavity_protection=true + args = DT.RefinementArguments( + tri; + min_angle = 30.5, + max_angle = 90.5, + min_area = 0.2, + max_area = 0.9, + max_points = 573, + custom_constraint = (tri, T) -> T == (1, 2, 3), + use_circumcenter = true, + use_lens = false, + steiner_scale = 0.95, + seditious_angle = 25.3, + rng = StableRNG(123), + concavity_protection = true, ) @test args.constraints.min_angle == 30.5 @test args.constraints.max_angle == 90.5 @@ -969,11 +972,11 @@ end @test DT.has_ghost_triangles(tri) @test DT.has_boundary_nodes(tri) # convex hull @test args.min_steiner_vertex == 51 - segment_list = Set{NTuple{2,Int}}() + segment_list = Set{NTuple{2, Int}}() segment_vertices = Set{Int}() - for i in 1:(length(tri.convex_hull.vertices)-1) + for i in 1:(length(tri.convex_hull.vertices) - 1) u = tri.convex_hull.vertices[i] - v = tri.convex_hull.vertices[i+1] + v = tri.convex_hull.vertices[i + 1] push!(segment_list, (u, v)) push!(segment_vertices, u, v) @test !DT.is_subsegment(args, (u, v)) && !DT.is_subsegment(args, (v, u)) @@ -984,28 +987,29 @@ end @test args.midpoint_split_list ⊢ Set{Int}() @test args.offcenter_split_list ⊢ Set{Int}() @test args.concavity_protection - @inferred DT.RefinementArguments(tri; - min_angle=30.5, - max_angle=90.5, - min_area=0.2, - max_area=0.9, - max_points=573, - custom_constraint=(tri, T) -> T == (1, 2, 3), - use_circumcenter=true, - use_lens=false, - steiner_scale=0.95, - rng=StableRNG(123), - concavity_protection=true + @inferred DT.RefinementArguments( + tri; + min_angle = 30.5, + max_angle = 90.5, + min_area = 0.2, + max_area = 0.9, + max_points = 573, + custom_constraint = (tri, T) -> T == (1, 2, 3), + use_circumcenter = true, + use_lens = false, + steiner_scale = 0.95, + rng = StableRNG(123), + concavity_protection = true, ) end @testset "Adding ghost triangles" begin points = rand(2, 50) - tri = triangulate(points, delete_ghosts=true) + tri = triangulate(points, delete_ghosts = true) args = DT.RefinementArguments(tri) @test !args.had_ghosts @test DT.has_ghost_triangles(tri) - @test tri == triangulate(points, delete_ghosts=false, boundary_nodes=tri.convex_hull.vertices) + @test tri == triangulate(points, delete_ghosts = false, boundary_nodes = tri.convex_hull.vertices) end @testset "Checking free vertices" begin @@ -1035,7 +1039,7 @@ end @testset "Iteration" begin tri = triangulate([(rand(), rand()) for _ in 1:50]) - args = DT.RefinementArguments(tri; max_points=55) + args = DT.RefinementArguments(tri; max_points = 55) DT.unlock_convex_hull!(tri) # if the random points later are added outside the domain, they don't always get added as a vertex @test !DT.keep_iterating(tri, args) args.queue[(1, 2, 3)] = 1.0 @@ -1069,12 +1073,12 @@ end @testset verbose = true "is_encroached/encroaches_upon" begin @testset "Testing if point is in diametral circle" begin - args1 = DT.RefinementArguments(ptri; use_lens=false) - @inferred DT.RefinementArguments(ptri; use_lens=false) - args2 = DT.RefinementArguments(ptri; use_lens=true, min_angle=45.0) - p = Vector{NTuple{2,Float64}}(undef, 7) - q = Vector{NTuple{2,Float64}}(undef, 7) - r = Vector{NTuple{2,Float64}}(undef, 7) + args1 = DT.RefinementArguments(ptri; use_lens = false) + @inferred DT.RefinementArguments(ptri; use_lens = false) + args2 = DT.RefinementArguments(ptri; use_lens = true, min_angle = 45.0) + p = Vector{NTuple{2, Float64}}(undef, 7) + q = Vector{NTuple{2, Float64}}(undef, 7) + r = Vector{NTuple{2, Float64}}(undef, 7) p[1], q[1], r[1] = (2.6, 1.63), (5.68, 1.37), (4.5, 4.63) p[2], q[2], r[2] = p[1], q[1], (4.18, 1.96) @@ -1109,10 +1113,10 @@ end end @testset "Testing if a point is in a diametral lens" begin - args = DT.RefinementArguments(ptri; use_lens=true, min_angle=30.0) + args = DT.RefinementArguments(ptri; use_lens = true, min_angle = 30.0) p = (-7.0, 4.0) q = (-2.0, 4.0) - points = Vector{Tuple{NTuple{2,Float64},Function}}(undef, 0) + points = Vector{Tuple{NTuple{2, Float64}, Function}}(undef, 0) push!(points, ((-5.5, 5.0), DT.is_inside)) push!(points, ((-4.0, 4.5), DT.is_inside)) push!(points, ((-5.0, 4.5), DT.is_inside)) @@ -1143,25 +1147,25 @@ end p, q = (-7.0, 4.0), (-2.0, 4.0) upper_circle, lower_circle, circle = compute_diametral_circle(p, q) points_in_diametral_circle, points_outside_diametral_circle = get_points_in_diametral_circle(p, q) - fig = Figure(fontsize=43) - ax = Axis(fig[1, 1], width=600, height=600, title="Diametral circle", titlealign=:left) - scatter!(ax, points_in_diametral_circle, markersize=4, color=:blue) - scatter!(ax, points_outside_diametral_circle, markersize=4, color=:red) + fig = Figure(fontsize = 43) + ax = Axis(fig[1, 1], width = 600, height = 600, title = "Diametral circle", titlealign = :left) + scatter!(ax, points_in_diametral_circle, markersize = 4, color = :blue) + scatter!(ax, points_outside_diametral_circle, markersize = 4, color = :red) #band!(ax, lower_circle, upper_circle, color=(:green, 0.4)) - lines!(ax, circle, color=:black, linewidth=7) - lines!(ax, [p, q], color=:black, linewidth=7) + lines!(ax, circle, color = :black, linewidth = 7) + lines!(ax, [p, q], color = :black, linewidth = 7) xlims!(ax, -7.5, -1.5) ylims!(ax, 1, 7) for (i, lens_angle) in enumerate((45.0, 30.0, 20.0, 10.0)) upper_lens, lower_lens, lens = compute_diametral_lens(p, q, lens_angle) points_in_diametral_lens, points_outside_diametral_lens = get_points_in_diametral_lens(p, q, lens_angle) - ax = Axis(fig[1, 1+i], width=600, height=600, title="Diametral lens (angle $(lens_angle)°)", titlealign=:left) - scatter!(ax, points_in_diametral_lens, markersize=4, color=:blue) - scatter!(ax, points_outside_diametral_lens, markersize=4, color=(:red, 0.1)) + ax = Axis(fig[1, 1 + i], width = 600, height = 600, title = "Diametral lens (angle $(lens_angle)°)", titlealign = :left) + scatter!(ax, points_in_diametral_lens, markersize = 4, color = :blue) + scatter!(ax, points_outside_diametral_lens, markersize = 4, color = (:red, 0.1)) #band!(ax, lower_lens, upper_lens, color=(:green, 0.4)) - lines!(ax, lens, color=:black, linewidth=7) - lines!(ax, [p, q], color=:black, linewidth=7) + lines!(ax, lens, color = :black, linewidth = 7) + lines!(ax, [p, q], color = :black, linewidth = 7) xlims!(ax, -7.5, -1.5) ylims!(ax, 1, 7) end @@ -1175,25 +1179,25 @@ end x = _x y = _y boundary_nodes, points = convert_boundary_points_to_indices(x, y) - tri_1 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_1 = triangulate(points; boundary_nodes, delete_ghosts = false) boundary_nodes, points = convert_boundary_points_to_indices(x[1], y[1]) - tri_2 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_2 = triangulate(points; boundary_nodes, delete_ghosts = false) boundary_nodes, points = convert_boundary_points_to_indices([0.0, 2.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 2.0, 0.0]) - tri_3 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_3 = triangulate(points; boundary_nodes, delete_ghosts = false) boundary_nodes, points = convert_boundary_points_to_indices(reverse(reverse.(x[2])), reverse(reverse.(y[2]))) - tri_4 = triangulate(points; boundary_nodes, delete_ghosts=false) + tri_4 = triangulate(points; boundary_nodes, delete_ghosts = false) a, b = 0.0, 5.0 c, d = 3.0, 7.0 nx = 3 ny = 3 - tri_5 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=false) - tri_6 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true) + tri_5 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = false) + tri_6 = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true) @static if VERSION ≥ v"1.10" @inferred triangulate(rand(2, 250)) end for (iii, tri) in enumerate((tri_1, tri_2, tri_3, tri_4, tri_5, tri_6)) @info "Testing if encroached edges are detected. Run: $iii." - args = DT.RefinementArguments(tri; use_lens=false) + args = DT.RefinementArguments(tri; use_lens = false) in_dt_encroached_edges, not_in_dt_encroached_edges = slow_encroachment_test(tri) all_bn = DT.get_all_boundary_nodes(tri) for (e, (b, k)) in not_in_dt_encroached_edges @@ -1218,7 +1222,7 @@ end all_bn = DT.get_all_boundary_nodes(tri) for (lens_angle, not_in_dt_encroached_edges) in zip((45.0, 30.0, 20.0), (not_in_dt_encroached_edges_lens_45, not_in_dt_encroached_edges_lens_30, not_in_dt_encroached_edges_lens_20)) @info "Testing encroached edge detection. lens angle: $lens_angle" - args = DT.RefinementArguments(tri; use_lens=true, min_angle=lens_angle) + args = DT.RefinementArguments(tri; use_lens = true, min_angle = lens_angle) for (e, (b, k)) in not_in_dt_encroached_edges if DT.initial(e) ∈ all_bn && DT.terminal(e) ∈ all_bn && !DT.contains_segment(tri, e) # e.g. if an edge crosses an interior continue @@ -1231,7 +1235,7 @@ end end end for (lens_angle, in_dt_encroached_edges) in zip((45.0, 30.0, 20.0), (in_dt_encroached_edges_lens_45, in_dt_encroached_edges_lens_30, in_dt_encroached_edges_lens_20)) - args = DT.RefinementArguments(tri; use_lens=true, min_angle=lens_angle) + args = DT.RefinementArguments(tri; use_lens = true, min_angle = lens_angle) for (e, (b, k)) in in_dt_encroached_edges if DT.initial(e) ∈ all_bn && DT.terminal(e) ∈ all_bn && !DT.contains_segment(tri, e) continue @@ -1327,7 +1331,7 @@ end @testset "segment_vertices_adjoin_other_segments_at_acute_angle/compute_split_position" begin for _ in 1:10 points = [(-10.0, -10.0), (10.0, -10.0), (10.0, 10.0), (-10.0, 10.0), (0.05717272721, 0.00000001), (0.99988881, -0.000000998881)] # don't use (0, 1), else the split positions are all 1/2 since 1/2 is a power of 2 split - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([(5, 6)])) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([(5, 6)])) args = DT.RefinementArguments(tri) e = (5, 6) # if e = (6, 5) instead, we would need to be sure that t3 below is replaced by 1 - t3, since we always compute relative to the least vertex. See the comment in compute_split_position. adde! = args -> push!(args.segment_list, e) @@ -1447,7 +1451,7 @@ end one_test(tri, args, p, q, e, m2_q) _points = [(0.0, 0.0), (9.0, 0.0), (9.0, 7.0)] - _tri = triangulate(_points; segments=Set([(1, 2), (1, 3)])) + _tri = triangulate(_points; segments = Set([(1, 2), (1, 3)])) @test DT.segment_vertices_adjoin_other_segments_at_acute_angle(_tri, (1, 2)) == (1, 1) @test DT.segment_vertices_adjoin_other_segments_at_acute_angle(_tri, (1, 3)) == (1, 1) @@ -1507,7 +1511,7 @@ end for _ in 1:10 points = [(-2.0, -2.0), (2.0, -2.0), (2.0, 2.0), (-2.0, 2.0), (-1.1, 0.0), (1.1, 0.0)] orig_points = copy(points) - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([(5, 6)])) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([(5, 6)])) orig_tri = deepcopy(tri) args = DT.RefinementArguments(tri) e = (5, 6) @@ -1515,7 +1519,7 @@ end # just a normal split @test DT.is_free(args, 7) DT.split_subsegment!(tri, args, e) - @test tri == triangulate([orig_points; (0.0, 0.0)]; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([(5, 7), (7, 6)])) + @test tri == triangulate([orig_points; (0.0, 0.0)]; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([(5, 7), (7, 6)])) @test DT.is_midpoint_split(args, 7) @test !DT.is_midpoint_split(args, 6) && !DT.is_midpoint_split(args, 5) @test get_point(tri, 7) == (0.0, 0.0) @@ -1531,7 +1535,7 @@ end orig_points = copy(orig_tri.points) DT.split_subsegment!(tri, args, (8, 7)) @test !DT.is_free(args, 9) - @test tri == triangulate([orig_points; (-0.275, 0.0)]; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([(8, 7), (7, 6), (5, 8)])) + @test tri == triangulate([orig_points; (-0.275, 0.0)]; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([(8, 7), (7, 6), (5, 8)])) @test args.midpoint_split_list ⊢ Set([7, 8, 9]) @test get_point(tri, 9) == (-0.275, 0.0) validate_insertion_event_history(tri, orig_tri, args.events) @@ -1551,13 +1555,13 @@ end @test !DT.is_free(args, 12) @test collect(get_point(tri, 11)) ≈ [-0.825, 0.0] @test collect(get_point(tri, 12)) ≈ [-0.4125, 0.0] - @test tri == triangulate([orig_points; get_point(tri, 12)]; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([get_interior_segments(tri)..., (8, 9)])) + @test tri == triangulate([orig_points; get_point(tri, 12)]; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([get_interior_segments(tri)..., (8, 9)])) @test args.midpoint_split_list ⊢ Set([7, 8, 9, 11, 12]) validate_insertion_event_history(tri, orig_tri, args.events) # a small-input angle points = [(0.0, 0.0), (9.0, 0.0), (9.0, 7.0)] - tri = triangulate(points; segments=Set([(1, 2), (1, 3)])) + tri = triangulate(points; segments = Set([(1, 2), (1, 3)])) args = DT.RefinementArguments(tri) orig_tri = deepcopy(tri) orig_points = copy(orig_tri.points) @@ -1597,14 +1601,14 @@ end @test !DT.encroaches_upon(get_point(tri, 1), get_point(tri, 8), get_point(tri, 9), args) # edges aligned on the same concentric circular shell should not encroach upon one another @test !DT.encroaches_upon(get_point(tri, 1), get_point(tri, 9), get_point(tri, 8), args) # edges aligned on the same concentric circular shell should not encroach upon one another @test validate_triangulation(tri) - DT.unlock_convex_hull!(tri; reconstruct=true) + DT.unlock_convex_hull!(tri; reconstruct = true) @test validate_triangulation(tri) # a small-input angle: Same as above, but flipped along vertical axis points = [(0.0, 0.0), (7.0, 0.0), (0.0, 7.0)] - tri = triangulate(points; segments=Set([(1, 2), (2, 3)])) + tri = triangulate(points; segments = Set([(1, 2), (2, 3)])) args = DT.RefinementArguments(tri) - unlock_convex_hull!(tri; reconstruct=true) # so that (1, 3) is not a segment + unlock_convex_hull!(tri; reconstruct = true) # so that (1, 3) is not a segment DT.split_subsegment!(tri, args, (2, 1)) @test collect(get_point(tri, 4)) ≈ [3.5, 0.0] # midpoint DT.split_subsegment!(tri, args, (1, 4)) @@ -1643,7 +1647,7 @@ end segments = Set([(1, 2), (1, 3), (1, 4), (1, 5)]) # (1, 5) doesn't adjoin any at an acute angle tri = triangulate(points; segments) args = DT.RefinementArguments(tri) - unlock_convex_hull!(tri; reconstruct=true) + unlock_convex_hull!(tri; reconstruct = true) DT.split_subsegment!(tri, args, (1, 2)) # -> 6 DT.split_subsegment!(tri, args, (1, 3)) # -> 7 DT.split_subsegment!(tri, args, (1, 4)) # -> 8 @@ -1722,7 +1726,7 @@ end p4 = (1.0, 1.0) p5 = (0.5, 0.5) pts = [p1, p2, p3, p4, p5] - C = Set{NTuple{2,Int}}() + C = Set{NTuple{2, Int}}() for i in 1:15 θ = 2π * rand() r = 0.5sqrt(rand()) @@ -1731,11 +1735,11 @@ end push!(pts, (x, y)) push!(C, (5, 5 + i)) end - tri = triangulate(pts; delete_ghosts=false, boundary_nodes=[1, 2, 4, 3, 1], segments=C, predicates=PT()) - args = DT.RefinementArguments(tri, use_lens=use_lens, min_angle=25.0, seditious_angle=15.0, max_area=0.1, predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, boundary_nodes = [1, 2, 4, 3, 1], segments = C, predicates = PT()) + args = DT.RefinementArguments(tri, use_lens = use_lens, min_angle = 25.0, seditious_angle = 15.0, max_area = 0.1, predicates = PT()) DT.enqueue_all_encroached_segments!(args, tri) @inferred DT.enqueue_all_encroached_segments!(args, tri) - manual_enqueue = PriorityQueue{NTuple{2,Int},Float64}(Base.Order.Reverse) + manual_enqueue = PriorityQueue{NTuple{2, Int}, Float64}(Base.Order.Reverse) for e in each_edge(tri) if DT.contains_segment(tri, e...) flag = DT.is_encroached(tri, args, e) @@ -1770,10 +1774,10 @@ end for _ in 1:10 push!(points, (rand(), rand())) end - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], predicates=PT()) - args = DT.RefinementArguments(tri, use_lens=use_lens, min_angle=29.0, predicates=PT(), seditious_angle=19.0, max_area=0.05) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], predicates = PT()) + args = DT.RefinementArguments(tri, use_lens = use_lens, min_angle = 29.0, predicates = PT(), seditious_angle = 19.0, max_area = 0.05) DT.enqueue_all_encroached_segments!(args, tri) - manual_enqueue = PriorityQueue{NTuple{2,Int},Float64}(Base.Order.Reverse) + manual_enqueue = PriorityQueue{NTuple{2, Int}, Float64}(Base.Order.Reverse) for e in each_edge(tri) if DT.contains_segment(tri, e...) flag = DT.is_encroached(tri, args, e) @@ -1806,7 +1810,7 @@ end @testset "triangle assessment" begin @testset "is_triangle_nestled" begin - tri = triangulate_rectangle(0, 10, 0, 10, 6, 6, single_boundary=false) + tri = triangulate_rectangle(0, 10, 0, 10, 6, 6, single_boundary = false) segments = get_all_segments(tri) @inferred get_all_segments(tri) for T in each_solid_triangle(tri) @@ -1875,7 +1879,7 @@ end points = [(0.0, 0.0), (2.0, 0.0), (10.0, 0.0), (1.0, 1.0), (8.0, 2.0), (0.0, 6.0), (10.0, 6.0)] segments = Set([(1, 2), (1, 5), (1, 4)]) tri = triangulate(points; segments) - args = DT.RefinementArguments(tri; min_angle=15.0, min_area=3.01, max_area=10.0) + args = DT.RefinementArguments(tri; min_angle = 15.0, min_area = 3.01, max_area = 10.0) good_T, bad_T = slow_triangle_assess(tri, args) @test DT.contains_triangle((1, 4, 6), good_T)[2] # small angle, but area = 3 < min_area @test DT.contains_triangle((6, 4, 5), bad_T)[2] # large area @@ -1888,7 +1892,7 @@ end points = [(0.0, 0.0), (6.0, 0.0), (12.0, 0.0), (11.0, 3.0), (5.788590116313, 1.5787063953581)] segments = Set([(1, 2), (2, 3), (1, 5), (5, 4)]) tri = triangulate(points; segments) - args = DT.RefinementArguments(tri, min_angle=31.0) + args = DT.RefinementArguments(tri, min_angle = 31.0) @test !DT.assess_triangle_quality(tri, args, (1, 2, 5))[2] # seditious @test !DT.assess_triangle_quality(tri, args, (5, 2, 4))[2] # seditious @test DT.assess_triangle_quality(tri, args, (4, 2, 3))[2] # small angle @@ -1900,7 +1904,7 @@ end points = [Tuple(rand(2)) for _ in 1:250] push!(points, (-1, -1), (2, -1), (2, 2), (-1, 2)) tri = triangulate(points) - args = DT.RefinementArguments(tri; min_area=1e-8, max_area=1e-2, min_angle=28.5) + args = DT.RefinementArguments(tri; min_area = 1.0e-8, max_area = 1.0e-2, min_angle = 28.5) @test isempty(args.queue.triangles) DT.enqueue_all_bad_triangles!(args, tri) @test !isempty(args.queue.triangles) @@ -1911,11 +1915,13 @@ end points = [(0.0, 0.0), (2.0, 0.0), (10.0, 0.0), (1.0, 1.0), (8.0, 2.0), (0.0, 6.0), (10.0, 6.0)] segments = Set([(1, 2), (1, 5), (1, 4)]) tri = triangulate(points; segments) - args = DT.RefinementArguments(tri; min_angle=15.0, min_area=3.01, max_area=10.0) + args = DT.RefinementArguments(tri; min_angle = 15.0, min_area = 3.01, max_area = 10.0) DT.enqueue_all_bad_triangles!(args, tri) - queue = PriorityQueue(Base.Order.Reverse, + queue = PriorityQueue( + Base.Order.Reverse, (6, 4, 5) => DT.triangle_radius_edge_ratio(get_point(tri, (6, 4, 5)...)...), - (6, 5, 7) => DT.triangle_radius_edge_ratio(get_point(tri, (6, 5, 7)...)...)) + (6, 5, 7) => DT.triangle_radius_edge_ratio(get_point(tri, (6, 5, 7)...)...), + ) compare_triangle_queues(args, queue) end end @@ -1924,9 +1930,9 @@ end @testset "get_steiner_point" begin for _ in 1:10 tri = triangulate(rand(2, 5000)) - args = DT.RefinementArguments(tri, use_circumcenter=true) - good_results = Dict{NTuple{3,Int},NTuple{2,Float64}}() - bad_results = Dict{NTuple{3,Int},NTuple{2,Float64}}() + args = DT.RefinementArguments(tri, use_circumcenter = true) + good_results = Dict{NTuple{3, Int}, NTuple{2, Float64}}() + bad_results = Dict{NTuple{3, Int}, NTuple{2, Float64}}() for T in each_solid_triangle(tri) flag, c = DT.get_steiner_point(tri, args, T) DT.is_none(flag) && @test c == DT.triangle_circumcenter(get_point(tri, T...)...) @@ -1945,7 +1951,7 @@ end # random tests for _ in 1:10 tri = triangulate(randn(2, 5000)) - args = DT.RefinementArguments(tri, use_circumcenter=true) + args = DT.RefinementArguments(tri, use_circumcenter = true) for T in each_solid_triangle(tri) flag, c = DT.get_steiner_point(tri, args, T) V, loc_flag = DT.locate_steiner_point(tri, args, T, c) @@ -1961,7 +1967,7 @@ end # circumcenter on hypotenuse tri = triangulate([(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)]) - args = DT.RefinementArguments(tri, use_circumcenter=true) + args = DT.RefinementArguments(tri, use_circumcenter = true) c = (0.5, 0.5) for _ in 1:100 for T in ((1, 2, 3), (2, 3, 1), (3, 1, 2)) @@ -1976,13 +1982,13 @@ end @testset "many triangles" begin for _ in 1:10 a, b, c, d, e, f, g, h, i, j, k, ℓ = (0.0, 0.0), (8.0, 0.0), (4.0, 0.0), - (8.0, 4.0), (8.0, 8.0), (4.0, 8.0), (0.0, 8.0), - (0.0, 4.0), (4.0, 6.0), (2.0, 4.0), (4.0, 2.0), (6.0, 4.0) + (8.0, 4.0), (8.0, 8.0), (4.0, 8.0), (0.0, 8.0), + (0.0, 4.0), (4.0, 6.0), (2.0, 4.0), (4.0, 2.0), (6.0, 4.0) boundary_nodes, points = convert_boundary_points_to_indices([[[a, c, b, d, e, f, g, h, a]], [[i, ℓ, k, j, i]]]) m, n, o, p, q, r = (1.0, 7.0), (6.0, 7.0), (6.0, 3.0), (2.0, 3.0), (2.5, 2.5), (1.0, 1.0) push!(points, m, n, o, p, q, r) - tri = triangulate(points; boundary_nodes=boundary_nodes) - args = DT.RefinementArguments(tri, use_circumcenter=true) + tri = triangulate(points; boundary_nodes = boundary_nodes) + args = DT.RefinementArguments(tri, use_circumcenter = true) _to_T = ((p, q, r),) -> (findfirst(==(p), points), findfirst(==(q), points), findfirst(==(r), points)) _ls = T -> DT.locate_steiner_point(tri, args, _to_T(T), DT.triangle_circumcenter(get_point(tri, _to_T(T)...)...)) _check = (T, V, flag) -> DT.check_for_invisible_steiner_point(tri, V, _to_T(T), flag, DT.triangle_circumcenter(get_point(tri, _to_T(T)...)...)) @@ -2052,8 +2058,8 @@ end @testset "triangle on boundary edge" begin for _ in 1:10 points = [(0.0, 0.0), (2.0, 0.0), (0.0, 2.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 1]) - args = DT.RefinementArguments(tri, use_circumcenter=true) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 1]) + args = DT.RefinementArguments(tri, use_circumcenter = true) flag, c = DT.get_steiner_point(tri, args, (1, 2, 3)) @inferred DT.get_steiner_point(tri, args, (1, 2, 3)) @test DT.is_none(flag) && c == DT.triangle_circumcenter(get_point(tri, 1, 2, 3)...) @@ -2071,8 +2077,8 @@ end @testset "triangle on segment edge" begin for _ in 1:10 points = [(0.0, 0.0), (1.0, 0.0), (0.7, 0.7), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], segments=Set([(2, 4)])) - args = DT.RefinementArguments(tri, use_circumcenter=true) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], segments = Set([(2, 4)])) + args = DT.RefinementArguments(tri, use_circumcenter = true) T = (1, 2, 4) flag, c = DT.get_steiner_point(tri, args, T) @test DT.is_none(flag) && c == DT.triangle_circumcenter(get_point(tri, T...)...) @@ -2099,7 +2105,7 @@ end for _ in 1:10 points = [(0.0, 0.0), (0.0, 8.0), (10.0, 8.0), (8.0, 0.0), (4.0, 6.0), (4.5, 5.0), (5.0, 8.0)] tri = triangulate(points) - args = DT.RefinementArguments(tri, use_circumcenter=true) + args = DT.RefinementArguments(tri, use_circumcenter = true) orig_tri = deepcopy(tri) orig_points = deepcopy(points) @@ -2128,7 +2134,7 @@ end points = [(0.0, 0.0), (0.0, 8.0), (10.0, 8.0), (8.0, 0.0), (4.0, 6.0), (4.0, 1.0), (5.0, 8.0)] tri = triangulate(points) - args = DT.RefinementArguments(tri, use_circumcenter=true) + args = DT.RefinementArguments(tri, use_circumcenter = true) orig_tri = deepcopy(tri) orig_points = deepcopy(points) flag = DT.split_triangle!(tri, args, (6, 1, 4)) @@ -2140,7 +2146,7 @@ end tri = triangulate(points) orig_tri = deepcopy(tri) orig_points = deepcopy(points) - args = DT.RefinementArguments(tri, use_circumcenter=true) + args = DT.RefinementArguments(tri, use_circumcenter = true) unlock_convex_hull!(tri) # don't want to deal with EncroachmentFailure proper, only if it's outside of the domain flag = DT.split_triangle!(tri, args, (6, 1, 4)) @test DT.is_successful_insertion(flag) @@ -2153,7 +2159,7 @@ end @testset "check_for_steiner_point_on_segment" begin for PT in subtypes(DT.AbstractPredicateKernel) points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; randomise=false) + tri = triangulate(points; randomise = false) push!(points, (1 / 2, 1 / 2)) V = (1, 2, 3) V′ = (1, 2, 3) @@ -2184,7 +2190,7 @@ end @test !DT.has_boundary_nodes(tri) @test DT.has_ghost_triangles(tri) - tri = triangulate_rectangle(0, 1, 0, 1, 5, 5, delete_ghosts=true) + tri = triangulate_rectangle(0, 1, 0, 1, 5, 5, delete_ghosts = true) args = DT.RefinementArguments(tri) @test DT.has_boundary_nodes(tri) @test DT.has_ghost_triangles(tri) @@ -2200,7 +2206,7 @@ end @test DT.has_boundary_nodes(tri) @test DT.has_ghost_triangles(tri) - tri = triangulate(rand(2, 50), delete_ghosts=true) + tri = triangulate(rand(2, 50), delete_ghosts = true) args = DT.RefinementArguments(tri) @test DT.has_boundary_nodes(tri) @test DT.has_ghost_triangles(tri) @@ -2218,15 +2224,15 @@ end for p in [(4.0, 2.0), (5.0, 2.5), (3.0, 3.5), (5.0, 4.5), (6.5, 3.5), (7.0, 4.0), (6.5, 1.5), (4.0, 3.5)] add_point!(tri, p) end - fig = Figure(fontsize=33) - ax = Axis(fig[1, 1], width=600, height=400) + fig = Figure(fontsize = 33) + ax = Axis(fig[1, 1], width = 600, height = 400) _, _, C = compute_diametral_circle(get_point(tri, 5, 6)...) triplot!(ax, tri) - lines!(ax, C, color=:red) + lines!(ax, C, color = :red) DT.split_subsegment!(tri, args, (5, 6)) - ax = Axis(fig[1, 2], width=600, height=400) + ax = Axis(fig[1, 2], width = 600, height = 400) triplot!(ax, tri) - lines!(ax, C, color=:red) + lines!(ax, C, color = :red) resize_to_layout!(fig) fig @test_reference "delete_free_vertices_around_subsegment.png" fig @@ -2240,15 +2246,15 @@ end for p in [(4.0, 2.0), (5.0, 2.5), (3.0, 3.5), (5.0, 4.5), (6.5, 3.5), (7.0, 4.0), (6.5, 1.5), (4.0, 3.5)] add_point!(tri, p) end - fig = Figure(fontsize=33) - ax = Axis(fig[1, 1], width=600, height=400) + fig = Figure(fontsize = 33) + ax = Axis(fig[1, 1], width = 600, height = 400) _, _, C = compute_diametral_circle(get_point(tri, 5, 6)...) triplot!(ax, tri) - lines!(ax, C, color=:red) + lines!(ax, C, color = :red) DT.split_subsegment!(tri, args, (5, 6)) - ax = Axis(fig[1, 2], width=600, height=400) + ax = Axis(fig[1, 2], width = 600, height = 400) triplot!(ax, tri) - lines!(ax, C, color=:red) + lines!(ax, C, color = :red) resize_to_layout!(fig) fig @test_reference "delete_free_vertices_around_subsegment2.png" fig @@ -2260,22 +2266,22 @@ end @testset "A simple convex example" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((20.0, 27.5, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-1, 1e-2)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-1, 1.0e-2)) for (idx5, seditious_angle) in enumerate((10.0, 20.0)) @info "Testing refinement of a simple convex example. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], rng) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], rng) custom_constraint = (_tri, T) -> begin i, j, k = triangle_vertices(T) p, q, r = get_point(_tri, i, j, k) c = (p .+ q .+ r) ./ 3 y = gety(c) - return y < 1 / 2 && DT.triangle_area(p, q, r) > 1e-3 + return y < 1 / 2 && DT.triangle_area(p, q, r) > 1.0e-3 end - refine!(tri; min_angle, min_area, max_area, custom_constraint, seditious_angle, use_circumcenter=true, use_lens, rng) - args = DT.RefinementArguments(tri; min_angle, min_area, max_area, seditious_angle, custom_constraint, use_circumcenter=true, use_lens) + refine!(tri; min_angle, min_area, max_area, custom_constraint, seditious_angle, use_circumcenter = true, use_lens, rng) + args = DT.RefinementArguments(tri; min_angle, min_area, max_area, seditious_angle, custom_constraint, use_circumcenter = true, use_lens) @test validate_refinement(tri, args) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 3, 1, 2, 2) fig, ax, sc = triplot(tri) @@ -2294,17 +2300,19 @@ end @testset "Triangulation with a hole" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((12.9, 27.5, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-2, 1e-3, 1e-4)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-2, 1.0e-3, 1.0e-4)) for (idx5, seditious_angle) in enumerate((20.0, 40.0)) @info "Testing refinement of a triangulation with a hole. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) - points = [(0.0, 0.0), (0.5, 0.1), (1.0, 0.0), (0.9, 0.5), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), - (0.3, 0.3), (0.7, 0.3), (0.7, 0.7), (0.3, 0.7)] + points = [ + (0.0, 0.0), (0.5, 0.1), (1.0, 0.0), (0.9, 0.5), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), + (0.3, 0.3), (0.7, 0.3), (0.7, 0.7), (0.3, 0.7), + ] boundary_nodes = [[[1, 2, 3, 4, 5, 6, 7, 1]], [[11, 10, 9, 8, 11]]] tri = triangulate(points; boundary_nodes, rng) - refine!(tri; min_angle, min_area, max_area, use_circumcenter=true, use_lens, rng, seditious_angle) - @test validate_refinement(tri, DT.RefinementArguments(tri; min_angle, min_area, seditious_angle, max_area, use_circumcenter=true, use_lens)) + refine!(tri; min_angle, min_area, max_area, use_circumcenter = true, use_lens, rng, seditious_angle) + @test validate_refinement(tri, DT.RefinementArguments(tri; min_angle, min_area, seditious_angle, max_area, use_circumcenter = true, use_lens)) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 3, 1, 3, 1) fig, ax, sc = triplot(tri) @test_reference "triangulation_with_a_hole_circle.png" fig by = psnr_equality(15) @@ -2322,12 +2330,13 @@ end @testset "A very non-convex example" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((12.9, 15.8, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-1, 1e-3, 1e-4)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-1, 1.0e-3, 1.0e-4)) for (idx5, seditious_angle) in enumerate((10.0, 20.0, 60.0)) @info "Testing refinement of a very non-convex example. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) - points = [(0.0, 0.0), (0.0, 1.0), (0.1, 1.0), + points = [ + (0.0, 0.0), (0.0, 1.0), (0.1, 1.0), (0.1, 0.1), (0.2, 0.1), (0.2, 1.0), (0.3, 1.0), (0.3, 0.0), (0.4, 0.0), (0.4, 0.9), (0.5, 0.9), (0.5, 0.1), @@ -2335,11 +2344,12 @@ end (0.7, 0.1), (0.8, 0.1), (0.8, 0.9), (0.9, 0.9), (0.9, 0.1), (0.9, 0.0), (1.0, 0.0), (1.0, -0.1), (0.0, -0.1), - (0.0, 0.0)] |> reverse! + (0.0, 0.0), + ] |> reverse! boundary_nodes, points = convert_boundary_points_to_indices(points) tri = triangulate(points; boundary_nodes, rng) - refine!(tri; min_angle, min_area, max_area, use_circumcenter=true, use_lens, seditious_angle, rng) - @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter=true, use_lens, check_conformal=false) + refine!(tri; min_angle, min_area, max_area, use_circumcenter = true, use_lens, seditious_angle, rng) + @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter = true, use_lens, check_conformal = false) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 3, 1, 3, 2) fig, ax, sc = triplot(tri) @test_reference "a_very_non_convex_example_circle.png" fig @@ -2357,24 +2367,28 @@ end @testset "A constrained triangulation with multiple holes" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((12.9, 15.8, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-2, 1e-3, 1e-4)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-2, 1.0e-3, 1.0e-4)) for (idx5, seditious_angle) in enumerate((20.0, 40.0)) @info "Testing refinement of a triangulation with multiple holes. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) - curve_1 = [[ - (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), - (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), - (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), - (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), - (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), - (-4.0, 0.0), (0.0, 0.0), - ]] - curve_2 = [[ - (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), - (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), - (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) - ]] + curve_1 = [ + [ + (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), + (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), + (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), + (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), + (-4.0, 0.0), (0.0, 0.0), + ], + ] + curve_2 = [ + [ + (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), + (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0), + ], + ] curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] curves = [curve_1, curve_2, curve_3, curve_4] @@ -2389,12 +2403,13 @@ end (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), - (7.0, 7.8), (7.0, 7.4)] - boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) + (7.0, 7.8), (7.0, 7.4), + ] + boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points = points) tri = triangulate(points; boundary_nodes, rng) _max_area = max_area * get_area(tri) - refine!(tri; min_angle, min_area, max_area=_max_area, use_circumcenter=true, seditious_angle, use_lens, rng) - @test validate_refinement(tri; min_angle, min_area, max_area=_max_area, use_circumcenter=true, seditious_angle, use_lens, check_conformal=false) + refine!(tri; min_angle, min_area, max_area = _max_area, use_circumcenter = true, seditious_angle, use_lens, rng) + @test validate_refinement(tri; min_angle, min_area, max_area = _max_area, use_circumcenter = true, seditious_angle, use_lens, check_conformal = false) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 3, 1, 3, 1) fig, ax, sc = triplot(tri) @test_reference "a_constrained_triangulation_with_multiple_holes_circle.png" fig by = psnr_equality(15) @@ -2412,8 +2427,8 @@ end @testset "another square example, directly testing stats" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((12.9, 15.8, 27.5, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-1, 1e-2, 1e-4)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-1, 1.0e-2, 1.0e-4)) for (idx5, seditious_angle) in enumerate((10.0, 20.0)) @info "Testing refinement of a square. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) @@ -2423,7 +2438,7 @@ end p4 = (1.0, 1.0) pts = [p1, p2, p3, p4] tri = triangulate(pts; rng) - refine!(tri; min_angle, min_area, max_area, use_circumcenter=true, seditious_angle, use_lens, rng) + refine!(tri; min_angle, min_area, max_area, use_circumcenter = true, seditious_angle, use_lens, rng) stats = statistics(tri) @test DT.get_smallest_angle(stats) ≥ deg2rad(min_angle) @test DT.get_largest_area(stats) ≤ max_area @@ -2432,7 +2447,7 @@ end @test DT.convex_hull(tri).vertices == DT.convex_hull(tri.points).vertices @test validate_triangulation(tri) validate_statistics(tri) - @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter=true, use_lens) + @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter = true, use_lens) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 4, 1, 3, 2) fig, ax, sc = triplot(tri) @test_reference "another_square_example_circle.png" fig by = psnr_equality(15) @@ -2455,18 +2470,18 @@ end p4 = (1.0, 1.0) pts = [p1, p2, p3, p4] tri = triangulate(pts) - refine!(tri; max_area=1e-6, max_points=5_000, use_circumcenter=true) + refine!(tri; max_area = 1.0e-6, max_points = 5_000, use_circumcenter = true) @test DT.num_solid_vertices(tri) == 5000 @test validate_triangulation(tri) - @test !validate_refinement(tri; max_area=1e-6, max_points=5_000, use_circumcenter=true, warn=false) + @test !validate_refinement(tri; max_area = 1.0e-6, max_points = 5_000, use_circumcenter = true, warn = false) end end @testset "avoiding infinite bouncing with concentric circular shells" begin for (idx1, use_lens) in enumerate((false, true)) for (idx2, min_angle) in enumerate((23.0, 27.5, 30.0)) - for (idx3, min_area) in enumerate((1e-12,)) - for (idx4, max_area) in enumerate((1e-1, 1e-2)) + for (idx3, min_area) in enumerate((1.0e-12,)) + for (idx4, max_area) in enumerate((1.0e-1, 1.0e-2)) for (idx5, seditious_angle) in enumerate((10.0, 20.0)) @info "Testing that infinite bouncing is avoided during refinement. use_lens: $use_lens; min_angle: $min_angle; min_area: $min_area; max_area: $max_area; seditious_angle: $seditious_angle." p1 = (0.0, 0.0) @@ -2477,8 +2492,8 @@ end rng = StableRNG(_rng_num(idx1, idx2, idx3, idx4, idx5)) tri = triangulate(pts; rng) add_segment!(tri, 1, 4; rng) - refine!(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter=true, use_lens, rng) - @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter=true, use_lens) + refine!(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter = true, use_lens, rng) + @test validate_refinement(tri; min_angle, min_area, max_area, seditious_angle, use_circumcenter = true, use_lens) validate_statistics(tri) if _rng_num(idx1, idx2, idx3, idx4, idx5) == _rng_num(1, 3, 1, 2, 2) fig, ax, sc = triplot(tri) @@ -2499,21 +2514,21 @@ end @info "Testing seditious edges. Run: $i" points = [(0.0, 0.0), (1.0, 0.0), (0.8, 0.2)] tri = triangulate(points) - refine!(tri, use_circumcenter=true) + refine!(tri, use_circumcenter = true) @test_reference "seditious_edge_testing_1.png" triplot(tri) by = psnr_equality(15) - @test validate_refinement(tri, use_circumcenter=true) + @test validate_refinement(tri, use_circumcenter = true) validate_statistics(tri) points = [(0.0, 0.0), (1.0, 0.0), (0.8, 0.2)] tri = triangulate(points) - refine!(tri, use_circumcenter=true, use_lens=false) + refine!(tri, use_circumcenter = true, use_lens = false) @test_reference "seditious_edge_testing_2.png" triplot(tri) by = psnr_equality(15) - @test validate_refinement(tri, use_circumcenter=true, use_lens=false) + @test validate_refinement(tri, use_circumcenter = true, use_lens = false) validate_statistics(tri) points = [(0.0, 0.0), (1.0, 0.0), (0.8, 0.2)] tri = triangulate(points) - args = DT.RefinementArguments(tri, use_circumcenter=true, use_lens=false, max_area=1e-3get_area(tri)) + args = DT.RefinementArguments(tri, use_circumcenter = true, use_lens = false, max_area = 1.0e-3get_area(tri)) refine!(tri, args) @test validate_refinement(tri, args) @test_reference "seditious_edge_testing_3.png" triplot(tri) by = psnr_equality(15) @@ -2534,7 +2549,7 @@ end pts = [p1, p2, p3, p4, p5, p6, p7, p8] boundary_nodes = [[[1, 2, 3, 4, 1]], [[8, 7, 6, 5, 8]]] rng = StableRNG(123) - tri = triangulate(pts; rng, boundary_nodes=boundary_nodes, delete_ghosts=false) + tri = triangulate(pts; rng, boundary_nodes = boundary_nodes, delete_ghosts = false) add_point!(tri, 0.1, 0.8; rng) add_point!(tri, 0.3, 0.2; rng) add_point!(tri, 0.7, 0.2; rng) @@ -2543,7 +2558,7 @@ end add_segment!(tri, 11, 12; rng) add_segment!(tri, 9, 12; rng) add_segment!(tri, 10, 11; rng) - refine!(tri; max_area=0.001, max_points=5000, use_circumcenter=true, use_lens=true, rng) + refine!(tri; max_area = 0.001, max_points = 5000, use_circumcenter = true, use_lens = true, rng) stats = statistics(tri) @test DT.get_smallest_angle(stats) ≥ deg2rad(30) @test DT.get_largest_area(stats) ≤ 0.001 @@ -2551,7 +2566,7 @@ end @test DT.convex_hull(tri).vertices == DT.convex_hull(tri.points).vertices validate_statistics(tri, stats) @test validate_triangulation(tri) - @test validate_refinement(tri; max_area=0.001, max_points=5000, use_circumcenter=true, use_lens=true) + @test validate_refinement(tri; max_area = 0.001, max_points = 5000, use_circumcenter = true, use_lens = true) fig, ax, sc = triplot(tri) @test_reference "triangulating_with_an_interior_hole.png" fig by = psnr_equality(15) end @@ -2560,7 +2575,7 @@ end @info "Testing the refinement of disjoint sets" θ = LinRange(0, 2π, 30) |> collect θ[end] = 0 - xy = Vector{Vector{Vector{NTuple{2,Float64}}}}() + xy = Vector{Vector{Vector{NTuple{2, Float64}}}}() rng = StableRNG(123) cx = 0.0 for i in 1:2 @@ -2569,14 +2584,14 @@ end cx += 3.0 end boundary_nodes, points = convert_boundary_points_to_indices(xy) - tri = triangulate(points; boundary_nodes=boundary_nodes, rng) + tri = triangulate(points; boundary_nodes = boundary_nodes, rng) A = DT.get_area(tri) max_area = 0.001A - min_area = 1e-9A - refine!(tri; min_area, rng, max_area, use_circumcenter=true) + min_area = 1.0e-9A + refine!(tri; min_area, rng, max_area, use_circumcenter = true) stats = statistics(tri) validate_statistics(tri) - @test validate_refinement(tri; min_area, max_area, use_circumcenter=true) + @test validate_refinement(tri; min_area, max_area, use_circumcenter = true) fig, ax, sc = triplot(tri) @test_reference "refining_disjoint_sets.png" fig by = psnr_equality(15) end @@ -2584,16 +2599,16 @@ end @testset "Small angles" begin for PT in (DT.ExactKernel, DT.AdaptiveKernel) ps = 0 - fig = Figure(fontsize=52) + fig = Figure(fontsize = 52) for i in 1:12 @info "Testing refinement with small angles. Run: $i; Predicates: $PT" if i > 6 use_lens = true i -= 6 - ax = Axis(fig[2, i], title="Lens; $i", width=600, height=600) + ax = Axis(fig[2, i], title = "Lens; $i", width = 600, height = 600) else use_lens = false - ax = Axis(fig[1, i], title="Circle; $i", width=600, height=600) + ax = Axis(fig[1, i], title = "Circle; $i", width = 600, height = 600) end hidedecorations!(ax) hidespines!(ax) @@ -2604,7 +2619,7 @@ end p4 = (1.0, 1.0) p5 = (0.5, 0.5) pts = [p1, p2, p3, p4, p5] - C = Set{NTuple{2,Int}}() + C = Set{NTuple{2, Int}}() for i in 1:20 θ = 2π * rand(rng) r = 0.5sqrt(rand(rng)) @@ -2613,12 +2628,12 @@ end push!(pts, (x, y)) push!(C, (5, 5 + i)) end - tri = triangulate(pts; rng, boundary_nodes=[1, 2, 4, 3, 1], segments=C, predicates=PT()) - refine!(tri; min_angle=27.3, min_area=0.0, use_circumcenter=true, rng, use_lens, predicates=PT()) + tri = triangulate(pts; rng, boundary_nodes = [1, 2, 4, 3, 1], segments = C, predicates = PT()) + refine!(tri; min_angle = 27.3, min_area = 0.0, use_circumcenter = true, rng, use_lens, predicates = PT()) stats = statistics(tri) ps += DT.get_largest_angle(stats) ≤ max(π - 2 * deg2rad(17.0), 2asin((sqrt(3) - 1) / 2)) # Corollary 8 of "When and Why Ruppert's Algorithm Works. In Twelfth International Meshing Roundtable, pp. 91–102, Santa Fe, NM, Sept 2003." validate_statistics(tri) - @test validate_refinement(tri; min_angle=27.3, min_area=0.0, use_circumcenter=true, warn=false, use_lens, rng) + @test validate_refinement(tri; min_angle = 27.3, min_area = 0.0, use_circumcenter = true, warn = false, use_lens, rng) triplot!(ax, tri) end resize_to_layout!(fig) @@ -2641,21 +2656,25 @@ end reverse!(inverse_points) curve_points = [[points], [inverse_points]] boundary_nodes, points = convert_boundary_points_to_indices(curve_points) - C = Set([[(50, i) for i in 98:-1:81]..., [(50, i) for i in 69:-1:51]..., - [(10, i) for i in 36:49]...]) + C = Set( + [ + [(50, i) for i in 98:-1:81]..., [(50, i) for i in 69:-1:51]..., + [(10, i) for i in 36:49]..., + ], + ) C′ = empty(C) bem = DT.construct_boundary_edge_map(boundary_nodes) for c in C c′ = DT.reverse_edge(c) c ∉ keys(bem) && c′ ∉ keys(bem) && push!(C′, c) end - tri = triangulate(points; boundary_nodes, rng, segments=C′) + tri = triangulate(points; boundary_nodes, rng, segments = C′) @test DT.is_disjoint(tri) @test validate_triangulation(tri) A = DT.get_area(tri) - refine!(tri, max_area=1e-3A, min_area=1e-12A, rng=rng, use_circumcenter=true, use_lens=true) + refine!(tri, max_area = 1.0e-3A, min_area = 1.0e-12A, rng = rng, use_circumcenter = true, use_lens = true) validate_statistics(tri) - @test validate_refinement(tri, max_area=1e-3A, min_area=0.0, use_circumcenter=true, use_lens=true, warn=false) + @test validate_refinement(tri, max_area = 1.0e-3A, min_area = 0.0, use_circumcenter = true, use_lens = true, warn = false) fig, ax, sc = triplot(tri) @test_reference "refining_disjoint_sets_2.png" fig by = psnr_equality(15) end @@ -2703,12 +2722,12 @@ end boundary_pts = [[pts], [inner_pts]] nodes, points = convert_boundary_points_to_indices(boundary_pts) rng = StableRNG(123) - tri = triangulate(points; boundary_nodes=nodes, rng) + tri = triangulate(points; boundary_nodes = nodes, rng) @test validate_triangulation(tri) A = get_area(tri) - refine!(tri; max_area=1e-3A, use_circumcenter=true, rng) + refine!(tri; max_area = 1.0e-3A, use_circumcenter = true, rng) validate_statistics(tri) - @test validate_refinement(tri; max_area=1e-3A, rng, use_circumcenter=true, warn=true) + @test validate_refinement(tri; max_area = 1.0e-3A, rng, use_circumcenter = true, warn = true) fig, ax, sc = triplot(tri) @test_reference "tight_example_with_a_single_triangle_boundary_interior.png" fig by = psnr_equality(15) end @@ -2768,7 +2787,7 @@ end boundary_pts = [[pts], [inner_pts]] nodes, points = convert_boundary_points_to_indices(boundary_pts) push!(points, (20.0, 20.0)) - C = Set{NTuple{2,Int}}() + C = Set{NTuple{2, Int}}() for i in 1:50 θ = 2π * rand(rng) r = 4sqrt(rand(rng)) @@ -2777,10 +2796,10 @@ end push!(points, (x, y)) push!(C, (48, 48 + i)) end - tri = triangulate(points; boundary_nodes=nodes, segments=C, rng) + tri = triangulate(points; boundary_nodes = nodes, segments = C, rng) @test validate_triangulation(tri) A = get_area(tri) - refine!(tri; max_area=1.0, rng, use_circumcenter=true) + refine!(tri; max_area = 1.0, rng, use_circumcenter = true) validate_statistics(tri) fig, ax, sc = triplot(tri) @test_reference "complicated_example_with_tight_walls_and_small_angles.png" fig by = psnr_equality(15) @@ -2820,9 +2839,9 @@ end p3 = (0.0f0, 1.0f0) p4 = (1.0f0, 1.0f0) pts = [p1, p2, p3, p4] - tri = triangulate(pts; delete_ghosts=false, predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, predicates = PT()) validate_statistics(tri) - refine!(tri; max_area=0.001, max_points=25_000, use_circumcenter=true, predicates=PT()) + refine!(tri; max_area = 0.001, max_points = 25_000, use_circumcenter = true, predicates = PT()) stats = statistics(tri) @inferred statistics(tri) @test DT.get_smallest_angle(stats) ≥ deg2rad(30.0) @@ -2830,7 +2849,7 @@ end @test !DT.is_constrained(tri) @test DT.convex_hull(tri).vertices == DT.convex_hull(tri.points).vertices @test validate_triangulation(tri) - @test validate_refinement(tri; max_area=0.001, max_points=25_000, use_circumcenter=true) + @test validate_refinement(tri; max_area = 0.001, max_points = 25_000, use_circumcenter = true) end for _ in 1:5 @@ -2845,22 +2864,22 @@ end p8 = (0.4f0, 0.6f0) pts = [p1, p2, p3, p4, p5, p6, p7, p8] boundary_nodes = [[[1, 2, 3, 4, 1]], [[8, 7, 6, 5, 8]]] - tri = triangulate(pts; rng, boundary_nodes=boundary_nodes, delete_ghosts=false, predicates=PT()) - add_point!(tri, 0.1f0, 0.8f0, predicates=PT()) - add_point!(tri, 0.3f0, 0.2f0, predicates=PT()) - add_point!(tri, 0.7f0, 0.2f0, predicates=PT()) - add_point!(tri, 0.9, 0.8, predicates=PT()) - add_segment!(tri, 9, 10, predicates=PT()) - add_segment!(tri, 11, 12, predicates=PT()) - add_segment!(tri, 9, 12, predicates=PT()) - add_segment!(tri, 10, 11, predicates=PT()) - refine!(tri; rng, max_area=0.001f0, max_points=25000, min_angle=24.0f0, min_area=0.0, use_circumcenter=true, predicates=PT()) + tri = triangulate(pts; rng, boundary_nodes = boundary_nodes, delete_ghosts = false, predicates = PT()) + add_point!(tri, 0.1f0, 0.8f0, predicates = PT()) + add_point!(tri, 0.3f0, 0.2f0, predicates = PT()) + add_point!(tri, 0.7f0, 0.2f0, predicates = PT()) + add_point!(tri, 0.9, 0.8, predicates = PT()) + add_segment!(tri, 9, 10, predicates = PT()) + add_segment!(tri, 11, 12, predicates = PT()) + add_segment!(tri, 9, 12, predicates = PT()) + add_segment!(tri, 10, 11, predicates = PT()) + refine!(tri; rng, max_area = 0.001f0, max_points = 25000, min_angle = 24.0f0, min_area = 0.0, use_circumcenter = true, predicates = PT()) stats = statistics(tri) @test DT.get_smallest_angle(stats) ≥ deg2rad(24.0f0) @test DT.get_largest_area(stats) ≤ 0.001f0 @test DT.is_constrained(tri) @test DT.convex_hull(tri).vertices == DT.convex_hull(tri.points).vertices - @test validate_refinement(tri; max_area=0.001, max_points=25000, min_angle=24.0f0, min_area=0.0, use_circumcenter=true) + @test validate_refinement(tri; max_area = 0.001, max_points = 25000, min_angle = 24.0f0, min_area = 0.0, use_circumcenter = true) end end end @@ -2901,14 +2920,14 @@ end return A ≥ 0.008 || θ ≤ 30.0 end end - refine!(tri; custom_constraint=custom_refine_ex, rng, use_circumcenter=true) + refine!(tri; custom_constraint = custom_refine_ex, rng, use_circumcenter = true) stat = Bool[] delete_ghost_triangles!(tri) for T in each_triangle(tri) push!(stat, custom_refine_ex(tri, T)) end @test !any(stat) - @test validate_refinement(tri; custom_constraint=custom_refine_ex, use_circumcenter=true) + @test validate_refinement(tri; custom_constraint = custom_refine_ex, use_circumcenter = true) validate_statistics(tri) end @@ -3059,10 +3078,13 @@ end U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] - A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] + A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], + ] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -3070,12 +3092,12 @@ end dot_4 = [[K3, L3, M3, N3, O3, P3, Q3, R3, S3, T3, U3, V3, K3]] curves = [J_curve, U_curve, L_curve, I_curve, A_curve_outline, A_curve_hole, dot_1, dot_2, dot_3, dot_4] nodes, points = convert_boundary_points_to_indices(curves) - tri = triangulate(points; boundary_nodes=nodes, rng) + tri = triangulate(points; boundary_nodes = nodes, rng) A = get_area(tri) - refine!(tri; min_angle=26.45, max_area=0.005A / 9, rng, use_circumcenter=true) + refine!(tri; min_angle = 26.45, max_area = 0.005A / 9, rng, use_circumcenter = true) validate_statistics(tri) - @test validate_refinement(tri; min_angle=26.45, max_area=0.005A / 9, rng, use_circumcenter=true) + @test validate_refinement(tri; min_angle = 26.45, max_area = 0.005A / 9, rng, use_circumcenter = true) fig, ax, sc = triplot(tri) @test_reference "julia_logo.png" fig by = psnr_equality(15) end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 68a8b575c..ba8030b16 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,7 @@ include("helper_functions.jl") using .HelperFunctions ct() = Dates.format(now(), "HH:MM:SS") -function safe_include(filename; name=filename, push=true, verbose=true) # Workaround for not being able to interpolate into SafeTestset test names +function safe_include(filename; name = filename, push = true, verbose = true) # Workaround for not being able to interpolate into SafeTestset test names push && push!(ALL_TEST_SCRIPTS, normpath(filename)) mod = @eval module $(gensym()) end @info "[$(ct())] Testing $name" @@ -28,7 +28,7 @@ end @testset verbose = true "DelaunayTriangulation.jl" begin @testset verbose = true "Aqua" begin - Aqua.test_all(DelaunayTriangulation; ambiguities=false, project_extras=false) # don't care about julia < 1.2 + Aqua.test_all(DelaunayTriangulation; ambiguities = false, project_extras = false) # don't care about julia < 1.2 Aqua.test_ambiguities(DelaunayTriangulation) # don't pick up Base and Core... end @@ -39,7 +39,7 @@ end safe_include("triangulation/convex_triangulation.jl") safe_include("triangulation/constrained.jl") safe_include("triangulation/check_args.jl") - + # Needs to be setup properly before we do more testing of it. Please see the # comments at the end of the weighted.jl file (the one included in the comment below). # safe_include("triangulation/weighted.jl") @@ -68,7 +68,7 @@ end safe_include("data_structures/curves.jl") safe_include("data_structures/rtree.jl") safe_include("data_structures/bst.jl") - safe_include("data_structures/polygon_hierarchy.jl", verbose=false) + safe_include("data_structures/polygon_hierarchy.jl", verbose = false) end @testset verbose = true "Predicates" begin @@ -128,7 +128,7 @@ end app_dir = joinpath(dirname(dirname(pathof(DelaunayTriangulation))), "docs", "src", "literate_applications") app_files = readdir(app_dir) for file in app_files - safe_include(joinpath(app_dir, file); push=false) + safe_include(joinpath(app_dir, file); push = false) end mp4_path = joinpath(dirname(dirname(pathof(DelaunayTriangulation))), "cell_simulation.mp4") isfile(mp4_path) && rm(mp4_path) @@ -138,7 +138,7 @@ end tut_dir = joinpath(dirname(dirname(pathof(DelaunayTriangulation))), "docs", "src", "literate_tutorials") tut_files = readdir(tut_dir) for file in tut_files - safe_include(joinpath(tut_dir, file); push=false) + safe_include(joinpath(tut_dir, file); push = false) end end @@ -166,4 +166,4 @@ end end @test isempty(missing_set) end -end \ No newline at end of file +end diff --git a/test/triangulation/bowyer_watson.jl b/test/triangulation/bowyer_watson.jl index 3ba44514c..1b3331869 100644 --- a/test/triangulation/bowyer_watson.jl +++ b/test/triangulation/bowyer_watson.jl @@ -38,14 +38,15 @@ end end @testset "Initialising the Bowyer-Watson algorithm" begin - tri = triangulate_rectangle(0.0, 10.0, 0.0, 20.0, 11, 21, delete_ghosts=false) + tri = triangulate_rectangle(0.0, 10.0, 0.0, 20.0, 11, 21, delete_ghosts = false) _tri = DT.Triangulation(tri.points) DT.initialise_bowyer_watson!(_tri, DT.each_point_index(_tri) |> collect, rt()) S = filter(!DT.is_ghost_triangle, _tri.triangles) u, v, w = first(S) BI = DT.𝒢 @test get_triangles(_tri) == Set(((u, v, w), (w, v, BI), (v, u, BI), (u, w, BI))) - @test get_adjacent(get_adjacent(_tri)) == Dict((u, v) => w, + @test get_adjacent(get_adjacent(_tri)) == Dict( + (u, v) => w, (v, w) => u, (w, u) => v, (w, v) => BI, @@ -56,55 +57,62 @@ end (BI, v) => u, (u, w) => BI, (w, BI) => u, - (BI, u) => w) + (BI, u) => w, + ) @test get_adjacent2vertex(get_adjacent2vertex(_tri)) == - Dict(BI => Set{NTuple{2,Int}}([(w, v), (v, u), (u, w)]), - u => Set{NTuple{2,Int}}([(v, w), (BI, v), (w, BI)]), - v => Set{NTuple{2,Int}}([(w, u), (BI, w), (u, BI)]), - w => Set{NTuple{2,Int}}([(u, v), (v, BI), (BI, u)])) + Dict( + BI => Set{NTuple{2, Int}}([(w, v), (v, u), (u, w)]), + u => Set{NTuple{2, Int}}([(v, w), (BI, v), (w, BI)]), + v => Set{NTuple{2, Int}}([(w, u), (BI, w), (u, BI)]), + w => Set{NTuple{2, Int}}([(u, v), (v, BI), (BI, u)]), + ) @test DT.get_graph(_tri).vertices == Set([u, v, w, BI]) end @testset "A basic triangulation" begin a, b, c, d, e, f, g = [-1.78, 5.77], [-4.96, 0.31], [0.08, -3.73], [7.74, -3.03], - [8.0, 3.0], [-0.6, 1.57], [3.58, 6.15] + [8.0, 3.0], [-0.6, 1.57], [3.58, 6.15] points = [a, b, c, d, e, f, g] rng = StableRNG(8881) - tri = DT.triangulate(points; rng, predicates=rt(), delete_ghosts=false) + tri = DT.triangulate(points; rng, predicates = rt(), delete_ghosts = false) @static if VERSION ≥ v"1.9" - @inferred DT.triangulate(points; predicates=rt(), rng, delete_ghosts=false) + @inferred DT.triangulate(points; predicates = rt(), rng, delete_ghosts = false) end BI = DT.𝒢 - @test get_triangles(tri) == Set{NTuple{3,Int}}(((3, 2, BI), - (4, BI, 5), - (5, 7, 6), - (3, 6, 2), - (5, BI, 7), - (4, 6, 3), - (4, 3, BI), - (4, 5, 6), - (1, 2, 6), - (1, 6, 7), - (1, 7, BI), - (1, BI, 2))) + @test get_triangles(tri) == Set{NTuple{3, Int}}( + ( + (3, 2, BI), + (4, BI, 5), + (5, 7, 6), + (3, 6, 2), + (5, BI, 7), + (4, 6, 3), + (4, 3, BI), + (4, 5, 6), + (1, 2, 6), + (1, 6, 7), + (1, 7, BI), + (1, BI, 2), + ), + ) @test validate_triangulation(tri) end @testset "A random triangulation" begin for PT in subtypes(DT.AbstractPredicateKernel) pts = randn(2, 500) - tri = DT.triangulate(pts; predicates=PT(), delete_ghosts=false) - @test validate_triangulation(tri; predicates=PT()) + tri = DT.triangulate(pts; predicates = PT(), delete_ghosts = false) + @test validate_triangulation(tri; predicates = PT()) end end @testset "Lots of collinearity" begin for PT in (DT.ExactKernel, DT.AdaptiveKernel) - _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary=true) - @test validate_triangulation(_tri; predicates=PT()) + _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary = true) + @test validate_triangulation(_tri; predicates = PT()) for _ in 1:25 - tri = DT.triangulate(_tri.points; predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = DT.triangulate(_tri.points; predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -112,38 +120,47 @@ end @testset "A detailed example" begin for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:100 - T = Set{NTuple{3,Int}}(((2, 9, 8), - (2, 8, 6), - (2, 6, 1), - (1, 6, 10), - (6, 8, 10), - (10, 8, 3), - (10, 3, 4), - (10, 4, 5), - (1, 10, 5), - (8, 9, 3), - (9, 7, 3), - (3, 7, 4), - (1, 5, DT.𝒢), - (5, 4, DT.𝒢), - (4, 7, DT.𝒢), - (7, 9, DT.𝒢), - (9, 2, DT.𝒢), - (2, 1, DT.𝒢))) - T2 = Set{NTuple{3,Int}}(((2, 9, 8), - (2, 8, 6), - (2, 6, 1), - (1, 6, 10), - (6, 8, 10), - (10, 8, 3), - (10, 3, 4), - (10, 4, 5), - (1, 10, 5), - (8, 9, 3), - (9, 7, 3), - (3, 7, 4))) + T = Set{NTuple{3, Int}}( + ( + (2, 9, 8), + (2, 8, 6), + (2, 6, 1), + (1, 6, 10), + (6, 8, 10), + (10, 8, 3), + (10, 3, 4), + (10, 4, 5), + (1, 10, 5), + (8, 9, 3), + (9, 7, 3), + (3, 7, 4), + (1, 5, DT.𝒢), + (5, 4, DT.𝒢), + (4, 7, DT.𝒢), + (7, 9, DT.𝒢), + (9, 2, DT.𝒢), + (2, 1, DT.𝒢), + ), + ) + T2 = Set{NTuple{3, Int}}( + ( + (2, 9, 8), + (2, 8, 6), + (2, 6, 1), + (1, 6, 10), + (6, 8, 10), + (10, 8, 3), + (10, 3, 4), + (10, 4, 5), + (1, 10, 5), + (8, 9, 3), + (9, 7, 3), + (3, 7, 4), + ), + ) adj = DT.Adjacent( - Dict(@_adj(2, 9, 8)..., + Dict( + @_adj(2, 9, 8)..., @_adj(2, 8, 6)..., @_adj(2, 6, 1)..., @_adj(1, 6, 10)..., @@ -160,9 +177,12 @@ end @_adj(4, 7, DT.𝒢)..., @_adj(7, 9, DT.𝒢)..., @_adj(9, 2, DT.𝒢)..., - @_adj(2, 1, DT.𝒢)...)) + @_adj(2, 1, DT.𝒢)..., + ), + ) adj2 = DT.Adjacent( - Dict(@_adj(2, 9, 8)..., + Dict( + @_adj(2, 9, 8)..., @_adj(2, 8, 6)..., @_adj(2, 6, 1)..., @_adj(1, 6, 10)..., @@ -179,69 +199,159 @@ end (4, 7) => DT.𝒢, (7, 9) => DT.𝒢, (9, 2) => DT.𝒢, - (2, 1) => DT.𝒢)) - adj2v = DT.Adjacent2Vertex(Dict(DT.𝒢 => Set{NTuple{2,Int}}(((1, 5), - (5, 4), - (4, 7), - (7, 9), - (9, 2), - (2, 1))), - 1 => Set{NTuple{2,Int}}(((2, 6), (6, 10), - (10, 5), - (5, DT.𝒢), - (DT.𝒢, 2))), - 2 => Set{NTuple{2,Int}}(((9, 8), (8, 6), (6, 1), - (1, DT.𝒢), - (DT.𝒢, 9))), - 3 => Set{NTuple{2,Int}}(((9, 7), (7, 4), (4, 10), - (10, 8), (8, 9))), - 4 => Set{NTuple{2,Int}}(((5, 10), (10, 3), - (3, 7), - (7, DT.𝒢), - (DT.𝒢, 5))), - 5 => Set{NTuple{2,Int}}(((1, 10), (10, 4), - (4, DT.𝒢), - (DT.𝒢, 1))), - 6 => Set{NTuple{2,Int}}(((2, 8), (8, 10), - (10, 1), (1, 2))), - 7 => Set{NTuple{2,Int}}(((4, 3), (3, 9), - (9, DT.𝒢), - (DT.𝒢, 4))), - 8 => Set{NTuple{2,Int}}(((3, 10), (10, 6), - (6, 2), (2, 9), (9, 3))), - 9 => Set{NTuple{2,Int}}(((7, 3), (3, 8), (8, 2), - (2, DT.𝒢), - (DT.𝒢, 7))), - 10 => Set{NTuple{2,Int}}(((8, 3), (3, 4), (4, 5), - (5, 1), (1, 6), - (6, 8))))) - adj2v2 = DT.Adjacent2Vertex(Dict(DT.𝒢 => Set{NTuple{2,Int}}(((1, 5), - (5, 4), - (4, 7), - (7, 9), - (9, 2), - (2, 1))), - 1 => Set{NTuple{2,Int}}(((2, 6), (6, 10), - (10, 5))), - 2 => Set{NTuple{2,Int}}(((9, 8), (8, 6), - (6, 1))), - 3 => Set{NTuple{2,Int}}(((9, 7), (7, 4), - (4, 10), (10, 8), - (8, 9))), - 4 => Set{NTuple{2,Int}}(((5, 10), (10, 3), - (3, 7))), - 5 => Set{NTuple{2,Int}}(((1, 10), (10, 4))), - 6 => Set{NTuple{2,Int}}(((2, 8), (8, 10), - (10, 1), (1, 2))), - 7 => Set{NTuple{2,Int}}(((4, 3), (3, 9))), - 8 => Set{NTuple{2,Int}}(((3, 10), (10, 6), - (6, 2), (2, 9), - (9, 3))), - 9 => Set{NTuple{2,Int}}(((7, 3), (3, 8), - (8, 2))), - 10 => Set{NTuple{2,Int}}(((8, 3), (3, 4), - (4, 5), (5, 1), - (1, 6), (6, 8))))) + (2, 1) => DT.𝒢, + ), + ) + adj2v = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}( + ( + (1, 5), + (5, 4), + (4, 7), + (7, 9), + (9, 2), + (2, 1), + ), + ), + 1 => Set{NTuple{2, Int}}( + ( + (2, 6), (6, 10), + (10, 5), + (5, DT.𝒢), + (DT.𝒢, 2), + ), + ), + 2 => Set{NTuple{2, Int}}( + ( + (9, 8), (8, 6), (6, 1), + (1, DT.𝒢), + (DT.𝒢, 9), + ), + ), + 3 => Set{NTuple{2, Int}}( + ( + (9, 7), (7, 4), (4, 10), + (10, 8), (8, 9), + ), + ), + 4 => Set{NTuple{2, Int}}( + ( + (5, 10), (10, 3), + (3, 7), + (7, DT.𝒢), + (DT.𝒢, 5), + ), + ), + 5 => Set{NTuple{2, Int}}( + ( + (1, 10), (10, 4), + (4, DT.𝒢), + (DT.𝒢, 1), + ), + ), + 6 => Set{NTuple{2, Int}}( + ( + (2, 8), (8, 10), + (10, 1), (1, 2), + ), + ), + 7 => Set{NTuple{2, Int}}( + ( + (4, 3), (3, 9), + (9, DT.𝒢), + (DT.𝒢, 4), + ), + ), + 8 => Set{NTuple{2, Int}}( + ( + (3, 10), (10, 6), + (6, 2), (2, 9), (9, 3), + ), + ), + 9 => Set{NTuple{2, Int}}( + ( + (7, 3), (3, 8), (8, 2), + (2, DT.𝒢), + (DT.𝒢, 7), + ), + ), + 10 => Set{NTuple{2, Int}}( + ( + (8, 3), (3, 4), (4, 5), + (5, 1), (1, 6), + (6, 8), + ), + ), + ), + ) + adj2v2 = DT.Adjacent2Vertex( + Dict( + DT.𝒢 => Set{NTuple{2, Int}}( + ( + (1, 5), + (5, 4), + (4, 7), + (7, 9), + (9, 2), + (2, 1), + ), + ), + 1 => Set{NTuple{2, Int}}( + ( + (2, 6), (6, 10), + (10, 5), + ), + ), + 2 => Set{NTuple{2, Int}}( + ( + (9, 8), (8, 6), + (6, 1), + ), + ), + 3 => Set{NTuple{2, Int}}( + ( + (9, 7), (7, 4), + (4, 10), (10, 8), + (8, 9), + ), + ), + 4 => Set{NTuple{2, Int}}( + ( + (5, 10), (10, 3), + (3, 7), + ), + ), + 5 => Set{NTuple{2, Int}}(((1, 10), (10, 4))), + 6 => Set{NTuple{2, Int}}( + ( + (2, 8), (8, 10), + (10, 1), (1, 2), + ), + ), + 7 => Set{NTuple{2, Int}}(((4, 3), (3, 9))), + 8 => Set{NTuple{2, Int}}( + ( + (3, 10), (10, 6), + (6, 2), (2, 9), + (9, 3), + ), + ), + 9 => Set{NTuple{2, Int}}( + ( + (7, 3), (3, 8), + (8, 2), + ), + ), + 10 => Set{NTuple{2, Int}}( + ( + (8, 3), (3, 4), + (4, 5), (5, 1), + (1, 6), (6, 8), + ), + ), + ), + ) A = zeros(Int, 10, 10) A[1, [2, 6, 10, 5]] .= 1 A[2, [1, 6, 8, 9]] .= 1 @@ -255,8 +365,8 @@ end A[10, [1, 6, 8, 3, 4, 5]] .= 1 B = zeros(Int, 11, 11) B[2:end, 2:end] .= A - B[1, [1, 5, 4, 7, 9, 2].+1] .= 1 - B[[1, 5, 4, 7, 9, 2].+1, 1] .= 1 + B[1, [1, 5, 4, 7, 9, 2] .+ 1] .= 1 + B[[1, 5, 4, 7, 9, 2] .+ 1, 1] .= 1 graph = _make_graph_from_adjacency(B, Dict(1 => DT.𝒢, (2:11 .=> 1:10)...)) a = [1.5, 4.0] b = [0.0, 3.5] @@ -270,20 +380,20 @@ end j = [1.5, 3.0] pts = [a, b, c, d, e, f, g, h, i, j] ch = DT.ConvexHull(pts, [1, 2, 9, 7, 4, 5, 1]) - tri = DT.triangulate(pts; delete_ghosts=false, predicates=PT()) + tri = DT.triangulate(pts; delete_ghosts = false, predicates = PT()) @test DT.compare_triangle_collections(T, get_triangles(tri)) && - get_adjacent(tri) == adj && - get_adjacent2vertex(tri) == adj2v && - DT.get_graph(tri) == graph && - get_convex_hull(tri) == ch - @test validate_triangulation(tri; predicates=PT()) + get_adjacent(tri) == adj && + get_adjacent2vertex(tri) == adj2v && + DT.get_graph(tri) == graph && + get_convex_hull(tri) == ch + @test validate_triangulation(tri; predicates = PT()) delete_ghost_triangles!(tri) @test DT.compare_triangle_collections(T2, get_triangles(tri)) && - get_adjacent(tri) == adj2 && - get_adjacent2vertex(tri) == adj2v2 && - get_graph(tri) == graph && - get_convex_hull(tri) == ch - @test validate_triangulation(tri; predicates=PT()) + get_adjacent(tri) == adj2 && + get_adjacent2vertex(tri) == adj2v2 && + get_graph(tri) == graph && + get_convex_hull(tri) == ch + @test validate_triangulation(tri; predicates = PT()) end a = [1.5, 4.0] b = [0.0, 3.5] @@ -296,8 +406,8 @@ end i = [0.0, 0.5] j = [1.5, 3.0] pts = [a, b, c, d, e, f, g, h, i, j] - tri = DT.triangulate(pts; delete_ghosts=false, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = DT.triangulate(pts; delete_ghosts = false, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end @@ -306,7 +416,7 @@ end i = 265 rng = StableRNG(i) points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.5, 0.5), (0.2, 0.8), (0.1, 0.785)] - tri = triangulate(points; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + tri = triangulate(points; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end -end \ No newline at end of file +end diff --git a/test/triangulation/check_args.jl b/test/triangulation/check_args.jl index 3ea95bad2..9f51a6914 100644 --- a/test/triangulation/check_args.jl +++ b/test/triangulation/check_args.jl @@ -1,7 +1,7 @@ using ..DelaunayTriangulation const DT = DelaunayTriangulation -_test_throws(e1, e2=e1) = @static VERSION ≥ v"1.9" ? e1 : e2 +_test_throws(e1, e2 = e1) = @static VERSION ≥ v"1.9" ? e1 : e2 @testset "A simple case" begin @@ -17,7 +17,7 @@ end hierarchy = DT.construct_polygon_hierarchy(points) @test_throws _test_throws(DT.InsufficientPointsError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InsufficientPointsError: The provided point set has 2 points, but triangulations require at least three points.", DT.InsufficientPointsError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InsufficientPointsError) triangulate(points, predicates=rt()) + @test_throws _test_throws(DT.InsufficientPointsError) triangulate(points, predicates = rt()) end @testset "Duplicate points" begin @@ -29,7 +29,7 @@ end (1.0, 1.0) at indices [1, 4] (2.0, 2.0) at indices [2, 7, 8] (5.5, 17.3) at indices [3, 10].", DT.DuplicatePointsError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.DuplicatePointsError) triangulate(points, predicates=rt()) + @test_throws _test_throws(DT.DuplicatePointsError) triangulate(points, predicates = rt()) end @testset "Orientation and connectivity of a single boundary curve" begin @@ -40,13 +40,13 @@ end boundary_nodes[5] = 3 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary ends in vertex 3 but starts at vertex 1.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [4, 3, 2, 1, 4] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(curve).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[1, 2, 3, 4, 1]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @@ -54,13 +54,13 @@ end boundary_nodes[1][1] = 2 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary ends in vertex 1 but starts at vertex 2.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[4, 3, 2, 1, 4]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[[1, 2, 3, 4, 1]]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @@ -68,13 +68,13 @@ end boundary_nodes[1][1][end] = 2 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary ends in vertex 2 but starts at vertex 1.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[[4, 3, 2, 1, 4]]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) end @testset "Orientation and connectivity of a sectioned boundary curve" begin @@ -85,17 +85,17 @@ end boundary_nodes[1][3] = 5 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: Segment 1 ends at vertex 5 but the next segment, segment 2, starts at vertex 3.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes[1][3] = 3 boundary_nodes[4][4] = 2 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: Segment 4 ends at vertex 2 but the next segment, segment 1, starts at vertex 1.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes[4][4] = 1 boundary_nodes[1][1] = 8 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: Segment 4 ends at vertex 1 but the next segment, segment 1, starts at vertex 8.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) points = [(0.0, 0.0), (0.5, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.0), (0.0, 1.0), (0.0, 0.5), (0.0, 0.25)] @@ -103,7 +103,7 @@ end hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] boundary_nodes = [[1, 2], [2, 3, 1]] @@ -112,7 +112,7 @@ end boundary_nodes[1][2] = 3 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: Segment 1 ends at vertex 3 but the next segment, segment 2, starts at vertex 2.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes[1][2] = 2 boundary_nodes[2][3] = 5 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @@ -121,40 +121,42 @@ end boundary_nodes[1][1] = 3 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: Segment 2 ends at vertex 1 but the next segment, segment 1, starts at vertex 3.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) end @testset "Orientation and connectivity of a multiply-connected boundary" begin - points = [(0.0, 0.0), (0.5, 0.1), (1.0, 0.0), (0.9, 0.5), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), - (0.3, 0.3), (0.7, 0.3), (0.7, 0.7), (0.3, 0.7)] + points = [ + (0.0, 0.0), (0.5, 0.1), (1.0, 0.0), (0.9, 0.5), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), + (0.3, 0.3), (0.7, 0.3), (0.7, 0.7), (0.3, 0.7), + ] boundary_nodes = [[[1, 2, 3, 4, 5, 6, 7, 1]], [[11, 10, 9, 8, 11]]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test DT.check_args(points, boundary_nodes, hierarchy) boundary_nodes[1][1][end] = 8 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary curve with index 1 ends in vertex 8 but starts at vertex 1.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes[1][1][end] = 1 boundary_nodes[1][1][1] = 4 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary curve with index 1 ends in vertex 1 but starts at vertex 4.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes[1][1][1] = 1 boundary_nodes[2][1][end] = 5 @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentConnectionError: The boundary curve with index 2 ends in vertex 5 but starts at vertex 11.", DT.InconsistentConnectionError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentConnectionError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[[1, 7, 6, 5, 4, 3, 2, 1]], [[11, 10, 9, 8, 11]]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) boundary_nodes = [[[1, 2, 3, 4, 5, 6, 7, 1]], [[11, 8, 9, 10, 11]]] hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 2 should be negative, but it is positive. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) end @testset "Orientation and connectivity of a disjoint boundary" begin @@ -302,10 +304,13 @@ end U_curve = [[T, U, V, W, Z, A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, K1, L1, M1, N1, O1, T]] L_curve = [[P1, Q1, R1, S1, P1]] I_curve = [[T1, U1, V1, W1, T1]] - A_curve_outline = [[ - K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, - O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, - H5, I5, J5, K5]] + A_curve_outline = [ + [ + K5, W3, Z3, A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, K4, L4, M4, N4, + O4, P4, Q4, R4, S4, T4, U4, V4, W4, Z4, A5, B5, C5, D5, E5, F5, G5, + H5, I5, J5, K5, + ], + ] A_curve_hole = [[L5, M5, N5, O5, P5, Q5, R5, S5, T5, U5, L5]] dot_1 = [[Z1, A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, Z1]] dot_2 = [[Z2, A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, Z2]] @@ -322,7 +327,7 @@ end hierarchy = DT.construct_polygon_hierarchy(points, boundary_nodes) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 7 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy) - @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates=rt()) + @test_throws _test_throws(DT.InconsistentOrientationError) triangulate(points; boundary_nodes, predicates = rt()) end @testset "Curve-bounded domains" begin @@ -338,7 +343,7 @@ end points_II = [ (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), - (0.75, 0.75), (0.25, 0.25) + (0.75, 0.75), (0.25, 0.25), ] enricher_II = DT.BoundaryEnricher(points_II, curve_II) points, boundary_nodes = get_points(enricher_II), get_boundary_nodes(enricher_II) @@ -351,7 +356,7 @@ end (0.0, 0.0), (0.25, 0.0), (0.5, 0.0), (0.75, 0.0), (1.0, 0.0), (1.0, 0.25), (1.0, 0.5), (1.0, 0.75), (1.0, 1.0), (0.0, 1.0), (0.0, 0.5), - (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75), (0.5, 0.5) + (0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75), (0.5, 0.5), ] enricher_III = DT.BoundaryEnricher(points_III, curve_III) points, boundary_nodes = get_points(enricher_III), get_boundary_nodes(enricher_III) @@ -360,14 +365,14 @@ end @test DT.check_args(enricher_III) curve_IV = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0))] - points_IV = NTuple{2,Float64}[] + points_IV = NTuple{2, Float64}[] enricher_IV = DT.BoundaryEnricher(points_IV, curve_IV) points, boundary_nodes = get_points(enricher_IV), get_boundary_nodes(enricher_IV) hierarchy = DT.get_polygon_hierarchy(enricher_IV) @test DT.check_args(points, boundary_nodes, hierarchy) @test DT.check_args(enricher_IV) - curve_IV = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0), positive=false)] - points_IV = NTuple{2,Float64}[] + curve_IV = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0), positive = false)] + points_IV = NTuple{2, Float64}[] enricher_IV = DT.BoundaryEnricher(points_IV, curve_IV) points, boundary_nodes = get_points(enricher_IV), get_boundary_nodes(enricher_IV) hierarchy = DT.get_polygon_hierarchy(enricher_IV) @@ -375,7 +380,7 @@ end str = "If this curve is defined by an AbstractParametricCurve, you may instead need to reverse the order of the control points defining the sections of the curve; the `positive` keyword may also be of interest for CircularArcs and EllipticalArcs." @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(curve).\n$str", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy, DT.get_boundary_curves(enricher_IV)) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(enricher_IV) - @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(curve).\n$str", DT.InconsistentOrientationError) DT.triangulate(NTuple{2,Float64}[]; boundary_nodes=[CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0), positive=false)], predicates=rt()) + @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 1 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(curve).\n$str", DT.InconsistentOrientationError) DT.triangulate(NTuple{2, Float64}[]; boundary_nodes = [CircularArc((1.0, 0.0), (1.0, 0.0), (0.0, 0.0), positive = false)], predicates = rt()) curve_V = [BezierCurve([(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)])] points_V = [(0.0, 0.0), (0.2, 0.25)] @@ -388,7 +393,7 @@ end curve_VI = [ [CircularArc((1.0, 0.0), (0.0, 1.0), (0.0, 0.0))], [BSpline([(0.0, 1.0), (-1.0, 2.0), (-2.0, 0.0), (-2.0, -1.0), (0.0, -2.0)])], - [5, 6, 10] + [5, 6, 10], ] points_VI = [(0.1, 0.1), (0.15, 0.15), (0.23, 0.23), (0.009, 0.11), (0.0, -2.0), (0.2, -1.7), (0.000591, 0.00019), (0.111, -0.005), (-0.0001, -0.00991), (1.0, 0.0)] enricher_VI = DT.BoundaryEnricher(points_VI, curve_VI) @@ -399,7 +404,7 @@ end curve_VII = [ [CircularArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0))], - [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])] + [BSpline([(-2.0, 0.0), (-2.0, -1.0), (0.0, -1.0), (1.0, -1.0), (2.0, -1.0), (2.0, 0.0)])], ] points_VII = [(2.0, 0.0), (0.0, 0.5)] enricher_VII = DT.BoundaryEnricher(points_VII, curve_VII) @@ -412,10 +417,12 @@ end [1, 2, 3, 4, 5], [DT.EllipticalArc((0.0, 0.0), (2.0, -2.0), (1.0, -1.0), sqrt(2), sqrt(2), 45.0)], [6, 7, 8, 9, 10], - [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)])] + [CatmullRomSpline([(10.0, -3.0), (20.0, 0.0), (18.0, 0.0), (10.0, 0.0)])], + ] + points_VIII = [ + (10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), + (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, 12.0), (14.0, 0.0), ] - points_VIII = [(10.0, 0.0), (8.0, 0.0), (4.0, 0.0), (2.0, 2.0), (0.0, 0.0), (2.0, -2.0), - (2.5, -2.0), (3.5, -2.0), (4.5, -3.0), (10.0, -3.0), (10.0, 12.0), (14.0, 0.0)] enricher_VIII = DT.BoundaryEnricher(points_VIII, curve_VIII) points, boundary_nodes = get_points(enricher_VIII), get_boundary_nodes(enricher_VIII) hierarchy = DT.get_polygon_hierarchy(enricher_VIII) @@ -424,13 +431,13 @@ end curve_IX = [ - [ - [1, 2, 3, 4, 5, 6, 7, 1] - ], - [ - [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive=false)] - ], - ] + [ + [1, 2, 3, 4, 5, 6, 7, 1], + ], + [ + [CircularArc((0.6, 0.5), (0.6, 0.5), (0.5, 0.5), positive = false)], + ], + ] points_IX = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 1.5), (0.0, 1.0), (0.0, 0.5), (0.0, 0.2)] enricher_IX = DT.BoundaryEnricher(points_IX, curve_IX) points, boundary_nodes = get_points(enricher_IX), get_boundary_nodes(enricher_IX) @@ -440,14 +447,14 @@ end curve_X = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]) - ] + [BSpline(reverse([(1.0, 0.2), (0.0, 0.4), (0.0, 0.3), (-1.0, 0.2)]))], reverse([4, 5, 6, 7, 8]), + ], ] points_X = [ - (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2) + (-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-1.0, 0.2), (-1.0, 0.1), (0.0, 0.1), (1.0, 0.1), (1.0, 0.2), ] enricher_X = DT.BoundaryEnricher(points_X, curve_X) points, boundary_nodes = get_points(enricher_X), get_boundary_nodes(enricher_X) @@ -457,23 +464,23 @@ end curve_XI = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))] + [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline(reverse([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)]))], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points_XI = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] enricher_XI = DT.BoundaryEnricher(points_XI, curve_XI) @@ -483,23 +490,23 @@ end @test DT.check_args(enricher_XI) curve_XI = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)])] + [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline([(0.0, -2.0), (1.0, -3.0), (0.0, -4.0), (-1.0, -3.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] points_XI = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] enricher_XI = DT.BoundaryEnricher(points_XI, curve_XI) @@ -509,23 +516,23 @@ end @test_throws _test_throws(DT.InconsistentConnectionError) DT.check_args(enricher_XI) curve_XI = [ [ - [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)] + [1, 2, 3], [DT.EllipticalArc((2.0, 0.0), (-2.0, 0.0), (0.0, 0.0), 2, 1 / 2, 0.0)], ], [ - [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])] + [BSpline([(0.0, 0.4), (1.0, 0.2), (0.0, 0.1), (-1.0, 0.2), (0.0, 0.4)])], ], [ - [4, 5, 6, 7, 4] + [4, 5, 6, 7, 4], ], [ - [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline([(-1.0, -3.0), (1.0, -3.0), (0.0, -4.0), (0.0, -2.0)])] + [BezierCurve(reverse([(-1.0, -3.0), (-1.0, -2.5), (0.0, -2.5), (0.0, -2.0)]))], [CatmullRomSpline([(-1.0, -3.0), (1.0, -3.0), (0.0, -4.0), (0.0, -2.0)])], ], [ - [12, 11, 10, 12] + [12, 11, 10, 12], ], [ - [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive=false)] - ] + [CircularArc((1.1, -3.0), (1.1, -3.0), (0.0, -3.0), positive = false)], + ], ] _curve_XI = deepcopy(curve_XI) points_XI = [(-2.0, 0.0), (0.0, 0.0), (2.0, 0.0), (-2.0, -5.0), (2.0, -5.0), (2.0, -1 / 10), (-2.0, -1 / 10), (-1.0, -3.0), (0.0, -4.0), (0.0, -2.3), (-0.5, -3.5), (0.9, -3.0)] @@ -536,19 +543,19 @@ end @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy, DT.get_boundary_curves(enricher_XI)) @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 4 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).\n$str", DT.InconsistentOrientationError) DT.check_args(points, boundary_nodes, hierarchy, DT.get_boundary_curves(enricher_XI)) @test_throws _test_throws(DT.InconsistentOrientationError) DT.check_args(enricher_XI) - @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 4 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).\n$str", DT.InconsistentOrientationError) triangulate(_points_XI; boundary_nodes=_curve_XI, predicates=rt()) + @test_throws _test_throws("InconsistentOrientationError: The orientation of the boundary curve with index 4 should be positive, but it is negative. You may be able to fix this by passing the curve as reverse(reverse.(curve)).\n$str", DT.InconsistentOrientationError) triangulate(_points_XI; boundary_nodes = _curve_XI, predicates = rt()) ctrl = [ (0.0, 0.0), (2.0, 0.0), (1.6, -0.1), (0.3, -0.2), (-0.31, -0.35), (-0.2, 1.0), (0.0, 0.8), (0.2, 0.6), (0.4, 0.4), - (2.0, 0.4), (0.0, 0.0) + (2.0, 0.4), (0.0, 0.0), ] reverse!(ctrl) points_XII = [ (-0.1, 0.8), (-0.15, -0.15), (0.3, -0.1), (0.0, -0.1), (-0.1, 0.0), - (0.4, 0.2), (0.2, 0.4), (0.0, 0.6) + (0.4, 0.2), (0.2, 0.4), (0.0, 0.6), ] curve_XII = [[[BSpline(ctrl)]], [[1, 8, 7, 6, 5, 4, 3, 2, 1]]] enricher_XII = DT.BoundaryEnricher(points_XII, curve_XII) @@ -556,4 +563,4 @@ end hierarchy = DT.get_polygon_hierarchy(enricher_XII) @test DT.check_args(points, boundary_nodes, hierarchy) @test DT.check_args(enricher_XII) -end \ No newline at end of file +end diff --git a/test/triangulation/constrained.jl b/test/triangulation/constrained.jl index 91bbd6d44..6143ad9da 100644 --- a/test/triangulation/constrained.jl +++ b/test/triangulation/constrained.jl @@ -11,24 +11,24 @@ using StableRNGs rng = StableRNG(i) points, edges, mat_edges = get_random_vertices_and_constrained_edges(40, 100, 20, rng) # Need to deepcopy edges below, else it gets changed and updated on the first call to tri, which changes the insertion order of the segments and thus comparing tri to _tri might not work - tri = triangulate(points; segments=deepcopy(edges), rng=StableRNG(i), predicates=PT()) + tri = triangulate(points; segments = deepcopy(edges), rng = StableRNG(i), predicates = PT()) if i % 5 == 0 - _tri = retriangulate(tri; segments=deepcopy(edges), rng=StableRNG(i), predicates=PT()) - @inferred retriangulate(tri; segments=deepcopy(edges), rng=StableRNG(i), predicates=PT()) + _tri = retriangulate(tri; segments = deepcopy(edges), rng = StableRNG(i), predicates = PT()) + @inferred retriangulate(tri; segments = deepcopy(edges), rng = StableRNG(i), predicates = PT()) @test tri == _tri end - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) empty!(get_all_segments(tri)) - @test !validate_triangulation(tri; predicates=PT(), print_result=false) + @test !validate_triangulation(tri; predicates = PT(), print_result = false) end for i in 1:4 @info "Testing random constrained Delaunay triangulations. Run: $i; Block: 2; Predicates: $PT" rng = StableRNG(i^5) points, edges, mat_edges = get_random_vertices_and_constrained_edges(200, 500, 100, rng) - tri = triangulate(points; segments=edges, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(points; segments = edges, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) empty!(get_all_segments(tri)) - @test !validate_triangulation(tri; predicates=PT(), print_result=false) + @test !validate_triangulation(tri; predicates = PT(), print_result = false) end end end @@ -38,8 +38,8 @@ end for PT in subtypes(DT.AbstractPredicateKernel) for i in 1:500 rng = StableRNG(i^6) - tri = triangulate(pts; segments=C, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(pts; segments = C, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -53,14 +53,14 @@ end pts = [(2rand(rng) - 1, rand(rng)) for _ in 1:100] x = LinRange(-1, 1, 26) a = 10.0 .^ (LinRange(0, log10(2), 20)) .- 1 - C = Set{NTuple{2,Int}}() + C = Set{NTuple{2, Int}}() for i in eachindex(a) y = a[i] * x .^ 2 append!(pts, zip(x, y)) - push!(C, [(j, j + 1) for j in (np+nx*(i-1)+1):(np+nx*(i-1)+(nx-1))]...) + push!(C, [(j, j + 1) for j in (np + nx * (i - 1) + 1):(np + nx * (i - 1) + (nx - 1))]...) end - tri = triangulate(pts; segments=C, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(pts; segments = C, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -70,8 +70,8 @@ end for i in 1:4 @info "Testing random collection of straight lines. Run: $i. Predicates: $PT" rng = StableRNG(i) - pts = NTuple{2,Float64}[] - C = Set{NTuple{2,Int}}() + pts = NTuple{2, Float64}[] + C = Set{NTuple{2, Int}}() j = 1 for i in 1:10 push!(pts, (2i / 11 - 1, 2rand(rng) - 1)) @@ -79,21 +79,21 @@ end push!(C, (j, j + 1)) j += 2 end - x1 = LinRange(-1, 1 - 1e-12, 10) + x1 = LinRange(-1, 1 - 1.0e-12, 10) y1 = LinRange(-1, -1, 10) x2 = LinRange(1, 1, 10) - y2 = LinRange(-1, 1 - 1e-12, 10) - x3 = LinRange(1, -1 + 1e-12, 10) + y2 = LinRange(-1, 1 - 1.0e-12, 10) + x3 = LinRange(1, -1 + 1.0e-12, 10) y3 = LinRange(1, 1, 10) x4 = LinRange(-1, -1, 10) - y4 = LinRange(1, -1 + 1e-12, 10) + y4 = LinRange(1, -1 + 1.0e-12, 10) append!(pts, zip(x1, y1), zip(x2, y2), zip(x3, y3), zip(x4, y4)) push!(C, [(j, j + 1) for j in 21:29]...) push!(C, [(j, j + 1) for j in 31:39]...) push!(C, [(j, j + 1) for j in 41:49]...) push!(C, [(j, j + 1) for j in 51:59]...) - tri = triangulate(pts; segments=C, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(pts; segments = C, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -109,16 +109,16 @@ end d = 7.0 nx = 13 ny = 20 - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - add_segment!(tri, 56, 162; rng, predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + add_segment!(tri, 56, 162; rng, predicates = PT()) for e in [(1, 249), (1, 250), (1, 251), (1, 26), (1, 39), (1, 52)] - add_segment!(tri, e; rng, predicates=PT()) + add_segment!(tri, e; rng, predicates = PT()) end - add_segment!(tri, 190, 99; rng, predicates=PT()) + add_segment!(tri, 190, 99; rng, predicates = PT()) for e in [(99, 113), (113, 101), (101, 115)] - add_segment!(tri, e; rng, predicates=PT()) + add_segment!(tri, e; rng, predicates = PT()) end - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) a = -0.1 b = 0.1 @@ -126,21 +126,21 @@ end d = 0.01 nx = 25 ny = 25 - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - tri = triangulate(get_points(tri); predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + tri = triangulate(get_points(tri); predicates = PT()) for i in 2:24 - add_segment!(tri, i, 600 + i; rng, predicates=PT()) + add_segment!(tri, i, 600 + i; rng, predicates = PT()) end - @test validate_triangulation(tri; predicates=PT()) - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - tri = triangulate(get_points(tri); rng, predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + tri = triangulate(get_points(tri); rng, predicates = PT()) for e in [(1, 28), (28, 103), (103, 180), (180, 625), (625, 523)] - add_segment!(tri, e; rng, predicates=PT()) + add_segment!(tri, e; rng, predicates = PT()) end for e in [(437, 614), (527, 602), (528, 603), (555, 605)] - add_segment!(tri, e; rng, predicates=PT()) + add_segment!(tri, e; rng, predicates = PT()) end - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) end for m in 1:10 rng = StableRNG(m) @@ -151,9 +151,9 @@ end d = 1.0 nx = 2 ny = 2 - tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts=false, single_boundary=true, predicates=PT()) - add_segment!(tri, 1, 4; rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate_rectangle(a, b, c, d, nx, ny; delete_ghosts = false, single_boundary = true, predicates = PT()) + add_segment!(tri, 1, 4; rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) a = 0 b = 1 @@ -161,19 +161,19 @@ end d = 5 nx = 25 ny = 3 - tri = triangulate_rectangle(a, b, c, d, nx, ny; predicates=PT(), delete_ghosts=false, single_boundary=true) - tri = triangulate(get_points(tri); rng, predicates=PT()) - for i in 1:(nx-1) + tri = triangulate_rectangle(a, b, c, d, nx, ny; predicates = PT(), delete_ghosts = false, single_boundary = true) + tri = triangulate(get_points(tri); rng, predicates = PT()) + for i in 1:(nx - 1) u = i v = 2nx - add_segment!(tri, u, v; rng, predicates=PT()) + add_segment!(tri, u, v; rng, predicates = PT()) end for i in 51:75 u = i v = 26 - add_segment!(tri, u, v; rng, predicates=PT()) + add_segment!(tri, u, v; rng, predicates = PT()) end - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -187,10 +187,10 @@ end bnd_pts = [(0.3cos(θ), 0.3sin(θ)) .+ 0.5 for θ in LinRange(0, 2π - 1 / 250, 25)] bnd_id = [(51:75)..., 51] append!(pts, bnd_pts) - tri = triangulate(pts; boundary_nodes=bnd_id, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) - _tri = retriangulate(tri; predicates=PT()) - @inferred retriangulate(tri; predicates=PT()) + tri = triangulate(pts; boundary_nodes = bnd_id, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) + _tri = retriangulate(tri; predicates = PT()) + @inferred retriangulate(tri; predicates = PT()) @test tri == _tri end end @@ -222,9 +222,9 @@ end inner_circle_y = [last.(circ_pts)] x = [outer_square_x, inner_circle_x] y = [outer_square_y, inner_circle_y] - nodes, pts = convert_boundary_points_to_indices(x, y; existing_points=pts) - tri = triangulate(pts; boundary_nodes=nodes, rng, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + nodes, pts = convert_boundary_points_to_indices(x, y; existing_points = pts) + tri = triangulate(pts; boundary_nodes = nodes, rng, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -234,12 +234,12 @@ end for L in 1:4 @info "Testing the addition of points into a constrained triangulation. Run: $L. Predicates: $PT" pts, C = example_for_testing_add_point_on_constrained_triangulation() - tri = triangulate(pts; segments=C, delete_ghosts=false, predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(pts; segments = C, delete_ghosts = false, predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) DT.push_point!(tri, 2, 1.8) - add_point!(tri, 15; predicates=PT()) + add_point!(tri, 15; predicates = PT()) DT.push_point!(tri, 1.57, 1.778) - add_point!(tri, 16; predicates=PT()) + add_point!(tri, 16; predicates = PT()) T = [ (1, 10, 11) (10, 6, 11) @@ -273,10 +273,10 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) (x, y) = (2.3258217552204066, 1.4540267924574883) # a while loop was used to find this point that broke the triangulation (fixed now, obviously) DT.push_point!(tri, x, y) - add_point!(tri, DT.num_points(tri); predicates=PT()) + add_point!(tri, DT.num_points(tri); predicates = PT()) T = [ (1, 10, 11) (10, 6, 11) @@ -312,13 +312,13 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) for i in 1:25 x = 4rand() y = 5rand() DT.push_point!(tri, x, y) - add_point!(tri, DT.num_points(tri); predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + add_point!(tri, DT.num_points(tri); predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) @test DT.edge_exists(tri, 1, 2) && DT.edge_exists(tri, 2, 1) end end @@ -331,19 +331,19 @@ end @info "Testing the addition of points into a constrained triangulation with interior segment collinearities. Run: $m. Predicates: $PT" pts, C = example_for_testing_add_point_on_constrained_triangulation() push!(C, (1, 12)) - tri = triangulate(pts; segments=C, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts; segments = C, delete_ghosts = false, predicates = PT()) new_points = [ (1.0, 3.0), (2.0, 3.0), (3.0, 3.0), - (4.0, 3.0) + (4.0, 3.0), ] DT.push_point!(tri, new_points[1]) - add_point!(tri, DT.num_points(tri), predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) @test sort_edge_vector(collect(get_interior_segments(tri))) == - sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 12)]))) == - sort_edge_vector(collect(get_interior_segments(tri))) + sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 12)]))) == + sort_edge_vector(collect(get_interior_segments(tri))) T = [ (1, 15, 5) (10, 6, 11) @@ -375,13 +375,13 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) DT.push_point!(tri, new_points[2]) - add_point!(tri, DT.num_points(tri), predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) @test sort_edge_vector(collect(get_interior_segments(tri))) == - sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 12)]))) == - sort_edge_vector(collect(get_interior_segments(tri))) + sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 12)]))) == + sort_edge_vector(collect(get_interior_segments(tri))) T = [ (16, 9, 15) (1, 10, 11) @@ -415,13 +415,13 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) DT.push_point!(tri, new_points[3]) - add_point!(tri, DT.num_points(tri), predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) @test sort_edge_vector(collect(get_interior_segments(tri))) == - sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 17), (17, 12)]))) == - sort_edge_vector(collect(get_interior_segments(tri))) + sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 17), (17, 12)]))) == + sort_edge_vector(collect(get_interior_segments(tri))) T = [ (13, 16, 14) (15, 1, 14) @@ -457,13 +457,13 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) DT.push_point!(tri, new_points[4]) - add_point!(tri, DT.num_points(tri), predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) @test sort_edge_vector(collect(get_interior_segments(tri))) == - sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 17), (17, 18), (18, 12)]))) == - sort_edge_vector(collect(get_interior_segments(tri))) + sort_edge_vector(collect(Set([(1, 2), (1, 15), (15, 16), (16, 17), (17, 18), (18, 12)]))) == + sort_edge_vector(collect(get_interior_segments(tri))) T = [ (13, 16, 14) (15, 1, 14) @@ -501,17 +501,17 @@ end (6, 4, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) - add_segment!(tri, 6, 10, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + add_segment!(tri, 6, 10, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) new_points = LinRange(-1.8, 2.8, 25) new_points = collect(new_points) shuffle!(new_points) foreach(new_points) do p DT.push_point!(tri, -3.0, p) - add_point!(tri, DT.num_points(tri), predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end @test length(get_interior_segments(tri)) == 32 @test length(get_all_segments(tri)) == 32 @@ -521,8 +521,8 @@ end shuffle!(new_points) foreach(new_points) do p DT.push_point!(tri, p, 3.0) - add_point!(tri, DT.num_points(tri), predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + add_point!(tri, DT.num_points(tri), predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end end @@ -531,9 +531,9 @@ end @testset "Adding a point onto a single boundary edge" begin for PT in subtypes(DT.AbstractPredicateKernel) for i in 1:8 - tri = triangulate_rectangle(0, 10, 0, 20, 11, 21; delete_ghosts=false, predicates=PT()) - add_point!(tri, 1.5, 0.0; initial_search_point=i, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + tri = triangulate_rectangle(0, 10, 0, 20, 11, 21; delete_ghosts = false, predicates = PT()) + add_point!(tri, 1.5, 0.0; initial_search_point = i, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) @test tri.boundary_nodes[1] == [1, 2, 232, 3, 4, 5, 6, 7, 8, 9, 10, 11] @test isempty(tri.interior_segments) @test (2, 232) ∈ get_all_segments(tri) || (232, 2) ∈ get_all_segments(tri) @@ -549,27 +549,27 @@ end @testset "Adding a point onto multiple boundary edges with multiple ghost indices" begin for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:8 - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, predicates=PT()) - add_point!(tri, 1.5, 0.0, predicates=PT()) - add_segment!(tri, 1, 45, predicates=PT()) - add_point!(tri, 4.0, 2.5, predicates=PT()) - add_point!(tri, 4.0, 2.6, predicates=PT()) - add_point!(tri, 4.0, 7.3, predicates=PT()) - add_point!(tri, 2.5, 8.0, predicates=PT()) - add_point!(tri, 1.3, 8.0, predicates=PT()) - add_point!(tri, 0.0, 6.7, predicates=PT()) - add_point!(tri, 0.0, 2.5, predicates=PT()) - add_segment!(tri, 11, 43, predicates=PT()) - add_segment!(tri, 4, 34, predicates=PT()) - add_segment!(tri, 4, 23, predicates=PT()) - add_segment!(tri, 45, 27, predicates=PT()) + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, predicates = PT()) + add_point!(tri, 1.5, 0.0, predicates = PT()) + add_segment!(tri, 1, 45, predicates = PT()) + add_point!(tri, 4.0, 2.5, predicates = PT()) + add_point!(tri, 4.0, 2.6, predicates = PT()) + add_point!(tri, 4.0, 7.3, predicates = PT()) + add_point!(tri, 2.5, 8.0, predicates = PT()) + add_point!(tri, 1.3, 8.0, predicates = PT()) + add_point!(tri, 0.0, 6.7, predicates = PT()) + add_point!(tri, 0.0, 2.5, predicates = PT()) + add_segment!(tri, 11, 43, predicates = PT()) + add_segment!(tri, 4, 34, predicates = PT()) + add_segment!(tri, 4, 23, predicates = PT()) + add_segment!(tri, 45, 27, predicates = PT()) @test DT.get_boundary_nodes(tri) == [ [1, 2, 46, 3, 4, 5], [5, 10, 15, 47, 48, 20, 25, 30, 35, 40, 49, 45], [45, 44, 50, 43, 51, 42, 41], - [41, 36, 52, 31, 26, 21, 16, 53, 11, 6, 1] + [41, 36, 52, 31, 26, 21, 16, 53, 11, 6, 1], ] - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) end end end @@ -577,23 +577,25 @@ end @testset "Handling only a single boundary index" begin for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:8 - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, single_boundary=true, predicates=PT()) + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, single_boundary = true, predicates = PT()) for x in [0.2, 0.3, 1.5, 2.3, 2.8, 3.5] - add_point!(tri, x, 0.0, predicates=PT()) + add_point!(tri, x, 0.0, predicates = PT()) end for y in [0.2, 0.4, 1.6, 4.5, 6.7, 7.5] - add_point!(tri, 4.0, y, predicates=PT()) + add_point!(tri, 4.0, y, predicates = PT()) end for x in [0.4, 1.5, 1.8, 2.3, 2.5, 3.9] - add_point!(tri, x, 8.0, predicates=PT()) + add_point!(tri, x, 8.0, predicates = PT()) end for y in [7.5, 5.9, 3.4, 1.9, 0.1] - add_point!(tri, 0.0, y, predicates=PT()) + add_point!(tri, 0.0, y, predicates = PT()) end - @test DT.get_boundary_nodes(tri) == [1, 46, 47, 2, 48, 3, 49, 50, 4, 51, 5, 52, 53, + @test DT.get_boundary_nodes(tri) == [ + 1, 46, 47, 2, 48, 3, 49, 50, 4, 51, 5, 52, 53, 10, 54, 15, 20, 25, 55, 30, 35, 56, 40, 57, 45, 63, 44, 62, 61, 43, 60, 59, 42, 58, - 41, 64, 36, 31, 65, 26, 21, 66, 16, 11, 67, 6, 68, 1] - @test validate_triangulation(tri, predicates=PT()) + 41, 64, 36, 31, 65, 26, 21, 66, 16, 11, 67, 6, 68, 1, + ] + @test validate_triangulation(tri, predicates = PT()) end end end @@ -602,38 +604,40 @@ end @testset "Contiguous boundary" begin for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:8 - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, predicates=PT()) + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, predicates = PT()) pts = get_points(tri) boundary_nodes = [1, 5, 45, 41, 1] - tri = triangulate(pts; boundary_nodes, randomise=false, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts; boundary_nodes, randomise = false, delete_ghosts = false, predicates = PT()) flip_edge!(tri, 1, 7) flip_edge!(tri, 2, 8) - @test sort_edge_vector(collect(get_all_segments(tri))) == sort_edge_vector([ - (1, 2) - (2, 3) - (3, 4) - (4, 5) - (5, 10) - (6, 1) - (10, 15) - (11, 6) - (15, 20) - (16, 11) - (20, 25) - (21, 16) - (25, 30) - (26, 21) - (30, 35) - (31, 26) - (35, 40) - (36, 31) - (40, 45) - (41, 36) - (42, 41) - (43, 42) - (44, 43) - (45, 44) - ]) + @test sort_edge_vector(collect(get_all_segments(tri))) == sort_edge_vector( + [ + (1, 2) + (2, 3) + (3, 4) + (4, 5) + (5, 10) + (6, 1) + (10, 15) + (11, 6) + (15, 20) + (16, 11) + (20, 25) + (21, 16) + (25, 30) + (26, 21) + (30, 35) + (31, 26) + (35, 40) + (36, 31) + (40, 45) + (41, 36) + (42, 41) + (43, 42) + (44, 43) + (45, 44) + ], + ) T = [ (11, 7, 12) (22, 27, 26) @@ -725,15 +729,17 @@ end (2, 1, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test get_boundary_nodes(tri) == [1, 2, 3, 4, 5, + @test get_boundary_nodes(tri) == [ + 1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45, 44, 43, 42, 41, 36, 31, 26, - 21, 16, 11, 6, 1] - @test validate_triangulation(tri, predicates=PT()) - add_segment!(tri, 1, 45, predicates=PT()) - add_segment!(tri, 6, 44, predicates=PT()) - add_segment!(tri, 34, 4, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + 21, 16, 11, 6, 1, + ] + @test validate_triangulation(tri, predicates = PT()) + add_segment!(tri, 1, 45, predicates = PT()) + add_segment!(tri, 6, 44, predicates = PT()) + add_segment!(tri, 34, 4, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end end @@ -741,38 +747,40 @@ end @testset "Multiple segments" begin for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:8 - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, predicates=PT()) + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, predicates = PT()) pts = get_points(tri) boundary_nodes = [[1, 5], [5, 45], [45, 41], [41, 1]] - tri = triangulate(pts; boundary_nodes, randomise=false, delete_ghosts=false, predicates=PT()) + tri = triangulate(pts; boundary_nodes, randomise = false, delete_ghosts = false, predicates = PT()) flip_edge!(tri, 1, 7) flip_edge!(tri, 2, 8) - @test sort_edge_vector(collect(get_all_segments(tri))) == sort_edge_vector([ - (1, 2) - (2, 3) - (3, 4) - (4, 5) - (5, 10) - (6, 1) - (10, 15) - (11, 6) - (15, 20) - (16, 11) - (20, 25) - (21, 16) - (25, 30) - (26, 21) - (30, 35) - (31, 26) - (35, 40) - (36, 31) - (40, 45) - (41, 36) - (42, 41) - (43, 42) - (44, 43) - (45, 44) - ]) + @test sort_edge_vector(collect(get_all_segments(tri))) == sort_edge_vector( + [ + (1, 2) + (2, 3) + (3, 4) + (4, 5) + (5, 10) + (6, 1) + (10, 15) + (11, 6) + (15, 20) + (16, 11) + (20, 25) + (21, 16) + (25, 30) + (26, 21) + (30, 35) + (31, 26) + (35, 40) + (36, 31) + (40, 45) + (41, 36) + (42, 41) + (43, 42) + (44, 43) + (45, 44) + ], + ) T = [ (11, 7, 12) (22, 27, 26) @@ -864,15 +872,17 @@ end (2, 1, DT.𝒢) ] @test DT.compare_triangle_collections(get_triangles(tri), T) - @test get_boundary_nodes(tri) == [[1, 2, 3, 4, 5], + @test get_boundary_nodes(tri) == [ + [1, 2, 3, 4, 5], [5, 10, 15, 20, 25, 30, 35, 40, 45], [45, 44, 43, 42, 41], - [41, 36, 31, 26, 21, 16, 11, 6, 1]] - @test validate_triangulation(tri, predicates=PT()) - add_segment!(tri, 1, 45, predicates=PT()) - add_segment!(tri, 6, 44, predicates=PT()) - add_segment!(tri, 34, 4, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + [41, 36, 31, 26, 21, 16, 11, 6, 1], + ] + @test validate_triangulation(tri, predicates = PT()) + add_segment!(tri, 1, 45, predicates = PT()) + add_segment!(tri, 6, 44, predicates = PT()) + add_segment!(tri, 34, 4, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end end @@ -880,15 +890,16 @@ end @testset "Adding points and segments into a multiply-connected domain" begin for PT in subtypes(DT.AbstractPredicateKernel) - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, predicates=PT()) - boundary_nodes = [[ - [1, 5, 45], [45, 41], [41, 1] + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, predicates = PT()) + boundary_nodes = [ + [ + [1, 5, 45], [45, 41], [41, 1], ], - [[12, 32, 34], [34, 14, 12]] + [[12, 32, 34], [34, 14, 12]], ] points = get_points(tri) rng = StableRNG(19119) - tri = triangulate(points; boundary_nodes, delete_ghosts=false, randomise=false, rng, predicates=PT()) + tri = triangulate(points; boundary_nodes, delete_ghosts = false, randomise = false, rng, predicates = PT()) flip_edge!(tri, 1, 7) flip_edge!(tri, 2, 8) T = [ @@ -1017,106 +1028,111 @@ end ] @test sort_edge_vector(collect(get_all_segments(tri))) == sort_edge_vector(C) @test DT.compare_triangle_collections(get_triangles(tri), T) - @test validate_triangulation(tri, predicates=PT()) - @test get_boundary_nodes(tri) == [[ - [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45], [45, 44, 43, 42, 41], [41, 36, 31, 26, 21, 16, 11, 6, 1] + @test validate_triangulation(tri, predicates = PT()) + @test get_boundary_nodes(tri) == [ + [ + [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45], [45, 44, 43, 42, 41], [41, 36, 31, 26, 21, 16, 11, 6, 1], ], - [[12, 17, 22, 27, 32, 33, 34], [34, 29, 24, 19, 14, 13, 12]] + [[12, 17, 22, 27, 32, 33, 34], [34, 29, 24, 19, 14, 13, 12]], ] - add_point!(tri, 1.5, 0.0; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 2.5, 0.0; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 4.0, 2.5; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 4.0, 7.5; rng, predicates=PT()) - add_point!(tri, 2.5, 8.0; rng, predicates=PT()) - add_point!(tri, 0.0, 5.5; rng, predicates=PT()) - add_point!(tri, 0.5, 2.2; rng, predicates=PT()) - add_segment!(tri, 21, 27; rng, predicates=PT()) - add_segment!(tri, 14, 45; rng, predicates=PT()) - add_point!(tri, 1.0, 2.5; rng, predicates=PT()) - add_point!(tri, 1.0, 5.5; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 2.5, 2.0; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 3.0, 5.5; rng, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 2.5, 6.0; rng, predicates=PT()) - add_segment!(tri, 12, 5, predicates=PT()) - add_segment!(tri, 2, 52, predicates=PT()) - add_segment!(tri, 53, 21, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - @test get_boundary_nodes(tri) == [[ + add_point!(tri, 1.5, 0.0; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 2.5, 0.0; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 4.0, 2.5; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 4.0, 7.5; rng, predicates = PT()) + add_point!(tri, 2.5, 8.0; rng, predicates = PT()) + add_point!(tri, 0.0, 5.5; rng, predicates = PT()) + add_point!(tri, 0.5, 2.2; rng, predicates = PT()) + add_segment!(tri, 21, 27; rng, predicates = PT()) + add_segment!(tri, 14, 45; rng, predicates = PT()) + add_point!(tri, 1.0, 2.5; rng, predicates = PT()) + add_point!(tri, 1.0, 5.5; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 2.5, 2.0; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 3.0, 5.5; rng, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 2.5, 6.0; rng, predicates = PT()) + add_segment!(tri, 12, 5, predicates = PT()) + add_segment!(tri, 2, 52, predicates = PT()) + add_segment!(tri, 53, 21, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + @test get_boundary_nodes(tri) == [ + [ [1, 2, 46, 3, 47, 4, 5, 10, 15, 48, 20, 25, 30, 35, 40, 49, 45], [45, 44, 50, 43, 42, 41], - [41, 36, 31, 51, 26, 21, 16, 11, 6, 1] + [41, 36, 31, 51, 26, 21, 16, 11, 6, 1], ], [ [12, 53, 17, 22, 27, 54, 32, 33, 57, 34], - [34, 56, 29, 24, 19, 14, 55, 13, 12] - ] + [34, 56, 29, 24, 19, 14, 55, 13, 12], + ], ] - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 0.5, 4.4, predicates=PT()) - add_point!(tri, 0.5, 4.6, predicates=PT()) - add_point!(tri, 0.5, 4.5, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 0.5, 4.4, predicates = PT()) + add_point!(tri, 0.5, 4.6, predicates = PT()) + add_point!(tri, 0.5, 4.5, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) for L in 1:3 - tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts=false, predicates=PT()) - boundary_nodes = [[ - [1, 5, 45], [45, 41], [41, 1] + tri = triangulate_rectangle(0, 4, 0, 8, 5, 9; delete_ghosts = false, predicates = PT()) + boundary_nodes = [ + [ + [1, 5, 45], [45, 41], [41, 1], ], - [[12, 32, 34], [34, 14, 12]] + [[12, 32, 34], [34, 14, 12]], ] points = get_points(tri) - tri = triangulate(points; boundary_nodes, delete_ghosts=false, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - @test get_boundary_nodes(tri) == [[ - [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45], [45, 44, 43, 42, 41], [41, 36, 31, 26, 21, 16, 11, 6, 1] + tri = triangulate(points; boundary_nodes, delete_ghosts = false, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + @test get_boundary_nodes(tri) == [ + [ + [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45], [45, 44, 43, 42, 41], [41, 36, 31, 26, 21, 16, 11, 6, 1], ], - [[12, 17, 22, 27, 32, 33, 34], [34, 29, 24, 19, 14, 13, 12]] + [[12, 17, 22, 27, 32, 33, 34], [34, 29, 24, 19, 14, 13, 12]], ] - add_point!(tri, 1.5, 0.0, predicates=PT()) - add_point!(tri, 2.5, 0.0, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 4.0, 2.5, predicates=PT()) - add_point!(tri, 4.0, 7.5, predicates=PT()) - add_point!(tri, 2.5, 8.0, predicates=PT()) - add_point!(tri, 0.0, 5.5, predicates=PT()) - add_point!(tri, 0.5, 2.2, predicates=PT()) - add_segment!(tri, 21, 27, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_segment!(tri, 14, 45, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 1.0, 2.5, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 1.0, 5.5, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 2.5, 2.0, predicates=PT()) - add_point!(tri, 3.0, 5.5, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 2.5, 6.0, predicates=PT()) - add_segment!(tri, 12, 5, predicates=PT()) - add_segment!(tri, 2, 52, predicates=PT()) - add_segment!(tri, 53, 21, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) - @test get_boundary_nodes(tri) == [[ + add_point!(tri, 1.5, 0.0, predicates = PT()) + add_point!(tri, 2.5, 0.0, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 4.0, 2.5, predicates = PT()) + add_point!(tri, 4.0, 7.5, predicates = PT()) + add_point!(tri, 2.5, 8.0, predicates = PT()) + add_point!(tri, 0.0, 5.5, predicates = PT()) + add_point!(tri, 0.5, 2.2, predicates = PT()) + add_segment!(tri, 21, 27, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_segment!(tri, 14, 45, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 1.0, 2.5, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 1.0, 5.5, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 2.5, 2.0, predicates = PT()) + add_point!(tri, 3.0, 5.5, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 2.5, 6.0, predicates = PT()) + add_segment!(tri, 12, 5, predicates = PT()) + add_segment!(tri, 2, 52, predicates = PT()) + add_segment!(tri, 53, 21, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) + @test get_boundary_nodes(tri) == [ + [ [1, 2, 46, 3, 47, 4, 5, 10, 15, 48, 20, 25, 30, 35, 40, 49, 45], [45, 44, 50, 43, 42, 41], - [41, 36, 31, 51, 26, 21, 16, 11, 6, 1] + [41, 36, 31, 51, 26, 21, 16, 11, 6, 1], ], [ [12, 53, 17, 22, 27, 54, 32, 33, 57, 34], - [34, 56, 29, 24, 19, 14, 55, 13, 12] - ] + [34, 56, 29, 24, 19, 14, 55, 13, 12], + ], ] - @test validate_triangulation(tri, predicates=PT()) - add_point!(tri, 0.5, 4.4, predicates=PT()) - add_point!(tri, 0.5, 4.6, predicates=PT()) - add_point!(tri, 0.5, 4.5, predicates=PT()) - @test validate_triangulation(tri, predicates=PT()) + @test validate_triangulation(tri, predicates = PT()) + add_point!(tri, 0.5, 4.4, predicates = PT()) + add_point!(tri, 0.5, 4.6, predicates = PT()) + add_point!(tri, 0.5, 4.5, predicates = PT()) + @test validate_triangulation(tri, predicates = PT()) end end -end \ No newline at end of file +end diff --git a/test/triangulation/convex_triangulation.jl b/test/triangulation/convex_triangulation.jl index 550c32be1..bd5ec0fa4 100644 --- a/test/triangulation/convex_triangulation.jl +++ b/test/triangulation/convex_triangulation.jl @@ -14,10 +14,10 @@ using StatsBase S = get_random_convex_polygon(points) skip_points = setdiff(axes(points, 2), S) for delete_ghosts in (false, true) - tri_bowyer = triangulate(points; skip_points, delete_ghosts, predicates=PT()) - tri_chew = triangulate_convex(points, S; delete_ghosts, predicates=PT()) - @test validate_triangulation(tri_bowyer; predicates=PT()) - @test validate_triangulation(tri_chew; predicates=PT()) + tri_bowyer = triangulate(points; skip_points, delete_ghosts, predicates = PT()) + tri_chew = triangulate_convex(points, S; delete_ghosts, predicates = PT()) + @test validate_triangulation(tri_bowyer; predicates = PT()) + @test validate_triangulation(tri_chew; predicates = PT()) @test DT.compare_triangle_collections(get_triangles(tri_bowyer), get_triangles(tri_chew)) for (ij, k) in get_adjacent(tri_chew).adjacent if DT.edge_exists(k) @@ -60,8 +60,8 @@ end p12 = T[8.0, 6.0] pts = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12] for _ in 1:100 - tri_chew = triangulate_convex(pts, 1:12; predicates=PT()) - @test validate_triangulation(tri_chew; predicates=PT()) + tri_chew = triangulate_convex(pts, 1:12; predicates = PT()) + @test validate_triangulation(tri_chew; predicates = PT()) end end end @@ -78,16 +78,16 @@ end pts[:, 27] .= p2 pts[:, 5] .= p3 S = [11, 27, 5, 11] - @test_throws AssertionError("S must not be circular.") triangulate_convex(pts, S; predicates=PT()) + @test_throws AssertionError("S must not be circular.") triangulate_convex(pts, S; predicates = PT()) pop!(S) - tri_chew = triangulate_convex(pts, S; predicates=PT()) - tri_bowyer = triangulate(pts; skip_points=setdiff(1:50, [11, 27, 5]), predicates=PT(), delete_ghosts=false) + tri_chew = triangulate_convex(pts, S; predicates = PT()) + tri_bowyer = triangulate(pts; skip_points = setdiff(1:50, [11, 27, 5]), predicates = PT(), delete_ghosts = false) @test tri_chew == tri_bowyer pts[:, 28] .= [1.01, 1.01] S = [11, 27, 28, 5] - tri_chew = triangulate_convex(pts, S; predicates=PT()) - tri_bowyer = triangulate(pts; skip_points=setdiff(1:50, [11, 27, 5, 28]), predicates=PT(), delete_ghosts=false) + tri_chew = triangulate_convex(pts, S; predicates = PT()) + tri_bowyer = triangulate(pts; skip_points = setdiff(1:50, [11, 27, 5, 28]), predicates = PT(), delete_ghosts = false) @test get_convex_hull(tri_chew) == get_convex_hull(tri_bowyer) @test DT.compare_triangle_collections(get_triangles(tri_chew), get_triangles(tri_bowyer)) @test (get_adjacent ∘ get_adjacent)(tri_chew) == (get_adjacent ∘ get_adjacent)(tri_bowyer) @@ -95,4 +95,4 @@ end @test get_graph(tri_chew) == get_graph(tri_bowyer) end end -end \ No newline at end of file +end diff --git a/test/triangulation/rectangle.jl b/test/triangulation/rectangle.jl index bb42eadc5..5bf6fa7c4 100644 --- a/test/triangulation/rectangle.jl +++ b/test/triangulation/rectangle.jl @@ -12,11 +12,11 @@ using Test tri = DT.triangulate_rectangle(a, b, c, d, nx, ny) @test validate_triangulation(tri) for PT in subtypes(DT.AbstractPredicateKernel) - tri = DT.triangulate_rectangle(a, b, c, d, nx, ny; predicates=PT()) + tri = DT.triangulate_rectangle(a, b, c, d, nx, ny; predicates = PT()) if PT() == DT.FastKernel() - @test_broken validate_triangulation(tri; predicates=PT()) + @test_broken validate_triangulation(tri; predicates = PT()) else - @test validate_triangulation(tri; predicates=PT()) + @test validate_triangulation(tri; predicates = PT()) end end end @@ -26,8 +26,8 @@ end a, b, c, d = 2.0, 10.0, -5.0, 7.5 nx = 20 ny = 10 - tri = DT.triangulate_rectangle(a, b, c, d, nx, ny; single_boundary=true, predicates=PT()) - PT() != DT.FastKernel() && @test validate_triangulation(tri; predicates=PT()) + tri = DT.triangulate_rectangle(a, b, c, d, nx, ny; single_boundary = true, predicates = PT()) + PT() != DT.FastKernel() && @test validate_triangulation(tri; predicates = PT()) bn = reduce(vcat, [1:20, 20:20:200, 200:-1:181, 181:-20:1]) unique!(bn) push!(bn, 1) diff --git a/test/triangulation/triangulate.jl b/test/triangulation/triangulate.jl index d507ce3d3..101ddae27 100644 --- a/test/triangulation/triangulate.jl +++ b/test/triangulation/triangulate.jl @@ -9,12 +9,12 @@ using CairoMakie for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:100 pts = rand(2, 38) - tri = triangulate(pts; predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) - _tri = DT.triangulate(pts; predicates=PT()) + tri = triangulate(pts; predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) + _tri = DT.triangulate(pts; predicates = PT()) @test tri == _tri - __tri = retriangulate(_tri; predicates=PT()) - @inferred retriangulate(_tri; predicates=PT()) + __tri = retriangulate(_tri; predicates = PT()) + @inferred retriangulate(_tri; predicates = PT()) @test __tri == _tri end end @@ -22,18 +22,18 @@ end @testset "Retriangulate should ignore deleted points" begin points = [(0.0, 0.0), (0.87, 0.0), (1.0006, 0.7766), (0.0, 1.0), (0.5, 0.5)] - tri = triangulate(points; skip_points=5) + tri = triangulate(points; skip_points = 5) _tri = retriangulate(tri) @test tri == _tri && !DelaunayTriangulation.has_vertex(_tri, 5) && validate_triangulation(_tri) end @testset "Lots of collinearity" begin for PT in (DT.AdaptiveKernel, DT.ExactKernel) - _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary=true, predicates=PT()) - @test validate_triangulation(_tri; predicates=PT()) + _tri = triangulate_rectangle(-3.0, 2.0, 5.0, 17.3, 23, 57; single_boundary = true, predicates = PT()) + @test validate_triangulation(_tri; predicates = PT()) for _ in 1:10 - tri = triangulate(_tri.points; predicates=PT()) - @test validate_triangulation(tri; predicates=PT()) + tri = triangulate(_tri.points; predicates = PT()) + @test validate_triangulation(tri; predicates = PT()) end end -end \ No newline at end of file +end diff --git a/test/triangulation/weighted.jl b/test/triangulation/weighted.jl index c3b4076aa..5f3f8d725 100644 --- a/test/triangulation/weighted.jl +++ b/test/triangulation/weighted.jl @@ -35,11 +35,11 @@ end @testset "is_weighted" begin tri = Triangulation(rand(2, 10)) @test !DT.is_weighted(tri) - tri = Triangulation(rand(2, 10); weights=rand(10)) + tri = Triangulation(rand(2, 10); weights = rand(10)) @test DT.is_weighted(tri) - tri = Triangulation(rand(2, 10); weights=DT.ZeroWeight()) + tri = Triangulation(rand(2, 10); weights = DT.ZeroWeight()) @test !DT.is_weighted(tri) - tri = Triangulation(rand(2, 10); weights=zeros(10)) + tri = Triangulation(rand(2, 10); weights = zeros(10)) @test DT.is_weighted(tri) end @@ -116,15 +116,15 @@ end _weights[58] = weights[2] _weights[498] = weights[3] _weights[5] = weights[4] - tri = Triangulation(_points; weights=_weights) + tri = Triangulation(_points; weights = _weights) d = DT.get_distance_to_witness_plane(tri, 5, (137, 58, 498)) @test d ≈ -2.129523129725314 @test DT.get_distance_to_witness_plane(tri, 5, (137, 58, 498)) ≈ - DT.get_distance_to_witness_plane(tri, 5, (58, 137, 498)) ≈ - DT.get_distance_to_witness_plane(tri, 5, (498, 58, 137)) ≈ - DT.get_distance_to_witness_plane(tri, 5, (137, 498, 58)) ≈ - DT.get_distance_to_witness_plane(tri, 5, (58, 498, 137)) ≈ - DT.get_distance_to_witness_plane(tri, 5, (498, 137, 58)) + DT.get_distance_to_witness_plane(tri, 5, (58, 137, 498)) ≈ + DT.get_distance_to_witness_plane(tri, 5, (498, 58, 137)) ≈ + DT.get_distance_to_witness_plane(tri, 5, (137, 498, 58)) ≈ + DT.get_distance_to_witness_plane(tri, 5, (58, 498, 137)) ≈ + DT.get_distance_to_witness_plane(tri, 5, (498, 137, 58)) _points[5] = (-3.9, 2.01) _weights[5] = -15.0 d = DT.get_distance_to_witness_plane(tri, 5, (137, 58, 498)) @@ -208,7 +208,7 @@ end for i in 3:10 for j in 3:10 tri = triangulate_rectangle(0, 10, 0, 10, i, j) - tri = triangulate(get_points(tri); weights=zeros(i * j)) + tri = triangulate(get_points(tri); weights = zeros(i * j)) # @test validate_triangulation(tri) # Why is this failing sometimes? Is validate not branching at weighted triangulations? end end @@ -226,7 +226,7 @@ end for i in 3:10 for j in 3:10 tri = triangulate_rectangle(0, 10, 0, 10, i, j) - tri = triangulate(get_points(tri); weights=10randn() * ones(i * j)) + tri = triangulate(get_points(tri); weights = 10randn() * ones(i * j)) # @test validate_triangulation(tri) # Why is this failing sometimes? Is validate not branching at weighted triangulations? end end @@ -266,4 +266,4 @@ end # While we have tested the convex polygons and everything else properly, # normal triangulations still need to be correctly updated. To test this, # we will need to test the ones provided in helper_functions.jl properly. -# See the get_weighted_example function in that file and the comments surrounding it. \ No newline at end of file +# See the get_weighted_example function in that file and the comments surrounding it. diff --git a/test/utils.jl b/test/utils.jl index 02150969e..65cf12720 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -6,565 +6,565 @@ using BenchmarkTools using StableRNGs @testset "is_true" begin - @test DT.is_true(true) - @test DT.is_true(Val(true)) - @test !DT.is_true(false) - @test !DT.is_true(Val(false)) + @test DT.is_true(true) + @test DT.is_true(Val(true)) + @test !DT.is_true(false) + @test !DT.is_true(Val(false)) end @testset "number_type" begin - @test DT.number_type([1, 2, 3]) == Int - @test DT.number_type([1.0, 2.0, 3.0]) == Float64 - @test DT.number_type([1.0 2.0; 3.0 3.5; 10.0 17.3]) == Float64 - @test DT.number_type((1.0, 5.0)) == Float64 - @test DT.number_type([(1.0f0, 2.0f0), (1.7f0, 2.5f0)]) == Float32 - @test DT.number_type(2.4) == Float64 + @test DT.number_type([1, 2, 3]) == Int + @test DT.number_type([1.0, 2.0, 3.0]) == Float64 + @test DT.number_type([1.0 2.0; 3.0 3.5; 10.0 17.3]) == Float64 + @test DT.number_type((1.0, 5.0)) == Float64 + @test DT.number_type([(1.0f0, 2.0f0), (1.7f0, 2.5f0)]) == Float32 + @test DT.number_type(2.4) == Float64 end @testset "get_ghost_vertex" begin - @test DT.get_ghost_vertex(1, 2, -3) == -3 - @test DT.get_ghost_vertex(1, 2, -1) == -1 - @test DT.get_ghost_vertex(1, -5, 2) == -5 - @test DT.get_ghost_vertex(-1, 2, 3) == -1 - @test DT.get_ghost_vertex(2, 5, 7) == 7 - @test DT.get_ghost_vertex(1, -2) == -2 - @test DT.get_ghost_vertex(-5, 1) == -5 - @test DT.get_ghost_vertex(2, 5) == 5 + @test DT.get_ghost_vertex(1, 2, -3) == -3 + @test DT.get_ghost_vertex(1, 2, -1) == -1 + @test DT.get_ghost_vertex(1, -5, 2) == -5 + @test DT.get_ghost_vertex(-1, 2, 3) == -1 + @test DT.get_ghost_vertex(2, 5, 7) == 7 + @test DT.get_ghost_vertex(1, -2) == -2 + @test DT.get_ghost_vertex(-5, 1) == -5 + @test DT.get_ghost_vertex(2, 5) == 5 end @testset "sort_triangle" begin - @test DT.sort_triangle(1, 2, DT.𝒢) == (1, 2, DT.𝒢) - @test DT.sort_triangle(DT.𝒢 - 2, 2, 3) == (2, 3, DT.𝒢 - 2) - @test DT.sort_triangle(5, DT.𝒢 - 1, 3) == (3, 5, DT.𝒢 - 1) - @test DT.sort_triangle((1, 5, DT.𝒢)) == (1, 5, DT.𝒢) - @test DT.sort_triangle([1, DT.𝒢 - 2, 7]) == [7, 1, DT.𝒢 - 2] - @test DT.sort_triangle((DT.𝒢 - 10, 5, 3)) == (5, 3, DT.𝒢 - 10) + @test DT.sort_triangle(1, 2, DT.𝒢) == (1, 2, DT.𝒢) + @test DT.sort_triangle(DT.𝒢 - 2, 2, 3) == (2, 3, DT.𝒢 - 2) + @test DT.sort_triangle(5, DT.𝒢 - 1, 3) == (3, 5, DT.𝒢 - 1) + @test DT.sort_triangle((1, 5, DT.𝒢)) == (1, 5, DT.𝒢) + @test DT.sort_triangle([1, DT.𝒢 - 2, 7]) == [7, 1, DT.𝒢 - 2] + @test DT.sort_triangle((DT.𝒢 - 10, 5, 3)) == (5, 3, DT.𝒢 - 10) end -const _POINTS = [ - ## Don't know why the points on 1.10 get slightly changed, e.g. with 357 replacing 363 and 363 replacing 357, so this is needed to make the next set of tests more robust. This is NOT some hack to force the test to pass when it shouldn't, it just makes sure the point order matches the hard-coded node numbers below. - 0.0 0.0 - 0.6666666666666666 0.0 - 1.3333333333333333 0.0 - 2.0 0.0 - 2.0 2.0 - 2.0 4.0 - 2.0 6.0 - 1.3333333333333335 6.0 - 0.6666666666666667 6.0 - 0.0 6.0 - 0.0 4.0 - 0.0 2.0 - 1.1 0.5999999999999999 - 1.095895006911623 0.5360614191577466 - 1.0836474315195146 0.47317270804524625 - 1.063458378673011 0.41236649756031307 - 1.0356593520616948 0.35464122399803105 - 1.0007068109339783 0.3009447347543919 - 0.9591746750488634 0.2521587246982565 - 0.9117449009293667 0.20908425876598502 - 0.8591962841552626 0.172428618497327 - 0.8023916715611968 0.14279368849209373 - 0.742263793315516 0.12066607348166958 - 0.6797999475166896 0.10640910829277489 - 0.6160257887858274 0.10025689189965603 - 0.5519884870461588 0.10231044352540092 - 0.4887395330218427 0.11253604390908817 - 0.4273174727893459 0.13076578897511987 - 0.36873085487958235 0.15670034681349998 - 0.31394166993891537 0.18991387270152188 - 0.26384955486934164 0.22986100146234217 - 0.21927702081543265 0.2758858023461059 - 0.18095594755407962 0.32723254939472574 - 0.1495155660487904 0.38305813044122095 - 0.12547212649466555 0.44244589098818987 - 0.10922042150446726 0.5044206856493141 - 0.10102730362483181 0.5679648900096435 - 0.10102730362483181 0.6320351099903566 - 0.10922042150446731 0.6955793143506862 - 0.1254721264946656 0.7575541090118102 - 0.14951556604879046 0.8169418695587791 - 0.18095594755407968 0.8727674506052743 - 0.21927702081543277 0.9241141976538942 - 0.2638495548693417 0.9701389985376578 - 0.3139416699389151 1.0100861272984778 - 0.36873085487958224 1.0432996531865 - 0.42731747278934623 1.0692342110248803 - 0.4887395330218428 1.0874639560909118 - 0.5519884870461592 1.0976895564745992 - 0.6160257887858274 1.099743108100344 - 0.6797999475166895 1.093590891707225 - 0.7422637933155162 1.0793339265183302 - 0.802391671561197 1.0572063115079062 - 0.8591962841552626 1.027571381502673 - 0.9117449009293666 0.990915741234015 - 0.9591746750488637 0.9478412753017432 - 1.0007068109339783 0.899055265245608 - 1.0356593520616948 0.8453587760019688 - 1.063458378673011 0.7876335024396869 - 1.0836474315195146 0.7268272919547538 - 1.095895006911623 0.6639385808422531 - 1.7 0.49999999999999994 - 1.6983580027646492 0.47442456766309865 - 1.693458972607806 0.4492690832180985 - 1.6853833514692045 0.42494659902412524 - 1.6742637408246779 0.40185648959921244 - 1.6602827243735914 0.38037789390175675 - 1.6436698700195453 0.3608634898793026 - 1.6246979603717466 0.343633703506394 - 1.603678513662105 0.3289714473989308 - 1.5809566686244787 0.3171174753968375 - 1.5569055173262063 0.3082664293926678 - 1.5319199790066758 0.30256364331710994 - 1.506410315514331 0.3001027567598624 - 1.4807953948184636 0.30092417741016037 - 1.455495813208737 0.30501441756363523 - 1.4309269891157383 0.31230631559004796 - 1.407492341951833 0.3226801387254 - 1.3855766679755661 0.3359655490806087 - 1.3655398219477366 0.35194440058493687 - 1.347710808326173 0.37035432093844234 - 1.3323823790216318 0.3908930197578903 - 1.3198062264195163 0.41322325217648836 - 1.3101888505978663 0.43697835639527594 - 1.303688168601787 0.4617682742597256 - 1.3004109214499326 0.4871859560038574 - 1.3004109214499326 0.5128140439961426 - 1.303688168601787 0.5382317257402746 - 1.3101888505978663 0.5630216436047241 - 1.3198062264195163 0.5867767478235116 - 1.3323823790216318 0.6091069802421097 - 1.347710808326173 0.6296456790615577 - 1.3655398219477366 0.6480555994150632 - 1.3855766679755661 0.6640344509193912 - 1.4074923419518328 0.6773198612746 - 1.4309269891157386 0.6876936844099522 - 1.4554958132087372 0.6949855824363648 - 1.4807953948184638 0.6990758225898397 - 1.506410315514331 0.6998972432401376 - 1.5319199790066758 0.6974363566828901 - 1.5569055173262065 0.6917335706073321 - 1.5809566686244787 0.6828825246031625 - 1.603678513662105 0.6710285526010692 - 1.6246979603717466 0.656366296493606 - 1.6436698700195456 0.6391365101206973 - 1.6602827243735914 0.6196221060982432 - 1.6742637408246779 0.5981435104007875 - 1.6853833514692043 0.5750534009758748 - 1.693458972607806 0.5507309167819016 - 1.6983580027646492 0.5255754323369012 - 1.0 2.0 - 1.0 3.0 - 1.0 4.000000000000001 - 1.0 5.0 - 1.1666666666666665 5.0 - 1.3333333333333333 5.0 - 1.5 5.0 - 1.5 4.0 - 1.5 3.0 - 1.5 2.0 - 1.3333333333333335 2.0 - 1.1666666666666667 2.0 - 0.2 2.0 - 0.2 5.0 - 0.75 4.0 - 0.75 3.0 - 0.5 2.0 - 0.2 3.5 - 2.0 5.0 - 0.0 3.0 - 2.0 3.0 - 2.0 1.0 - 0.0 5.0 - 0.0 1.0 - 0.2 4.5 - 0.2 3.0 - 0.2 4.0 - 0.0 4.5 - 0.0 0.5 - 2.0 0.5 - 0.0 3.5 - 1.6666666666666665 0.0 - 1.0 0.0 - 0.3333333333333333 0.0 - 0.0 0.25 - 0.0 0.75 - 0.7916666666666666 0.0 - 0.5416666666666666 0.0 - 0.0 0.625 - 1.4740544522373191 1.309077721762752 - 1.3499698939387508 1.0055012112239021 - 1.6795817213270934 0.9879815502040521 - 2.0 0.75 - 2.0 0.25 - 1.7828347010132077 0.1885675610394171 - 1.19953813886343 0.20901891414515464 - 1.7742377105455027 0.8019661970196654 - 0.0 1.5 - 0.9388315428915 1.5207147605911762 - 1.2572693115310343 0.8043746560736462 - 1.5416666666666665 0.0 - 1.4877125131091204 0.8831690890011553 - 1.8624474074396582 0.6203408303941387 - 1.862447407439658 0.37965916960586316 - 0.4487051545335375 1.535812115275885 - 1.441199151969013 0.13629596364476348 - 1.624263604487171 0.16233564360848637 - 1.6185917257370095 0.8222520295432142 - 1.1917579283891429 0.37520661583202014 - 1.3293751090374275 0.21853639574589828 - 1.2191572487719817 0.6581676907984143 - 1.0529166570030704 1.2492900864648844 - 0.0 1.25 - 1.3724252107559454 0.7881936711216704 - 1.7396173332189573 0.2960107901378373 - 1.8110061512826319 0.5199672573998425 - 1.761187193038501 0.6700140220581073 - 0.6745044586363241 1.372316652669158 - 0.28592779118073197 1.3094945905319997 - 1.1953751211197607 0.5 - 1.5289331661582095 0.2000774658667932 - 1.6681251875542065 0.7410200991200366 - 1.528217827526302 0.7925073008997648 - 1.775506905040127 0.40852540520001573 - 1.26831267650853 0.3270872565921958 - 1.418160934512214 0.22425703203449873 - 1.295455646032882 0.6980901602542381 - 1.6315588938199306 0.24782623088951797 - 1.137591811617686 1.057658581735622 - 1.0833333333333333 5.527777777777778 - 1.7661043175005355 0.5883527206490259 - 0.48832789133187804 1.290731478047606 - 0.8416520629881481 1.2566467201424116 - 0.16692117116205538 1.1430636744441975 - 1.2314189884870388 0.5704302352100531 - 1.4563071262047091 0.7702558737066645 - 1.2378485908218748 0.4312558050732817 - 1.5935642184148526 0.7542442070846888 - 1.3320629484886526 0.2894135981807518 - 0.125 0.0 - 0.0 2.5 - 0.2 2.5 - 0.0 5.5 - 1.363898107854514 0.7245143067518455 - 1.6763532155896466 0.3058155104275537 - 1.7198413454244592 0.35689914227621217 - 1.7603049822572803 0.48328786565231235 - 1.6986162550807449 0.6690844831441323 - 1.2732086411580512 0.6277265137313147 - 0.1357338269089258 0.15038328438526705 - 0.9681905883861459 1.127828895829673 - 1.5569357954505727 0.2505479812612332 - 1.4917990544438116 0.2442643181947033 - 1.4166666666666665 5.362573099415204 - 0.6610307417000465 1.2326474818074256 - 0.3427260032157782 1.181186440179403 - 1.4166666666666667 1.6571810441100427 - 1.0238883307733782 0.13325183852345296 - 1.2486746582268176 0.5 - 1.0 3.5000000000000004 - 0.75 3.5 - 0.47500000000000003 4.5 - 1.0 4.5 - 0.625 2.5 - 1.0 2.5 - 1.2821205078623963 0.3772925560903774 - 1.3990607282139222 0.271976426778746 - 1.1173493764498315 0.9367571253255303 - 0.0 0.375 - 1.741444624549862 0.5470213364192468 - 1.7216209675111749 0.6067270329489496 - 1.640658487617645 0.7016445193064772 - 1.523607866265877 0.7447202299680109 - 0.0 0.875 - 0.16036607072667938 1.0257617177590372 - 1.731605030618596 0.4231018317802659 - 1.4308793419171846 0.7328904331187506 - 1.1070433482398665 0.2699513556188709 - 0.875 0.0 - 1.326733072952154 0.6677996614425488 - 1.611490638036034 0.2862933200657552 - 1.3269281024201038 0.33238921406445593 - 1.0833333333333333 5.257309941520468 - 0.5647973445143255 5.392543859649123 - 0.5047539390232997 1.1891305650202075 - 0.8061070342543368 1.1600593943533914 - 1.0833333333333335 1.7458187278913946 - 0.4583333333333333 0.0 - 1.6810772213147687 0.34584671399258676 - 0.0820730652316044 0.30830898459576883 - 0.29187380922086326 0.09171361966873727 - 1.2701959364187478 0.5602617219999282 - 1.1611993909112273 0.7863310354349395 - 0.9961530910081264 1.036208580108681 - 1.462487223491946 0.2679702132241154 - 1.5225695030046766 0.2660434914632048 - 0.2962726981257435 1.1010299529782763 - 1.2735053984345062 0.44060612113937503 - 1.5808501167410969 0.7196958855831329 - 0.09063815833613441 0.886867244835494 - 0.9340092492886052 0.1211726241519101 - 1.3795327553781789 0.3012766796536391 - 0.0 3.75 - 0.2 3.75 - 0.2 2.25 - 0.0 2.25 - 0.0 4.25 - 0.2 4.25 - 0.2 4.75 - 0.0 4.75 - 0.0 2.75 - 0.2 2.75 - 0.0 5.25 - 0.0 3.25 - 0.2 3.25 - 0.0 1.75 - 1.7305994280094303 0.5148049744879046 - 1.6936605339465862 0.6260590379916767 - 1.7193022924897394 0.5728133777310767 - 1.4925952162260299 0.7309084256300289 - 1.6553197408864884 0.6710242963459636 - 2.0 1.5 - 1.7261014731069777 0.45596674205660387 - 1.7075375557401247 0.4000551807062032 - 1.406921135389704 0.7102667764910945 - 1.0370994517765144 0.22789181149262006 - 1.125 0.0 - 1.3570113367409984 0.6793021124621966 - 1.316206997826056 0.6371682824339902 - 1.6311751370246665 0.31195057690225014 - 1.5791854380321182 0.284827584238829 - 1.316282242285531 0.36288787396558325 - 1.1154407188558464 0.3517768322991175 - 0.5816906605550696 1.1709526266542052 - 0.864223205343458 1.1064664170034129 - 0.4374647190632682 1.1476352949226916 - 0.7271142209552935 1.1569237906798149 - 0.1428028406433256 0.25878489202052457 - 0.3690795881569608 0.07834676725460561 - 0.2443121381562888 0.15398152865993447 - 0.25 0.0 - 1.2737384055431993 0.5291732020831812 - 1.2885382384146338 0.5856113791101021 - 1.113130134633655 0.847110448984858 - 1.1590288414186054 0.7088708571143922 - 1.033197322819307 0.9687862576934944 - 1.4353052654987943 0.28202197206461327 - 0.24588090864430434 1.044051295369198 - 0.2688387528122659 5.375 - 0.33333333333333337 6.0 - 1.2894711087692583 0.4147662982391812 - 1.2747365658359935 0.47095549643502305 - 1.6050489090123727 0.701359091410823 - 1.550537613507314 0.7214197520535767 - 0.07387658485528542 0.8130037639664341 - 0.14511290432603197 0.939491062646291 - 0.7291666666666666 0.0 - 0.8624443884933936 0.09694324186960815 - 0.07431874516150205 0.3871752469020991 - 1.3586733685981895 0.32278200956665326 - 0.7743125163556892 1.7852573023241183 - 1.3951319674273832 0.7467489457540966 - 1.6723555903905802 0.6467284533501322 - 1.4638740821559169 0.7234515755624243 - 1.4927477124566209 0.2738469683956681 - 1.6895818983651612 0.3765958595614554 - 1.725742831711937 0.4855068293396377 - 1.3828391994677471 0.6932689949811435 - 1.5502891882510008 0.2796686701104153 - 1.6519383611714682 0.33269897851362074 - 1.4166666666666665 5.171709936804376 - 2.0 5.5 - 1.7470040926571286 5.26714151810979 - 1.762711901635018 0.44520425603505154 - 1.8366469302468644 0.45042453510946423 - 1.9060886700063842 0.5155263895621286 - 1.7432094576086072 0.3868933176340165 - 1.7985506191032619 0.3391937098408574 - 1.8878694231956714 0.26883597168004963 - 1.7916666666666665 0.0 - 2.0 0.125 - 0.9230460198845826 1.0631107620790716 - 1.1358084873427654 0.4220993253764972 - 0.19447305594557093 0.20726905545353125 - 1.3032549844320298 0.6108047284553858 - 2.0 0.625 - 1.2500000000000002 1.8319281123363502 - 0.6541111351264756 1.160918521091478 - 0.371895480593367 1.115292082681653 - 1.494273560202694 0.7688633005731953 - 1.4773323581048208 0.8252320844062707 - 1.4030882061420913 0.8684322443508078 - 0.7944598296275528 0.07158982321352167 - 1.0 3.25 - 0.75 3.25 - 0.595479687443039 4.280946022830838 - 1.0 4.25 - 2.0 4.5 - 1.5 4.5 - 2.0 2.5 - 1.5 2.5 - 2.0 3.5 - 1.5 3.5 - 0.6893660937409167 2.757464374963667 - 1.0 2.75 - 1.0 3.750000000000001 - 0.75 3.75 - 0.20607015431451464 0.07547310822581126 - 1.1137966762594949 0.1795335656241746 - 1.2083333333333333 0.0 - 1.1666666666666665 0.09271643952630988 - 0.3994151065612831 5.677353293275649 - 1.6783486674776207 0.70087084995281 - 1.7392543857928202 0.7377559547642759 - 1.8302710234553803 0.7298028546873176 - 2.0 0.875 - 1.8888519575683367 0.8331257280027056 - 1.800336932191529 0.9323381323744324 - 2.0 1.25 - 1.8227502338782238 1.1398294920180019 - 1.7994421968210412 1.375 - 1.7395586704615544 1.6944745976100235 - 1.7267593429098054 0.6440448038896638 - 1.7678827403626947 0.5201876828851476 - 1.2035918506774017 0.8877754751066075 - 1.16093306626047 0.5639869022785741 - 0.0 0.4375 - 1.291551342829673 0.6627651416324978 - 1.2538080175158937 0.6848149997324289 - 1.2577128301399019 0.7445318850453346 - 1.2090408575917337 0.7071751969044885 - 1.3306373761553634 0.7031246800642893 - 1.3160528628068418 0.7623584294631466 - 1.6462859848898292 0.27997768754971447 - 1.7020584160349093 0.234982296630739 - 1.5967635469661356 0.2541418634055588 - 1.6061662460929913 0.20693653438447443 - 1.570825246339907 0.16662443239081526 - 1.5905483961970126 0.07730943253130455 - 1.51018175705595 0.13363920248553696 - 1.4583333333333333 0.0 - 1.6590520810618847 0.20242355254666858 - 1.7125852936455277 0.12082842146382869 - 1.431068012499545 0.9581022021491937 - 1.477452094723081 1.130541403025688 - 1.5531080005501499 0.9914800857679006 - 1.2813569642026876 1.216110095730245 - 1.2018317226108364 1.4715704518745842 - 1.6198909607221894 1.1179240078762014 - 1.7983548141425743 0.46657478567124433 - 0.9770513066521348 0.18482460736504314 - 0.7938123559004582 5.2089259691333805 - 0.6407123629255758 4.851627018928146 - 1.319484941905665 0.8292893422114065 - 1.2761296818296555 0.5 - 1.8099178972915033 0.26187472706351006 - 1.7111729419512756 0.17826049305063374 - 1.759634673818009 0.34999662375758167 - 1.718142438071527 0.703889427730984 - 1.473230604388981 0.071097758315114 - 1.3863435254451124 0.06887822829586042 - 1.2782854698688741 0.09720405683617961 - 0.7375 4.501716097368583 - 0.44121509031025474 0.06500095027943562 - 1.305524838337339 0.3904736294480411 - 1.6684438208715549 0.25037958358667844 - 1.6996902177676332 0.2742036674155371 - 1.3624484903113168 0.2687327852709218 - 0.06974484917671708 0.9630027278134988 - 0.0 1.125 - 0.07352010305180143 1.054357451563032 - 1.1563399977503028 0.6357182129391813 - 0.5597884117036155 1.2501563862805738 - 0.5715382250636158 1.354065450073582 - 0.5980032696789671 1.504333348664305 - 0.5656039401938803 1.7204555756412738 - 0.3037866871454204 1.7568871511798612 - 0.46161571048938355 1.4121561268225087 - 0.3161306261019238 1.459468430239305 - 0.149758655496108 1.4149454869965006 - 0.16391023227107437 1.6142327799518283 - 0.7683057766893729 1.5148465969437765 - 0.7637530559523047 1.230480162353276 - 0.7720830332001749 1.3347191336230664 - 0.9050972636859582 1.3832137934898427 - 1.0559347141051296 1.4190962037054105 - 0.43329341865156223 1.2297056567872398 - 0.3893995908276335 1.3246186881965123 - 0.8840060412901801 1.1862259521425271 - 0.9479694782050885 1.272643328918064 - 1.4361522732329282 0.25034394087790574 - 1.4603794219490087 0.21438773060391503 - 1.4301726911242494 0.18040552911767954 - 1.3664948543862412 0.14105443922716654 - 1.3800869372880815 0.19025696838292824 - 1.4771932167810962 0.16902551127432658 - 1.40980282641639 0.2962430137342318 - 0.0 0.6875 - 2.0 0.375 - 1.9132736730754663 0.4382760179317226 - 0.055964514785385895 0.46875 - 1.6666208006494743 5.608342938440153 - 1.2445796724660527 0.5415967162439137 - 1.2035138373071206 0.5402730217783609 - 1.257035252439734 0.5890952409660676 - 1.2196380370307442 0.6135093363907388 - 1.383611268856942 0.23811038285103012 - 1.6226023422523703 0.7328606305005508 - 1.6335516540160544 0.7781375493960542 - 1.698042873799217 0.824601373114044 - 1.6559767278839401 0.902581204581636 - 1.5575918148450751 0.7567851055371636 - 1.5786042901358082 0.7983586872318487 - 1.561956830704648 0.8716273239716548 - 1.25 5.146519289061359 - 1.4166666666666667 1.853986608235224 - 1.6106377773288556 1.84006951687984 - 1.75 2.0547125573551916 - 1.5 2.25 - 1.75 2.375 - 1.75 2.6875 - 1.7351882330544273 0.25666486669089317 - 1.740696001877012 0.21209770142048218 - 1.7716317714671403 0.27248473247545524 - 1.780747250326824 0.23099526710030466 - 1.8315421621777004 0.21222918129712579 - 1.8571475226715097 0.09755754869299872 - 1.9212830619181216 0.17925938128868346 - 1.8307671503240839 0.15186156285696936 - 1.782563159254053 0.09488484980088335 - 1.7291666666666665 0.0 - 1.6979166666666665 0.05726348727905952 - 0.0635245517925628 0.7406804293007325 +const _POINTS = [ + ## Don't know why the points on 1.10 get slightly changed, e.g. with 357 replacing 363 and 363 replacing 357, so this is needed to make the next set of tests more robust. This is NOT some hack to force the test to pass when it shouldn't, it just makes sure the point order matches the hard-coded node numbers below. + 0.0 0.0 + 0.6666666666666666 0.0 + 1.3333333333333333 0.0 + 2.0 0.0 + 2.0 2.0 + 2.0 4.0 + 2.0 6.0 + 1.3333333333333335 6.0 + 0.6666666666666667 6.0 + 0.0 6.0 + 0.0 4.0 + 0.0 2.0 + 1.1 0.5999999999999999 + 1.095895006911623 0.5360614191577466 + 1.0836474315195146 0.47317270804524625 + 1.063458378673011 0.41236649756031307 + 1.0356593520616948 0.35464122399803105 + 1.0007068109339783 0.3009447347543919 + 0.9591746750488634 0.2521587246982565 + 0.9117449009293667 0.20908425876598502 + 0.8591962841552626 0.172428618497327 + 0.8023916715611968 0.14279368849209373 + 0.742263793315516 0.12066607348166958 + 0.6797999475166896 0.10640910829277489 + 0.6160257887858274 0.10025689189965603 + 0.5519884870461588 0.10231044352540092 + 0.4887395330218427 0.11253604390908817 + 0.4273174727893459 0.13076578897511987 + 0.36873085487958235 0.15670034681349998 + 0.31394166993891537 0.18991387270152188 + 0.26384955486934164 0.22986100146234217 + 0.21927702081543265 0.2758858023461059 + 0.18095594755407962 0.32723254939472574 + 0.1495155660487904 0.38305813044122095 + 0.12547212649466555 0.44244589098818987 + 0.10922042150446726 0.5044206856493141 + 0.10102730362483181 0.5679648900096435 + 0.10102730362483181 0.6320351099903566 + 0.10922042150446731 0.6955793143506862 + 0.1254721264946656 0.7575541090118102 + 0.14951556604879046 0.8169418695587791 + 0.18095594755407968 0.8727674506052743 + 0.21927702081543277 0.9241141976538942 + 0.2638495548693417 0.9701389985376578 + 0.3139416699389151 1.0100861272984778 + 0.36873085487958224 1.0432996531865 + 0.42731747278934623 1.0692342110248803 + 0.4887395330218428 1.0874639560909118 + 0.5519884870461592 1.0976895564745992 + 0.6160257887858274 1.099743108100344 + 0.6797999475166895 1.093590891707225 + 0.7422637933155162 1.0793339265183302 + 0.802391671561197 1.0572063115079062 + 0.8591962841552626 1.027571381502673 + 0.9117449009293666 0.990915741234015 + 0.9591746750488637 0.9478412753017432 + 1.0007068109339783 0.899055265245608 + 1.0356593520616948 0.8453587760019688 + 1.063458378673011 0.7876335024396869 + 1.0836474315195146 0.7268272919547538 + 1.095895006911623 0.6639385808422531 + 1.7 0.49999999999999994 + 1.6983580027646492 0.47442456766309865 + 1.693458972607806 0.4492690832180985 + 1.6853833514692045 0.42494659902412524 + 1.6742637408246779 0.40185648959921244 + 1.6602827243735914 0.38037789390175675 + 1.6436698700195453 0.3608634898793026 + 1.6246979603717466 0.343633703506394 + 1.603678513662105 0.3289714473989308 + 1.5809566686244787 0.3171174753968375 + 1.5569055173262063 0.3082664293926678 + 1.5319199790066758 0.30256364331710994 + 1.506410315514331 0.3001027567598624 + 1.4807953948184636 0.30092417741016037 + 1.455495813208737 0.30501441756363523 + 1.4309269891157383 0.31230631559004796 + 1.407492341951833 0.3226801387254 + 1.3855766679755661 0.3359655490806087 + 1.3655398219477366 0.35194440058493687 + 1.347710808326173 0.37035432093844234 + 1.3323823790216318 0.3908930197578903 + 1.3198062264195163 0.41322325217648836 + 1.3101888505978663 0.43697835639527594 + 1.303688168601787 0.4617682742597256 + 1.3004109214499326 0.4871859560038574 + 1.3004109214499326 0.5128140439961426 + 1.303688168601787 0.5382317257402746 + 1.3101888505978663 0.5630216436047241 + 1.3198062264195163 0.5867767478235116 + 1.3323823790216318 0.6091069802421097 + 1.347710808326173 0.6296456790615577 + 1.3655398219477366 0.6480555994150632 + 1.3855766679755661 0.6640344509193912 + 1.4074923419518328 0.6773198612746 + 1.4309269891157386 0.6876936844099522 + 1.4554958132087372 0.6949855824363648 + 1.4807953948184638 0.6990758225898397 + 1.506410315514331 0.6998972432401376 + 1.5319199790066758 0.6974363566828901 + 1.5569055173262065 0.6917335706073321 + 1.5809566686244787 0.6828825246031625 + 1.603678513662105 0.6710285526010692 + 1.6246979603717466 0.656366296493606 + 1.6436698700195456 0.6391365101206973 + 1.6602827243735914 0.6196221060982432 + 1.6742637408246779 0.5981435104007875 + 1.6853833514692043 0.5750534009758748 + 1.693458972607806 0.5507309167819016 + 1.6983580027646492 0.5255754323369012 + 1.0 2.0 + 1.0 3.0 + 1.0 4.000000000000001 + 1.0 5.0 + 1.1666666666666665 5.0 + 1.3333333333333333 5.0 + 1.5 5.0 + 1.5 4.0 + 1.5 3.0 + 1.5 2.0 + 1.3333333333333335 2.0 + 1.1666666666666667 2.0 + 0.2 2.0 + 0.2 5.0 + 0.75 4.0 + 0.75 3.0 + 0.5 2.0 + 0.2 3.5 + 2.0 5.0 + 0.0 3.0 + 2.0 3.0 + 2.0 1.0 + 0.0 5.0 + 0.0 1.0 + 0.2 4.5 + 0.2 3.0 + 0.2 4.0 + 0.0 4.5 + 0.0 0.5 + 2.0 0.5 + 0.0 3.5 + 1.6666666666666665 0.0 + 1.0 0.0 + 0.3333333333333333 0.0 + 0.0 0.25 + 0.0 0.75 + 0.7916666666666666 0.0 + 0.5416666666666666 0.0 + 0.0 0.625 + 1.4740544522373191 1.309077721762752 + 1.3499698939387508 1.0055012112239021 + 1.6795817213270934 0.9879815502040521 + 2.0 0.75 + 2.0 0.25 + 1.7828347010132077 0.1885675610394171 + 1.19953813886343 0.20901891414515464 + 1.7742377105455027 0.8019661970196654 + 0.0 1.5 + 0.9388315428915 1.5207147605911762 + 1.2572693115310343 0.8043746560736462 + 1.5416666666666665 0.0 + 1.4877125131091204 0.8831690890011553 + 1.8624474074396582 0.6203408303941387 + 1.862447407439658 0.37965916960586316 + 0.4487051545335375 1.535812115275885 + 1.441199151969013 0.13629596364476348 + 1.624263604487171 0.16233564360848637 + 1.6185917257370095 0.8222520295432142 + 1.1917579283891429 0.37520661583202014 + 1.3293751090374275 0.21853639574589828 + 1.2191572487719817 0.6581676907984143 + 1.0529166570030704 1.2492900864648844 + 0.0 1.25 + 1.3724252107559454 0.7881936711216704 + 1.7396173332189573 0.2960107901378373 + 1.8110061512826319 0.5199672573998425 + 1.761187193038501 0.6700140220581073 + 0.6745044586363241 1.372316652669158 + 0.28592779118073197 1.3094945905319997 + 1.1953751211197607 0.5 + 1.5289331661582095 0.2000774658667932 + 1.6681251875542065 0.7410200991200366 + 1.528217827526302 0.7925073008997648 + 1.775506905040127 0.40852540520001573 + 1.26831267650853 0.3270872565921958 + 1.418160934512214 0.22425703203449873 + 1.295455646032882 0.6980901602542381 + 1.6315588938199306 0.24782623088951797 + 1.137591811617686 1.057658581735622 + 1.0833333333333333 5.527777777777778 + 1.7661043175005355 0.5883527206490259 + 0.48832789133187804 1.290731478047606 + 0.8416520629881481 1.2566467201424116 + 0.16692117116205538 1.1430636744441975 + 1.2314189884870388 0.5704302352100531 + 1.4563071262047091 0.7702558737066645 + 1.2378485908218748 0.4312558050732817 + 1.5935642184148526 0.7542442070846888 + 1.3320629484886526 0.2894135981807518 + 0.125 0.0 + 0.0 2.5 + 0.2 2.5 + 0.0 5.5 + 1.363898107854514 0.7245143067518455 + 1.6763532155896466 0.3058155104275537 + 1.7198413454244592 0.35689914227621217 + 1.7603049822572803 0.48328786565231235 + 1.6986162550807449 0.6690844831441323 + 1.2732086411580512 0.6277265137313147 + 0.1357338269089258 0.15038328438526705 + 0.9681905883861459 1.127828895829673 + 1.5569357954505727 0.2505479812612332 + 1.4917990544438116 0.2442643181947033 + 1.4166666666666665 5.362573099415204 + 0.6610307417000465 1.2326474818074256 + 0.3427260032157782 1.181186440179403 + 1.4166666666666667 1.6571810441100427 + 1.0238883307733782 0.13325183852345296 + 1.2486746582268176 0.5 + 1.0 3.5000000000000004 + 0.75 3.5 + 0.47500000000000003 4.5 + 1.0 4.5 + 0.625 2.5 + 1.0 2.5 + 1.2821205078623963 0.3772925560903774 + 1.3990607282139222 0.271976426778746 + 1.1173493764498315 0.9367571253255303 + 0.0 0.375 + 1.741444624549862 0.5470213364192468 + 1.7216209675111749 0.6067270329489496 + 1.640658487617645 0.7016445193064772 + 1.523607866265877 0.7447202299680109 + 0.0 0.875 + 0.16036607072667938 1.0257617177590372 + 1.731605030618596 0.4231018317802659 + 1.4308793419171846 0.7328904331187506 + 1.1070433482398665 0.2699513556188709 + 0.875 0.0 + 1.326733072952154 0.6677996614425488 + 1.611490638036034 0.2862933200657552 + 1.3269281024201038 0.33238921406445593 + 1.0833333333333333 5.257309941520468 + 0.5647973445143255 5.392543859649123 + 0.5047539390232997 1.1891305650202075 + 0.8061070342543368 1.1600593943533914 + 1.0833333333333335 1.7458187278913946 + 0.4583333333333333 0.0 + 1.6810772213147687 0.34584671399258676 + 0.0820730652316044 0.30830898459576883 + 0.29187380922086326 0.09171361966873727 + 1.2701959364187478 0.5602617219999282 + 1.1611993909112273 0.7863310354349395 + 0.9961530910081264 1.036208580108681 + 1.462487223491946 0.2679702132241154 + 1.5225695030046766 0.2660434914632048 + 0.2962726981257435 1.1010299529782763 + 1.2735053984345062 0.44060612113937503 + 1.5808501167410969 0.7196958855831329 + 0.09063815833613441 0.886867244835494 + 0.9340092492886052 0.1211726241519101 + 1.3795327553781789 0.3012766796536391 + 0.0 3.75 + 0.2 3.75 + 0.2 2.25 + 0.0 2.25 + 0.0 4.25 + 0.2 4.25 + 0.2 4.75 + 0.0 4.75 + 0.0 2.75 + 0.2 2.75 + 0.0 5.25 + 0.0 3.25 + 0.2 3.25 + 0.0 1.75 + 1.7305994280094303 0.5148049744879046 + 1.6936605339465862 0.6260590379916767 + 1.7193022924897394 0.5728133777310767 + 1.4925952162260299 0.7309084256300289 + 1.6553197408864884 0.6710242963459636 + 2.0 1.5 + 1.7261014731069777 0.45596674205660387 + 1.7075375557401247 0.4000551807062032 + 1.406921135389704 0.7102667764910945 + 1.0370994517765144 0.22789181149262006 + 1.125 0.0 + 1.3570113367409984 0.6793021124621966 + 1.316206997826056 0.6371682824339902 + 1.6311751370246665 0.31195057690225014 + 1.5791854380321182 0.284827584238829 + 1.316282242285531 0.36288787396558325 + 1.1154407188558464 0.3517768322991175 + 0.5816906605550696 1.1709526266542052 + 0.864223205343458 1.1064664170034129 + 0.4374647190632682 1.1476352949226916 + 0.7271142209552935 1.1569237906798149 + 0.1428028406433256 0.25878489202052457 + 0.3690795881569608 0.07834676725460561 + 0.2443121381562888 0.15398152865993447 + 0.25 0.0 + 1.2737384055431993 0.5291732020831812 + 1.2885382384146338 0.5856113791101021 + 1.113130134633655 0.847110448984858 + 1.1590288414186054 0.7088708571143922 + 1.033197322819307 0.9687862576934944 + 1.4353052654987943 0.28202197206461327 + 0.24588090864430434 1.044051295369198 + 0.2688387528122659 5.375 + 0.33333333333333337 6.0 + 1.2894711087692583 0.4147662982391812 + 1.2747365658359935 0.47095549643502305 + 1.6050489090123727 0.701359091410823 + 1.550537613507314 0.7214197520535767 + 0.07387658485528542 0.8130037639664341 + 0.14511290432603197 0.939491062646291 + 0.7291666666666666 0.0 + 0.8624443884933936 0.09694324186960815 + 0.07431874516150205 0.3871752469020991 + 1.3586733685981895 0.32278200956665326 + 0.7743125163556892 1.7852573023241183 + 1.3951319674273832 0.7467489457540966 + 1.6723555903905802 0.6467284533501322 + 1.4638740821559169 0.7234515755624243 + 1.4927477124566209 0.2738469683956681 + 1.6895818983651612 0.3765958595614554 + 1.725742831711937 0.4855068293396377 + 1.3828391994677471 0.6932689949811435 + 1.5502891882510008 0.2796686701104153 + 1.6519383611714682 0.33269897851362074 + 1.4166666666666665 5.171709936804376 + 2.0 5.5 + 1.7470040926571286 5.26714151810979 + 1.762711901635018 0.44520425603505154 + 1.8366469302468644 0.45042453510946423 + 1.9060886700063842 0.5155263895621286 + 1.7432094576086072 0.3868933176340165 + 1.7985506191032619 0.3391937098408574 + 1.8878694231956714 0.26883597168004963 + 1.7916666666666665 0.0 + 2.0 0.125 + 0.9230460198845826 1.0631107620790716 + 1.1358084873427654 0.4220993253764972 + 0.19447305594557093 0.20726905545353125 + 1.3032549844320298 0.6108047284553858 + 2.0 0.625 + 1.2500000000000002 1.8319281123363502 + 0.6541111351264756 1.160918521091478 + 0.371895480593367 1.115292082681653 + 1.494273560202694 0.7688633005731953 + 1.4773323581048208 0.8252320844062707 + 1.4030882061420913 0.8684322443508078 + 0.7944598296275528 0.07158982321352167 + 1.0 3.25 + 0.75 3.25 + 0.595479687443039 4.280946022830838 + 1.0 4.25 + 2.0 4.5 + 1.5 4.5 + 2.0 2.5 + 1.5 2.5 + 2.0 3.5 + 1.5 3.5 + 0.6893660937409167 2.757464374963667 + 1.0 2.75 + 1.0 3.750000000000001 + 0.75 3.75 + 0.20607015431451464 0.07547310822581126 + 1.1137966762594949 0.1795335656241746 + 1.2083333333333333 0.0 + 1.1666666666666665 0.09271643952630988 + 0.3994151065612831 5.677353293275649 + 1.6783486674776207 0.70087084995281 + 1.7392543857928202 0.7377559547642759 + 1.8302710234553803 0.7298028546873176 + 2.0 0.875 + 1.8888519575683367 0.8331257280027056 + 1.800336932191529 0.9323381323744324 + 2.0 1.25 + 1.8227502338782238 1.1398294920180019 + 1.7994421968210412 1.375 + 1.7395586704615544 1.6944745976100235 + 1.7267593429098054 0.6440448038896638 + 1.7678827403626947 0.5201876828851476 + 1.2035918506774017 0.8877754751066075 + 1.16093306626047 0.5639869022785741 + 0.0 0.4375 + 1.291551342829673 0.6627651416324978 + 1.2538080175158937 0.6848149997324289 + 1.2577128301399019 0.7445318850453346 + 1.2090408575917337 0.7071751969044885 + 1.3306373761553634 0.7031246800642893 + 1.3160528628068418 0.7623584294631466 + 1.6462859848898292 0.27997768754971447 + 1.7020584160349093 0.234982296630739 + 1.5967635469661356 0.2541418634055588 + 1.6061662460929913 0.20693653438447443 + 1.570825246339907 0.16662443239081526 + 1.5905483961970126 0.07730943253130455 + 1.51018175705595 0.13363920248553696 + 1.4583333333333333 0.0 + 1.6590520810618847 0.20242355254666858 + 1.7125852936455277 0.12082842146382869 + 1.431068012499545 0.9581022021491937 + 1.477452094723081 1.130541403025688 + 1.5531080005501499 0.9914800857679006 + 1.2813569642026876 1.216110095730245 + 1.2018317226108364 1.4715704518745842 + 1.6198909607221894 1.1179240078762014 + 1.7983548141425743 0.46657478567124433 + 0.9770513066521348 0.18482460736504314 + 0.7938123559004582 5.2089259691333805 + 0.6407123629255758 4.851627018928146 + 1.319484941905665 0.8292893422114065 + 1.2761296818296555 0.5 + 1.8099178972915033 0.26187472706351006 + 1.7111729419512756 0.17826049305063374 + 1.759634673818009 0.34999662375758167 + 1.718142438071527 0.703889427730984 + 1.473230604388981 0.071097758315114 + 1.3863435254451124 0.06887822829586042 + 1.2782854698688741 0.09720405683617961 + 0.7375 4.501716097368583 + 0.44121509031025474 0.06500095027943562 + 1.305524838337339 0.3904736294480411 + 1.6684438208715549 0.25037958358667844 + 1.6996902177676332 0.2742036674155371 + 1.3624484903113168 0.2687327852709218 + 0.06974484917671708 0.9630027278134988 + 0.0 1.125 + 0.07352010305180143 1.054357451563032 + 1.1563399977503028 0.6357182129391813 + 0.5597884117036155 1.2501563862805738 + 0.5715382250636158 1.354065450073582 + 0.5980032696789671 1.504333348664305 + 0.5656039401938803 1.7204555756412738 + 0.3037866871454204 1.7568871511798612 + 0.46161571048938355 1.4121561268225087 + 0.3161306261019238 1.459468430239305 + 0.149758655496108 1.4149454869965006 + 0.16391023227107437 1.6142327799518283 + 0.7683057766893729 1.5148465969437765 + 0.7637530559523047 1.230480162353276 + 0.7720830332001749 1.3347191336230664 + 0.9050972636859582 1.3832137934898427 + 1.0559347141051296 1.4190962037054105 + 0.43329341865156223 1.2297056567872398 + 0.3893995908276335 1.3246186881965123 + 0.8840060412901801 1.1862259521425271 + 0.9479694782050885 1.272643328918064 + 1.4361522732329282 0.25034394087790574 + 1.4603794219490087 0.21438773060391503 + 1.4301726911242494 0.18040552911767954 + 1.3664948543862412 0.14105443922716654 + 1.3800869372880815 0.19025696838292824 + 1.4771932167810962 0.16902551127432658 + 1.40980282641639 0.2962430137342318 + 0.0 0.6875 + 2.0 0.375 + 1.9132736730754663 0.4382760179317226 + 0.055964514785385895 0.46875 + 1.6666208006494743 5.608342938440153 + 1.2445796724660527 0.5415967162439137 + 1.2035138373071206 0.5402730217783609 + 1.257035252439734 0.5890952409660676 + 1.2196380370307442 0.6135093363907388 + 1.383611268856942 0.23811038285103012 + 1.6226023422523703 0.7328606305005508 + 1.6335516540160544 0.7781375493960542 + 1.698042873799217 0.824601373114044 + 1.6559767278839401 0.902581204581636 + 1.5575918148450751 0.7567851055371636 + 1.5786042901358082 0.7983586872318487 + 1.561956830704648 0.8716273239716548 + 1.25 5.146519289061359 + 1.4166666666666667 1.853986608235224 + 1.6106377773288556 1.84006951687984 + 1.75 2.0547125573551916 + 1.5 2.25 + 1.75 2.375 + 1.75 2.6875 + 1.7351882330544273 0.25666486669089317 + 1.740696001877012 0.21209770142048218 + 1.7716317714671403 0.27248473247545524 + 1.780747250326824 0.23099526710030466 + 1.8315421621777004 0.21222918129712579 + 1.8571475226715097 0.09755754869299872 + 1.9212830619181216 0.17925938128868346 + 1.8307671503240839 0.15186156285696936 + 1.782563159254053 0.09488484980088335 + 1.7291666666666665 0.0 + 1.6979166666666665 0.05726348727905952 + 0.0635245517925628 0.7406804293007325 ] _NODES1 = [ - [1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370, 3, 401, 161, 142, 491, 340, 4], - [4, 341, 154, 459, 140, 346, 153, 376, 132, 379, 282, 5, 360, 131, 362, 6, 358, 129, 332, 7], - [7, 8, 9, 310, 10], - [10 203 273 133 270 138 267 11 263 141 274 130 271 201 266 12 276 158 173 430 134 234 146 458 149 139 387 229 145 1][:], + [1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370, 3, 401, 161, 142, 491, 340, 4], + [4, 341, 154, 459, 140, 346, 153, 376, 132, 379, 282, 5, 360, 131, 362, 6, 358, 129, 332, 7], + [7, 8, 9, 310, 10], + [10 203 273 133 270 138 267 11 263 141 274 130 271 201 266 12 276 158 173 430 134 234 146 458 149 139 387 229 145 1][:], ] _NODES2 = [ - [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 13][:], + [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 13][:], ] _NODES3 = [ - [62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 62][:], + [62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 62][:], ] _NODES4 = [ - [111, 225, 365, 112, 354, 220, 366, 113, 357, 223, 114][:], - [114, 115, 116, 117][:], - [117, 359, 118, 363, 119, 361, 479, 120][:], - [120, 121, 122, 111][:], + [111, 225, 365, 112, 354, 220, 366, 113, 357, 223, 114][:], + [114, 115, 116, 117][:], + [117, 359, 118, 363, 119, 361, 479, 120][:], + [120, 121, 122, 111][:], ] _NODES5 = [ - [123 265 202 272 136 275 128 264 137 268 135 269 124 222 356 125 367 221 355 126 364 224 127 123][:], + [123 265 202 272 136 275 128 264 137 268 135 269 124 222 356 125 367 221 355 126 364 224 127 123][:], ] const __BOUNDARY_NODES = [ - _NODES1, _NODES2, _NODES3, _NODES4, _NODES5 + _NODES1, _NODES2, _NODES3, _NODES4, _NODES5, ] @testset "get_left/right_boundary_node" begin - rng = StableRNG(1234555) - #= + rng = StableRNG(1234555) + #= _x, _y = complicated_geometry() x = _x y = _y @@ -573,1091 +573,1135 @@ const __BOUNDARY_NODES = [ A = get_area(tri) refine!(tri; max_area=1e-1A, rng) =# - points = tuple.(_POINTS[:, 1], _POINTS[:, 2]) - tri = triangulate(points; boundary_nodes=__BOUNDARY_NODES, rng, delete_ghosts=false) - nodes = [1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370] - right = [200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370, 3] - left = [145, 1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287] - @inferred DT.get_right_boundary_node(tri, 1, DT.𝒢) - @inferred DT.get_left_boundary_node(tri, 1, DT.𝒢) + points = tuple.(_POINTS[:, 1], _POINTS[:, 2]) + tri = triangulate(points; boundary_nodes = __BOUNDARY_NODES, rng, delete_ghosts = false) + nodes = [1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370] + right = [200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287, 370, 3] + left = [145, 1, 200, 301, 144, 248, 148, 2, 317, 147, 239, 143, 287] + @inferred DT.get_right_boundary_node(tri, 1, DT.𝒢) + @inferred DT.get_left_boundary_node(tri, 1, DT.𝒢) - for (i, r, ℓ) in zip(nodes, right, left) - DT.get_right_boundary_node(tri, i, DT.𝒢) == r - DT.get_left_boundary_node(tri, i, DT.𝒢) == ℓ - @inferred DT.get_left_boundary_node(tri, i, DT.𝒢) - end - nodes = [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] - right = [nodes[2:end]..., nodes[1]] - left = [nodes[end]..., nodes[1:(end-1)]...] - for (i, r, ℓ) in zip(nodes, right, left) - @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 4) == r - @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 4) == ℓ - end - nodes = [62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110] - right = [nodes[2:end]..., nodes[1]] - left = [nodes[end]..., nodes[1:(end-1)]...] - for (i, r, ℓ) in zip(nodes, right, left) - @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 5) == r - @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 5) == ℓ - end - nodes = [111 225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121 122] - right = [225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121 122 111] - left = [122 111 225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121] - for (i, r, ℓ) in zip(nodes, right, left) - @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 7) == r - @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 8) == ℓ - end - nodes = [123, 265, 202, 272, 136, 275, 128, 264] - right = [265, 202, 272, 136, 275, 128, 264, 137] - left = [127, 123, 265, 202, 272, 136, 275, 128] - for (i, r, ℓ) in zip(nodes, right, left) - @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 10) == r - @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 10) == ℓ - end + for (i, r, ℓ) in zip(nodes, right, left) + DT.get_right_boundary_node(tri, i, DT.𝒢) == r + DT.get_left_boundary_node(tri, i, DT.𝒢) == ℓ + @inferred DT.get_left_boundary_node(tri, i, DT.𝒢) + end + nodes = [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] + right = [nodes[2:end]..., nodes[1]] + left = [nodes[end]..., nodes[1:(end - 1)]...] + for (i, r, ℓ) in zip(nodes, right, left) + @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 4) == r + @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 4) == ℓ + end + nodes = [62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110] + right = [nodes[2:end]..., nodes[1]] + left = [nodes[end]..., nodes[1:(end - 1)]...] + for (i, r, ℓ) in zip(nodes, right, left) + @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 5) == r + @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 5) == ℓ + end + nodes = [111 225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121 122] + right = [225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121 122 111] + left = [122 111 225 365 112 354 220 366 113 357 223 114 115 116 117 359 118 363 119 361 479 120 121] + for (i, r, ℓ) in zip(nodes, right, left) + @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 7) == r + @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 8) == ℓ + end + nodes = [123, 265, 202, 272, 136, 275, 128, 264] + right = [265, 202, 272, 136, 275, 128, 264, 137] + left = [127, 123, 265, 202, 272, 136, 275, 128] + for (i, r, ℓ) in zip(nodes, right, left) + @test DT.get_right_boundary_node(tri, i, DT.𝒢 - 10) == r + @test DT.get_left_boundary_node(tri, i, DT.𝒢 - 10) == ℓ + end end @testset "find_edge" begin - for PT in subtypes(DT.AbstractPredicateKernel) - points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (0.5, 0.0), (0.5, 0.5), (0.0, 0.5)] - tri = triangulate(points, randomise=false) - T = (1, 2, 3) - ℓ = 4 - @test DT.find_edge(PT(), tri, T, ℓ) == (1, 2) - T = (2, 3, 1) - @test DT.find_edge(tri, T, ℓ) == (1, 2) - T = (1, 2, 3) - ℓ = 5 - @test DT.find_edge(PT(), tri, T, ℓ) == (2, 3) - T = (2, 3, 1) - @test DT.find_edge(tri, T, ℓ) == (2, 3) - T = (1, 2, 3) - ℓ = 6 - @test DT.find_edge(PT(), tri, T, ℓ) == (3, 1) - T = (2, 3, 1) - @test DT.find_edge(tri, T, ℓ) == (3, 1) - p1 = [2.0, 3.5] - p2 = [0.0, 0.0] - p3 = [3.0, 0.0] - p4 = [17.2, -2.5] - p5 = [0.0, 3.0] - points = [p1, p2, p3, p4, p5] - tri = triangulate(points, randomise=false) - T = (2, 3, 5) - push!(points, [1.0, 0.0]) - @test DT.find_edge(PT(), tri, T, length(points)) == (2, 3) - push!(points, [2.0, 0.0]) - @test DT.find_edge(PT(), tri, T, length(points)) == (2, 3) - push!(points, [1.5, 0.0]) - @test DT.find_edge(tri, T, length(points)) == (2, 3) - push!(points, [1.0, 0.0]) - @test DT.find_edge(tri, T, length(points)) == (2, 3) - push!(points, [0.5, 0.0]) - @test DT.find_edge(tri, T, length(points)) == (2, 3) - push!(points, [2.5, 0.5]) - @test DT.find_edge(tri, T, length(points)) == (3, 5) - push!(points, [2.0, 1.0]) - @test DT.find_edge(tri, T, length(points)) == (3, 5) - push!(points, [1.5, 1.5]) - @test DT.find_edge(tri, T, length(points)) == (3, 5) - push!(points, [1.0, 2.0]) - @test DT.find_edge(PT(), tri, T, length(points)) == (3, 5) - push!(points, [0.5, 2.5]) - @test DT.find_edge(PT(), tri, T, length(points)) == (3, 5) - push!(points, [0.0, 2.5]) - @test DT.find_edge(PT(), tri, T, length(points)) == (5, 2) - push!(points, [0.0, 2.2]) - @test DT.find_edge(tri, T, length(points)) == (5, 2) - push!(points, [0.0, 2.0]) - @test DT.find_edge(tri, T, length(points)) == (5, 2) - push!(points, [0.0, 1.5]) - @test DT.find_edge(tri, T, length(points)) == (5, 2) - push!(points, [0.0, 0.8]) - @test DT.find_edge(tri, T, length(points)) == (5, 2) - push!(points, [0.0, 0.2]) - @test DT.find_edge(PT(), tri, T, length(points)) == (5, 2) - end + for PT in subtypes(DT.AbstractPredicateKernel) + points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (0.5, 0.0), (0.5, 0.5), (0.0, 0.5)] + tri = triangulate(points, randomise = false) + T = (1, 2, 3) + ℓ = 4 + @test DT.find_edge(PT(), tri, T, ℓ) == (1, 2) + T = (2, 3, 1) + @test DT.find_edge(tri, T, ℓ) == (1, 2) + T = (1, 2, 3) + ℓ = 5 + @test DT.find_edge(PT(), tri, T, ℓ) == (2, 3) + T = (2, 3, 1) + @test DT.find_edge(tri, T, ℓ) == (2, 3) + T = (1, 2, 3) + ℓ = 6 + @test DT.find_edge(PT(), tri, T, ℓ) == (3, 1) + T = (2, 3, 1) + @test DT.find_edge(tri, T, ℓ) == (3, 1) + p1 = [2.0, 3.5] + p2 = [0.0, 0.0] + p3 = [3.0, 0.0] + p4 = [17.2, -2.5] + p5 = [0.0, 3.0] + points = [p1, p2, p3, p4, p5] + tri = triangulate(points, randomise = false) + T = (2, 3, 5) + push!(points, [1.0, 0.0]) + @test DT.find_edge(PT(), tri, T, length(points)) == (2, 3) + push!(points, [2.0, 0.0]) + @test DT.find_edge(PT(), tri, T, length(points)) == (2, 3) + push!(points, [1.5, 0.0]) + @test DT.find_edge(tri, T, length(points)) == (2, 3) + push!(points, [1.0, 0.0]) + @test DT.find_edge(tri, T, length(points)) == (2, 3) + push!(points, [0.5, 0.0]) + @test DT.find_edge(tri, T, length(points)) == (2, 3) + push!(points, [2.5, 0.5]) + @test DT.find_edge(tri, T, length(points)) == (3, 5) + push!(points, [2.0, 1.0]) + @test DT.find_edge(tri, T, length(points)) == (3, 5) + push!(points, [1.5, 1.5]) + @test DT.find_edge(tri, T, length(points)) == (3, 5) + push!(points, [1.0, 2.0]) + @test DT.find_edge(PT(), tri, T, length(points)) == (3, 5) + push!(points, [0.5, 2.5]) + @test DT.find_edge(PT(), tri, T, length(points)) == (3, 5) + push!(points, [0.0, 2.5]) + @test DT.find_edge(PT(), tri, T, length(points)) == (5, 2) + push!(points, [0.0, 2.2]) + @test DT.find_edge(tri, T, length(points)) == (5, 2) + push!(points, [0.0, 2.0]) + @test DT.find_edge(tri, T, length(points)) == (5, 2) + push!(points, [0.0, 1.5]) + @test DT.find_edge(tri, T, length(points)) == (5, 2) + push!(points, [0.0, 0.8]) + @test DT.find_edge(tri, T, length(points)) == (5, 2) + push!(points, [0.0, 0.2]) + @test DT.find_edge(PT(), tri, T, length(points)) == (5, 2) + end end @testset "choose_uvw" begin - i, j, k = rand(Int, 3) - @test DT.choose_uvw(true, false, false, i, j, k) == (i, j, k) - @test DT.choose_uvw(false, true, false, i, j, k) == (j, k, i) - @test DT.choose_uvw(false, false, true, i, j, k) == (k, i, j) + i, j, k = rand(Int, 3) + @test DT.choose_uvw(true, false, false, i, j, k) == (i, j, k) + @test DT.choose_uvw(false, true, false, i, j, k) == (j, k, i) + @test DT.choose_uvw(false, false, true, i, j, k) == (k, i, j) end @testset "is_circular" begin - x = rand(10) - @test !DT.is_circular(x) - push!(x, x[begin]) - @test DT.is_circular(x) - @test DT.is_circular(Float64[]) + x = rand(10) + @test !DT.is_circular(x) + push!(x, x[begin]) + @test DT.is_circular(x) + @test DT.is_circular(Float64[]) end @testset "circular_equality" begin - @test !DT.circular_equality([1, 2, 3, 4, 1], [3, 2, 4, 1, 3]) - @test !DT.circular_equality([1, 2, 3, 1], [3, 4, 5, 3]) - @test_throws AssertionError DT.circular_equality([1, 2, 3, 1], [3, 4, 5]) - @test_throws AssertionError DT.circular_equality([1, 2, 3], [5, 4, 3]) - @test !DT.circular_equality([1, 2, 3, 4, 1], [1, 2, 1]) - x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1] - for i in 1:10 - local y - y = @views circshift(x[begin:(end-1)], i) - push!(y, y[begin]) - @test DT.circular_equality(x, y) && DT.circular_equality(y, x) - end - @test DT.circular_equality([3, 2, 1, 13, 12, 11, 5, 4, 3], [1, 13, 12, 11, 5, 4, 3, 2, 1]) - @test DT.circular_equality(Float64[], Float64[]) + @test !DT.circular_equality([1, 2, 3, 4, 1], [3, 2, 4, 1, 3]) + @test !DT.circular_equality([1, 2, 3, 1], [3, 4, 5, 3]) + @test_throws AssertionError DT.circular_equality([1, 2, 3, 1], [3, 4, 5]) + @test_throws AssertionError DT.circular_equality([1, 2, 3], [5, 4, 3]) + @test !DT.circular_equality([1, 2, 3, 4, 1], [1, 2, 1]) + x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1] + for i in 1:10 + local y + y = @views circshift(x[begin:(end - 1)], i) + push!(y, y[begin]) + @test DT.circular_equality(x, y) && DT.circular_equality(y, x) + end + @test DT.circular_equality([3, 2, 1, 13, 12, 11, 5, 4, 3], [1, 13, 12, 11, 5, 4, 3, 2, 1]) + @test DT.circular_equality(Float64[], Float64[]) end @testset "get_surrounding_polygon" begin - tri = example_triangulation() - rng = StableRNG(999987897899) - tri = triangulate(get_points(tri); delete_ghosts=false, rng) - polys = Dict( - 1 => [6, 3, 7, 4, 6], - 2 => [8, 3, 6, DT.𝒢, 8], - 3 => [8, 7, 1, 6, 2, 8], - 4 => [6, 1, 7, 5, DT.𝒢, 6], - 5 => [4, 7, 8, DT.𝒢, 4], - 6 => [2, 3, 1, 4, DT.𝒢, 2], - 7 => [8, 5, 4, 1, 3, 8], - 8 => [5, 7, 3, 2, DT.𝒢, 5], - DT.𝒢 => [5, 8, 2, 6, 4, 5] - ) - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) - fnc_polys[i] = DT.get_surrounding_polygon(tri, i) - push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) - @test DT.circular_equality(poly_true, poly_f) - end - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) - fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices=true) - push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) - @test DT.circular_equality(filter(!DT.is_ghost_vertex, poly_true), poly_f) - end - tri, label_map, index_map = simple_geometry() - DT.compute_representative_points!(tri) - add_ghost_triangles!(tri) - polys = Dict( - 1 => [[2, 20, 19, 8, DT.𝒢, 2]], - 2 => [[3, 16, 20, 1, DT.𝒢, 3]], - 3 => [[4, 17, 16, 2, DT.𝒢, 4]], - 4 => [[5, 18, 17, 3, DT.𝒢, 5]], - 5 => [[6, 22, 24, 18, 4, DT.𝒢, 6]], - 6 => [[7, 25, 9, 12, 23, 22, 5, DT.𝒢, 7]], - 7 => [[8, 26, 9, 25, 6, DT.𝒢, 8]], - 8 => [[1, 19, 10, 26, 7, DT.𝒢, 1]], - 9 => [[6, 25, 7, 26, 10, DT.𝒢 - 1, 12, 6]], - 10 => [[11, DT.𝒢 - 1, 9, 26, 8, 19, 20, 21, 11]], - 11 => [[12, DT.𝒢 - 1, 10, 21, 23, 12]], - 12 => [[23, 6, 9, DT.𝒢 - 1, 11, 23]], - 13 => [[18, 24, 22, 23, 21, 14, DT.𝒢 - 2, 18], - [18, 24, 22, 23, 21, 14, DT.𝒢 - 3, 18]], - 14 => [[13, 21, 15, DT.𝒢 - 2, 13], - [13, 21, 15, DT.𝒢 - 3, 13]], - 15 => [[14, 21, 20, 16, DT.𝒢 - 2, 14], - [14, 21, 20, 16, DT.𝒢 - 3, 14]], - 16 => [[15, 20, 2, 3, 17, DT.𝒢 - 2, 15], - [15, 20, 2, 3, 17, DT.𝒢 - 3, 15]], - 17 => [[16, 3, 4, 18, DT.𝒢 - 2, 16], - [16, 3, 4, 18, DT.𝒢 - 3, 16]], - 18 => [[17, 4, 5, 24, 13, DT.𝒢 - 2, 17], - [17, 4, 5, 24, 13, DT.𝒢 - 3, 17]], - 19 => [[1, 20, 10, 8, 1]], - 20 => [[16, 15, 21, 10, 19, 1, 2, 16]], - 21 => [[15, 14, 13, 23, 11, 10, 20, 15]], - 22 => [[24, 5, 6, 23, 13, 24]], - 23 => [[13, 22, 6, 12, 11, 21, 13]], - 24 => [[18, 5, 22, 13, 18]], - 25 => [[9, 6, 7, 9]], - 26 => [[10, 9, 7, 8, 10]], - DT.𝒢 => [[5, 4, 3, 2, 1, 8, 7, 6, 5]], - DT.𝒢 - 1 => [[9, 10, 11, 12, 9]], - DT.𝒢 - 2 => [[14, 15, 16, 17, 18, 13, 14]], - DT.𝒢 - 3 => [[14, 15, 16, 17, 18, 13, 14]] - ) - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) + tri = example_triangulation() + rng = StableRNG(999987897899) + tri = triangulate(get_points(tri); delete_ghosts = false, rng) + polys = Dict( + 1 => [6, 3, 7, 4, 6], + 2 => [8, 3, 6, DT.𝒢, 8], + 3 => [8, 7, 1, 6, 2, 8], + 4 => [6, 1, 7, 5, DT.𝒢, 6], + 5 => [4, 7, 8, DT.𝒢, 4], + 6 => [2, 3, 1, 4, DT.𝒢, 2], + 7 => [8, 5, 4, 1, 3, 8], + 8 => [5, 7, 3, 2, DT.𝒢, 5], + DT.𝒢 => [5, 8, 2, 6, 4, 5], + ) + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) + fnc_polys[i] = DT.get_surrounding_polygon(tri, i) + push!(fnc_polys[i], fnc_polys[i][begin]) + end + for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) + @test DT.circular_equality(poly_true, poly_f) + end + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) + fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices = true) + push!(fnc_polys[i], fnc_polys[i][begin]) + end + for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) + @test DT.circular_equality(filter(!DT.is_ghost_vertex, poly_true), poly_f) + end + tri, label_map, index_map = simple_geometry() + DT.compute_representative_points!(tri) + add_ghost_triangles!(tri) + polys = Dict( + 1 => [[2, 20, 19, 8, DT.𝒢, 2]], + 2 => [[3, 16, 20, 1, DT.𝒢, 3]], + 3 => [[4, 17, 16, 2, DT.𝒢, 4]], + 4 => [[5, 18, 17, 3, DT.𝒢, 5]], + 5 => [[6, 22, 24, 18, 4, DT.𝒢, 6]], + 6 => [[7, 25, 9, 12, 23, 22, 5, DT.𝒢, 7]], + 7 => [[8, 26, 9, 25, 6, DT.𝒢, 8]], + 8 => [[1, 19, 10, 26, 7, DT.𝒢, 1]], + 9 => [[6, 25, 7, 26, 10, DT.𝒢 - 1, 12, 6]], + 10 => [[11, DT.𝒢 - 1, 9, 26, 8, 19, 20, 21, 11]], + 11 => [[12, DT.𝒢 - 1, 10, 21, 23, 12]], + 12 => [[23, 6, 9, DT.𝒢 - 1, 11, 23]], + 13 => [ + [18, 24, 22, 23, 21, 14, DT.𝒢 - 2, 18], + [18, 24, 22, 23, 21, 14, DT.𝒢 - 3, 18], + ], + 14 => [ + [13, 21, 15, DT.𝒢 - 2, 13], + [13, 21, 15, DT.𝒢 - 3, 13], + ], + 15 => [ + [14, 21, 20, 16, DT.𝒢 - 2, 14], + [14, 21, 20, 16, DT.𝒢 - 3, 14], + ], + 16 => [ + [15, 20, 2, 3, 17, DT.𝒢 - 2, 15], + [15, 20, 2, 3, 17, DT.𝒢 - 3, 15], + ], + 17 => [ + [16, 3, 4, 18, DT.𝒢 - 2, 16], + [16, 3, 4, 18, DT.𝒢 - 3, 16], + ], + 18 => [ + [17, 4, 5, 24, 13, DT.𝒢 - 2, 17], + [17, 4, 5, 24, 13, DT.𝒢 - 3, 17], + ], + 19 => [[1, 20, 10, 8, 1]], + 20 => [[16, 15, 21, 10, 19, 1, 2, 16]], + 21 => [[15, 14, 13, 23, 11, 10, 20, 15]], + 22 => [[24, 5, 6, 23, 13, 24]], + 23 => [[13, 22, 6, 12, 11, 21, 13]], + 24 => [[18, 5, 22, 13, 18]], + 25 => [[9, 6, 7, 9]], + 26 => [[10, 9, 7, 8, 10]], + DT.𝒢 => [[5, 4, 3, 2, 1, 8, 7, 6, 5]], + DT.𝒢 - 1 => [[9, 10, 11, 12, 9]], + DT.𝒢 - 2 => [[14, 15, 16, 17, 18, 13, 14]], + DT.𝒢 - 3 => [[14, 15, 16, 17, 18, 13, 14]], + ) + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) + fnc_polys[i] = DT.get_surrounding_polygon(tri, i) + push!(fnc_polys[i], fnc_polys[i][begin]) + end + for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) + @test any(DT.circular_equality(S, poly_f) for S in poly_true) + end + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) + fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices = true) + push!(fnc_polys[i], fnc_polys[i][begin]) + end + for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) + @test any(DT.circular_equality(filter(!DT.is_ghost_vertex, S), poly_f) for S in poly_true) + end + + tri2 = example_with_special_corners() + polys = Dict( + 1 => [DT.𝒢, 5, 4, 16, 3, 2, DT.𝒢], + 2 => [DT.𝒢, 1, 3, DT.𝒢], + 3 => [2, 1, 16, 6, 7, DT.𝒢, 2], + 4 => [5, 16, 1, 5], + 5 => [13, 18, 16, 4, 1, DT.𝒢, 13], + 6 => [3, 16, 17, 7, 3], + 7 => [3, 6, 17, 15, 8, DT.𝒢, 3], + 8 => [7, 15, 9, DT.𝒢, 7], + 9 => [8, 15, 11, 10, DT.𝒢, 8], + 10 => [9, 11, 12, 13, DT.𝒢, 9], + 11 => [9, 15, 12, 10, 9], + 12 => [18, 13, 10, 11, 15, 14, 18], + 13 => [10, 12, 18, 5, DT.𝒢, 10], + 14 => [15, 17, 18, 12, 15], + 15 => [8, 7, 17, 14, 12, 11, 9, 8], + 16 => [4, 5, 18, 17, 6, 3, 1, 4], + 17 => [7, 6, 16, 18, 14, 15, 7], + 18 => [5, 13, 12, 14, 17, 16, 5], + ) + for mmm in 1:1000 + local tri, fnc_polys + tri = triangulate(get_points(tri2); delete_ghosts = false) + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) fnc_polys[i] = DT.get_surrounding_polygon(tri, i) push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) - @test any(DT.circular_equality(S, poly_f) for S in poly_true) - end - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) - fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices=true) + end + for (k, S) in polys + @test DT.circular_equality(S, fnc_polys[k]) + end + fnc_polys = Dict{Int, Vector{Int}}() + for i in keys(polys) + fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices = true) push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (poly_true, poly_f) in zip(values(polys), values(fnc_polys)) - @test any(DT.circular_equality(filter(!DT.is_ghost_vertex, S), poly_f) for S in poly_true) - end - - tri2 = example_with_special_corners() - polys = Dict( - 1 => [DT.𝒢, 5, 4, 16, 3, 2, DT.𝒢], - 2 => [DT.𝒢, 1, 3, DT.𝒢], - 3 => [2, 1, 16, 6, 7, DT.𝒢, 2], - 4 => [5, 16, 1, 5], - 5 => [13, 18, 16, 4, 1, DT.𝒢, 13], - 6 => [3, 16, 17, 7, 3], - 7 => [3, 6, 17, 15, 8, DT.𝒢, 3], - 8 => [7, 15, 9, DT.𝒢, 7], - 9 => [8, 15, 11, 10, DT.𝒢, 8], - 10 => [9, 11, 12, 13, DT.𝒢, 9], - 11 => [9, 15, 12, 10, 9], - 12 => [18, 13, 10, 11, 15, 14, 18], - 13 => [10, 12, 18, 5, DT.𝒢, 10], - 14 => [15, 17, 18, 12, 15], - 15 => [8, 7, 17, 14, 12, 11, 9, 8], - 16 => [4, 5, 18, 17, 6, 3, 1, 4], - 17 => [7, 6, 16, 18, 14, 15, 7], - 18 => [5, 13, 12, 14, 17, 16, 5] - ) - for mmm in 1:1000 - local tri, fnc_polys - tri = triangulate(get_points(tri2); delete_ghosts=false) - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) - fnc_polys[i] = DT.get_surrounding_polygon(tri, i) - push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (k, S) in polys - @test DT.circular_equality(S, fnc_polys[k]) - end - fnc_polys = Dict{Int,Vector{Int}}() - for i in keys(polys) - fnc_polys[i] = DT.get_surrounding_polygon(tri, i; skip_ghost_vertices=true) - push!(fnc_polys[i], fnc_polys[i][begin]) - end - for (k, S) in polys - _S = filter(!DT.is_ghost_vertex, S) - DT.is_ghost_vertex(S[begin]) && push!(_S, _S[begin]) # might have removed a boundary index in the first entry, so we'd no longer have a circular array - @test DT.circular_equality(_S, fnc_polys[k]) - end - end + end + for (k, S) in polys + _S = filter(!DT.is_ghost_vertex, S) + DT.is_ghost_vertex(S[begin]) && push!(_S, _S[begin]) # might have removed a boundary index in the first entry, so we'd no longer have a circular array + @test DT.circular_equality(_S, fnc_polys[k]) + end + end end @testset "sort_edge_by_degree" begin - tri = triangulate(rand(2, 500); delete_ghosts=false) - graph = get_graph(tri) - for e in DT.get_edges(graph) - new_e = DT.sort_edge_by_degree(tri, e) - d1 = DT.num_neighbours(graph, e[1]) - d2 = DT.num_neighbours(graph, e[2]) - if d1 ≤ d2 - @test new_e == e - else - @test new_e == (e[2], e[1]) - end - end + tri = triangulate(rand(2, 500); delete_ghosts = false) + graph = get_graph(tri) + for e in DT.get_edges(graph) + new_e = DT.sort_edge_by_degree(tri, e) + d1 = DT.num_neighbours(graph, e[1]) + d2 = DT.num_neighbours(graph, e[2]) + if d1 ≤ d2 + @test new_e == e + else + @test new_e == (e[2], e[1]) + end + end end @testset "split_segment!" begin - constrained_edges = Set{NTuple{2,Int}}(((2, 7),)) - DT.split_segment!(constrained_edges, (2, 7), []) - @test constrained_edges == Set{NTuple{2,Int}}(((2, 7),)) - DT.split_segment!(constrained_edges, (2, 7), [(2, 3), (3, 5), (10, 12)]) - @test constrained_edges == Set{NTuple{2,Int}}(((2, 3), (3, 5), (10, 12))) - DT.split_segment!(constrained_edges, (2, 7), []) - @test constrained_edges == Set{NTuple{2,Int}}(((2, 3), (3, 5), (10, 12))) - DT.split_segment!(constrained_edges, (3, 5), [(2, 10), (11, 15), (2, 3)]) - @test constrained_edges == Set{NTuple{2,Int}}(((2, 3), (2, 10), (11, 15), (10, 12))) - DT.split_segment!(constrained_edges, (3, 2), []) - @test constrained_edges == Set{NTuple{2,Int}}(((2, 3), (2, 10), (11, 15), (10, 12))) - DT.split_segment!(constrained_edges, (3, 2), [(10, 2), (23, 10)]) - @test constrained_edges == Set{NTuple{2,Int}}(((11, 15), (10, 12), (23, 10), (2, 10))) + constrained_edges = Set{NTuple{2, Int}}(((2, 7),)) + DT.split_segment!(constrained_edges, (2, 7), []) + @test constrained_edges == Set{NTuple{2, Int}}(((2, 7),)) + DT.split_segment!(constrained_edges, (2, 7), [(2, 3), (3, 5), (10, 12)]) + @test constrained_edges == Set{NTuple{2, Int}}(((2, 3), (3, 5), (10, 12))) + DT.split_segment!(constrained_edges, (2, 7), []) + @test constrained_edges == Set{NTuple{2, Int}}(((2, 3), (3, 5), (10, 12))) + DT.split_segment!(constrained_edges, (3, 5), [(2, 10), (11, 15), (2, 3)]) + @test constrained_edges == Set{NTuple{2, Int}}(((2, 3), (2, 10), (11, 15), (10, 12))) + DT.split_segment!(constrained_edges, (3, 2), []) + @test constrained_edges == Set{NTuple{2, Int}}(((2, 3), (2, 10), (11, 15), (10, 12))) + DT.split_segment!(constrained_edges, (3, 2), [(10, 2), (23, 10)]) + @test constrained_edges == Set{NTuple{2, Int}}(((11, 15), (10, 12), (23, 10), (2, 10))) end @testset "connect_segments!" begin - C = [(7, 12), (12, 17), (17, 22), (32, 37), (37, 42), (42, 47)] - DT.connect_segments!(C) - @test C == [(7, 12), (12, 17), (17, 22), (22, 32), (32, 37), (37, 42), (42, 47)] - C = [(4, 9), (19, 24), (24, 29), (34, 39), (39, 44), (44, 49)] - DT.connect_segments!(C) - @test C == [(4, 9), (9, 19), (19, 24), (24, 29), (29, 34), (34, 39), (39, 44), (44, 49)] - C = [(4, 9), (9, 5)] - DT.connect_segments!(C) - @test C == [(4, 9), (9, 5)] - C = [(49, 44), (44, 39), (39, 34), (29, 24), (24, 19), (9, 4)] - DT.connect_segments!(C) - @test C == [(49, 44), (44, 39), (39, 34), (34, 29), (29, 24), (24, 19), (19, 9), (9, 4)] + C = [(7, 12), (12, 17), (17, 22), (32, 37), (37, 42), (42, 47)] + DT.connect_segments!(C) + @test C == [(7, 12), (12, 17), (17, 22), (22, 32), (32, 37), (37, 42), (42, 47)] + C = [(4, 9), (19, 24), (24, 29), (34, 39), (39, 44), (44, 49)] + DT.connect_segments!(C) + @test C == [(4, 9), (9, 19), (19, 24), (24, 29), (29, 34), (34, 39), (39, 44), (44, 49)] + C = [(4, 9), (9, 5)] + DT.connect_segments!(C) + @test C == [(4, 9), (9, 5)] + C = [(49, 44), (44, 39), (39, 34), (29, 24), (24, 19), (9, 4)] + DT.connect_segments!(C) + @test C == [(49, 44), (44, 39), (39, 34), (34, 29), (29, 24), (24, 19), (19, 9), (9, 4)] end @testset "extend_segments!" begin - segments = [(7, 12), (12, 17), (17, 22), (22, 27)] - constrained_edge = (7, 27) - DT.extend_segments!(segments, constrained_edge) - @test segments == [(7, 12), (12, 17), (17, 22), (22, 27)] - constrained_edge = (2, 32) - DT.extend_segments!(segments, constrained_edge) - @test segments == [(2, 7), (7, 12), (12, 17), (17, 22), (22, 27), (27, 32)] - segments = [(33, 29)] - constrained_edge = (37, 29) - DT.extend_segments!(segments, constrained_edge) - @test segments == [(37, 33), (33, 29)] - segments = [(29, 33)] - constrained_edge = (29, 37) - DT.extend_segments!(segments, constrained_edge) - @test segments == [(29, 33), (33, 37)] - segments = [(3, 25), (25, 1)] - DT.extend_segments!(segments, (3, 1)) - @test segments == [(3, 25), (25, 1)] + segments = [(7, 12), (12, 17), (17, 22), (22, 27)] + constrained_edge = (7, 27) + DT.extend_segments!(segments, constrained_edge) + @test segments == [(7, 12), (12, 17), (17, 22), (22, 27)] + constrained_edge = (2, 32) + DT.extend_segments!(segments, constrained_edge) + @test segments == [(2, 7), (7, 12), (12, 17), (17, 22), (22, 27), (27, 32)] + segments = [(33, 29)] + constrained_edge = (37, 29) + DT.extend_segments!(segments, constrained_edge) + @test segments == [(37, 33), (33, 29)] + segments = [(29, 33)] + constrained_edge = (29, 37) + DT.extend_segments!(segments, constrained_edge) + @test segments == [(29, 33), (33, 37)] + segments = [(3, 25), (25, 1)] + DT.extend_segments!(segments, (3, 1)) + @test segments == [(3, 25), (25, 1)] end @testset "convert_boundary_points_to_indices" begin - x = [[1.0, 2.0, 3.0, 4.0, 5.0], [5.0, 6.0, 7.0, 8.0], [8.0, 13.0, 15.0, 1.0]] - y = [[0.0, 2.5, 3.0, 9.0, 7.0], [7.0, 9.0, 2.0, 1.0], [1.0, 23.0, 25.0, 0.0]] - nodes, _pts = convert_boundary_points_to_indices(x, y) - @test nodes == [[1, 2, 3, 4, 5], [5, 6, 7, 8], [8, 9, 10, 1]] - @test _pts == [(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), - (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0)] - existing_points = [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)] - nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) - @test nodes == [[1, 2, 3, 4, 5] .+ 5, [5, 6, 7, 8] .+ 5, [8, 9, 10, 1] .+ 5] - @test _pts == existing_points == append!( - [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)], - [(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), - (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0)] - ) - nodes, _pts = convert_boundary_points_to_indices([[(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0)], - [(5.0, 7.0), (6.0, 9.0), (7.0, 2.0), (8.0, 1.0)], [(8.0, 1.0), (13.0, 23.0), (15.0, 25.0), (1.0, 0.0)]]) - @test nodes == [[1, 2, 3, 4, 5], [5, 6, 7, 8], [8, 9, 10, 1]] - @test _pts == [(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), - (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0)] - existing_points = [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)] - nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) - @test nodes == [[1, 2, 3, 4, 5] .+ 5, [5, 6, 7, 8] .+ 5, [8, 9, 10, 1] .+ 5] - @test _pts == existing_points == append!( - [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)], - [(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), - (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0)] - ) + x = [[1.0, 2.0, 3.0, 4.0, 5.0], [5.0, 6.0, 7.0, 8.0], [8.0, 13.0, 15.0, 1.0]] + y = [[0.0, 2.5, 3.0, 9.0, 7.0], [7.0, 9.0, 2.0, 1.0], [1.0, 23.0, 25.0, 0.0]] + nodes, _pts = convert_boundary_points_to_indices(x, y) + @test nodes == [[1, 2, 3, 4, 5], [5, 6, 7, 8], [8, 9, 10, 1]] + @test _pts == [ + (1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), + (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0), + ] + existing_points = [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)] + nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) + @test nodes == [[1, 2, 3, 4, 5] .+ 5, [5, 6, 7, 8] .+ 5, [8, 9, 10, 1] .+ 5] + @test _pts == existing_points == append!( + [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)], + [ + (1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), + (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0), + ], + ) + nodes, _pts = convert_boundary_points_to_indices( + [ + [(1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0)], + [(5.0, 7.0), (6.0, 9.0), (7.0, 2.0), (8.0, 1.0)], [(8.0, 1.0), (13.0, 23.0), (15.0, 25.0), (1.0, 0.0)], + ], + ) + @test nodes == [[1, 2, 3, 4, 5], [5, 6, 7, 8], [8, 9, 10, 1]] + @test _pts == [ + (1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), + (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0), + ] + existing_points = [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)] + nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) + @test nodes == [[1, 2, 3, 4, 5] .+ 5, [5, 6, 7, 8] .+ 5, [8, 9, 10, 1] .+ 5] + @test _pts == existing_points == append!( + [(1.0, 3.0), (15.0, 17.3), (9.3, 2.5), (11.0, 29.0), (35.0, -5.0)], + [ + (1.0, 0.0), (2.0, 2.5), (3.0, 3.0), (4.0, 9.0), (5.0, 7.0), (6.0, 9.0), + (7.0, 2.0), (8.0, 1.0), (13.0, 23.0), (15.0, 25.0), + ], + ) - x1 = [[1.0, 2.0, 3.0], [3.0, 4.0, 5.5, 6.7], [6.7, 2.0, 1.0]] - y1 = [[2.0, 2.5, 3.5], [3.5, 4.5, 7.7, 9.9], [9.9, 1.1, 2.0]] - x2 = [[1.0, 1.2, 1.3, 1.4, 1.5, 1.0]] - y2 = [[2.5, 2.7, 9.9, 2.0, 3.5, 2.5]] - x3 = [[9.5, 13.7, 3.3], [3.3, 5.5, 9.5]] - y3 = [[2.5, 11.7, 3.9], [3.9, 1.0, 2.5]] - x = [x1, x2, x3] - y = [y1, y2, y3] - nodes, _pts = convert_boundary_points_to_indices(x, y) - node1 = [[1, 2, 3], [3, 4, 5, 6], [6, 7, 1]] - node2 = [[8, 9, 10, 11, 12, 8]] - node3 = [[13, 14, 15], [15, 16, 13]] - @test nodes == [node1, node2, node3] - @test _pts == [(1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), + x1 = [[1.0, 2.0, 3.0], [3.0, 4.0, 5.5, 6.7], [6.7, 2.0, 1.0]] + y1 = [[2.0, 2.5, 3.5], [3.5, 4.5, 7.7, 9.9], [9.9, 1.1, 2.0]] + x2 = [[1.0, 1.2, 1.3, 1.4, 1.5, 1.0]] + y2 = [[2.5, 2.7, 9.9, 2.0, 3.5, 2.5]] + x3 = [[9.5, 13.7, 3.3], [3.3, 5.5, 9.5]] + y3 = [[2.5, 11.7, 3.9], [3.9, 1.0, 2.5]] + x = [x1, x2, x3] + y = [y1, y2, y3] + nodes, _pts = convert_boundary_points_to_indices(x, y) + node1 = [[1, 2, 3], [3, 4, 5, 6], [6, 7, 1]] + node2 = [[8, 9, 10, 11, 12, 8]] + node3 = [[13, 14, 15], [15, 16, 13]] + @test nodes == [node1, node2, node3] + @test _pts == [ + (1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), + (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), + (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0), + ] + existing_points = [(1.0, 3.0), (3.5, 5.5), (13.7, 25.0), (19.0, 37.3), (100.0, 100.0), (10.3, 5.5)] + nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) + node1 = [[1, 2, 3] .+ 6, [3, 4, 5, 6] .+ 6, [6, 7, 1] .+ 6] + node2 = [[8, 9, 10, 11, 12, 8] .+ 6] + node3 = [[13, 14, 15] .+ 6, [15, 16, 13] .+ 6] + @test nodes == [node1, node2, node3] + @test _pts == append!( + existing_points, + [ + (1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), - (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0)] - existing_points = [(1.0, 3.0), (3.5, 5.5), (13.7, 25.0), (19.0, 37.3), (100.0, 100.0), (10.3, 5.5)] - nodes, _pts = convert_boundary_points_to_indices(x, y; existing_points) - node1 = [[1, 2, 3] .+ 6, [3, 4, 5, 6] .+ 6, [6, 7, 1] .+ 6] - node2 = [[8, 9, 10, 11, 12, 8] .+ 6] - node3 = [[13, 14, 15] .+ 6, [15, 16, 13] .+ 6] - @test nodes == [node1, node2, node3] - @test _pts == append!( - existing_points, - [(1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), - (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), - (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0)] - ) - xy1 = [[(1.0, 2.0), (2.0, 2.5), (3.0, 3.5)], [(3.0, 3.5), (4.0, 4.5), (5.5, 7.7), (6.7, 9.9)], [(6.7, 9.9), (2.0, 1.1), (1.0, 2.0)]] - xy2 = [[(1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), (1.0, 2.5)]] - xy3 = [[(9.5, 2.5), (13.7, 11.7), (3.3, 3.9)], [(3.3, 3.9), (5.5, 1.0), (9.5, 2.5)]] - xy = [xy1, xy2, xy3] - nodes, _pts = convert_boundary_points_to_indices(xy) - node1 = [[1, 2, 3], [3, 4, 5, 6], [6, 7, 1]] - node2 = [[8, 9, 10, 11, 12, 8]] - node3 = [[13, 14, 15], [15, 16, 13]] - @test nodes == [node1, node2, node3] - @test _pts == [(1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), + (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0), + ], + ) + xy1 = [[(1.0, 2.0), (2.0, 2.5), (3.0, 3.5)], [(3.0, 3.5), (4.0, 4.5), (5.5, 7.7), (6.7, 9.9)], [(6.7, 9.9), (2.0, 1.1), (1.0, 2.0)]] + xy2 = [[(1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), (1.0, 2.5)]] + xy3 = [[(9.5, 2.5), (13.7, 11.7), (3.3, 3.9)], [(3.3, 3.9), (5.5, 1.0), (9.5, 2.5)]] + xy = [xy1, xy2, xy3] + nodes, _pts = convert_boundary_points_to_indices(xy) + node1 = [[1, 2, 3], [3, 4, 5, 6], [6, 7, 1]] + node2 = [[8, 9, 10, 11, 12, 8]] + node3 = [[13, 14, 15], [15, 16, 13]] + @test nodes == [node1, node2, node3] + @test _pts == [ + (1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), + (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), + (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0), + ] + existing_points = [(1.0, 3.0), (3.5, 5.5), (13.7, 25.0), (19.0, 37.3), (100.0, 100.0), (10.3, 5.5)] + nodes, _pts = convert_boundary_points_to_indices(xy; existing_points) + node1 = [[1, 2, 3] .+ 6, [3, 4, 5, 6] .+ 6, [6, 7, 1] .+ 6] + node2 = [[8, 9, 10, 11, 12, 8] .+ 6] + node3 = [[13, 14, 15] .+ 6, [15, 16, 13] .+ 6] + @test nodes == [node1, node2, node3] + @test _pts == append!( + existing_points, + [ + (1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), - (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0)] - existing_points = [(1.0, 3.0), (3.5, 5.5), (13.7, 25.0), (19.0, 37.3), (100.0, 100.0), (10.3, 5.5)] - nodes, _pts = convert_boundary_points_to_indices(xy; existing_points) - node1 = [[1, 2, 3] .+ 6, [3, 4, 5, 6] .+ 6, [6, 7, 1] .+ 6] - node2 = [[8, 9, 10, 11, 12, 8] .+ 6] - node3 = [[13, 14, 15] .+ 6, [15, 16, 13] .+ 6] - @test nodes == [node1, node2, node3] - @test _pts == append!( - existing_points, - [(1.0, 2.0), (2.0, 2.5), (3.0, 3.5), (4.0, 4.5), (5.5, 7.7), - (6.7, 9.9), (2.0, 1.1), (1.0, 2.5), (1.2, 2.7), (1.3, 9.9), (1.4, 2.0), (1.5, 3.5), - (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0)] - ) + (9.5, 2.5), (13.7, 11.7), (3.3, 3.9), (5.5, 1.0), + ], + ) - boundary_points = [[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]] - nodes, _pts = convert_boundary_points_to_indices(boundary_points) - @test nodes == [1, 2, 3, 4, 1] - @test _pts == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] + boundary_points = [[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]] + nodes, _pts = convert_boundary_points_to_indices(boundary_points) + @test nodes == [1, 2, 3, 4, 1] + @test _pts == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - points = rand(Makie.Point2{Float64}, 10) - _pt = copy(points) - _boundary_points = decompose(Point2f, Rect2{Float64}(0, 0, 1, 1)) - boundary_points = push!(copy(_boundary_points), [0.0, 0.0]) - boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points=points) - @test boundary_nodes == [11, 12, 13, 14, 11] - @test pts == append!(_pt, _boundary_points) + points = rand(Makie.Point2{Float64}, 10) + _pt = copy(points) + _boundary_points = decompose(Point2f, Rect2{Float64}(0, 0, 1, 1)) + boundary_points = push!(copy(_boundary_points), [0.0, 0.0]) + boundary_nodes, pts = convert_boundary_points_to_indices(boundary_points; existing_points = points) + @test boundary_nodes == [11, 12, 13, 14, 11] + @test pts == append!(_pt, _boundary_points) end @testset "get_ordinal_suffix" begin - @test DT.get_ordinal_suffix.(0:115) == [ - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "st" - "nd" - "rd" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - "th" - ] + @test DT.get_ordinal_suffix.(0:115) == [ + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "st" + "nd" + "rd" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + "th" + ] end @testset "fix_segment!" begin - c = [(2, 15), (2, 28), (2, 41), (2, 54)] - bad_indices = [1, 2, 3, 4] - DT.fix_segments!(c, bad_indices) - @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] - c = [(2, 15), (15, 28), (28, 41), (2, 54)] - bad_indices = [1, 4] - DT.fix_segments!(c, bad_indices) - @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] - c = [(2, 15), (15, 28), (2, 41), (41, 54)] - bad_indices = [1, 3] - DT.fix_segments!(c, bad_indices) - @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] - c = [(2, 15), (15, 28), (2, 41), (41, 54)] - bad_indices = [3] - DT.fix_segments!(c, bad_indices) - @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] - c = [(2, 7), (2, 12), (12, 17), (2, 22), (2, 27), (2, 32), (32, 37), (2, 42), (42, 47)] - bad_indices = [2, 4, 5, 6, 8] - DT.fix_segments!(c, bad_indices) - @test c == [(2, 7), (7, 12), (12, 17), (17, 22), (22, 27), (27, 32), (32, 37), (37, 42), (42, 47)] + c = [(2, 15), (2, 28), (2, 41), (2, 54)] + bad_indices = [1, 2, 3, 4] + DT.fix_segments!(c, bad_indices) + @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] + c = [(2, 15), (15, 28), (28, 41), (2, 54)] + bad_indices = [1, 4] + DT.fix_segments!(c, bad_indices) + @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] + c = [(2, 15), (15, 28), (2, 41), (41, 54)] + bad_indices = [1, 3] + DT.fix_segments!(c, bad_indices) + @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] + c = [(2, 15), (15, 28), (2, 41), (41, 54)] + bad_indices = [3] + DT.fix_segments!(c, bad_indices) + @test c == [(2, 15), (15, 28), (28, 41), (41, 54)] + c = [(2, 7), (2, 12), (12, 17), (2, 22), (2, 27), (2, 32), (32, 37), (2, 42), (42, 47)] + bad_indices = [2, 4, 5, 6, 8] + DT.fix_segments!(c, bad_indices) + @test c == [(2, 7), (7, 12), (12, 17), (17, 22), (22, 27), (27, 32), (32, 37), (37, 42), (42, 47)] end @testset "next/previndex_circular" begin - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 1) == 2 - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 2) == 3 - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 3) == 4 - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 4) == 5 - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 5) == 6 - @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 6) == 1 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 1) == 2 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 2) == 3 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 3) == 4 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 4) == 5 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 5) == 6 + @test DT.nextindex_circular([1, 2, 3, 4, 5, 6], 6) == 1 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 1) == 5 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 2) == 1 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 3) == 2 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 4) == 3 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 5) == 4 - @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 6) == 5 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 1) == 5 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 2) == 1 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 3) == 2 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 4) == 3 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 5) == 4 + @test DT.previndex_circular([1, 2, 3, 4, 5, 6], 6) == 5 end @testset "first/last_ghost_vertex" begin - @test DT.is_first_ghost_vertex([1, 2, 3, -1, -5], 4) - @test !DT.is_first_ghost_vertex([1, 2, 3, -1, -5], 5) - @test DT.is_first_ghost_vertex([-1, -2, 5, 4], 1) - @test DT.is_last_ghost_vertex([-1, 5, 4, 6, -2, -1], 1) - @test DT.is_first_ghost_vertex([-1, 2, 3, 4, 5, -6, -1], 6) + @test DT.is_first_ghost_vertex([1, 2, 3, -1, -5], 4) + @test !DT.is_first_ghost_vertex([1, 2, 3, -1, -5], 5) + @test DT.is_first_ghost_vertex([-1, -2, 5, 4], 1) + @test DT.is_last_ghost_vertex([-1, 5, 4, 6, -2, -1], 1) + @test DT.is_first_ghost_vertex([-1, 2, 3, 4, 5, -6, -1], 6) end @testset "get_neighbouring_boundary_edges" begin - tri = fixed_shewchuk_example_constrained() - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (10, 11)) - @test left_e == (11, 7) && right_e == (3, 10) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (11, 7)) - @test left_e == (7, 6) && right_e == (10, 11) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (7, 6)) - @test left_e == (6, 5) && right_e == (11, 7) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (6, 5)) - @test left_e == (5, 4) && right_e == (7, 6) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (5, 4)) - @test left_e == (4, 1) && right_e == (6, 5) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (4, 1)) - @test left_e == (1, 2) && right_e == (5, 4) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (1, 2)) - @test left_e == (2, 3) && right_e == (4, 1) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (2, 3)) - @test left_e == (3, 10) && right_e == (1, 2) - @test DT.get_neighbouring_boundary_edges(tri, (10, 11)) == DT.get_neighbouring_boundary_edges(tri, (11, 10)) - @test DT.get_neighbouring_boundary_edges(tri, (11, 7)) == DT.get_neighbouring_boundary_edges(tri, (7, 11)) - @test DT.get_neighbouring_boundary_edges(tri, (7, 6)) == DT.get_neighbouring_boundary_edges(tri, (6, 7)) - @test DT.get_neighbouring_boundary_edges(tri, (6, 5)) == DT.get_neighbouring_boundary_edges(tri, (5, 6)) - @test DT.get_neighbouring_boundary_edges(tri, (5, 4)) == DT.get_neighbouring_boundary_edges(tri, (4, 5)) - @test DT.get_neighbouring_boundary_edges(tri, (4, 1)) == DT.get_neighbouring_boundary_edges(tri, (1, 4)) - @test DT.get_neighbouring_boundary_edges(tri, (1, 2)) == DT.get_neighbouring_boundary_edges(tri, (2, 1)) - @test DT.get_neighbouring_boundary_edges(tri, (2, 3)) == DT.get_neighbouring_boundary_edges(tri, (3, 2)) + tri = fixed_shewchuk_example_constrained() + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (10, 11)) + @test left_e == (11, 7) && right_e == (3, 10) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (11, 7)) + @test left_e == (7, 6) && right_e == (10, 11) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (7, 6)) + @test left_e == (6, 5) && right_e == (11, 7) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (6, 5)) + @test left_e == (5, 4) && right_e == (7, 6) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (5, 4)) + @test left_e == (4, 1) && right_e == (6, 5) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (4, 1)) + @test left_e == (1, 2) && right_e == (5, 4) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (1, 2)) + @test left_e == (2, 3) && right_e == (4, 1) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (2, 3)) + @test left_e == (3, 10) && right_e == (1, 2) + @test DT.get_neighbouring_boundary_edges(tri, (10, 11)) == DT.get_neighbouring_boundary_edges(tri, (11, 10)) + @test DT.get_neighbouring_boundary_edges(tri, (11, 7)) == DT.get_neighbouring_boundary_edges(tri, (7, 11)) + @test DT.get_neighbouring_boundary_edges(tri, (7, 6)) == DT.get_neighbouring_boundary_edges(tri, (6, 7)) + @test DT.get_neighbouring_boundary_edges(tri, (6, 5)) == DT.get_neighbouring_boundary_edges(tri, (5, 6)) + @test DT.get_neighbouring_boundary_edges(tri, (5, 4)) == DT.get_neighbouring_boundary_edges(tri, (4, 5)) + @test DT.get_neighbouring_boundary_edges(tri, (4, 1)) == DT.get_neighbouring_boundary_edges(tri, (1, 4)) + @test DT.get_neighbouring_boundary_edges(tri, (1, 2)) == DT.get_neighbouring_boundary_edges(tri, (2, 1)) + @test DT.get_neighbouring_boundary_edges(tri, (2, 3)) == DT.get_neighbouring_boundary_edges(tri, (3, 2)) - tri, _, _ = simple_geometry() - add_ghost_triangles!(tri) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (18, 13)) - @test left_e == (13, 14) && right_e == (17, 18) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (13, 14)) - @test left_e == (14, 15) && right_e == (18, 13) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (12, 9)) - @test left_e == (9, 10) && right_e == (11, 12) - left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (5, 4)) - @test left_e == (4, 3) && right_e == (6, 5) + tri, _, _ = simple_geometry() + add_ghost_triangles!(tri) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (18, 13)) + @test left_e == (13, 14) && right_e == (17, 18) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (13, 14)) + @test left_e == (14, 15) && right_e == (18, 13) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (12, 9)) + @test left_e == (9, 10) && right_e == (11, 12) + left_e, right_e = DT.get_neighbouring_boundary_edges(tri, (5, 4)) + @test left_e == (4, 3) && right_e == (6, 5) end @testset "convert_to_edge_adjoining_ghost_vertex" begin - a = (3.0, 3.0) - b = (0.0, 3.0) - c = (0.0, 0.0) - d = (4.0, 0.0) - e = (1.0, 1.5) - pts = [a, b, c, d, e] - tri = triangulate(pts, delete_ghosts=false, randomise=false) - @test DT.convert_to_edge_adjoining_ghost_vertex(tri, (1, 2)) == (2, 1) - @test DT.convert_to_edge_adjoining_ghost_vertex(tri, (2, 1)) == (2, 1) + a = (3.0, 3.0) + b = (0.0, 3.0) + c = (0.0, 0.0) + d = (4.0, 0.0) + e = (1.0, 1.5) + pts = [a, b, c, d, e] + tri = triangulate(pts, delete_ghosts = false, randomise = false) + @test DT.convert_to_edge_adjoining_ghost_vertex(tri, (1, 2)) == (2, 1) + @test DT.convert_to_edge_adjoining_ghost_vertex(tri, (2, 1)) == (2, 1) end @testset "get_shared_vertex" begin - e = (1, 3) - f = (7, 5) - @test DT.get_shared_vertex(e, f) == DT.∅ - @test DT.get_shared_vertex(f, e) == DT.∅ - e = (7, 3) - f = (3, 8) - @test DT.get_shared_vertex(e, f) == 3 - @test DT.get_shared_vertex(f, e) == 3 - f = (9, 7) - @test DT.get_shared_vertex(e, f) == 7 - @test DT.get_shared_vertex(f, e) == 7 + e = (1, 3) + f = (7, 5) + @test DT.get_shared_vertex(e, f) == DT.∅ + @test DT.get_shared_vertex(f, e) == DT.∅ + e = (7, 3) + f = (3, 8) + @test DT.get_shared_vertex(e, f) == 3 + @test DT.get_shared_vertex(f, e) == 3 + f = (9, 7) + @test DT.get_shared_vertex(e, f) == 7 + @test DT.get_shared_vertex(f, e) == 7 end @testset "replace_(boundary/ghost)_triangle_with_(ghost/boundary)_triangle" begin - for _ in 1:10 - tri = triangulate(rand(2, 5000), delete_ghosts=false) - _tri = triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 25, 25, delete_ghosts=false) - for tri in (tri, _tri) - for T in each_ghost_triangle(tri) - T = DT.sort_triangle(T) - i, j, k = triangle_vertices(T) - w = get_adjacent(tri, j, i) - V = (j, i, w) - kr = count(e -> DT.is_boundary_edge(tri, e...), DT.triangle_edges(V)) - kr == 2 && continue # two associated ghosts, test is not clear - @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T - @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == V - V = (i, w, j) - @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T - @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == (j, i, w) - V = (w, j, i) - @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T - @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == (j, i, w) - end + for _ in 1:10 + tri = triangulate(rand(2, 5000), delete_ghosts = false) + _tri = triangulate_rectangle(0.0, 1.0, 0.0, 1.0, 25, 25, delete_ghosts = false) + for tri in (tri, _tri) + for T in each_ghost_triangle(tri) + T = DT.sort_triangle(T) + i, j, k = triangle_vertices(T) + w = get_adjacent(tri, j, i) + V = (j, i, w) + kr = count(e -> DT.is_boundary_edge(tri, e...), DT.triangle_edges(V)) + kr == 2 && continue # two associated ghosts, test is not clear + @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T + @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == V + V = (i, w, j) + @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T + @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == (j, i, w) + V = (w, j, i) + @test DT.replace_boundary_triangle_with_ghost_triangle(tri, V) == T + @test DT.replace_ghost_triangle_with_boundary_triangle(tri, T) == (j, i, w) end - end + end + end end @testset "iterated_neighbourhood" begin - points = NTuple{2,Float64}[] - for i in 1:5 - t = [0.0, π / 2, π, 3π / 2] - push!(points, [(i^2 * cos(t), i^2 * sin(t)) for t in t]...) - end - push!(points, (0.0, 0.0)) - n = DT.num_points(points) - tri = triangulate(points, delete_ghosts=false) + points = NTuple{2, Float64}[] + for i in 1:5 + t = [0.0, π / 2, π, 3π / 2] + push!(points, [(i^2 * cos(t), i^2 * sin(t)) for t in t]...) + end + push!(points, (0.0, 0.0)) + n = DT.num_points(points) + tri = triangulate(points, delete_ghosts = false) - neighbours = DT.iterated_neighbourhood(tri, n, 1) - @test neighbours == filter(!DT.is_ghost_vertex, get_neighbours(tri, n)) - neighbours = DT.iterated_neighbourhood(tri, n, 2) - S1 = get_neighbours(tri, n) - S2 = [get_neighbours(tri, i) for i in S1] - [union!(S1, S) for S in S2] - filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) - @test S1 == neighbours - neighbours = DT.iterated_neighbourhood(tri, n, 3) - S1 = get_neighbours(tri, n) - S2 = [get_neighbours(tri, i) for i in S1] - S3 = [get_neighbours(tri, i) for i in reduce(union, S2)] - [union!(S1, S) for S in S2] - [union!(S1, S) for S in S3] - filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) - @test S1 == neighbours - neighbours = DT.iterated_neighbourhood(tri, n, 4) - S1 = get_neighbours(tri, n) - S2 = [get_neighbours(tri, i) for i in S1] - S3 = [get_neighbours(tri, i) for i in reduce(union, S2)] - S4 = [get_neighbours(tri, i) for i in reduce(union, S3)] - [union!(S1, S) for S in S2] - [union!(S1, S) for S in S3] - [union!(S1, S) for S in S4] - filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) - @test S1 == neighbours + neighbours = DT.iterated_neighbourhood(tri, n, 1) + @test neighbours == filter(!DT.is_ghost_vertex, get_neighbours(tri, n)) + neighbours = DT.iterated_neighbourhood(tri, n, 2) + S1 = get_neighbours(tri, n) + S2 = [get_neighbours(tri, i) for i in S1] + [union!(S1, S) for S in S2] + filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) + @test S1 == neighbours + neighbours = DT.iterated_neighbourhood(tri, n, 3) + S1 = get_neighbours(tri, n) + S2 = [get_neighbours(tri, i) for i in S1] + S3 = [get_neighbours(tri, i) for i in reduce(union, S2)] + [union!(S1, S) for S in S2] + [union!(S1, S) for S in S3] + filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) + @test S1 == neighbours + neighbours = DT.iterated_neighbourhood(tri, n, 4) + S1 = get_neighbours(tri, n) + S2 = [get_neighbours(tri, i) for i in S1] + S3 = [get_neighbours(tri, i) for i in reduce(union, S2)] + S4 = [get_neighbours(tri, i) for i in reduce(union, S3)] + [union!(S1, S) for S in S2] + [union!(S1, S) for S in S3] + [union!(S1, S) for S in S4] + filter!(s -> !(s == n || DT.is_ghost_vertex(s)), S1) + @test S1 == neighbours - tri = triangulate_rectangle(0, 1, 0, 1, 10, 10) - neighbours = DT.iterated_neighbourhood(tri, 1, 3) - @test neighbours == Set(( + tri = triangulate_rectangle(0, 1, 0, 1, 10, 10) + neighbours = DT.iterated_neighbourhood(tri, 1, 3) + @test neighbours == Set( + ( 2, 11, 21, 12, 3, - 31, 22, 13, 4 - )) - neighbours = DT.iterated_neighbourhood!(neighbours, tri, 1, 2) - @test neighbours == Set(( + 31, 22, 13, 4, + ), + ) + neighbours = DT.iterated_neighbourhood!(neighbours, tri, 1, 2) + @test neighbours == Set( + ( 2, 11, - 21, 12, 3 - )) - neighbours = DT.iterated_neighbourhood!(neighbours, tri, 1, 6) - @test neighbours == Set(( + 21, 12, 3, + ), + ) + neighbours = DT.iterated_neighbourhood!(neighbours, tri, 1, 6) + @test neighbours == Set( + ( 2, 11, 21, 12, 3, 31, 22, 13, 4, 41, 32, 23, 14, 5, 51, 42, 33, 24, 15, 6, - 61, 52, 43, 34, 25, 16, 7 - )) - add_ghost_triangles!(tri) - neighbours = DT.iterated_neighbourhood(tri, 1, 3) - @test neighbours == Set(( + 61, 52, 43, 34, 25, 16, 7, + ), + ) + add_ghost_triangles!(tri) + neighbours = DT.iterated_neighbourhood(tri, 1, 3) + @test neighbours == Set( + ( 2, 11, 21, 12, 3, - 31, 22, 13, 4 - )) - neighbours = DT.iterated_neighbourhood(tri, 1, 2) - @test neighbours == Set(( + 31, 22, 13, 4, + ), + ) + neighbours = DT.iterated_neighbourhood(tri, 1, 2) + @test neighbours == Set( + ( 2, 11, - 21, 12, 3 - )) - neighbours = DT.iterated_neighbourhood(tri, 1, 6) - @test neighbours == Set(( + 21, 12, 3, + ), + ) + neighbours = DT.iterated_neighbourhood(tri, 1, 6) + @test neighbours == Set( + ( 2, 11, 21, 12, 3, 31, 22, 13, 4, 41, 32, 23, 14, 5, 51, 42, 33, 24, 15, 6, - 61, 52, 43, 34, 25, 16, 7 - )) + 61, 52, 43, 34, 25, 16, 7, + ), + ) end @testset "getxy" begin - @test DT.getxy((0.3, 0.5)) == (0.3, 0.5) - @test DT.getxy((0.3f0, 0.7f0)) == (Float64(0.3f0), Float64(0.7f0)) + @test DT.getxy((0.3, 0.5)) == (0.3, 0.5) + @test DT.getxy((0.3f0, 0.7f0)) == (Float64(0.3f0), Float64(0.7f0)) end @testset "norm" begin - # test that we avoid underflow - @test DT.norm((1e-300, 1e-300)) ≈ norm([1e-300, 1e-300]) ≈ 1.414213562373095e-300 - @test DT.norm((1e-300, 0.0)) ≈ norm([1e-300, 0.0]) ≈ 1e-300 - @test DT.norm((0.0, 1e-300)) ≈ norm([0.0, 1e-300]) ≈ 1e-300 + # test that we avoid underflow + @test DT.norm((1.0e-300, 1.0e-300)) ≈ norm([1.0e-300, 1.0e-300]) ≈ 1.414213562373095e-300 + @test DT.norm((1.0e-300, 0.0)) ≈ norm([1.0e-300, 0.0]) ≈ 1.0e-300 + @test DT.norm((0.0, 1.0e-300)) ≈ norm([0.0, 1.0e-300]) ≈ 1.0e-300 - # that we avoid overflow - @test DT.norm((1e300, 1e300)) ≈ norm([1e300, 1e300]) ≈ 1.414213562373095e300 - @test DT.norm((1e300, 0.0)) ≈ norm([1e300, 0.0]) ≈ 1e300 - @test DT.norm((0.0, 1e300)) ≈ norm([0.0, 1e300]) ≈ 1e300 + # that we avoid overflow + @test DT.norm((1.0e300, 1.0e300)) ≈ norm([1.0e300, 1.0e300]) ≈ 1.414213562373095e300 + @test DT.norm((1.0e300, 0.0)) ≈ norm([1.0e300, 0.0]) ≈ 1.0e300 + @test DT.norm((0.0, 1.0e300)) ≈ norm([0.0, 1.0e300]) ≈ 1.0e300 - # some other random tests - for _ in 1:10000 - x, y = rand(2) - @test DT.norm((x, y)) ≈ norm((x, y)) ≈ DT.norm((y, x)) - @test DT.norm((x, y))^2 ≈ DT.norm_sqr((x, y)) - end - @inferred DT.norm((1.0, 1.0)) - @inferred DT.norm((1.0f0, 1.0f0)) + # some other random tests + for _ in 1:10000 + x, y = rand(2) + @test DT.norm((x, y)) ≈ norm((x, y)) ≈ DT.norm((y, x)) + @test DT.norm((x, y))^2 ≈ DT.norm_sqr((x, y)) + end + @inferred DT.norm((1.0, 1.0)) + @inferred DT.norm((1.0f0, 1.0f0)) - # specific case - @test DT.dist_sqr((3.0, -1.0), (2.0, 0.0)) == 2.0 + # specific case + @test DT.dist_sqr((3.0, -1.0), (2.0, 0.0)) == 2.0 end @testset "edge_length" begin - tri = triangulate(rand(2, 50)) - for e in each_solid_edge(tri) - @test DT.edge_length(tri, e) ≈ - DT.edge_length(tri, DT.reverse_edge(e)) ≈ - DT.edge_length(tri, e...) ≈ - norm(get_point(tri, e[1]) .- get_point(tri, e[2])) - @test DT.edge_length_sqr(tri, e) ≈ - DT.edge_length_sqr(tri, DT.reverse_edge(e)) ≈ - DT.edge_length_sqr(tri, e...) ≈ - LinearAlgebra.norm_sqr(get_point(tri, e[1]) .- get_point(tri, e[2])) - end + tri = triangulate(rand(2, 50)) + for e in each_solid_edge(tri) + @test DT.edge_length(tri, e) ≈ + DT.edge_length(tri, DT.reverse_edge(e)) ≈ + DT.edge_length(tri, e...) ≈ + norm(get_point(tri, e[1]) .- get_point(tri, e[2])) + @test DT.edge_length_sqr(tri, e) ≈ + DT.edge_length_sqr(tri, DT.reverse_edge(e)) ≈ + DT.edge_length_sqr(tri, e...) ≈ + LinearAlgebra.norm_sqr(get_point(tri, e[1]) .- get_point(tri, e[2])) + end end @testset "midpoint" begin - tri = triangulate(rand(2, 50)) - for e in each_solid_edge(tri) - @test collect(DT.midpoint(tri, e)) ≈ - collect(DT.midpoint(tri, DT.reverse_edge(e))) ≈ - collect(DT.midpoint(tri, e...)) ≈ - 0.5 .* collect((get_point(tri, e[1]) .+ get_point(tri, e[2]))) - end + tri = triangulate(rand(2, 50)) + for e in each_solid_edge(tri) + @test collect(DT.midpoint(tri, e)) ≈ + collect(DT.midpoint(tri, DT.reverse_edge(e))) ≈ + collect(DT.midpoint(tri, e...)) ≈ + 0.5 .* collect((get_point(tri, e[1]) .+ get_point(tri, e[2]))) + end end @testset "check_precision" begin - @test DT.check_precision(sqrt(eps(Float64)) - 1e-32) - @test !DT.check_precision(1.0) - @test DT.check_precision(sqrt(eps(Float64))) + @test DT.check_precision(sqrt(eps(Float64)) - 1.0e-32) + @test !DT.check_precision(1.0) + @test DT.check_precision(sqrt(eps(Float64))) - @test DT.check_absolute_precision(1e-32, 0.0) - @test DT.check_absolute_precision(sqrt(eps(Float64)), 0) - @test !DT.check_absolute_precision(0.5, 2.0) + @test DT.check_absolute_precision(1.0e-32, 0.0) + @test DT.check_absolute_precision(sqrt(eps(Float64)), 0) + @test !DT.check_absolute_precision(0.5, 2.0) - @test !DT.check_relative_precision(1e-32, 0.0) - @test !DT.check_relative_precision(sqrt(eps(Float64)), 0) - @test !DT.check_relative_precision(0, 1e-32) - @test !DT.check_relative_precision(0, sqrt(eps(Float64))) + @test !DT.check_relative_precision(1.0e-32, 0.0) + @test !DT.check_relative_precision(sqrt(eps(Float64)), 0) + @test !DT.check_relative_precision(0, 1.0e-32) + @test !DT.check_relative_precision(0, sqrt(eps(Float64))) - @test DT.check_ratio_precision(1.0, 1.0) - @test !DT.check_ratio_precision(5, 2) - @test !DT.check_ratio_precision(0.0, 1.0) - @test !DT.check_ratio_precision(1.0, 0.0) + @test DT.check_ratio_precision(1.0, 1.0) + @test !DT.check_ratio_precision(5, 2) + @test !DT.check_ratio_precision(0.0, 1.0) + @test !DT.check_ratio_precision(1.0, 0.0) end @testset "get_boundary_chain" begin - rng = StableRNG(123) - points = randn(rng, 2, 250) - tri = triangulate(points; rng) - hull = get_convex_hull_vertices(tri) - chain = DT.get_boundary_chain(tri, 65, 147, -1) - @test DT.circular_equality([chain..., chain[1]], hull) - chain = DT.get_boundary_chain(tri, 199, 96, -1) - @test chain == [199, 151, 96] - chain = DT.get_boundary_chain(tri, 151, 96, -1) - @test chain == [151, 96] + rng = StableRNG(123) + points = randn(rng, 2, 250) + tri = triangulate(points; rng) + hull = get_convex_hull_vertices(tri) + chain = DT.get_boundary_chain(tri, 65, 147, -1) + @test DT.circular_equality([chain..., chain[1]], hull) + chain = DT.get_boundary_chain(tri, 199, 96, -1) + @test chain == [199, 151, 96] + chain = DT.get_boundary_chain(tri, 151, 96, -1) + @test chain == [151, 96] end @testset "dist" begin - for i in 1:10 - tri = triangulate(rand(StableRNG(i), 2, 500); rng=StableRNG(i + 1)) - for j in 1:10 - p = randn(StableRNG(i * j), 2) - δ = DT.distance_to_polygon(p, get_points(tri), get_convex_hull_vertices(tri)) - V = find_triangle(tri, p) - if DT.is_ghost_triangle(V) - @test δ < 0 - else - @test δ ≥ 0.0 - end - @test δ ≈ DT.dist(tri, p) - end - end - points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), (0.2, 0.2), (0.8, 0.2), (0.8, 0.8), (0.2, 0.8)] - tri = triangulate(points; boundary_nodes=[[[1, 2, 3, 4, 5, 1]], [[6, 9, 8, 7, 6]]]) - for i in 1:100 - p = randn(StableRNG(i^2), 2) - δ = DT.distance_to_polygon(p, get_points(tri), get_boundary_nodes(tri)) - V = find_triangle(tri, p; rng=StableRNG(i^3), concavity_protection=true) + for i in 1:10 + tri = triangulate(rand(StableRNG(i), 2, 500); rng = StableRNG(i + 1)) + for j in 1:10 + p = randn(StableRNG(i * j), 2) + δ = DT.distance_to_polygon(p, get_points(tri), get_convex_hull_vertices(tri)) + V = find_triangle(tri, p) if DT.is_ghost_triangle(V) - @test δ < 0 + @test δ < 0 else - @test δ ≥ 0.0 + @test δ ≥ 0.0 end @test δ ≈ DT.dist(tri, p) - end + end + end + points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.5, 0.9), (0.0, 1.0), (0.2, 0.2), (0.8, 0.2), (0.8, 0.8), (0.2, 0.8)] + tri = triangulate(points; boundary_nodes = [[[1, 2, 3, 4, 5, 1]], [[6, 9, 8, 7, 6]]]) + for i in 1:100 + p = randn(StableRNG(i^2), 2) + δ = DT.distance_to_polygon(p, get_points(tri), get_boundary_nodes(tri)) + V = find_triangle(tri, p; rng = StableRNG(i^3), concavity_protection = true) + if DT.is_ghost_triangle(V) + @test δ < 0 + else + @test δ ≥ 0.0 + end + @test δ ≈ DT.dist(tri, p) + end end @testset "adjust_θ" begin - θ₁ = deg2rad(77.4711922908485) - θ₂ = deg2rad(175.2363583092738) - θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, true) - @test (θ₁, θ₂) == (θ₁′, θ₂′) - θ₁′, θ₂′ = DT.adjust_θ(θ₂, θ₁, true) - @test (θ₁′, θ₂′) ⪧ (θ₂, θ₁ + 2π) && θ₂′ - θ₁′ ≈ deg2rad(262.2348339815747) - θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, false) - @test (θ₁′, θ₂′) ⪧ (θ₁, θ₂ - 2π) && θ₂′ - θ₁′ ≈ -deg2rad(360 - 97.7651660184254) - θ₁′, θ₂′ = DT.adjust_θ(θ₂, θ₁, false) - @test (θ₁′, θ₂′) ⪧ (θ₂, θ₁) && θ₂′ - θ₁′ ≈ -deg2rad(97.7651660184254) - for _ in 1:100000 - θ₁, θ₂ = 2π .* rand(2) - θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, rand() < 1 / 2) - @test abs(θ₂′ - θ₁′) ≤ 2π - end + θ₁ = deg2rad(77.4711922908485) + θ₂ = deg2rad(175.2363583092738) + θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, true) + @test (θ₁, θ₂) == (θ₁′, θ₂′) + θ₁′, θ₂′ = DT.adjust_θ(θ₂, θ₁, true) + @test (θ₁′, θ₂′) ⪧ (θ₂, θ₁ + 2π) && θ₂′ - θ₁′ ≈ deg2rad(262.2348339815747) + θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, false) + @test (θ₁′, θ₂′) ⪧ (θ₁, θ₂ - 2π) && θ₂′ - θ₁′ ≈ -deg2rad(360 - 97.7651660184254) + θ₁′, θ₂′ = DT.adjust_θ(θ₂, θ₁, false) + @test (θ₁′, θ₂′) ⪧ (θ₂, θ₁) && θ₂′ - θ₁′ ≈ -deg2rad(97.7651660184254) + for _ in 1:100000 + θ₁, θ₂ = 2π .* rand(2) + θ₁′, θ₂′ = DT.adjust_θ(θ₁, θ₂, rand() < 1 / 2) + @test abs(θ₂′ - θ₁′) ≤ 2π + end end @testset "uniquetol" begin - A = [0.0, 0.1, 0.2, 0.3, 0.4, 0.4 + 1e-16] - B = DT.uniquetol(A) - @test B == [0.0, 0.1, 0.2, 0.3, 0.4] - A = [-5, -4, -3, -3 - 1e-16, 0, 5 - 1e-16, 5 - 1e-14, 5 + 1e-16, 5 + 1e-14, 10, 15 + 1e-16] - sort!(A) - B = DT.uniquetol(A) - @test B == [-5, -4, -3, 0, 5 - 1e-14, 10.0, 15.0] + A = [0.0, 0.1, 0.2, 0.3, 0.4, 0.4 + 1.0e-16] + B = DT.uniquetol(A) + @test B == [0.0, 0.1, 0.2, 0.3, 0.4] + A = [-5, -4, -3, -3 - 1.0e-16, 0, 5 - 1.0e-16, 5 - 1.0e-14, 5 + 1.0e-16, 5 + 1.0e-14, 10, 15 + 1.0e-16] + sort!(A) + B = DT.uniquetol(A) + @test B == [-5, -4, -3, 0, 5 - 1.0e-14, 10.0, 15.0] end @testset "Evaluating functions over heterogeneous tuples" begin - @testset "eval_fnc_at_het_tuple_element" begin + @testset "eval_fnc_at_het_tuple_element" begin + global basic_def + f = x -> x isa Number + tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') + basic_def(f, tup, idx) = f(tup[idx]) + DT.eval_fnc_at_het_tuple_element(f, tup, 1) + DT.eval_fnc_at_het_tuple_element(f, tup, 4) + DT.eval_fnc_at_het_tuple_element(f, tup, 7) + basic_def(f, tup, 1) + basic_def(f, tup, 4) + basic_def(f, tup, 7) + a1 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 1) + a2 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 2) + a3 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 3) + a4 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 4) + a5 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 5) + a6 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 6) + a7 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 7) + b1 = @allocated basic_def(f, tup, 1) + b2 = @allocated basic_def(f, tup, 2) + b3 = @allocated basic_def(f, tup, 3) + b4 = @allocated basic_def(f, tup, 4) + b5 = @allocated basic_def(f, tup, 5) + b6 = @allocated basic_def(f, tup, 6) + b7 = @allocated basic_def(f, tup, 7) + a = (a1, a2, a3, a4, a5, a6, a7) + b = (b1, b2, b3, b4, b5, b6, b7) + @test all(iszero, a) || all(iszero, a .- 16) + for i in 1:7 global basic_def - f = x -> x isa Number - tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') - basic_def(f, tup, idx) = f(tup[idx]) - DT.eval_fnc_at_het_tuple_element(f, tup, 1) - DT.eval_fnc_at_het_tuple_element(f, tup, 4) - DT.eval_fnc_at_het_tuple_element(f, tup, 7) - basic_def(f, tup, 1) - basic_def(f, tup, 4) - basic_def(f, tup, 7) - a1 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 1) - a2 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 2) - a3 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 3) - a4 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 4) - a5 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 5) - a6 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 6) - a7 = @allocated DT.eval_fnc_at_het_tuple_element(f, tup, 7) - b1 = @allocated basic_def(f, tup, 1) - b2 = @allocated basic_def(f, tup, 2) - b3 = @allocated basic_def(f, tup, 3) - b4 = @allocated basic_def(f, tup, 4) - b5 = @allocated basic_def(f, tup, 5) - b6 = @allocated basic_def(f, tup, 6) - b7 = @allocated basic_def(f, tup, 7) - a = (a1,a2,a3,a4,a5,a6,a7) - b = (b1,b2,b3,b4,b5,b6,b7) - @test all(iszero, a) || all(iszero, a.- 16) - for i in 1:7 - global basic_def - @test DT.eval_fnc_at_het_tuple_element(f, tup, i) == basic_def(f, tup, i) - @inferred DT.eval_fnc_at_het_tuple_element(f, tup, i) - end - end + @test DT.eval_fnc_at_het_tuple_element(f, tup, i) == basic_def(f, tup, i) + @inferred DT.eval_fnc_at_het_tuple_element(f, tup, i) + end + end - @testset "eval_fnc_in_het_tuple" begin + @testset "eval_fnc_in_het_tuple" begin + global basic_def2 + gg1(x) = x + gg2(x) = x^2 + gg3(x) = x^3 + gg4(x) = x^4 + gg5(x) = x^5 + gg6(x) = x^6 + gg7(x) = x^7 + tup = (gg1, gg2, gg3, gg4, gg5, gg6, gg7) + arg = rand() + basic_def2(tup, arg, idx) = tup[idx](arg) + DT.eval_fnc_in_het_tuple(tup, arg, 1) + DT.eval_fnc_in_het_tuple(tup, arg, 4) + DT.eval_fnc_in_het_tuple(tup, arg, 7) + basic_def2(tup, arg, 1) + basic_def2(tup, arg, 4) + basic_def2(tup, arg, 7) + a1 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 1) + a2 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 2) + a3 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 3) + a4 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 4) + a5 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 5) + a6 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 6) + a7 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 7) + b1 = @allocated basic_def2(tup, arg, 1) + b2 = @allocated basic_def2(tup, arg, 2) + b3 = @allocated basic_def2(tup, arg, 3) + b4 = @allocated basic_def2(tup, arg, 4) + b5 = @allocated basic_def2(tup, arg, 5) + b6 = @allocated basic_def2(tup, arg, 6) + b7 = @allocated basic_def2(tup, arg, 7) + a = (a1, a2, a3, a4, a5, a6, a7) + @test all(iszero, a) || all(iszero, a .- 16) + for i in 1:7 global basic_def2 - gg1(x) = x - gg2(x) = x^2 - gg3(x) = x^3 - gg4(x) = x^4 - gg5(x) = x^5 - gg6(x) = x^6 - gg7(x) = x^7 - tup = (gg1, gg2, gg3, gg4, gg5, gg6, gg7) - arg = rand() - basic_def2(tup, arg, idx) = tup[idx](arg) - DT.eval_fnc_in_het_tuple(tup, arg, 1) - DT.eval_fnc_in_het_tuple(tup, arg, 4) - DT.eval_fnc_in_het_tuple(tup, arg, 7) - basic_def2(tup, arg, 1) - basic_def2(tup, arg, 4) - basic_def2(tup, arg, 7) - a1 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 1) - a2 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 2) - a3 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 3) - a4 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 4) - a5 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 5) - a6 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 6) - a7 = @allocated DT.eval_fnc_in_het_tuple(tup, arg, 7) - b1 = @allocated basic_def2(tup, arg, 1) - b2 = @allocated basic_def2(tup, arg, 2) - b3 = @allocated basic_def2(tup, arg, 3) - b4 = @allocated basic_def2(tup, arg, 4) - b5 = @allocated basic_def2(tup, arg, 5) - b6 = @allocated basic_def2(tup, arg, 6) - b7 = @allocated basic_def2(tup, arg, 7) - a = (a1,a2,a3,a4,a5,a6,a7) - @test all(iszero, a) || all(iszero, a .- 16) - for i in 1:7 - global basic_def2 - @test DT.eval_fnc_in_het_tuple(tup, arg, i) == basic_def2(tup, arg, i) - @inferred DT.eval_fnc_in_het_tuple(tup, arg, i) - end - end + @test DT.eval_fnc_in_het_tuple(tup, arg, i) == basic_def2(tup, arg, i) + @inferred DT.eval_fnc_in_het_tuple(tup, arg, i) + end + end - @testset "eval_fnc_at_het_tuple_two_elements" begin - global fft - global basic_defft - fft(x, y) = objectid(x) + objectid(y) - tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') - basic_defft(f, tup, idx, idx2) = f(tup[idx], tup[idx2]) - DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 1, 4) - DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 4, 3) - DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 2, 5) - basic_defft(fft, tup, 1, 4) - basic_defft(fft, tup, 4, 3) - basic_defft(fft, tup, 2, 5) - a = zeros(length(tup), length(tup)) - b = similar(a) - for i in eachindex(tup) - for j in eachindex(tup) - global fft - global basic_defft - a[i, j] = @allocated DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) - b[i, j] = @allocated basic_defft(fft, tup, i, j) - @test DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) == basic_defft(fft, tup, i, j) - @inferred DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) - end + @testset "eval_fnc_at_het_tuple_two_elements" begin + global fft + global basic_defft + fft(x, y) = objectid(x) + objectid(y) + tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') + basic_defft(f, tup, idx, idx2) = f(tup[idx], tup[idx2]) + DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 1, 4) + DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 4, 3) + DT.eval_fnc_at_het_tuple_two_elements(fft, tup, 2, 5) + basic_defft(fft, tup, 1, 4) + basic_defft(fft, tup, 4, 3) + basic_defft(fft, tup, 2, 5) + a = zeros(length(tup), length(tup)) + b = similar(a) + for i in eachindex(tup) + for j in eachindex(tup) + global fft + global basic_defft + a[i, j] = @allocated DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) + b[i, j] = @allocated basic_defft(fft, tup, i, j) + @test DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) == basic_defft(fft, tup, i, j) + @inferred DT.eval_fnc_at_het_tuple_two_elements(fft, tup, i, j) end - @test all(iszero, a .- 16) || all(iszero, a) - end + end + @test all(iszero, a .- 16) || all(iszero, a) + end - @testset "eval_fnc_at_het_tuple_element_with_arg" begin + @testset "eval_fnc_at_het_tuple_element_with_arg" begin + global fft + global basic_defft + fft(x, y, z, w) = objectid(x) + objectid(y) + objectid(z) + objectid(w) + tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') + basic_defft(f, tup, arg, idx) = f(tup[idx], arg...) + DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 1) + DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 2) + DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 3) + DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 4) + basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 1) + basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 2) + basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 3) + basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 4) + a = zeros(length(tup)) + b = similar(a) + arg = ((2.0, 3.0), -1.0, "5") + for i in eachindex(tup) global fft global basic_defft - fft(x, y, z, w) = objectid(x) + objectid(y) + objectid(z) + objectid(w) - tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') - basic_defft(f, tup, arg, idx) = f(tup[idx], arg...) - DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 1) - DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 2) - DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 3) - DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, ((2.0, 3.0), -1.0, "5"), 4) - basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 1) - basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 2) - basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 3) - basic_defft(fft, tup, ((2.0, 3.0), -1.0, "5"), 4) - a = zeros(length(tup)) - b = similar(a) - arg = ((2.0, 3.0), -1.0, "5") - for i in eachindex(tup) - global fft - global basic_defft - a[i] = @allocated DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) - b[i] = @allocated basic_defft(fft, tup, arg, i) - @test DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) == basic_defft(fft, tup, arg, i) - @inferred DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) - end - @test all(iszero, a .- 16) || all(iszero, a) - end + a[i] = @allocated DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) + b[i] = @allocated basic_defft(fft, tup, arg, i) + @test DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) == basic_defft(fft, tup, arg, i) + @inferred DT.eval_fnc_at_het_tuple_element_with_arg(fft, tup, arg, i) + end + @test all(iszero, a .- 16) || all(iszero, a) + end - @testset "eval_fnc_at_het_tuple_element_with_arg_and_prearg" begin + @testset "eval_fnc_at_het_tuple_element_with_arg_and_prearg" begin + global fft + global basic_defft + fft(x, y, z, w) = objectid(x) + objectid(y) + objectid(z) + objectid(w) + tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') + basic_defft(f, tup, prearg, arg, idx) = f(prearg, tup[idx], arg...) + DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 1) + DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 2) + DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 3) + DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 4) + basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 1) + basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 2) + basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 3) + basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 4) + a = zeros(length(tup)) + b = similar(a) + arg = ((2.0, 3.0), "5") + prearg = -3.0 + for i in eachindex(tup) global fft global basic_defft - fft(x, y, z, w) = objectid(x) + objectid(y) + objectid(z) + objectid(w) - tup = (1, 2.0, "string", [1 2 3], [5, 7, 9], 0x00, 'A') - basic_defft(f, tup, prearg, arg, idx) = f(prearg, tup[idx], arg...) - DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 1) - DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 2) - DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 3) - DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, -3.0, ((2.0, 3.0), "5"), 4) - basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 1) - basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 2) - basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 3) - basic_defft(fft, tup, -3.0, ((2.0, 3.0), "5"), 4) - a = zeros(length(tup)) - b = similar(a) - arg = ((2.0, 3.0), "5") - prearg = -3.0 - for i in eachindex(tup) - global fft - global basic_defft - a[i] = @allocated DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) - b[i] = @allocated basic_defft(fft, tup, prearg, arg, i) - @test DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) == basic_defft(fft, tup, prearg, arg, i) - @inferred DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) - end - @test all(iszero, a .- 16) || all(iszero, a) - end + a[i] = @allocated DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) + b[i] = @allocated basic_defft(fft, tup, prearg, arg, i) + @test DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) == basic_defft(fft, tup, prearg, arg, i) + @inferred DT.eval_fnc_at_het_tuple_element_with_arg_and_prearg(fft, tup, prearg, arg, i) + end + @test all(iszero, a .- 16) || all(iszero, a) + end end @testset "_to_val" begin - @test DT._to_val(2) == Val(2) - @test DT._to_val(Val(2)) == Val(2) + @test DT._to_val(2) == Val(2) + @test DT._to_val(Val(2)) == Val(2) end @testset "ε" begin - @test DT.ε(Float64) == DT.ε(1.0) == sqrt(eps(Float64)) - @test DT.ε(Float32) == DT.ε(1.0f0) == sqrt(eps(Float32)) -end \ No newline at end of file + @test DT.ε(Float64) == DT.ε(1.0) == sqrt(eps(Float64)) + @test DT.ε(Float32) == DT.ε(1.0f0) == sqrt(eps(Float32)) +end diff --git a/test/voronoi/voronoi.jl b/test/voronoi/voronoi.jl index b35f5ad82..0dd7e0b46 100644 --- a/test/voronoi/voronoi.jl +++ b/test/voronoi/voronoi.jl @@ -23,13 +23,13 @@ using GeometryBasics F = (1.0, 4.0) G = (-3.0, 5.0) pts = [A, B, C, D, E, F, G] - tri = triangulate(pts; delete_ghosts=false, randomise=false) + tri = triangulate(pts; delete_ghosts = false, randomise = false) - vorn = voronoi(tri; predicates=PT()) + vorn = voronoi(tri; predicates = PT()) for (i, p) in DT.get_generators(vorn) @test get_point(tri, i) == get_generator(vorn, i) == p end - @test validate_tessellation(vorn; predicates=PT()) + @test validate_tessellation(vorn; predicates = PT()) @test DT.get_triangulation(vorn) == tri circumcenter_to_triangle = DT.get_circumcenter_to_triangle(vorn) triangle_to_circumcenter = DT.get_triangle_to_circumcenter(vorn) @@ -53,45 +53,59 @@ using GeometryBasics @test isempty(DT.get_boundary_polygons(vorn)) @test DT.circular_equality( get_polygon(vorn, 1), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (7, 4, 1), (4, 6, 1), (6, 2, 1), (1, 2, -1), (7, 1, -1), (7, 4, 1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (7, 4, 1), (4, 6, 1), (6, 2, 1), (1, 2, -1), (7, 1, -1), (7, 4, 1), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 2), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (2, 5, -1), (1, 2, -1), (6, 2, 1), (6, 5, 2), (2, 5, -1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (2, 5, -1), (1, 2, -1), (6, 2, 1), (6, 5, 2), (2, 5, -1), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 3), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (5, 3, -1), (5, 4, 3), (4, 7, 3), (3, 7, -1), (5, 3, -1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (5, 3, -1), (5, 4, 3), (4, 7, 3), (3, 7, -1), (5, 3, -1), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 4), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (5, 6, 4), (4, 6, 1), (7, 4, 1), (4, 7, 3), (5, 4, 3), (5, 6, 4) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (5, 6, 4), (4, 6, 1), (7, 4, 1), (4, 7, 3), (5, 4, 3), (5, 6, 4), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 5), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (6, 5, 2), (5, 6, 4), (5, 4, 3), (5, 3, -1), (2, 5, -1), (6, 5, 2) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (6, 5, 2), (5, 6, 4), (5, 4, 3), (5, 3, -1), (2, 5, -1), (6, 5, 2), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 6), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (6, 5, 2), (6, 2, 1), (4, 6, 1), (5, 6, 4), (6, 5, 2) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (6, 5, 2), (6, 2, 1), (4, 6, 1), (5, 6, 4), (6, 5, 2), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 7), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (7, 4, 1), (7, 1, -1), (3, 7, -1), (4, 7, 3), (7, 4, 1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (7, 4, 1), (7, 1, -1), (3, 7, -1), (4, 7, 3), (7, 4, 1), + ], + ), ) end end @@ -102,73 +116,101 @@ end for _ in 1:10 tri = example_triangulation() tri = triangulate(get_points(tri)) - vorn = voronoi(tri; predicates=PT()) - @test validate_tessellation(vorn; predicates=PT()) + vorn = voronoi(tri; predicates = PT()) + @test validate_tessellation(vorn; predicates = PT()) bbox = DT.polygon_bounds(vorn, 0.1) xmin, xmax, ymin, ymax = bbox - c1 = DT.get_polygon_coordinates(vorn, 1, bbox, predicates=PT()) - c2 = DT.get_polygon_coordinates(vorn, 2, bbox, predicates=PT()) - c3 = DT.get_polygon_coordinates(vorn, 3, bbox, predicates=PT()) - c4 = DT.get_polygon_coordinates(vorn, 4, bbox, predicates=PT()) - c5 = DT.get_polygon_coordinates(vorn, 5, bbox, predicates=PT()) - c6 = DT.get_polygon_coordinates(vorn, 6, bbox, predicates=PT()) - c7 = DT.get_polygon_coordinates(vorn, 7, bbox, predicates=PT()) + c1 = DT.get_polygon_coordinates(vorn, 1, bbox, predicates = PT()) + c2 = DT.get_polygon_coordinates(vorn, 2, bbox, predicates = PT()) + c3 = DT.get_polygon_coordinates(vorn, 3, bbox, predicates = PT()) + c4 = DT.get_polygon_coordinates(vorn, 4, bbox, predicates = PT()) + c5 = DT.get_polygon_coordinates(vorn, 5, bbox, predicates = PT()) + c6 = DT.get_polygon_coordinates(vorn, 6, bbox, predicates = PT()) + c7 = DT.get_polygon_coordinates(vorn, 7, bbox, predicates = PT()) @test all(DT.is_circular, (c1, c2, c3, c4, c5, c6, c7)) - @test DT.circular_equality(collect.(c1), collect.([ - (-1.5, 0.5) - (0.166666666666, -1.1666666666666665) - (1.0, 0.5) - (1.0, 3.0) - (-1.5, 0.5) - ]), ≈) - @test DT.circular_equality(collect.(c2), collect.([ - (0.5, -3.2) - (5.7, -3.2) - (5.7, -1.700000000000001) - (3.5, 0.5) - (0.5, -2.5) - (0.5, -3.2) - ]), ≈) - @test DT.circular_equality(collect.(c3), collect.([ - (3.5, 0.5) - (1.0, 0.5) - (0.16666666666666666, -1.1666666666666665) - (0.5, -2.5) - (3.5, 0.5) - ]), ≈) - @test DT.circular_equality(collect.(c4), collect.([ - (1.5, 5.2) - (-2.7, 5.2) - (-2.7, 0.9000000000000001) - (-1.5, 0.5) - (1.0, 3.0) - (1.5, 4.5) - (1.5, 5.2) - ]), ≈) - @test DT.circular_equality(collect.(c5), collect.([ - (1.5, 4.5) - (3.5, 0.5) - (5.7, 2.6999999999999997) - (5.7, 5.2) - (1.5, 5.2) - (1.5, 4.5) - ]), ≈) - @test DT.circular_equality(collect.(c6), collect.([ - (-2.7, 0.9000000000000001) - (-2.7, -3.2) - (0.5, -3.2) - (0.5, -2.5) - (0.16666666666666666, -1.1666666666666665) - (-1.5, 0.5) - (-2.7, 0.9000000000000001) - ]), ≈) - @test DT.circular_equality(collect.(c7), collect.([ - (1.5, 4.5) - (1.0, 3.0) - (1.0, 0.5) - (3.5, 0.5) - (1.5, 4.5) - ]), ≈) + @test DT.circular_equality( + collect.(c1), collect.( + [ + (-1.5, 0.5) + (0.166666666666, -1.1666666666666665) + (1.0, 0.5) + (1.0, 3.0) + (-1.5, 0.5) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c2), collect.( + [ + (0.5, -3.2) + (5.7, -3.2) + (5.7, -1.700000000000001) + (3.5, 0.5) + (0.5, -2.5) + (0.5, -3.2) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c3), collect.( + [ + (3.5, 0.5) + (1.0, 0.5) + (0.16666666666666666, -1.1666666666666665) + (0.5, -2.5) + (3.5, 0.5) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c4), collect.( + [ + (1.5, 5.2) + (-2.7, 5.2) + (-2.7, 0.9000000000000001) + (-1.5, 0.5) + (1.0, 3.0) + (1.5, 4.5) + (1.5, 5.2) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c5), collect.( + [ + (1.5, 4.5) + (3.5, 0.5) + (5.7, 2.6999999999999997) + (5.7, 5.2) + (1.5, 5.2) + (1.5, 4.5) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c6), collect.( + [ + (-2.7, 0.9000000000000001) + (-2.7, -3.2) + (0.5, -3.2) + (0.5, -2.5) + (0.16666666666666666, -1.1666666666666665) + (-1.5, 0.5) + (-2.7, 0.9000000000000001) + ], + ), ≈, + ) + @test DT.circular_equality( + collect.(c7), collect.( + [ + (1.5, 4.5) + (1.0, 3.0) + (1.0, 0.5) + (3.5, 0.5) + (1.5, 4.5) + ], + ), ≈, + ) end end end @@ -184,38 +226,38 @@ end F = (1.0, 4.0) G = (-3.0, 5.0) pts = [A, B, C, D, E, F, G] - tri = triangulate(pts; delete_ghosts=false, randomise=false) - vorn = voronoi(tri; predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, randomise = false) + vorn = voronoi(tri; predicates = PT()) @test get_adjacent(vorn, 1, -2) == get_adjacent(vorn, -2, -1) == - get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == - 5 + get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == + 5 DT.delete_polygon_adjacent!(vorn, 5) @test get_adjacent(vorn, 1, -2) == get_adjacent(vorn, -2, -1) == - get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == - DT.∅ + get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == + DT.∅ DT.add_polygon_adjacent!(vorn, 5) @test get_adjacent(vorn, 1, -2) == get_adjacent(vorn, -2, -1) == - get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == - 5 + get_adjacent(vorn, -1, 7) == get_adjacent(vorn, 7, 3) == get_adjacent(vorn, 3, 1) == + 5 end end end @testset "Voronoi point location" begin for PT in subtypes(DT.AbstractPredicateKernel) - A = (-1.0, 7.0) .+ (1e-6rand(), 1e-6rand()) # perturb to allow the tests to work even without ExactPredicates - B = (4.0, 4.0) .+ (1e-6rand(), 1e-6rand()) - C = (-2.0, -1.0) .+ (1e-6rand(), 1e-6rand()) - D = (-1.0, 3.0) .+ (1e-6rand(), 1e-6rand()) - E = (3.0, -1.0) .+ (1e-6rand(), 1e-6rand()) - F = (1.0, 4.0) .+ (1e-6rand(), 1e-6rand()) - G = (-3.0, 5.0) .+ (1e-6rand(), 1e-6rand()) + A = (-1.0, 7.0) .+ (1.0e-6rand(), 1.0e-6rand()) # perturb to allow the tests to work even without ExactPredicates + B = (4.0, 4.0) .+ (1.0e-6rand(), 1.0e-6rand()) + C = (-2.0, -1.0) .+ (1.0e-6rand(), 1.0e-6rand()) + D = (-1.0, 3.0) .+ (1.0e-6rand(), 1.0e-6rand()) + E = (3.0, -1.0) .+ (1.0e-6rand(), 1.0e-6rand()) + F = (1.0, 4.0) .+ (1.0e-6rand(), 1.0e-6rand()) + G = (-3.0, 5.0) .+ (1.0e-6rand(), 1.0e-6rand()) pts = [A, B, C, D, E, F, G] - tri = triangulate(pts; delete_ghosts=false, randomise=false) - vor = voronoi(tri, predicates=PT()) - @test validate_tessellation(vor, predicates=PT()) + tri = triangulate(pts; delete_ghosts = false, randomise = false) + vor = voronoi(tri, predicates = PT()) + @test validate_tessellation(vor, predicates = PT()) xmin, xmax, ymin, ymax = DT.polygon_bounds(get_points(tri), get_convex_hull_vertices(tri)) - p = NTuple{2,Float64}[] + p = NTuple{2, Float64}[] n = 10000 while length(p) ≤ n # only going to test points that are inside the polygon pt = (xmin + rand() * (xmax - xmin), ymin + rand() * (ymax - ymin)) @@ -224,7 +266,7 @@ end end end for p in p - u = get_nearest_neighbour(vor, p; predicates=PT()) + u = get_nearest_neighbour(vor, p; predicates = PT()) all_dists = [norm(p .- get_generator(vor, i)) for i in sort(collect(each_generator(vor)))] @test findmin(all_dists)[2] == u end @@ -236,24 +278,24 @@ end (0.1, -1.0), (-0.8, -1.0), (-1.0, -1.0), (-1.0, -0.7), (-1.0, -0.1), (-1.0, 0.6), (-0.1, -0.8), (0.2, -0.8), - (-0.6, -0.4), (0.9, 0.0), (-0.5, 0.5), (-0.4, 0.6), (-0.1, 0.8) + (-0.6, -0.4), (0.9, 0.0), (-0.5, 0.5), (-0.4, 0.6), (-0.1, 0.8), ] - tri = triangulate(points, delete_ghosts=false) - vorn = voronoi(tri, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + tri = triangulate(points, delete_ghosts = false) + vorn = voronoi(tri, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) xg = LinRange(-1, 1, 50) yg = LinRange(-1, 1, 50) x = vec([x for x in xg, _ in yg]) y = vec([y for _ in xg, y in yg]) for (ξ, η) in zip(x, y) p = (ξ, η) - u = get_nearest_neighbour(vorn, p; predicates=PT()) - @inferred get_nearest_neighbour(vorn, p; predicates=PT()) + u = get_nearest_neighbour(vorn, p; predicates = PT()) + @inferred get_nearest_neighbour(vorn, p; predicates = PT()) all_dists = [norm(p .- get_generator(vorn, i)) for i in sort(collect(each_generator(vorn)))] k = findmin(all_dists)[2] @test k == u for m in DT.each_point_index(tri) - u = get_nearest_neighbour(vorn, p, try_points=m; predicates=PT()) + u = get_nearest_neighbour(vorn, p, try_points = m; predicates = PT()) @test u == k end end @@ -272,9 +314,9 @@ end F = (1.0, 4.0) G = (-3.0, 5.0) pts = [A, B, C, D, E, F, G] - tri = triangulate(pts; delete_ghosts=false, randomise=true) + tri = triangulate(pts; delete_ghosts = false, randomise = true) #lock_convex_hull!(tri) - vorn = voronoi(tri; clip=true, predicates=PT()) + vorn = voronoi(tri; clip = true, predicates = PT()) for (i, p) in DT.get_generators(vorn) @test get_point(tri, i) == get_generator(vorn, i) == p end @@ -298,26 +340,30 @@ end @test DT.get_circumcenter_to_triangle(vorn, c) == V @test DT.get_triangle_to_circumcenter(vorn, V) == c end - orig_pt = collect.([(0.5, 0.5) - (2.5, 7.166666666666667) - (1.1666666666666665, 1.1666666666666667) - (-4.3, 1.7000000000000002) - (-1.0, 5.0) - (-0.75, 5.0) - (2.5, 1.7000000000000002) - (0.5, -1.0) - (3.5, 1.5) - (3.0, -1.0) - (-2.7142857142857144, 3.2857142857142856) - (-2.369565217391304, 1.2173913043478262) - (2.5000000000000004, 4.8999999999999995) - (0.7105263157894739, 5.973684210526315) - (-2.0, 6.0) - (-3.0, 5.0) - (4.0, 4.0) - (-2.0, -1.0) - (-1.0, 7.0)]) - @test validate_tessellation(vorn, predicates=PT()) + orig_pt = collect.( + [ + (0.5, 0.5) + (2.5, 7.166666666666667) + (1.1666666666666665, 1.1666666666666667) + (-4.3, 1.7000000000000002) + (-1.0, 5.0) + (-0.75, 5.0) + (2.5, 1.7000000000000002) + (0.5, -1.0) + (3.5, 1.5) + (3.0, -1.0) + (-2.7142857142857144, 3.2857142857142856) + (-2.369565217391304, 1.2173913043478262) + (2.5000000000000004, 4.8999999999999995) + (0.7105263157894739, 5.973684210526315) + (-2.0, 6.0) + (-3.0, 5.0) + (4.0, 4.0) + (-2.0, -1.0) + (-1.0, 7.0) + ], + ) + @test validate_tessellation(vorn, predicates = PT()) @test isempty(DT.get_unbounded_polygons(vorn)) @test all([0 ≤ get_area(vorn, i) < Inf for i in each_polygon_index(vorn)]) @test DT.circular_equality(collect.(get_polygon_point.(Ref(vorn), get_polygon(vorn, 5))), getindex.(Ref(orig_pt), [8, 10, 9, 7, 3, 1, 8]), ≈) @@ -332,7 +378,7 @@ end C = get_polygon(vorn, i) for (j, v) in pairs(C) δ = DT.distance_to_polygon(get_polygon_point(vorn, v), get_points(tri), get_convex_hull_vertices(tri)) - @test δ ≥ -1e-15 + @test δ ≥ -1.0e-15 end end end @@ -343,8 +389,8 @@ end for PT in subtypes(DT.AbstractPredicateKernel) for _ in 1:100 tri = fixed_shewchuk_example_constrained() - vorn = voronoi(tri; clip=false, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri; clip = false, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) for (i, p) in DT.get_generators(vorn) @test get_point(tri, i) == get_generator(vorn, i) == p end @@ -371,67 +417,87 @@ end end @test DT.circular_equality( get_polygon(vorn, 1), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (4, 2, 1), (1, 2, -1), (4, 1, -1), (4, 2, 1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (4, 2, 1), (1, 2, -1), (4, 1, -1), (4, 2, 1), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 2), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (4, 2, 1), (4, 3, 2), (2, 3, -1), (1, 2, -1), (4, 2, 1) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (4, 2, 1), (4, 3, 2), (2, 3, -1), (1, 2, -1), (4, 2, 1), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 3), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (4, 3, 2), (4, 10, 3), (3, 10, -1), (2, 3, -1), (4, 3, 2) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (4, 3, 2), (4, 10, 3), (3, 10, -1), (2, 3, -1), (4, 3, 2), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 4), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (5, 9, 4), (9, 10, 4), (4, 10, 3), (4, 3, 2), (4, 2, 1), (4, 1, -1), (5, 4, -1), (5, 9, 4) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (5, 9, 4), (9, 10, 4), (4, 10, 3), (4, 3, 2), (4, 2, 1), (4, 1, -1), (5, 4, -1), (5, 9, 4), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 5), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (6, 8, 5), (8, 10, 5), (10, 9, 5), (5, 9, 4), (5, 4, -1), (6, 5, -1), (6, 8, 5) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (6, 8, 5), (8, 10, 5), (10, 9, 5), (5, 9, 4), (5, 4, -1), (6, 5, -1), (6, 8, 5), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 6), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (7, 8, 6), (6, 8, 5), (6, 5, -1), (7, 6, -1), (7, 8, 6) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (7, 8, 6), (6, 8, 5), (6, 5, -1), (7, 6, -1), (7, 8, 6), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 7), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (11, 8, 7), (7, 8, 6), (7, 6, -1), (11, 7, -1), (11, 8, 7) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (11, 8, 7), (7, 8, 6), (7, 6, -1), (11, 7, -1), (11, 8, 7), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 8), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (7, 8, 6), (11, 8, 7), (11, 10, 8), (8, 10, 5), (6, 8, 5), (7, 8, 6) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (7, 8, 6), (11, 8, 7), (11, 10, 8), (8, 10, 5), (6, 8, 5), (7, 8, 6), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 9), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (10, 9, 5), (9, 10, 4), (5, 9, 4), (10, 9, 5) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (10, 9, 5), (9, 10, 4), (5, 9, 4), (10, 9, 5), + ], + ), ) @test DT.circular_equality( get_polygon(vorn, 10), - DT.get_triangle_to_circumcenter.(Ref(vorn), [ - (9, 10, 4), (10, 9, 5), (8, 10, 5), (11, 10, 8), (10, 11, -1), (3, 10, -1), (4, 10, 3), (9, 10, 4) - ]) + DT.get_triangle_to_circumcenter.( + Ref(vorn), [ + (9, 10, 4), (10, 9, 5), (8, 10, 5), (11, 10, 8), (10, 11, -1), (3, 10, -1), (4, 10, 3), (9, 10, 4), + ], + ), ) - _vorn = voronoi(tri; clip=true, predicates=PT()) - @test validate_tessellation(_vorn, predicates=PT()) + _vorn = voronoi(tri; clip = true, predicates = PT()) + @test validate_tessellation(_vorn, predicates = PT()) for (i, p) in DT.get_generators(_vorn) @test get_point(tri, i) == get_generator(_vorn, i) == p end @@ -521,30 +587,30 @@ end d = (4.0, 0.0) e = (2.0, 1.5) pts = [a, b, c, d, e] - tri = triangulate(pts, delete_ghosts=false, randomise=false) - vorn = voronoi(tri, predicates=PT()) - lock_convex_hull!(tri; predicates=PT()) + tri = triangulate(pts, delete_ghosts = false, randomise = false) + vorn = voronoi(tri, predicates = PT()) + lock_convex_hull!(tri; predicates = PT()) edges_to_process, - polygon_edge_queue, - boundary_sites, - segment_intersections, - processed_pairs, - intersected_edge_cache, - exterior_circumcenters, - left_edge_intersectors, - right_edge_intersectors, - current_edge_intersectors, - equal_circumcenter_mapping = DT.initialise_clipping_arrays(vorn) + polygon_edge_queue, + boundary_sites, + segment_intersections, + processed_pairs, + intersected_edge_cache, + exterior_circumcenters, + left_edge_intersectors, + right_edge_intersectors, + current_edge_intersectors, + equal_circumcenter_mapping = DT.initialise_clipping_arrays(vorn) @test edges_to_process == Set(((1, 2), (4, 1), (3, 4), (2, 3))) - @test polygon_edge_queue == DT.Queue{Tuple{NTuple{2,Int},Int}}() - @test boundary_sites == Dict{Int,Set{Int}}() - @test segment_intersections == NTuple{2,Int}[] - @test processed_pairs == Set{Tuple{NTuple{2,Int},Int}}() - @test intersected_edge_cache == Pair{NTuple{2,Int},NTuple{2,Int}}[] - @test left_edge_intersectors == Set{NTuple{2,Int}}() - @test right_edge_intersectors == Set{NTuple{2,Int}}() - @test current_edge_intersectors == Set{NTuple{2,Int}}() - @test equal_circumcenter_mapping == Dict{Int,Int}() + @test polygon_edge_queue == DT.Queue{Tuple{NTuple{2, Int}, Int}}() + @test boundary_sites == Dict{Int, Set{Int}}() + @test segment_intersections == NTuple{2, Int}[] + @test processed_pairs == Set{Tuple{NTuple{2, Int}, Int}}() + @test intersected_edge_cache == Pair{NTuple{2, Int}, NTuple{2, Int}}[] + @test left_edge_intersectors == Set{NTuple{2, Int}}() + @test right_edge_intersectors == Set{NTuple{2, Int}}() + @test current_edge_intersectors == Set{NTuple{2, Int}}() + @test equal_circumcenter_mapping == Dict{Int, Int}() end end @@ -557,9 +623,9 @@ end d = (4.0, 0.0) e = (1.0, 1.5) pts = [a, b, c, d, e] - tri = triangulate(pts, delete_ghosts=false) - vorn = voronoi(tri; predicates=PT()) - lock_convex_hull!(tri; predicates=PT()) + tri = triangulate(pts, delete_ghosts = false) + vorn = voronoi(tri; predicates = PT()) + lock_convex_hull!(tri; predicates = PT()) edges_to_process, polygon_edge_queue = DT.initialise_clipping_arrays(vorn) e = (1, 2) DT.enqueue_new_edge!(polygon_edge_queue, vorn, e, Random.default_rng(), PT()) @@ -598,7 +664,7 @@ end @testset "add_to_intersected_edge_cache" begin u, v, a, b = 1, 7, 5, 9 - intersected_edge_cache = Pair{NTuple{2,Int},NTuple{2,Int}}[] + intersected_edge_cache = Pair{NTuple{2, Int}, NTuple{2, Int}}[] DT.add_to_intersected_edge_cache!(intersected_edge_cache, u, v, a, b) @test intersected_edge_cache == [(u, v) => (a, b)] u, v, a, b = -2, 5, 10, 17 @@ -614,20 +680,20 @@ end d = (4.0, 0.0) e = (1.0, 1.5) pts = [a, b, c, d, e] - tri = triangulate(pts, delete_ghosts=false, randomise=false) - vorn = voronoi(tri, predicates=PT()) - lock_convex_hull!(tri, predicates=PT()) + tri = triangulate(pts, delete_ghosts = false, randomise = false) + vorn = voronoi(tri, predicates = PT()) + lock_convex_hull!(tri, predicates = PT()) edges_to_process, - polygon_edge_queue, - boundary_sites, - segment_intersections, - processed_pairs, - intersected_edge_cache, - exterior_circumcenters, - left_edge_intersectors, - right_edge_intersectors, - current_edge_intersectors, - equal_circumcenter_mapping = DT.initialise_clipping_arrays(vorn) + polygon_edge_queue, + boundary_sites, + segment_intersections, + processed_pairs, + intersected_edge_cache, + exterior_circumcenters, + left_edge_intersectors, + right_edge_intersectors, + current_edge_intersectors, + equal_circumcenter_mapping = DT.initialise_clipping_arrays(vorn) e = DT.convert_to_edge_adjoining_ghost_vertex(vorn, first(edges_to_process)) DT.enqueue_new_edge!(polygon_edge_queue, vorn, e, Random.default_rng(), PT()) @@ -676,15 +742,17 @@ end @test intersected_edge_cache == [(-3, 3) => e, (u, v) => right_edge] DT.classify_intersections!(intersected_edge_cache, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, left_edge, right_edge, e) - @test left_edge_intersectors == Set{NTuple{2,Int}}() + @test left_edge_intersectors == Set{NTuple{2, Int}}() @test right_edge_intersectors == Set([(u, v)]) @test current_edge_intersectors == Set([(-3, 3)]) - DT.process_intersection_points!(polygon_edge_queue, vorn, incident_polygon, + DT.process_intersection_points!( + polygon_edge_queue, vorn, incident_polygon, left_edge_intersectors, right_edge_intersectors, current_edge_intersectors, - left_edge, right_edge, e, processed_pairs, segment_intersections, boundary_sites) + left_edge, right_edge, e, processed_pairs, segment_intersections, boundary_sites, + ) - _queue = DT.Queue{Tuple{NTuple{2,Int},Int}}() + _queue = DT.Queue{Tuple{NTuple{2, Int}, Int}}() push!(_queue, ((3, 2), 3)) push!(_queue, ((3, 2), 2)) push!(_queue, ((3, 2), 5)) @@ -697,22 +765,24 @@ end d = (4.0, 0.0) e = (1.0, 1.5) pts = [a, b, c, d, e] - tri = triangulate(pts, delete_ghosts=false, randomise=false) - vorn = voronoi(tri; predicates=PT()) - lock_convex_hull!(tri; predicates=PT()) - boundary_sites, segment_intersections, exterior_circumcenters = DT.find_all_intersections(vorn, predicates=PT()) - @test collect.(segment_intersections) ≈ collect.([ - (1.5, 3.0) - (0.0, 1.9166666666666665) - (0.0, 3.0) - (0.0, 1.0833333333333333) - (1.625, 0.0) - (0.0, 0.0) - (2.125, 0.0) - (3.5, 1.5) - (3.0, 3.0) - (4.0, 0.0) - ]) + tri = triangulate(pts, delete_ghosts = false, randomise = false) + vorn = voronoi(tri; predicates = PT()) + lock_convex_hull!(tri; predicates = PT()) + boundary_sites, segment_intersections, exterior_circumcenters = DT.find_all_intersections(vorn, predicates = PT()) + @test collect.(segment_intersections) ≈ collect.( + [ + (1.5, 3.0) + (0.0, 1.9166666666666665) + (0.0, 3.0) + (0.0, 1.0833333333333333) + (1.625, 0.0) + (0.0, 0.0) + (2.125, 0.0) + (3.5, 1.5) + (3.0, 3.0) + (4.0, 0.0) + ], + ) @test boundary_sites[4] == Set((7, 10, 8)) @test boundary_sites[2] == Set((2, 3, 1)) @test boundary_sites[1] == Set((9, 8, 1)) @@ -720,32 +790,34 @@ end @test boundary_sites[5] == Set((5, 4, 7, 2)) @test exterior_circumcenters == Set((2, 1)) - DT.clip_voronoi_tessellation!(vorn, predicates=PT()) + DT.clip_voronoi_tessellation!(vorn, predicates = PT()) @test isempty(vorn.unbounded_polygons) - @test validate_tessellation(vorn, predicates=PT()) + @test validate_tessellation(vorn, predicates = PT()) @test DT.points_are_unique(vorn.polygon_points) - @test collect.(DT.get_polygon_points(vorn)) ≈ collect.([ - (2.0, -0.25) - (-0.625, 1.5) - (1.5, 2.9166666666666665) - (2.75, 1.25) - (1.5, 3.0) - (0.0, 1.9166666666666665) - (0.0, 3.0) - (0.0, 1.0833333333333333) - (1.625, 0.0) - (0.0, 0.0) - (2.125, 0.0) - (3.5, 1.5) - (3.0, 3.0) - (4.0, 0.0) - ]) + @test collect.(DT.get_polygon_points(vorn)) ≈ collect.( + [ + (2.0, -0.25) + (-0.625, 1.5) + (1.5, 2.9166666666666665) + (2.75, 1.25) + (1.5, 3.0) + (0.0, 1.9166666666666665) + (0.0, 3.0) + (0.0, 1.0833333333333333) + (1.625, 0.0) + (0.0, 0.0) + (2.125, 0.0) + (3.5, 1.5) + (3.0, 3.0) + (4.0, 0.0) + ], + ) @test vorn.polygons == Dict( 5 => [8, 9, 11, 4, 3, 6, 8], 4 => [11, 14, 12, 4, 11], 2 => [6, 3, 5, 7, 6], 3 => [10, 9, 8, 10], - 1 => [4, 12, 13, 5, 3, 4] + 1 => [4, 12, 13, 5, 3, 4], ) @test DT.get_boundary_polygons(vorn) == Set((4, 2, 1, 3, 5)) end @@ -756,10 +828,10 @@ end for _ in 1:333 points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) - vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) + vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) @test vorn.polygon_points == [ (0.5, 0.5), (0.5, 0.5), @@ -767,7 +839,7 @@ end (0.0, 0.5), (1.0, 0.0), (0.0, 1.0), - (0.0, 0.0) + (0.0, 0.0), ] end @@ -776,26 +848,30 @@ end 0.290978 0.830755 0.0139574 0.386411 0.630008 0.803881 ] - tri = triangulate(points, delete_ghosts=false) - vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) - @test collect.(sort(vorn.polygon_points)) ≈ collect.(sort([ - (0.43655799581398663, 0.7836598194374879) - (0.5608665, 0.5082095) - (0.4713751999728193, 0.7065097477648392) - (0.1524677, 0.595146) - (0.35698797851173, 0.7308595369379512) - (0.830755, 0.630008) - (0.0139574, 0.803881) - (0.290978, 0.386411) - ])) + tri = triangulate(points, delete_ghosts = false) + vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) + @test collect.(sort(vorn.polygon_points)) ≈ collect.( + sort( + [ + (0.43655799581398663, 0.7836598194374879) + (0.5608665, 0.5082095) + (0.4713751999728193, 0.7065097477648392) + (0.1524677, 0.595146) + (0.35698797851173, 0.7308595369379512) + (0.830755, 0.630008) + (0.0139574, 0.803881) + (0.290978, 0.386411) + ], + ), + ) end for _ in 1:1000 pts = rand(2, 3) tri = triangulate(pts) - vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) end end end @@ -813,10 +889,10 @@ end h = (0.2, 0.1) pts = [a, b, c, d, e, f, g, h] tri = triangulate(pts) - vorn = voronoi(tri, predicates=PT()) - _vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) - @test validate_tessellation(_vorn, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) + _vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) + @test validate_tessellation(_vorn, predicates = PT()) orig_pt = [ (3.1112716763005785, 0.703757225433526) (3.000000000000019, -5.750000000000036) @@ -857,7 +933,7 @@ end C = get_polygon(_vorn, i) for (j, v) in pairs(C) δ = DT.distance_to_polygon(get_polygon_point(_vorn, v), get_points(tri), get_convex_hull_vertices(tri)) - @test δ ≥ -1e-14 + @test δ ≥ -1.0e-14 end end @test DT.get_boundary_polygons(_vorn) == Set((4, 6, 3, 5, 2, 8, 1, 7)) @@ -872,10 +948,10 @@ end rng = StableRNG(2^(isqrt(n)) * 3^(isqrt(n))) pts = rand(rng, 2, n) tri = triangulate(pts; rng) - vorn = voronoi(tri, predicates=PT()) - flag1 = validate_tessellation(vorn, predicates=PT()) - vorn = voronoi(tri, clip=true, predicates=PT()) - flag2 = validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) + flag1 = validate_tessellation(vorn, predicates = PT()) + vorn = voronoi(tri, clip = true, predicates = PT()) + flag2 = validate_tessellation(vorn, predicates = PT()) @test flag1 @test flag2 end @@ -890,21 +966,21 @@ end for i in 1:25 @info "Testing centroidal tessellation: Run: $i" p1 = randn(2, 50) - p2 = rand(SVector{2,Float64}, 30) + p2 = rand(SVector{2, Float64}, 30) p3 = rand(Point2f, 250) p4 = randn(Float32, 2, 70) p5 = randn(2, 4) - p6 = rand(SVector{2,Float64}, 7) + p6 = rand(SVector{2, Float64}, 7) p7 = rand(Point2f, 5) p8 = randn(Float32, 2, 15) _pts = (p1, p2, p3, p4, p5, p6, p7, p8) for jj in eachindex(_pts) points = _pts[jj] - tri = triangulate(points, predicates=PT()) - vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn, check_convex=!(jj ∈ (3, 4, 7, 8)), predicates=PT()) - for smooth_vorn in (centroidal_smooth(vorn, maxiters=5000, predicates=PT()), voronoi(tri, clip=true, smooth=true, maxiters=5000, predicates=PT())) - @test validate_tessellation(smooth_vorn, check_convex=!(jj ∈ (3, 4, 7, 8)), predicates=PT()) + tri = triangulate(points, predicates = PT()) + vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn, check_convex = !(jj ∈ (3, 4, 7, 8)), predicates = PT()) + for smooth_vorn in (centroidal_smooth(vorn, maxiters = 5000, predicates = PT()), voronoi(tri, clip = true, smooth = true, maxiters = 5000, predicates = PT())) + @test validate_tessellation(smooth_vorn, check_convex = !(jj ∈ (3, 4, 7, 8)), predicates = PT()) for i in each_polygon_index(smooth_vorn) p = get_generator(smooth_vorn, i) c = DT.get_centroid(smooth_vorn, i) @@ -912,7 +988,7 @@ end cx, cy = DT.getxy(c) dx, dy = px - cx, py - cy ℓ = sqrt(dx^2 + dy^2) - _flag = ℓ ≤ 1e-1 + _flag = ℓ ≤ 1.0e-1 flag += _flag tot += 1 end @@ -926,48 +1002,60 @@ end @testset "Lattice" begin for PT in (DT.ExactKernel, DT.AdaptiveKernel) for _ in 1:50 - tri = triangulate_rectangle(0, 1, 0, 1, 11, 11, delete_ghosts=false, predicates=PT()) - tri = triangulate(tri.points, predicates=PT()) - vorn = voronoi(tri, predicates=PT()) - @test validate_tessellation(vorn; check_convex=false, predicates=PT()) - vorn = voronoi(tri, clip=true, predicates=PT()) - @test validate_tessellation(vorn; check_convex=false, check_adjacent=false, predicates=PT()) + tri = triangulate_rectangle(0, 1, 0, 1, 11, 11, delete_ghosts = false, predicates = PT()) + tri = triangulate(tri.points, predicates = PT()) + vorn = voronoi(tri, predicates = PT()) + @test validate_tessellation(vorn; check_convex = false, predicates = PT()) + vorn = voronoi(tri, clip = true, predicates = PT()) + @test validate_tessellation(vorn; check_convex = false, check_adjacent = false, predicates = PT()) end end end @testset "Example that used to previously break: Plotting a Voronoi tile with unbounded edges intersecting over non-neighbouring sides" begin for PT in subtypes(DT.AbstractPredicateKernel) - pts = [0.508812 0.656662 0.785124 0.63427 0.444969 0.609253 0.0826304 0.265388 0.830807 0.658346 - 0.647732 0.482994 0.809909 0.482046 0.0170022 0.821742 0.835057 0.591724 0.881006 0.97652] + pts = [ + 0.508812 0.656662 0.785124 0.63427 0.444969 0.609253 0.0826304 0.265388 0.830807 0.658346 + 0.647732 0.482994 0.809909 0.482046 0.0170022 0.821742 0.835057 0.591724 0.881006 0.97652 + ] tri = triangulate(pts) - vorn = voronoi(tri, predicates=PT()) - clip = DT.get_polygon_coordinates(vorn, 9, DT.polygon_bounds(vorn, 0.1), predicates=PT()) - @test DT.circular_equality(collect.(clip), collect.([ - (0.8374509236290323, 1.0964579554357115) - (0.7271857522962732, 0.8973620981454822) - (1.7423743304675243, 0.24505806539308744) - (2.0053766736553027, 0.1299847935961671) - (2.0053766736553027, 1.0964579554357115) - (0.8374509236290323, 1.0964579554357115) - ]), ≈) + vorn = voronoi(tri, predicates = PT()) + clip = DT.get_polygon_coordinates(vorn, 9, DT.polygon_bounds(vorn, 0.1), predicates = PT()) + @test DT.circular_equality( + collect.(clip), collect.( + [ + (0.8374509236290323, 1.0964579554357115) + (0.7271857522962732, 0.8973620981454822) + (1.7423743304675243, 0.24505806539308744) + (2.0053766736553027, 0.1299847935961671) + (2.0053766736553027, 1.0964579554357115) + (0.8374509236290323, 1.0964579554357115) + ], + ), ≈, + ) end end @testset "Example that used to previously break: Plotting a Voronoi tile with unbounded edges intersecting over non-neighbouring sides, needing THREE corners" begin for PT in subtypes(DT.AbstractPredicateKernel) - pts = [0.279402 0.874842 0.163028 - 0.274178 0.831658 0.223709] - tri = triangulate(pts, predicates=PT()) - vorn = voronoi(tri, predicates=PT()) - clip = DT.get_polygon_coordinates(vorn, 2, DT.polygon_bounds(vorn, 2.0), predicates=PT()) - @test DT.circular_equality(collect.(clip), collect.([ - (-2.551580488601045, 4.122780970352073) - (-0.3314903102646037, 1.5233996567840244) - (3.2875066205292076, -2.3420224793856605) - (3.2875066205292076, 4.122780970352073) - (-2.551580488601045, 4.122780970352073) - ]), ≈) + pts = [ + 0.279402 0.874842 0.163028 + 0.274178 0.831658 0.223709 + ] + tri = triangulate(pts, predicates = PT()) + vorn = voronoi(tri, predicates = PT()) + clip = DT.get_polygon_coordinates(vorn, 2, DT.polygon_bounds(vorn, 2.0), predicates = PT()) + @test DT.circular_equality( + collect.(clip), collect.( + [ + (-2.551580488601045, 4.122780970352073) + (-0.3314903102646037, 1.5233996567840244) + (3.2875066205292076, -2.3420224793856605) + (3.2875066205292076, 4.122780970352073) + (-2.551580488601045, 4.122780970352073) + ], + ), ≈, + ) end end @@ -998,11 +1086,11 @@ end Float32[0.90867966, 0.55974066], Float32[0.580766, 0.7668439], Float32[0.8563475, 0.88143903], - Float32[0.18311942, 0.8367877] + Float32[0.18311942, 0.8367877], ] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) points = [ [0.01877582f0, 0.33188105f0], @@ -1024,19 +1112,19 @@ end [0.19257814f0, 0.30570602f0], [0.12954468f0, 0.11141288f0], [0.28790158f0, 0.39447558f0], - [0.6525599f0, 0.6425986f0] + [0.6525599f0, 0.6425986f0], ] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) - @test validate_tessellation(vorn, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) + @test validate_tessellation(vorn, predicates = PT()) end end @testset "Polygon bounds with generators only" begin points = rand(2, 50) tri = triangulate(points) - vorn = voronoi(tri, predicates=rt()) - xmin, xmax, ymin, ymax = DT.polygon_bounds(vorn, 0.1; include_polygon_vertices=false) + vorn = voronoi(tri, predicates = rt()) + xmin, xmax, ymin, ymax = DT.polygon_bounds(vorn, 0.1; include_polygon_vertices = false) _xmin, _xmax = extrema(points[1, :]) _ymin, _ymax = extrema(points[2, :]) @test xmin == _xmin - 0.1(_xmax - _xmin) @@ -1057,51 +1145,61 @@ end H = (3.0, 8.0) points = [A, B, C, D, E, F, G, H] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) a, b, c, d = -4.0, 6.0, -2.0, 4.0 bounding_box = (a, b, c, d) new_vertices, new_points = DT.grow_polygon_outside_of_box(vorn, 1, bounding_box, PT()) - @test collect.(new_points) ≈ collect.([ - (-1.1363636363636365, 5.954545454545455) - (-0.2999999999999998, 9.3) - (-2.3999999999999986, 21.900000000000006) - (-61.96153846153845, 7.846153846153847) - (-10.807692307692307, 2.730769230769231) - ]) + @test collect.(new_points) ≈ collect.( + [ + (-1.1363636363636365, 5.954545454545455) + (-0.2999999999999998, 9.3) + (-2.3999999999999986, 21.900000000000006) + (-61.96153846153845, 7.846153846153847) + (-10.807692307692307, 2.730769230769231) + ], + ) @test new_vertices == [1, 2, 3, 4, 5] new_vertices, new_points = DT.grow_polygon_outside_of_box(vorn, 5, bounding_box, PT()) - @test collect.(new_points) ≈ collect.([ - (2.710526315789474, 1.868421052631579) - (-0.7307692307692308, -0.8846153846153846) - (1.1153846153846159, -13.807692307692308) - (13.026315789473683, -1.0789473684210529) - ]) + @test collect.(new_points) ≈ collect.( + [ + (2.710526315789474, 1.868421052631579) + (-0.7307692307692308, -0.8846153846153846) + (1.1153846153846159, -13.807692307692308) + (13.026315789473683, -1.0789473684210529) + ], + ) @test new_vertices == [1, 2, 3, 4] new_vertices, new_points = DT.grow_polygon_outside_of_box(vorn, 6, bounding_box, PT()) - @test collect.(new_points) ≈ collect.([ - (23.34210526315789, -4.026315789473685) - (17.5, 15.499999999999995) - (3.1, 5.9) - (2.357142857142857, 2.9285714285714284) - (2.710526315789474, 1.868421052631579) - ]) + @test collect.(new_points) ≈ collect.( + [ + (23.34210526315789, -4.026315789473685) + (17.5, 15.499999999999995) + (3.1, 5.9) + (2.357142857142857, 2.9285714285714284) + (2.710526315789474, 1.868421052631579) + ], + ) @test new_vertices == [1, 2, 3, 4, 5] new_vertices, new_points = DT.grow_polygon_outside_of_box(vorn, 7, bounding_box, PT()) - @test collect.(new_points) ≈ collect.([ - (-0.7307692307692308, -0.8846153846153846) - (-4.166666666666666, 0.8333333333333335) - (-10.807692307692307, 2.730769230769231) - (-61.96153846153845, 7.846153846153847) - (1.1153846153846159, -13.807692307692308) - ]) + @test collect.(new_points) ≈ collect.( + [ + (-0.7307692307692308, -0.8846153846153846) + (-4.166666666666666, 0.8333333333333335) + (-10.807692307692307, 2.730769230769231) + (-61.96153846153845, 7.846153846153847) + (1.1153846153846159, -13.807692307692308) + ], + ) @test new_vertices == [1, 2, 3, 4, 5] new_vertices, new_points = DT.grow_polygon_outside_of_box(vorn, 8, bounding_box, PT()) - @test collect.(new_points) ≈ collect.([ - (17.5, 15.499999999999995) - (-4.799999999999997, 36.30000000000001) - (-0.2999999999999998, 9.3) - (3.1, 5.9) - ]) + @test collect.(new_points) ≈ collect.( + [ + (17.5, 15.499999999999995) + (-4.799999999999997, 36.30000000000001) + (-0.2999999999999998, 9.3) + (3.1, 5.9) + ], + ) @test new_vertices == [1, 2, 3, 4] @inferred DT.grow_polygon_outside_of_box(vorn, 8, bounding_box, PT()) end @@ -1119,25 +1217,25 @@ end H = (3.0, 8.0) points = [A, B, C, D, E, F, G, H] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) a, b, c, d = -4.0, 6.0, -2.0, 4.0 bounding_box = (a, b, c, d) - _pa = get_polygon_coordinates(vorn, 1, bounding_box; predicates=PT()) - _pb = get_polygon_coordinates(vorn, 2, bounding_box; predicates=PT()) - _pc = get_polygon_coordinates(vorn, 3, bounding_box; predicates=PT()) - _pd = get_polygon_coordinates(vorn, 4, bounding_box; predicates=PT()) - _pe = get_polygon_coordinates(vorn, 5, bounding_box; predicates=PT()) - _pf = get_polygon_coordinates(vorn, 6, bounding_box; predicates=PT()) - _pg = get_polygon_coordinates(vorn, 7, bounding_box; predicates=PT()) - _ph = get_polygon_coordinates(vorn, 8, bounding_box; predicates=PT()) - pa = NTuple{2,Float64}[] + _pa = get_polygon_coordinates(vorn, 1, bounding_box; predicates = PT()) + _pb = get_polygon_coordinates(vorn, 2, bounding_box; predicates = PT()) + _pc = get_polygon_coordinates(vorn, 3, bounding_box; predicates = PT()) + _pd = get_polygon_coordinates(vorn, 4, bounding_box; predicates = PT()) + _pe = get_polygon_coordinates(vorn, 5, bounding_box; predicates = PT()) + _pf = get_polygon_coordinates(vorn, 6, bounding_box; predicates = PT()) + _pg = get_polygon_coordinates(vorn, 7, bounding_box; predicates = PT()) + _ph = get_polygon_coordinates(vorn, 8, bounding_box; predicates = PT()) + pa = NTuple{2, Float64}[] pb = [(0.75, 4.0), (2.357142857142857, 2.9285714285714284), (2.625, 4.0), (0.75, 4.0)] pc = [(2.710526315789474, 1.868421052631579), (2.357142857142857, 2.9285714285714284), (0.75, 4.0), (-1.0, 4.0), (-4.0, 1.0), (-4.0, 0.75), (-0.7307692307692308, -0.8846153846153846), (2.710526315789474, 1.868421052631579)] pd = [(-4.0, 4.0), (-4.0, 1.0), (-1.0, 4.0), (-4.0, 4.0)] pe = [(6.0, 0.9285714285714279), (2.710526315789474, 1.868421052631579), (-0.7307692307692308, -0.8846153846153846), (-0.5714285714285712, -2.0), (6.0, -2.0), (6.0, 0.9285714285714279)] pf = [(6.0, 0.9285714285714284), (6.0, 4.0), (2.625, 4.0), (2.357142857142857, 2.9285714285714284), (2.710526315789474, 1.868421052631579), (6.0, 0.9285714285714284)] pg = [(-0.5714285714285721, -2.0), (-0.7307692307692308, -0.8846153846153846), (-4.0, 0.75), (-4.0, -2.0), (-0.5714285714285721, -2.0)] - ph = NTuple{2,Float64}[] + ph = NTuple{2, Float64}[] @test DT.circular_equality(collect.(pa), collect.(_pa), ≈) @test DT.circular_equality(collect.(pb), collect.(_pb), ≈) @test DT.circular_equality(collect.(pc), collect.(_pc), ≈) @@ -1150,11 +1248,11 @@ end # test a small example points = [(0.0, 1.0), (-1.0, 2.0), (-2.0, -1.0)] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) bb = (-1.0, 0.0, -1.0, 2.0) - coord1 = get_polygon_coordinates(vorn, 1, bb;predicates= PT()) - coord2 = get_polygon_coordinates(vorn, 2, bb;predicates= PT()) - coord3 = get_polygon_coordinates(vorn, 3, bb;predicates= PT()) + coord1 = get_polygon_coordinates(vorn, 1, bb; predicates = PT()) + coord2 = get_polygon_coordinates(vorn, 2, bb; predicates = PT()) + coord3 = get_polygon_coordinates(vorn, 3, bb; predicates = PT()) _coord1 = [(0.0, 2.0), (0.0, 2.0), (-1.0, 1.0), (-1.0, 0.0), (0.0, -1.0), (0.0, 2.0)] _coord2 = [(-1.0, 2.0), (-1.0, 1.0), (0.0, 2.0), (-1.0, 2.0)] _coord3 = [(-1.0, -1.0), (0.0, -1.0), (0.0, -1.0), (-1.0, 0.0), (-1.0, -1.0)] @@ -1174,23 +1272,23 @@ end H = (3.0, 8.0) points = [A, B, C, D, E, F, G, H] tri = triangulate(points) - vorn = voronoi(tri, predicates=PT()) + vorn = voronoi(tri, predicates = PT()) bounding_box = (0.0, 5.0, -15.0, 15.0) - _pa = get_polygon_coordinates(vorn, 1, bounding_box; predicates=PT()) - _pb = get_polygon_coordinates(vorn, 2, bounding_box; predicates=PT()) - _pc = get_polygon_coordinates(vorn, 3, bounding_box; predicates=PT()) - _pd = get_polygon_coordinates(vorn, 4, bounding_box; predicates=PT()) - _pe = get_polygon_coordinates(vorn, 5, bounding_box; predicates=PT()) - _pf = get_polygon_coordinates(vorn, 6, bounding_box; predicates=PT()) - _pg = get_polygon_coordinates(vorn, 7, bounding_box; predicates=PT()) + _pa = get_polygon_coordinates(vorn, 1, bounding_box; predicates = PT()) + _pb = get_polygon_coordinates(vorn, 2, bounding_box; predicates = PT()) + _pc = get_polygon_coordinates(vorn, 3, bounding_box; predicates = PT()) + _pd = get_polygon_coordinates(vorn, 4, bounding_box; predicates = PT()) + _pe = get_polygon_coordinates(vorn, 5, bounding_box; predicates = PT()) + _pf = get_polygon_coordinates(vorn, 6, bounding_box; predicates = PT()) + _pg = get_polygon_coordinates(vorn, 7, bounding_box; predicates = PT()) # For _pg: This case used to be broken because the initial unbounded ray did not touch the bounding box, # but then later it does! So just using the Liang-Barsky algorithm by itself is not sufficient. # To fix this, I added the stuff about maximum_distance_to_box inside grow_polygon_outside_of_box _ph = get_polygon_coordinates(vorn, 8, bounding_box; predicates = PT()) - pa = NTuple{2,Float64}[] + pa = NTuple{2, Float64}[] pb = [(0.0, 4.499999999999998), (2.357142857142857, 2.9285714285714284), (3.1, 5.9), (0.0, 9.000000000000002), (0.0, 4.499999999999998)] pc = [(0.0, -0.3000000000000007), (2.710526315789474, 1.868421052631579), (2.357142857142857, 2.9285714285714284), (0.0, 4.499999999999998), (0.0, -0.3000000000000007)] - pd = NTuple{2,Float64}[] + pd = NTuple{2, Float64}[] pe = [(5.0, 1.2142857142857117), (2.710526315789474, 1.868421052631579), (0.0, -0.3000000000000007), (0.0, -6.0), (1.2857142857142865, -15.0), (5.0, -15.0), (5.0, 1.2142857142857117)] pf = [(5.0, 1.2142857142857153), (5.0, 7.166666666666664), (3.1, 5.9), (2.357142857142857, 2.9285714285714284), (2.710526315789474, 1.868421052631579), (5.0, 1.2142857142857153)] pg = [(1.2857142857142865, -15.0), (0.0, -6.0), (0.0, -15.0), (1.2857142857142865, -15.0)] @@ -1224,11 +1322,11 @@ end # The points were duplicated from refine and not included in tri, but # retriangulate kept trying to use them points = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] - tri = triangulate(points; boundary_nodes=[1, 2, 3, 4, 1], predicates=PT()) - refine!(tri; max_area=1e-2, min_angle=29.871, predicates=PT()) - vorn = voronoi(tri, predicates=PT()) - smooth_vorn = centroidal_smooth(vorn; maxiters=250, predicates=PT()) - @test validate_tessellation(smooth_vorn, predicates=PT()) + tri = triangulate(points; boundary_nodes = [1, 2, 3, 4, 1], predicates = PT()) + refine!(tri; max_area = 1.0e-2, min_angle = 29.871, predicates = PT()) + vorn = voronoi(tri, predicates = PT()) + smooth_vorn = centroidal_smooth(vorn; maxiters = 250, predicates = PT()) + @test validate_tessellation(smooth_vorn, predicates = PT()) end end @@ -1244,11 +1342,11 @@ end function is_point_in_polygon(point::Point, polygon::Polygon) # Check if the point is on the boundary of the polygon point in polygon && return false - + n = length(coordinates(polygon)) inside = false p1 = polygon[1] - for i in 2:n+1 + for i in 2:(n + 1) p2 = polygon[mod1(i, n)] if ((p1[2] > point[2]) != (p2[2] > point[2])) && (point[1] < (p2[1] - p1[1]) * (point[2] - p1[2]) / (p2[2] - p1[2]) + p1[1]) inside = !inside @@ -1260,13 +1358,13 @@ end b_vec = reverse([Point(0.0, 0.0), Point(0.0, 1.0), Point(1.0, 1.0), Point(1.0, 0.0), Point(0.5, 0.5)]) p = Polygon(b_vec) p2 = coordinates(p) - push!(p2,p2[1]) + push!(p2, p2[1]) boundary_nodes, points2 = convert_boundary_points_to_indices(getxy.(p2)) triangulation = triangulate(points2; boundary_nodes) minx, miny = extrema(p2)[1] maxx, maxy = extrema(p2)[2] - for i in range(minx + 0.05, maxx - 0.05, step=0.05) - for j in range(maxy - 0.05, miny + 0.05, step=-0.05) + for i in range(minx + 0.05, maxx - 0.05, step = 0.05) + for j in range(maxy - 0.05, miny + 0.05, step = -0.05) if is_point_in_polygon(Point(i, j), p) try add_point!(triangulation, (i, j)) @@ -1277,5 +1375,5 @@ end end end vorn = voronoi(triangulation, clip = false) - @test validate_tessellation(vorn, check_convex=false) -end \ No newline at end of file + @test validate_tessellation(vorn, check_convex = false) +end