Skip to content

Commit

Permalink
Change jump_and_march to find_triangle (#133)
Browse files Browse the repository at this point in the history
* Change jump_and_march to find_triangle

* news

* news

* oops

* filename
  • Loading branch information
DanielVandH authored Jul 8, 2024
1 parent a2acefb commit 6e940b4
Show file tree
Hide file tree
Showing 29 changed files with 210 additions and 206 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added `DelauanyTriangulation.validate_triangulation` for validating triangulations. See [#131](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/131).
- Fixed a bug with the currently unused `orient(p, q, r, s)` predicate. See [#131](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/131).
- Added private functions `getz`, `_getz`, `getxyz`, and `_getxyz`. See [#131](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/131).
- `jump_and_march` has now been renamed to `find_triangle`. For compatibility, `jump_and_march` still works and is simply an alias of `find_triangle`. See [#133](https://github.com/JuliaGeometry/DelaunayTriangulation.jl/pull/133).

## v1.0.5

Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DelaunayTriangulation"
uuid = "927a84f5-c5f4-47a5-9785-b46e178433df"
authors = ["Daniel VandenHeuvel <[email protected]>"]
version = "1.1.0-DEV"
version = "1.1.0"

[deps]
EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/api/point_location.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CurrentModule = DelaunayTriangulation

```@docs
brute_force_search
jump_and_march
find_triangle
get_nearest_neighbour
find_polygon
```
6 changes: 3 additions & 3 deletions docs/src/literate_tutorials/point_in_polygon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,16 @@ fig

# Here is the second method.
tri = triangulate(points; boundary_nodes=nodes)
is_inside_2 = [DelaunayTriangulation.dist(tri, q) > 0 for q in query_points]
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]
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

# 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]
is_inside_4 = [find_polygon(hierarchy, points, nodes, q) 0 for q in query_points];
@test is_inside_4 == is_inside_3 #src
26 changes: 13 additions & 13 deletions docs/src/literate_tutorials/point_location.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# In this tutorial, we demonstrate how triangulations can be
# used to perform point location. The problem of interest is: Given
# a point `p` and a triangulation `tri`, what triangle `T` in `tri`
# contains `p`? We provide a function [`jump_and_march`](@ref) for this task,
# contains `p`? We provide a function [`find_triangle`](@ref) for this task,
# implementing the algorithm of [Mücke, Saias, and Zhu (1999)](https://doi.org/10.1016/S0925-7721(98)00035-2).
# The algorithm has been slightly modified to allow for regions with holes.
# Support is also provided for non-convex and disjoint domains, but the algorithm
Expand Down Expand Up @@ -35,30 +35,30 @@ scatter!(ax, q)
fig

# The aim is to, from `tri`, find which triangle contains the point `q` shown.
# Using the `jump_and_march` function, this is simple.
V = jump_and_march(tri, q)
# Using the `find_triangle` function, this is simple.
V = find_triangle(tri, q)

# The result means that the triangle `(2, 7, 6)` contains the point, as we can easily check:
DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)
@test DelaunayTriangulation.is_inside(DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)) #src

# When we provide no keyword arguments, the default behaviour of `jump_and_march` is to first
# When we provide no keyword arguments, the default behaviour of `find_triangle` is to first
# 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 = jump_and_march(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 = jump_and_march(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`.

# Note also that the triangles found from `jump_and_march` do not have to be given in the same order as they appear
# Note also that the triangles found from `find_triangle` do not have to be given in the same order as they appear
# in the triangulation. For example, if a triangle `(i, j, k)` contains the point `q`, then any of `(i, j, k)`, `(j, k, i)`,
# or `(k, i, j)` could be returned.

Expand All @@ -69,7 +69,7 @@ scatter!(ax, q)
fig

# We obtain:
V = jump_and_march(tri, q)
V = find_triangle(tri, q)
@test DelaunayTriangulation.is_inside(DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)) #src

# See that the result is a ghost triangle `(1, 5, -1)`. As discussed in the [manual](../manual/ghost_triangles.md),
Expand Down Expand Up @@ -121,7 +121,7 @@ fig
load_preference(DelaunayTriangulation, "USE_EXACTPREDICATES", true) && @test_reference joinpath(fig_path, "point_location_ex_3.png") fig #src

# Now let's find the triangles.
Vs = [jump_and_march(tri, q; rng) for q in qs]
Vs = [find_triangle(tri, q; rng) for q in qs]

# While we do find some triangles, they may not all be correct. For example,
# the triangle found for `(1.2, 1.6)` is
Expand All @@ -132,7 +132,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 = [jump_and_march(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
Expand All @@ -159,7 +159,7 @@ results
# ## Disjoint domains
# Now we continue the previous example by adding in another set of
# domains that are disjoint to the current domain, thus allowing us to
# demonstrate how `jump_and_march` applies here. The new domain is below,
# demonstrate how `find_triangle` applies here. The new domain is below,
# along with the points we will be searching for.
m₁, n₁, o₁ = (6.0, 8.0), (8.0, 8.0), (8.0, 4.0)
p₁, q₁, r₁ = (10.0, 4.0), (6.0, 6.0), (8.0, 6.0)
Expand All @@ -184,8 +184,8 @@ scatter!(ax, qs, color=:blue, markersize=16)
fig
load_preference(DelaunayTriangulation, "USE_EXACTPREDICATES", true) && @test_reference joinpath(fig_path, "point_location_ex_4.png") fig by=psnr_equality(10) #src

# Here are the `jump_and_march` results.
Vs = [jump_and_march(tri, q; rng, concavity_protection=true) for q in qs]
# Here are the `find_triangle` results.
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.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/manual/ghost_triangles.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ fig

As you can see, the outer boundary has ghost edges (shown in blue) going out to infinity, oriented with the pole of inaccessibility of the entire domain (shown in red). The ghost edges along the circular boundary are finite and simply connect with the pole of inaccessibility of the circle (shown in magenta).

For more complex domains, in particular non-convex domains, the ghost edges start to overlap and they become less useful, which unfortunately slows down point location (see [`jump_and_march`](@ref)'s docstring).
For more complex domains, in particular non-convex domains, the ghost edges start to overlap and they become less useful, which unfortunately slows down point location (see [`find_triangle`](@ref)'s docstring).
2 changes: 1 addition & 1 deletion docs/src/math/constrained.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fig, ax, sc = triplot(tri)
lines!(ax, [get_point(tri, e...)...], color = :blue, linewidth = 4)
history = DelaunayTriangulation.PointLocationHistory{NTuple{3,Int},NTuple{2,Int},Int}()
q = get_point(tri, 7)
jump_and_march(tri, q; k = 2, history, store_history = Val(true))
find_triangle(tri, q; k = 2, history, store_history = Val(true))
lines!(ax, [get_point(tri, 2, history.left_vertices..., 7)...], color = :red, linewidth = 4)
lines!(ax, [get_point(tri, 2, history.right_vertices..., 7)...], color = :green, linewidth = 4)
for T in history.triangles
Expand Down
2 changes: 1 addition & 1 deletion docs/src/math/delaunay.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ history = DelaunayTriangulation.PointLocationHistory{NTuple{3,Int},NTuple{2,Int}
q = (0.8, 0.8)
p = get_point(tri, 226)
fig, ax, sc = triplot(tri)
V = jump_and_march(tri, q; k = 226, store_history = Val(true), history)
V = find_triangle(tri, q; k = 226, store_history = Val(true), history)
for T in history.triangles
ii, jj, kk = triangle_vertices(T)
pp, qq, rr = get_point(tri, ii, jj, kk)
Expand Down
46 changes: 23 additions & 23 deletions docs/src/tutorials/point_location.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ EditURL = "https://github.com/JuliaGeometry/DelaunayTriangulation.jl/tree/main/d
In this tutorial, we demonstrate how triangulations can be
used to perform point location. The problem of interest is: Given
a point `p` and a triangulation `tri`, what triangle `T` in `tri`
contains `p`? We provide a function [`jump_and_march`](@ref) for this task,
contains `p`? We provide a function [`find_triangle`](@ref) for this task,
implementing the algorithm of [Mücke, Saias, and Zhu (1999)](https://doi.org/10.1016/S0925-7721(98)00035-2).
The algorithm has been slightly modified to allow for regions with holes.
Support is also provided for non-convex and disjoint domains, but the algorithm
Expand Down Expand Up @@ -37,10 +37,10 @@ fig
````

The aim is to, from `tri`, find which triangle contains the point `q` shown.
Using the `jump_and_march` function, this is simple.
Using the `find_triangle` function, this is simple.

````@example point_location
V = jump_and_march(tri, q)
V = find_triangle(tri, q)
````

The result means that the triangle `(2, 7, 6)` contains the point, as we can easily check:
Expand All @@ -49,13 +49,13 @@ The result means that the triangle `(2, 7, 6)` contains the point, as we can eas
DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)
````

When we provide no keyword arguments, the default behaviour of `jump_and_march` is to first
When we provide no keyword arguments, the default behaviour of `find_triangle` is to first
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,

````@example point_location
V = jump_and_march(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.
Expand All @@ -64,12 +64,12 @@ You could also instead specify the point to start at using the `k` keyword argum
For example,

````@example point_location
V = jump_and_march(tri, q, k=6)
V = find_triangle(tri, q, k=6)
````

starts the algorithm at the point `6`.

Note also that the triangles found from `jump_and_march` do not have to be given in the same order as they appear
Note also that the triangles found from `find_triangle` do not have to be given in the same order as they appear
in the triangulation. For example, if a triangle `(i, j, k)` contains the point `q`, then any of `(i, j, k)`, `(j, k, i)`,
or `(k, i, j)` could be returned.

Expand All @@ -85,7 +85,7 @@ fig
We obtain:

````@example point_location
V = jump_and_march(tri, q)
V = find_triangle(tri, q)
````

See that the result is a ghost triangle `(1, 5, -1)`. As discussed in the [manual](../manual/ghost_triangles.md),
Expand Down Expand Up @@ -149,7 +149,7 @@ fig
Now let's find the triangles.

````@example point_location
Vs = [jump_and_march(tri, q; rng) for q in qs]
Vs = [find_triangle(tri, q; rng) for q in qs]
````

While we do find some triangles, they may not all be correct. For example,
Expand All @@ -160,10 +160,10 @@ Vs[end]
````

but the point `(1.2, 1.6)` is actually inside the triangulation. We can even see
this if we run `jump_and_march` again:
this if we run `find_triangle` again:

````@example point_location
V = jump_and_march(tri, (1.2, 1.6); rng)
V = find_triangle(tri, (1.2, 1.6); rng)
````

To protect against this, you need to use `concavity_protection=true`, which
Expand All @@ -172,7 +172,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 = [jump_and_march(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
Expand Down Expand Up @@ -202,7 +202,7 @@ As we see, the triangles are now all correct.
## Disjoint domains
Now we continue the previous example by adding in another set of
domains that are disjoint to the current domain, thus allowing us to
demonstrate how `jump_and_march` applies here. The new domain is below,
demonstrate how `find_triangle` applies here. The new domain is below,
along with the points we will be searching for.

````@example point_location
Expand All @@ -229,10 +229,10 @@ scatter!(ax, qs, color=:blue, markersize=16)
fig
````

Here are the `jump_and_march` results.
Here are the `find_triangle` results.

````@example point_location
Vs = [jump_and_march(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`,
Expand Down Expand Up @@ -274,20 +274,20 @@ fig, ax, sc = triplot(tri)
scatter!(ax, q)
fig

V = jump_and_march(tri, q)
V = find_triangle(tri, q)

DelaunayTriangulation.point_position_relative_to_triangle(tri, V, q)

V = jump_and_march(tri, q, m=10)
V = find_triangle(tri, q, m=10)

V = jump_and_march(tri, q, k=6)
V = find_triangle(tri, q, k=6)

q = (-5.0, 8.0)
fig, ax, sc = triplot(tri)
scatter!(ax, q)
fig

V = jump_and_march(tri, q)
V = find_triangle(tri, q)

fig, ax, sc = triplot(tri, show_ghost_edges=true)
scatter!(ax, q)
Expand Down Expand Up @@ -321,13 +321,13 @@ fig, ax, sc = triplot(tri, show_ghost_edges=false)
scatter!(ax, qs, color=:blue, markersize=16)
fig

Vs = [jump_and_march(tri, q; rng) for q in qs]
Vs = [find_triangle(tri, q; rng) for q in qs]

Vs[end]

V = jump_and_march(tri, (1.2, 1.6); rng)
V = find_triangle(tri, (1.2, 1.6); rng)

Vs = [jump_and_march(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))
Expand Down Expand Up @@ -365,7 +365,7 @@ fig, ax, sc = triplot(tri)
scatter!(ax, qs, color=:blue, markersize=16)
fig

Vs = [jump_and_march(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))
Expand Down
3 changes: 3 additions & 0 deletions src/DelaunayTriangulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ include("algorithms/voronoi/unbounded.jl")

include("validation.jl")

const jump_and_march = find_triangle # Remove in 2.0

export
each_triangle,
each_solid_triangle,
Expand Down Expand Up @@ -257,6 +259,7 @@ export
triangulate_rectangle,
triangulate_convex,
brute_force_search,
find_triangle,
jump_and_march,
convert_boundary_points_to_indices,
refine!,
Expand Down
2 changes: 1 addition & 1 deletion src/algorithms/point_location/brute_force.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ end
Searches for the triangle containing the point `q` by brute force. An exception will be
raised if no triangle contains the point.
See also [`jump_and_march`](@ref).
See also [`find_triangle`](@ref).
# Arguments
- `tri::Triangulation`: The [`Triangulation`](@ref).
Expand Down
Loading

0 comments on commit 6e940b4

Please sign in to comment.