Visual Computing Library  devel
Loading...
Searching...
No Matches
distance.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_CORE_DISTANCE_DISTANCE_H
24#define VCL_ALGORITHMS_CORE_DISTANCE_DISTANCE_H
25
26#include <vclib/algorithms/core/bounding_box.h>
27
28#include <vclib/space/core.h>
29
30namespace vcl {
31
44template<PointConcept PointType>
45auto distance(const PointType& point0, const PointType& point1)
46{
47 return point0.dist(point1);
48}
49
67template<Point3Concept PointType, PlaneConcept PlaneType>
69 const PointType& point,
70 const PlaneType& plane,
71 bool signedDist = false)
72{
73 auto dist = plane.direction().dot(point) - plane.offset();
74 if (!signedDist)
75 dist = std::abs(dist);
76 return dist;
77}
78
84template<PlaneConcept PlaneType, Point3Concept PointType>
86 const PlaneType& plane,
87 const PointType& point,
88 bool signedDist = false)
89{
90 return distance(point, plane, signedDist);
91}
92
110template<PointConcept PointType, SegmentConcept SegmentType>
112 const PointType& point,
113 const SegmentType& segment,
114 PointType& closestPoint) requires (PointType::DIM == SegmentType::DIM)
115{
116 using ScalarType = PointType::ScalarType;
117
118 ScalarType dist;
119
120 PointType dir = segment.direction();
121 ScalarType esn = dir.squaredNorm();
122
123 if (esn < std::numeric_limits<ScalarType>::min()) {
124 closestPoint = segment.midPoint();
125 }
126 else {
127 ScalarType t = ((point - segment.p0()).dot(dir)) / esn;
128 if (t < 0)
129 t = 0;
130 else if (t > 1)
131 t = 1;
132
133 closestPoint = segment.p0() * (1 - t) + segment.p1() * t;
134 }
135 dist = point.dist(closestPoint);
136 return dist;
137}
138
153template<PointConcept PointType, SegmentConcept SegmentType>
154auto distance(const PointType& point, const SegmentType& segment)
155 requires (PointType::DIM == SegmentType::DIM)
156{
157 PointType closestPoint;
158 return distance(point, segment, closestPoint);
159}
160
166template<SegmentConcept SegmentType, PointConcept PointType>
167auto distance(const SegmentType& segment, const PointType& point)
168 requires (PointType::DIM == SegmentType::DIM)
169{
170 return distance(point, segment);
171}
172
199template<
200 Point3Concept PointType,
201 Triangle3Concept TriangleType,
202 typename ScalarType>
204 const PointType& p,
205 const TriangleType& triangle,
206 ScalarType maxDist,
207 PointType& closest,
208 bool signedDist = false)
209{
210 using TPointType = TriangleType::PointType;
211
212 ScalarType dist;
213
214 // Extract the positions of the vertices of the face.
215 const TPointType& tp0 = triangle.point(0);
216 const TPointType& tp1 = triangle.point(1);
217 const TPointType& tp2 = triangle.point(2);
218
219 // If the face is degenerate (i.e. its normal vector has zero length),
220 // consider it as a segment.
221 if (triangle.normal().norm() == 0) {
222 // Calculate the bounding box of the face.
225 // If the diagonal of the bounding box is greater than zero, calculate
226 // the distance between the query point and the segment.
227 if (box.diagonal() > 0) {
228 dist = distance(p, s, closest);
229 }
230 else {
231 // If the diagonal of the bounding box is zero, set the closest
232 // point to be the minimum corner of the bounding box and calculate
233 // the distance between the query point and this point.
234 closest = box.min();
235 dist = p.dist(closest);
236 }
237 }
238 else {
239 // Calculate the distance between the query point and the plane of the
240 // triangle.
242 dist = distance(p, fPlane, true);
243
244 if (std::abs(dist) >= maxDist)
245 return std::abs(dist);
246
247 // Project the query point onto the triangle plane to obtain the closest
248 // point on the triangle.
249 closest = p - fPlane.direction() * dist;
250
251 // Calculate the three edges of the triangle.
253 fEdge[0] = tp1 - tp0;
254 fEdge[1] = tp2 - tp1;
255 fEdge[2] = tp0 - tp2;
256
257 // Determine the best axis to use for projection by finding the axis
258 // with the largest component of the normal vector.
259 int bestAxis;
260 if (std::abs(triangle.normal()[0]) > std::abs(triangle.normal()[1])) {
261 if (std::abs(triangle.normal()[0]) > std::abs(triangle.normal()[2]))
262 bestAxis = 0;
263 else
264 bestAxis = 2;
265 }
266 else {
267 if (std::abs(triangle.normal()[1]) > std::abs(triangle.normal()[2]))
268 bestAxis = 1; /* 1 > 0 ? 2 */
269 else
270 bestAxis = 2; /* 2 > 1 ? 2 */
271 }
272
273 // Scale the edges by the inverse of the projection direction on the
274 // best axis.
275 ScalarType scaleFactor = 1 / fPlane.direction()[bestAxis];
276 fEdge[0] *= scaleFactor;
277 fEdge[1] *= scaleFactor;
278 fEdge[2] *= scaleFactor;
279
280 // Compute barycentric coordinates of closest point
281 ScalarType b0, b1, b2;
282 int ba = (bestAxis + 2) % 3;
283 int bb = (bestAxis + 1) % 3;
284
286 b0 = fEdge[1][bb] * (closest[ba] - tp1[ba]) -
287 fEdge[1][ba] * (closest[bb] - tp1[bb]);
288 if (b0 <= 0) {
289 return distance(p, s0, closest);
290 }
291 b1 = fEdge[2][bb] * (closest[ba] - tp2[ba]) -
292 fEdge[2][ba] * (closest[bb] - tp2[bb]);
293 if (b1 <= 0) {
294 return distance(p, s1, closest);
295 }
296 b2 = fEdge[0][bb] * (closest[ba] - tp0[ba]) -
297 fEdge[0][ba] * (closest[bb] - tp0[bb]);
298 if (b2 <= 0) {
299 return distance(p, s2, closest);
300 }
301
302 const ScalarType EPS = ScalarType(0.000001);
303 ScalarType b = min(b0, b1, b2);
304 if (b < EPS * triangle.area()) {
305 ScalarType bt;
306 if (b == b0)
307 bt = distance(p, s0, closest);
308 else if (b == b1)
309 bt = distance(p, s1, closest);
310 else {
311 assert(b == b2);
312 bt = distance(p, s2, closest);
313 }
314 dist = bt;
315 }
316
317 if (!signedDist)
318 dist = std::abs(dist);
319 }
320
321 return dist;
322}
323
341template<
342 Point3Concept PointType,
343 Triangle3Concept TriangleType,
344 typename ScalarType>
346 const PointType& p,
347 const TriangleType& triangle,
348 ScalarType maxDist,
349 bool signedDist = false)
350{
351 PointType closest;
352 return boundedDistance(p, triangle, maxDist, closest, signedDist);
353}
354
370template<
371 Point3Concept PointType,
372 Triangle3Concept TriangleType,
373 typename ScalarType>
375 const PointType& p,
376 const TriangleType& triangle,
377 PointType& closest,
378 bool signedDist = false)
379{
380 ScalarType maxDist = std::numeric_limits<ScalarType>::max();
381 return boundedDistance(p, triangle, maxDist, closest, signedDist);
382}
383
398template<
399 Point3Concept PointType,
400 Triangle3Concept TriangleType,
401 typename ScalarType>
403 const PointType& p,
404 const TriangleType& triangle,
405 bool signedDist = false)
406{
407 PointType closest;
408
409 ScalarType maxDist = std::numeric_limits<ScalarType>::max();
410 return boundedDistance(p, triangle, maxDist, closest, signedDist);
411}
412
418template<
419 Triangle3Concept TriangleType,
420 Point3Concept PointType,
421 typename ScalarType>
423 const TriangleType& triangle,
424 const PointType& p,
425 bool signedDist = false)
426{
427 return distance(p, triangle, signedDist);
428}
429
430} // namespace vcl
431
432#endif // VCL_ALGORITHMS_CORE_DISTANCE_DISTANCE_H
A class representing a box in N-dimensional space.
Definition box.h:46
auto diagonal() const
Calculates the diagonal length of the box.
Definition box.h:246
PointT & max()
Returns a reference to the maximum point of the box.
Definition box.h:104
PointT & min()
Returns a reference to the minimum point of the box.
Definition box.h:90
constexpr auto min(const T &p1, const T &p2)
Returns the minimum between the two parameters.
Definition min_max.h:40
auto boundingBox(const PointType &p)
Compute the bounding box of a single point.
Definition bounding_box.h:59
auto boundedDistance(const PointType &p, const TriangleType &triangle, ScalarType maxDist, PointType &closest, bool signedDist=false)
Compute the bounded distance between a 3D point and a 3D triangle.
Definition distance.h:203
auto distance(const PointType &point0, const PointType &point1)
Compute the distance between two Points of any dimension.
Definition distance.h:45