47 namespace Intersection
52 bool does_plane_intersect_plane;
53 Geometry::Line3D inter;
54 std::tie( does_plane_intersect_plane, inter ) =
56 if( !does_plane_intersect_plane )
58 return std::make_tuple(
false, std::vector< vec3 >() );
70 double a1{ dot( diff, inter.direction ) };
71 double a0{ diff.length2() - circle.
radius * circle.
radius };
73 double discr{ a1 * a1 - a0 };
76 return std::make_tuple(
false, std::vector< vec3 >() );
79 std::vector< vec3 > result;
80 if( discr < global_epsilon )
82 result.emplace_back( inter.origin - a1 * inter.direction );
86 double root{ std::sqrt( discr ) };
88 inter.origin - ( a1 + root ) * inter.direction );
90 inter.origin - ( a1 - root ) * inter.direction );
92 return std::make_tuple(
true, result );
120 if( std::fabs( std::fabs( norm_d ) - 1 ) < global_epsilon )
122 return std::make_tuple(
false, Geometry::Line3D{} );
125 double invDet{ 1.0 / ( 1.0 - norm_d * norm_d ) };
128 double c0{ ( const_P0 - norm_d * const_P1 ) * invDet };
129 double c1{ ( const_P1 - norm_d * const_P0 ) * invDet };
132 return std::make_tuple(
133 true, Geometry::Line3D{ D_inter, O_inter } );
137 const Geometry::Line2D& line0,
const Geometry::Line2D& line1 )
150 vec2 diff{ line1.origin - line0.origin };
151 double D0DotPerpD1{
dot_perp( line0.direction, line1.direction ) };
152 if( std::fabs( D0DotPerpD1 ) < global_epsilon )
155 return std::make_tuple(
false,
vec2() );
158 double invD0DotPerpD1{ 1.0 / D0DotPerpD1 };
159 double diffDotPerpD1{
dot_perp( diff, line1.direction ) };
160 double s0{ diffDotPerpD1 * invD0DotPerpD1 };
161 vec2 result{ line0.origin + s0 * line0.direction };
162 return std::make_tuple(
true, result );
166 const Geometry::Segment2D& segment0,
167 const Geometry::Segment2D& segment1 )
169 bool does_segment_intersect_segment;
170 vec2 line_intersection_result;
172 does_segment_intersect_segment, line_intersection_result ) =
174 Geometry::Line2D{ segment1 } );
175 if( does_segment_intersect_segment )
179 segment0.p0, segment1 ) };
181 segment0.p1, segment1 ) };
182 if( s0_seg0 !=
ZERO && ( s0_seg0 == s1_seg0 ) )
184 return std::make_tuple(
false,
vec2() );
187 segment1.p0, segment0 ) };
189 segment1.p1, segment0 ) };
190 if( s0_seg1 !=
ZERO && ( s0_seg1 == s1_seg1 ) )
192 return std::make_tuple(
false,
vec2() );
195 if( s0_seg0 ==
ZERO || s1_seg0 ==
ZERO 196 || ( s0_seg0 != s1_seg0 ) )
198 if( s0_seg1 ==
ZERO || s1_seg1 ==
ZERO 199 || ( s0_seg1 != s1_seg1 ) )
201 return std::make_tuple(
202 true, line_intersection_result );
206 return std::make_tuple(
false,
vec2() );
210 const Geometry::Segment2D& segment,
const Geometry::Line2D& line )
212 bool does_segment_intersect_line;
213 vec2 line_intersection_result;
214 std::tie( does_segment_intersect_line, line_intersection_result ) =
215 line_line( Geometry::Line2D{ segment }, line );
216 if( does_segment_intersect_line )
219 Geometry::Segment2D line_segment{ { line_intersection_result
221 { line_intersection_result + line.direction } };
223 segment.p0, line_segment ) };
225 segment.p1, line_segment ) };
226 if( s0 ==
ZERO || s1 ==
ZERO || ( s0 != s1 ) )
228 return std::make_tuple(
true, line_intersection_result );
231 return std::make_tuple(
false,
vec2() );
237 double dot_directions{ dot( line.direction, plane.
normal ) };
238 if( std::fabs( dot_directions ) > global_epsilon )
240 double signed_distance{ dot( plane.
normal, line.origin )
242 vec3 result{ line.origin
243 - signed_distance * line.direction
245 return std::make_tuple(
true, result );
248 return std::make_tuple(
false,
vec3() );
254 bool does_line_intersect_plane;
255 vec3 line_plane_result;
256 std::tie( does_line_intersect_plane, line_plane_result ) =
257 line_plane( Geometry::Line3D{ segment }, plane );
258 if( does_line_intersect_plane )
261 line_plane_result, segment ) )
264 return std::make_tuple(
true, line_plane_result );
266 return std::make_tuple(
false,
vec3() );
268 return std::make_tuple(
false,
vec3() );
274 bool does_segment_intersect_plane{
false };
275 vec3 segment_plane_result;
276 std::tie( does_segment_intersect_plane, segment_plane_result ) =
278 if( does_segment_intersect_plane )
280 if( ( segment_plane_result - disk.
plane.
origin ).length()
283 return std::make_tuple(
true, segment_plane_result );
286 return std::make_tuple(
false,
vec3() );
290 const Geometry::Triangle3D& triangle,
293 bool does_circle_intersect_plane{
false };
294 std::vector< vec3 > inter_circle_plane;
295 std::tie( does_circle_intersect_plane, inter_circle_plane ) =
297 std::vector< vec3 > result;
298 if( does_circle_intersect_plane )
300 for(
const vec3& p : inter_circle_plane )
304 result.push_back( p );
308 return std::make_tuple( !result.empty(), result );
312 const Geometry::Segment3D& segment,
313 const Geometry::Triangle3D& triangle )
317 vec3 seg_center{ segment.barycenter() };
318 vec3 diff{ seg_center - triangle.p0 };
319 vec3 edge1{ triangle.p1 - triangle.p0 };
320 vec3 edge2{ triangle.p2 - triangle.p0 };
321 vec3 normal{ cross( edge1, edge2 ) };
328 vec3 D{ segment.direction() };
329 double DdN{ dot( D, normal ) };
331 if( DdN > global_epsilon )
335 else if( DdN < -global_epsilon )
345 return std::make_tuple(
false,
vec3() );
348 double DdQxE2{ sign * dot( D, cross( diff, edge2 ) ) };
351 double DdE1xQ{ sign * dot( D, cross( edge1, diff ) ) };
354 if( DdQxE2 + DdE1xQ <= DdN )
357 double QdN{ -sign * dot( diff, normal ) };
358 double extDdN{ segment.length() * DdN / 2. };
359 if( -extDdN <= QdN && QdN <= extDdN )
362 double inv{ 1. / DdN };
363 double seg_parameter{ QdN * inv };
365 vec3 result{ seg_center + seg_parameter * D };
366 return std::make_tuple(
true, result );
375 return std::make_tuple(
false,
vec3() );
387 double a0{ dot( diff, diff ) - sphere.
radius * sphere.
radius };
388 double a1{ dot( line.direction, diff ) };
391 double discr{ a1 * a1 - a0 };
392 std::vector< vec3 > results;
393 if( discr > global_epsilon )
395 double root{ std::sqrt( discr ) };
396 results.reserve( 2 );
397 results.emplace_back(
398 line.origin + ( -a1 - root ) * line.direction );
399 results.emplace_back(
400 line.origin + ( -a1 + root ) * line.direction );
402 else if( discr > -global_epsilon )
404 results.reserve( 1 );
405 results.emplace_back( line.origin + -a1 * line.direction );
407 return std::make_tuple( !results.empty(), results );
414 std::vector< vec3 > line_intersections;
415 std::tie( line_intersect, line_intersections ) =
416 line_sphere( Geometry::Line3D{ segment }, sphere );
418 std::vector< vec3 > segment_intersections;
421 segment_intersections.reserve( line_intersections.size() );
422 for(
auto& point : line_intersections )
426 segment_intersections.emplace_back( point );
430 return std::make_tuple(
431 !segment_intersections.empty(), segment_intersections );
double RINGMESH_API dot_perp(const vec2 &v0, const vec2 &v1)
bool RINGMESH_API point_inside_segment(const Geometry::Point3D &point, const Geometry::Segment3D &segment)
Tests if a point is on a segment.
std::tuple< bool, vec3 > RINGMESH_API segment_disk(const Geometry::Segment3D &segment, const Geometry::Disk &disk)
std::tuple< bool, vec2 > RINGMESH_API segment_line(const Geometry::Segment2D &segment, const Geometry::Line2D &line)
std::tuple< bool, Geometry::Line3D > RINGMESH_API plane_plane(const Geometry::Plane &plane0, const Geometry::Plane &plane1)
std::tuple< bool, std::vector< vec3 > > RINGMESH_API line_sphere(const Geometry::Line3D &line, const Geometry::Sphere &sphere)
Sign RINGMESH_API point_side_to_segment(const Geometry::Point2D &point, const Geometry::Segment2D &segment)
std::tuple< bool, std::vector< vec3 > > RINGMESH_API triangle_circle(const Geometry::Triangle3D &triangle, const Geometry::Circle &circle)
std::tuple< bool, vec3 > RINGMESH_API segment_plane(const Geometry::Segment3D &segment, const Geometry::Plane &plane)
std::tuple< bool, std::vector< vec3 > > RINGMESH_API segment_sphere(const Geometry::Segment3D &segment, const Geometry::Sphere &sphere)
std::tuple< bool, vec3 > RINGMESH_API segment_triangle(const Geometry::Segment3D &segment, const Geometry::Triangle3D &triangle)
double plane_constant() const
bool point_inside_triangle(const Geometry::Point< DIMENSION > &point, const Geometry::Triangle< DIMENSION > &triangle)
Tests if a point is inside a triangle.
std::tuple< bool, vec2 > RINGMESH_API line_line(const Geometry::Line2D &line0, const Geometry::Line2D &line1)
std::tuple< bool, vec2 > RINGMESH_API segment_segment(const Geometry::Segment2D &segment0, const Geometry::Segment2D &segment1)
Classes to build GeoModel from various inputs.
std::tuple< bool, vec3 > RINGMESH_API line_plane(const Geometry::Line3D &line, const Geometry::Plane &plane)
std::tuple< bool, std::vector< vec3 > > RINGMESH_API circle_plane(const Geometry::Circle &circle, const Geometry::Plane &plane)