From c94b0b6def121ec0c1f1474d455b5af6f172ab15 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Fri, 25 Oct 2024 10:33:12 -0300 Subject: [PATCH 1/3] Add custom 'EuclideanDistance' --- src/Meshes.jl | 4 ++-- src/distances.jl | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/Meshes.jl b/src/Meshes.jl index 02514fe24..473a0d4fc 100644 --- a/src/Meshes.jl +++ b/src/Meshes.jl @@ -17,7 +17,6 @@ using Unitful: AbstractQuantity, numtype using StatsBase: AbstractWeights, Weights, quantile using Distances: PreMetric, Euclidean, Mahalanobis using Distances: Haversine, SphericalAngle -using Distances: evaluate, result_type using Rotations: Rotation, QuatRotation, Angle2d using Rotations: rotation_between using CoordRefSystems: Basic, Projected, Geographic @@ -37,7 +36,7 @@ import Base: ==, ! import Base: +, -, * import Base: <, >, ≤, ≥ import StatsBase: sample -import Distances: evaluate +import Distances: evaluate, result_type import NearestNeighbors: MinkowskiMetric # Transforms API @@ -558,6 +557,7 @@ export measurematrix, adjacencymatrix, atol, + EuclideanDistance, # visualization viz, diff --git a/src/distances.jl b/src/distances.jl index 569f063c6..eb1618c34 100644 --- a/src/distances.jl +++ b/src/distances.jl @@ -5,6 +5,51 @@ # flip arguments so that points always come first evaluate(d::PreMetric, g::Geometry, p::Point) = evaluate(d, p, g) +# ---------- +# EUCLIDEAN +# ---------- + +struct EuclideanDistance <: MinkowskiMetric end + +# Distances.jl interface +result_type(::EuclideanDistance, ::Type{T₁}, ::Type{T₂}) where {T₁,T₂} = float(promote_type(T₁, T₂)) + +@propagate_inbounds function (d::EuclideanDistance)(a, b) + @boundscheck if length(a) ≠ length(b) + throw( + DimensionMismatch( + "first collection has length $(length(a)) which does not match the length of the second, $(length(b))." + ) + ) + end + norm((bᵢ - aᵢ) for (aᵢ, bᵢ) in zip(a, b)) +end + +# implementations for geometries +(d::EuclideanDistance)(p₁::Point, p₂::Point) = norm(p₂ - p₁) + +function (d::EuclideanDistance)(p::Point, l::Line) + a, b = l(0), l(1) + u = p - a + v = b - a + α = (u ⋅ v) / (v ⋅ v) + norm(u - α * v) +end + +(d::EuclideanDistance)(l::Line, p::Point) = d(p, l) + +function (d::EuclideanDistance)(l₁::Line, l₂::Line) + λ₁, λ₂, r, rₐ = intersectparameters(l₁(0), l₁(1), l₂(0), l₂(1)) + + if (r == rₐ == 2) || (r == rₐ == 1) # lines intersect or are colinear + zero(result_type(d, lentype(l₁), lentype(l₂))) + elseif (r == 1) && (rₐ == 2) # lines are parallel + d(l₁(0), l₂) + else # get distance between closest points on each line + d(l₁(λ₁), l₂(λ₂)) + end +end + """ evaluate(distance::Euclidean, point, line) From 35cce99b2a9dc802b6aed42b61406b53b64dfa8f Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Fri, 25 Oct 2024 10:43:58 -0300 Subject: [PATCH 2/3] Remove unused code --- src/Meshes.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Meshes.jl b/src/Meshes.jl index 473a0d4fc..98d879bb9 100644 --- a/src/Meshes.jl +++ b/src/Meshes.jl @@ -37,7 +37,6 @@ import Base: +, -, * import Base: <, >, ≤, ≥ import StatsBase: sample import Distances: evaluate, result_type -import NearestNeighbors: MinkowskiMetric # Transforms API import TransformsBase: Transform, → From bd18907ec4a5b63997f825efa180e9669fa137a1 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Fri, 25 Oct 2024 10:53:07 -0300 Subject: [PATCH 3/3] Update imports --- src/Meshes.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Meshes.jl b/src/Meshes.jl index 98d879bb9..fb3126c55 100644 --- a/src/Meshes.jl +++ b/src/Meshes.jl @@ -15,7 +15,7 @@ using Random using Bessels: gamma using Unitful: AbstractQuantity, numtype using StatsBase: AbstractWeights, Weights, quantile -using Distances: PreMetric, Euclidean, Mahalanobis +using Distances: PreMetric, MinkowskiMetric, Euclidean, Mahalanobis using Distances: Haversine, SphericalAngle using Rotations: Rotation, QuatRotation, Angle2d using Rotations: rotation_between @@ -37,6 +37,7 @@ import Base: +, -, * import Base: <, >, ≤, ≥ import StatsBase: sample import Distances: evaluate, result_type +using NearestNeighbors: eval_pow, eval_diff # Transforms API import TransformsBase: Transform, →