Add intersection Tetrahedron_3 / Segment_3

This commit is contained in:
Maxime Gimeno 2019-06-04 16:17:17 +02:00
parent 469ed5396b
commit 9cb1173a41
4 changed files with 181 additions and 6 deletions

View File

@ -40,7 +40,6 @@ CGAL_INTERSECTION_TRAITS_2(Segment_3, Line_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Line_3, Triangle_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Line_3, Tetrahedron_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Tetrahedron_3, Line_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Triangle_3, Line_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Plane_3, Plane_3, Line_3, Plane_3)
@ -68,10 +67,15 @@ CGAL_INTERSECTION_TRAITS_2(Triangle_3, Ray_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Segment_3, Segment_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Segment_3, Triangle_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Segment_3, Tetrahedron_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Triangle_3, Segment_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_3(Sphere_3, Sphere_3, Point_3, Circle_3, Sphere_3)
CGAL_INTERSECTION_TRAITS_2(Tetrahedron_3, Line_3, Point_3, Segment_3)
CGAL_INTERSECTION_TRAITS_2(Tetrahedron_3, Segment_3, Point_3, Segment_3)
template<typename K>
struct Intersection_traits<K, typename K::Triangle_3, typename K::Triangle_3> {
typedef typename

View File

@ -27,9 +27,11 @@
#include <CGAL/Tetrahedron_3.h>
#include <CGAL/Intersections_3/internal/Tetrahedron_3_Bounded_3_do_intersect.h>
#include <CGAL/Intersections_3/internal/Tetrahedron_3_Segment_3_intersections.h>
namespace CGAL {
CGAL_DO_INTERSECT_FUNCTION(Segment_3, Tetrahedron_3, 3)
CGAL_INTERSECTION_FUNCTION(Segment_3, Tetrahedron_3, 3)
}
#endif // CGAL_INTERSECTIONS_3_SEGMENT_3_TETRAHEDRON_3_H

View File

@ -0,0 +1,150 @@
// Copyright (c) 2019 GeometryFactory(France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
//
// Author(s) : Maxime Gimeno
//
#ifndef CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_Segment_3_INTERSECTION_H
#define CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_Segment_3_INTERSECTION_H
#include <CGAL/kernel_basic.h>
#include <CGAL/intersections.h>
namespace CGAL {
namespace Intersections {
namespace internal {
//Tetrahedron_3 Segment_3
template <class K>
typename Intersection_traits<K, typename K::Tetrahedron_3, typename K::Segment_3>::result_type
intersection(
const typename K::Tetrahedron_3 &tet,
const typename K::Segment_3 &seg,
const K&)
{
typedef typename Intersection_traits<K,
typename K::Tetrahedron_3,
typename K::Segment_3>::result_type Result_type;
typedef typename Intersection_traits<K,
typename K::Triangle_3,
typename K::Segment_3>::result_type Inter_type;
//if both segment extremities are inside tet, return the input segment.
if(tet.has_on_bounded_side(seg.source())
&& tet.has_on_bounded_side(seg.target())){
typename K::Segment_3 result = seg;
return Result_type(std::forward<typename K::Segment_3>(result));
}
int res_id = -1;
Inter_type tr_seg[4];
for(std::size_t i = 0; i < 4; ++i)
{
const typename K::Triangle_3 triangle(tet.vertex((i+1)%4),
tet.vertex((i+2)%4),
tet.vertex((i+3)%4));
tr_seg[i] = CGAL::intersection(seg, triangle);
if(tr_seg[i])
if( boost::get<typename K::Segment_3>(&*tr_seg[i]) != nullptr)
res_id = i;
}
//if there is a segment in the intersections, then we return it
if(res_id !=-1)
return tr_seg[res_id];
//else if there is only 1 intersection
std::vector<typename K::Point_3> res_points;
res_points.reserve(4);
res_id = -1;
for(std::size_t i = 0; i< 4; ++i)
{
if(tr_seg[i])
{
if (const typename K::Point_3* p = boost::get<typename K::Point_3>(&*tr_seg[i]))
{
if(res_points.empty())
{
res_id = i;
}
else {
if(*p != res_points.front())
{
res_id = -1;
}
}
res_points.push_back(*p);
}
}
}
if(res_id != -1)
{
//If one extremity is inside tet : return a segment
if(tet.has_on_bounded_side(seg.source()))
{
typename K::Segment_3 result(seg.source(), res_points.front());
return Result_type(std::forward<typename K::Segment_3>(result));
}
else if(tet.has_on_bounded_side(seg.target())){
typename K::Segment_3 result(res_points.front(), seg.target());
return Result_type(std::forward<typename K::Segment_3>(result));
}
//else point and segment entirely not inside:
return tr_seg[res_id];
}
//else, we return a segment of the 2 intersection points (the most far away, in case of inexact)
typename K::FT max_dist = 0;
std::size_t res_id_2 = -1;
std::vector<std::vector<typename K::FT> > sq_distances(res_points.size());
for(std::size_t i = 0; i< res_points.size(); ++i)
{
auto p1 = res_points[i];
for(auto p2 : res_points)
{
sq_distances[i].push_back(CGAL::squared_distance(p1, p2));
if(sq_distances[i].back() > max_dist)
{
res_id = i;
res_id_2 = sq_distances[i].size()-1;
max_dist = sq_distances[i].back();
}
}
}
CGAL_assertion(res_id != -1);
CGAL_assertion(res_id_2 != -1);
CGAL_assertion(max_dist >0 );
typename K::Segment_3 res_seg(res_points[res_id], res_points[res_id_2]);
return Result_type(std::forward<typename K::Segment_3>(res_seg));
}
template <class K>
typename Intersection_traits<K, typename K::Tetrahedron_3, typename K::Segment_3>::result_type
intersection(
const typename K::Segment_3 &seg,
const typename K::Tetrahedron_3 &tet,
const K& k)
{
return intersection(tet, seg, k);
}
}}}
#endif // CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_Segment_3_INTERSECTION_H

View File

@ -134,6 +134,7 @@ struct Test {
Res tmp;
assert(CGAL::do_intersect(o1, o2));
assert(CGAL::assign(tmp, CGAL::intersection(o1, o2)));
std::cout<<tmp<<std::endl;
assert(approx_equal(tmp, result));
if (do_opposite) {
assert(CGAL::do_intersect(o2, o1));
@ -569,8 +570,6 @@ struct Test {
{
std::cout << "Tetrahedron_3 - Line_3\n";
//check_intersection (S(P(-3,0,0),P(3,0,0)),R(P(3,-2,0),P(3,0,0)),P(3,0,0));
//check_no_intersection (S(P(-3,0,0),P(3,0,0)),R(P(0,-1,0),P(0,-2,0)));
Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1));
check_no_intersection (tet, L(P(5,0,0), P(5,1,0)));
check_intersection (tet, L(P(0,2,0), P(0,3,0)), S(P(0,0,0), P(0,1,0)));
@ -579,11 +578,27 @@ struct Test {
}
void Tet_S()
{
std::cout << "Tetrahedron_3 - Segment_3\n";
Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1));
check_no_intersection (tet, L(P(5,0,0), P(5,1,0)));
check_intersection (tet, S(P(0,2,0), P(0,-2,0)), S(P(0,1,0), P(0,0,0)));
check_intersection (tet, S(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25)));
check_intersection (tet, S(P(2,1,0), P(-2,1,0)), P(0,1,0));
check_intersection (tet, S(P(0.1,0.1,0.1), P(0.2,0.2,0.2)), S(P(0.1,0.1,0.1), P(0.2,0.2,0.2)));
typename K::FT coord = 1.0/3.0;
check_intersection (tet, S(P(0.25,0.25,0.25), P(2,2,2)), S(P(0.25,0.25,0.25), P(coord, coord, coord)));
}
void run(bool is_exact = false)
{
std::cout << "3D Intersection tests\n";
P_do_intersect();
Cub_Cub();
/* Cub_Cub();
L_Cub();
Pl_L();
Pl_Pl();
@ -596,12 +611,16 @@ struct Test {
S_L();
R_L();
R_S();
R_R();
if(is_exact)
R_R();*/
if(is_exact){
Tet_L();
Tet_S();
}
/*
Bbox_L();
Bbox_R();
Bbox_Tr();
*/
}
};