40 #include <geogram/mesh/mesh.h> 55 const Geometry::Point3D& point,
56 const Geometry::Triangle3D& triangle )
58 const vec3& V0 = triangle.p0;
59 const vec3& V1 = triangle.p1;
60 const vec3& V2 = triangle.p2;
61 vec3 diff{ V0 - point };
62 vec3 edge0{ V1 - V0 };
63 vec3 edge1{ V2 - V0 };
64 double a00{ length2( edge0 ) };
65 double a01{ dot( edge0, edge1 ) };
66 double a11{ length2( edge1 ) };
67 double b0{ dot( diff, edge0 ) };
68 double b1{ dot( diff, edge1 ) };
69 double c{ length2( diff ) };
70 double det{ std::fabs( a00 * a11 - a01 * a01 ) };
71 double s{ a01 * b1 - a11 * b0 };
72 double t{ a01 * b0 - a00 * b1 };
87 sqrDistance = a00 + 2.0 * b0 + c;
92 sqrDistance = b0 * s + c;
103 else if( -b1 >= a11 )
106 sqrDistance = a11 + 2.0 * b1 + c;
111 sqrDistance = b1 * t + c;
123 else if( -b1 >= a11 )
126 sqrDistance = a11 + 2.0 * b1 + c;
131 sqrDistance = b1 * t + c;
143 else if( -b0 >= a00 )
146 sqrDistance = a00 + 2.0 * b0 + c;
151 sqrDistance = b0 * s + c;
157 double invDet =
double( 1.0 ) / det;
160 sqrDistance = s * ( a00 * s + a01 * t + 2.0 * b0 )
161 + t * ( a01 * s + a11 * t + 2.0 * b1 ) + c;
166 double tmp0, tmp1, numer, denom;
175 denom = a00 - 2.0 * a01 + a11;
180 sqrDistance = a00 + 2.0 * b0 + c;
186 sqrDistance = s * ( a00 * s + a01 * t + 2.0 * b0 )
187 + t * ( a01 * s + a11 * t + 2.0 * b1 )
197 sqrDistance = a11 + 2.0 * b1 + c;
207 sqrDistance = b1 * t + c;
218 denom = a00 - 2.0 * a01 + a11;
223 sqrDistance = a11 + 2.0 * b1 + c;
229 sqrDistance = s * ( a00 * s + a01 * t + 2.0 * b0 )
230 + t * ( a01 * s + a11 * t + 2.0 * b1 )
240 sqrDistance = a00 + 2.0 * b0 + c;
250 sqrDistance = b0 * s + c;
256 numer = a11 + b1 - a01 - b0;
261 sqrDistance = a11 + 2.0 * b1 + c;
265 denom = a00 - 2.0 * a01 + a11;
270 sqrDistance = a00 + 2.0 * b0 + c;
276 sqrDistance = s * ( a00 * s + a01 * t + 2.0 * b0 )
277 + t * ( a01 * s + a11 * t + 2.0 * b1 )
285 if( sqrDistance < 0.0 )
290 vec3 closest_point{ V0 + s * edge0 + t * edge1 };
291 return std::make_tuple( std::sqrt( sqrDistance ), closest_point );
296 const Geometry::Point2D& point,
const Geometry::Segment2D& segment )
301 vec2 direction = segment.p1 - segment.p0;
302 vec2 diff = point - segment.p1;
303 double t = dot( direction, diff );
305 if( t >= global_epsilon )
307 nearest_p = segment.p1;
311 diff = point - segment.p0;
312 t = dot( direction, diff );
313 if( t <= global_epsilon )
315 nearest_p = segment.p0;
319 double sqrLength = dot( direction, direction );
320 if( sqrLength > global_epsilon )
323 nearest_p = segment.p0 + t * direction;
327 nearest_p = segment.p0;
332 diff = point - nearest_p;
333 return std::make_tuple( std::sqrt( dot( diff, diff ) ), nearest_p );
338 const Geometry::Point2D& point,
339 const Geometry::Triangle2D& triangle )
345 closest_point = point;
350 std::array< vec2, 3 > closest;
351 std::array< double, 3 > distance;
353 point, Geometry::Segment2D{ triangle.p0, triangle.p1 } );
355 point, Geometry::Segment2D{ triangle.p1, triangle.p2 } );
357 point, Geometry::Segment2D{ triangle.p2, triangle.p0 } );
358 if( distance[0] < distance[1] )
360 if( distance[0] < distance[2] )
362 result = distance[0];
363 closest_point = closest[0];
367 result = distance[2];
368 closest_point = closest[2];
373 if( distance[1] < distance[2] )
375 result = distance[1];
376 closest_point = closest[1];
380 result = distance[2];
381 closest_point = closest[2];
385 return std::make_tuple( result, closest_point );
391 std::array< vec3, 4 > vertices{ { tetra.
p0, tetra.
p1, tetra.
p2,
393 double dist{ max_float64() };
396 range( GEO::MeshCellDescriptors::tet_descriptor.nb_facets ) )
398 double distance{ max_float64() };
401 point, Geometry::Triangle3D{
402 vertices[GEO::MeshCellDescriptors::tet_descriptor
403 .facet_vertex[f][0]],
404 vertices[GEO::MeshCellDescriptors::tet_descriptor
405 .facet_vertex[f][1]],
406 vertices[GEO::MeshCellDescriptors::tet_descriptor
407 .facet_vertex[f][2]] } );
408 if( distance < dist )
414 return std::make_tuple( dist, nearest_p );
419 const Geometry::Point3D& point,
const Geometry::Segment3D& segment )
421 bool can_point_be_projected;
423 std::tie( can_point_be_projected, nearest_p ) =
425 if( can_point_be_projected )
427 return std::make_tuple(
428 length( nearest_p - point ), nearest_p );
430 double p0_sq{ length2( segment.p0 - point ) };
431 double p1_sq{ length2( segment.p1 - point ) };
434 return std::make_tuple( std::sqrt( p0_sq ), segment.p0 );
436 return std::make_tuple( std::sqrt( p1_sq ), segment.p1 );
443 double distance{ dot( v, plane.
normal ) };
444 vec3 projected_p{ point - distance * plane.
normal };
445 return std::make_tuple( distance, projected_p );
std::tuple< bool, vecn< DIMENSION > > point_segment_projection(const vecn< DIMENSION > &p, const vecn< DIMENSION > &p0, const vecn< DIMENSION > &p1)
std::tuple< double, vec3 > RINGMESH_API point_to_tetra(const Geometry::Point3D &point, const Geometry::Tetra &tetra)
std::tuple< double, vecn< DIMENSION > > point_to_triangle(const Geometry::Point< DIMENSION > &point, const Geometry::Triangle< DIMENSION > &triangle)
std::tuple< double, vec3 > RINGMESH_API point_to_plane(const Geometry::Point3D &point, const Geometry::Plane &plane)
bool point_inside_triangle(const Geometry::Point< DIMENSION > &point, const Geometry::Triangle< DIMENSION > &triangle)
Tests if a point is inside a triangle.
Classes to build GeoModel from various inputs.
std::tuple< double, vecn< DIMENSION > > point_to_segment(const Geometry::Point< DIMENSION > &point, const Geometry::Segment< DIMENSION > &segment)