mirror of https://github.com/CGAL/cgal
Merge pull request #5435 from afabri/Intersect_3-fix_isocuboid_plane-GF
Intersect_3: Fix Iso_cuboid_3/Plane_3 and Tetrahedon_/Plane_3 intersection using PMP::clip internal function # Conflicts: # Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h
This commit is contained in:
commit
dcf9dfd0fe
|
|
@ -8,7 +8,7 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Maxime Gimeno
|
||||
// Author(s) : Sebastien Loriot and Andreas Fabri
|
||||
//
|
||||
|
||||
#ifndef CGAL_INTERNAL_INTERSECTIONS_3_ISO_CUBOID_3_PLANE_3_INTERSECTION_H
|
||||
|
|
@ -16,320 +16,195 @@
|
|||
|
||||
#include <CGAL/kernel_basic.h>
|
||||
#include <CGAL/intersections.h>
|
||||
#include <CGAL/utility.h>
|
||||
|
||||
#include <CGAL/Intersections_3/internal/tetrahedron_intersection_helpers.h>
|
||||
#include <CGAL/Intersections_3/Iso_cuboid_3_Segment_3.h>
|
||||
#include <CGAL/Intersections_3/Plane_3_Plane_3.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Intersections {
|
||||
namespace internal {
|
||||
|
||||
template<typename Point>
|
||||
void filter_points(std::vector<Point>& input,
|
||||
std::vector<Point>& output)
|
||||
{
|
||||
std::sort(input.begin(), input.end());
|
||||
auto last = std::unique(input.begin(), input.end());
|
||||
input.erase(last, input.end());
|
||||
output = std::move(input);
|
||||
}
|
||||
|
||||
//Tetrahedron_3 Line_3
|
||||
//Iso_cuboid_3 Plane_3
|
||||
template <class K>
|
||||
typename Intersection_traits<K, typename K::Iso_cuboid_3, typename K::Plane_3>::result_type
|
||||
intersection(
|
||||
const typename K::Iso_cuboid_3 &cub,
|
||||
const typename K::Plane_3 &pl,
|
||||
const K& k)
|
||||
const typename K::Iso_cuboid_3& cub,
|
||||
const typename K::Plane_3& plane,
|
||||
const K& k)
|
||||
{
|
||||
typedef typename K::Point_3 Point_3;
|
||||
typedef typename K::Segment_3 Segment_3;
|
||||
typedef typename K::Line_3 Line_3;
|
||||
typedef typename K::Plane_3 Plane_3;
|
||||
typedef std::vector<Point_3> Poly;
|
||||
typedef typename Intersection_traits<K, typename K::Iso_cuboid_3, typename K::Plane_3>::result_type result_type;
|
||||
typename K::Oriented_side_3 oriented_side = k.oriented_side_3_object();
|
||||
|
||||
typedef typename Intersection_traits<K, CGAL::Iso_cuboid_3<K>,
|
||||
CGAL::Plane_3<K> >::result_type result_type;
|
||||
std::vector<Point_3> corners(8);
|
||||
corners.reserve(14); // 8 corners + up to 6 polygon points
|
||||
corners[0] = cub[0];
|
||||
corners[1] = cub[3];
|
||||
corners[2] = cub[2];
|
||||
corners[3] = cub[1];
|
||||
corners[4] = cub[5];
|
||||
corners[5] = cub[4];
|
||||
corners[6] = cub[7];
|
||||
corners[7] = cub[6];
|
||||
|
||||
typedef typename Intersection_traits<K, CGAL::Segment_3<K>,
|
||||
CGAL::Plane_3<K> >::result_type Inter_type;
|
||||
const std::array<CGAL::Oriented_side, 8> orientations { {
|
||||
oriented_side(plane, corners[0]),
|
||||
oriented_side(plane, corners[1]),
|
||||
oriented_side(plane, corners[2]),
|
||||
oriented_side(plane, corners[3]),
|
||||
oriented_side(plane, corners[4]),
|
||||
oriented_side(plane, corners[5]),
|
||||
oriented_side(plane, corners[6]),
|
||||
oriented_side(plane, corners[7])
|
||||
} };
|
||||
|
||||
std::vector<Segment_3> edges;
|
||||
edges.reserve(12);
|
||||
// description of faces of the bbox
|
||||
constexpr std::array<int, 24> face_indices
|
||||
{ { 0, 1, 2, 3,
|
||||
2, 1, 5, 6,
|
||||
3, 2, 6, 7,
|
||||
1, 0, 4, 5,
|
||||
4, 0, 3, 7,
|
||||
6, 5, 4, 7 } };
|
||||
|
||||
//get all edges of cub
|
||||
for(int i=0; i< 4; ++i)
|
||||
edges.emplace_back(cub.vertex(i), cub.vertex((i+1)%4));
|
||||
for(int i=0; i < 4; ++i)
|
||||
edges.emplace_back(cub.vertex(i+4), cub.vertex((i+1)%4+4));
|
||||
for(int i=0; i < 4; ++i)
|
||||
edges.emplace_back(cub.vertex(i), cub.vertex((i+1)%4+4));
|
||||
constexpr std::array<int, 24> edge_indices
|
||||
{ { 0, 1, 2, 3,
|
||||
1, 4, 5, 6,
|
||||
2, 6, 7, 8,
|
||||
0, 9, 10, 4,
|
||||
9, 3, 8, 11,
|
||||
5, 10, 11, 7 } };
|
||||
|
||||
//get all intersections between pl and cub edges
|
||||
std::vector<Segment_3> segments;
|
||||
std::vector<Point_3> points;
|
||||
std::array<int, 12> edge_ipt_id;
|
||||
edge_ipt_id.fill(-1);
|
||||
|
||||
for(int i=0; i < 12; ++i)
|
||||
auto inter_pt_index =
|
||||
[&plane, &corners, &edge_ipt_id](int i, int j, int edge_id)
|
||||
{
|
||||
// Intersect_3 checks the orientation of the segment's extremities to avoid actually computing
|
||||
// the intersection if possible
|
||||
Inter_type inter = typename K::Intersect_3()(pl, edges[i]);
|
||||
if(inter)
|
||||
if (edge_ipt_id[edge_id]==-1)
|
||||
{
|
||||
if(const Segment_3* seg = boost::get<Segment_3>(&*inter))
|
||||
segments.push_back(*seg);
|
||||
else if(const Point_3* p = boost::get<Point_3>(&*inter))
|
||||
points.push_back(*p);
|
||||
edge_ipt_id[edge_id] = static_cast<int> (corners.size());
|
||||
corners.push_back(typename K::Construct_plane_line_intersection_point_3()
|
||||
(plane, corners[i], corners[j]));
|
||||
}
|
||||
}
|
||||
|
||||
if(segments.empty() && points.empty())
|
||||
return result_type();
|
||||
return edge_ipt_id[edge_id];
|
||||
};
|
||||
|
||||
switch(segments.size())
|
||||
bool all_in = true;
|
||||
bool all_out = true;
|
||||
|
||||
std::vector<std::array<int,2>> neighbor_ids(14, {-1,-1});
|
||||
|
||||
auto add_neighbor = [&neighbor_ids](int i, int j)
|
||||
{
|
||||
case 0:
|
||||
//points dealt with later
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
//adj to an edge
|
||||
if(points.size() == 4)
|
||||
if (neighbor_ids[i][0] == -1 ) {
|
||||
neighbor_ids[i][0] = j;
|
||||
}
|
||||
else {
|
||||
if (neighbor_ids[i][0]!=j && neighbor_ids[i][1]==-1)
|
||||
{
|
||||
return result_type(std::forward<Segment_3>(segments.front()));
|
||||
neighbor_ids[i][1] = j;
|
||||
}
|
||||
//plane intersecting through an edge (not 2)
|
||||
else
|
||||
{
|
||||
Poly res(4);
|
||||
const Segment_3& entry_seg(segments.front());
|
||||
Point_3 p1, p2;
|
||||
bool p1_found(false),
|
||||
p2_found(false);
|
||||
}
|
||||
};
|
||||
|
||||
for(const Point_3& p : points)
|
||||
int start_id = -1;
|
||||
int solo_id = -1;
|
||||
// for each face of the bbox, we look for intersection of the plane with its edges
|
||||
std::vector<int> ids;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
ids.clear();
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
|
||||
int current_id = face_indices[4 * i + k];
|
||||
int next_id = face_indices[4 * i + (k + 1) % 4];
|
||||
int edge_id = edge_indices[4 * i + k];
|
||||
|
||||
switch (orientations[current_id])
|
||||
{
|
||||
case ON_NEGATIVE_SIDE:
|
||||
{
|
||||
if(!k.equal_3_object()(entry_seg.source(), p)
|
||||
&& ! k.equal_3_object()(entry_seg.target(), p))
|
||||
all_out = false;
|
||||
// check for intersection of the edge
|
||||
if (orientations[next_id] == ON_POSITIVE_SIDE)
|
||||
{
|
||||
if(!p1_found)
|
||||
{
|
||||
p1 = p;
|
||||
p1_found = true;
|
||||
}
|
||||
else {
|
||||
p2 = p;
|
||||
p2_found = true;
|
||||
break;
|
||||
}
|
||||
ids.push_back(
|
||||
inter_pt_index(current_id, next_id, edge_id));
|
||||
}
|
||||
}
|
||||
CGAL_USE(p2_found);
|
||||
CGAL_assertion(p1_found && p2_found);
|
||||
res[0] = entry_seg.target();
|
||||
res[1] = p2;
|
||||
res[2] = p1;
|
||||
res[3] = entry_seg.source();
|
||||
|
||||
typename K::Coplanar_orientation_3 coplanar_orientation =
|
||||
k.coplanar_orientation_3_object();
|
||||
|
||||
if( coplanar_orientation(res[0], res[1], res[2])
|
||||
!= coplanar_orientation(res[0], res[1], res[3]))
|
||||
{
|
||||
std::swap(res[1], res[2]);
|
||||
}
|
||||
|
||||
return result_type(std::forward<Poly>(res));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: //intersects diagonally
|
||||
{
|
||||
Poly res(4);
|
||||
Segment_3 &front(segments.front()),
|
||||
&back(segments.back());
|
||||
res[0] = front.target();
|
||||
res[1] = back.target();
|
||||
res[2] = back.source();
|
||||
res[3] = front.source();
|
||||
typename K::Coplanar_orientation_3 coplanar_orientation =
|
||||
k.coplanar_orientation_3_object();
|
||||
|
||||
if( coplanar_orientation(res[0], res[1], res[2])
|
||||
!= coplanar_orientation(res[0], res[1], res[3]))
|
||||
{
|
||||
std::swap(res[1], res[2]);
|
||||
}
|
||||
|
||||
return result_type(std::forward<Poly>(res));
|
||||
}
|
||||
break;
|
||||
case 4: // intersects a face
|
||||
{
|
||||
Poly res;
|
||||
res.reserve(4);
|
||||
typename K::Has_on_3 has_on;
|
||||
if(has_on(pl, cub.vertex(0))
|
||||
&& has_on(pl, cub.vertex(5))
|
||||
&& has_on(pl, cub.vertex(4)))
|
||||
{
|
||||
res.push_back(cub.vertex(0));
|
||||
res.push_back(cub.vertex(5));
|
||||
res.push_back(cub.vertex(4));
|
||||
res.push_back(cub.vertex(3));
|
||||
}
|
||||
else if(has_on(pl, cub.vertex(0))
|
||||
&& has_on(pl, cub.vertex(1))
|
||||
&& has_on(pl, cub.vertex(6)))
|
||||
{
|
||||
res.push_back(cub.vertex(0));
|
||||
res.push_back(cub.vertex(1));
|
||||
res.push_back(cub.vertex(6));
|
||||
res.push_back(cub.vertex(5));
|
||||
|
||||
}
|
||||
else if(has_on(pl, cub.vertex(1))
|
||||
&& has_on(pl, cub.vertex(2))
|
||||
&& has_on(pl, cub.vertex(7)))
|
||||
{
|
||||
res.push_back(cub.vertex(1));
|
||||
res.push_back(cub.vertex(2));
|
||||
res.push_back(cub.vertex(7));
|
||||
res.push_back(cub.vertex(6));
|
||||
}
|
||||
else if(has_on(pl, cub.vertex(2))
|
||||
&& has_on(pl, cub.vertex(3))
|
||||
&& has_on(pl, cub.vertex(4)))
|
||||
{
|
||||
res.push_back(cub.vertex(2));
|
||||
res.push_back(cub.vertex(3));
|
||||
res.push_back(cub.vertex(4));
|
||||
res.push_back(cub.vertex(7));
|
||||
}
|
||||
else if(has_on(pl, cub.vertex(6))
|
||||
&& has_on(pl, cub.vertex(7))
|
||||
&& has_on(pl, cub.vertex(4)))
|
||||
{
|
||||
res.push_back(cub.vertex(6));
|
||||
res.push_back(cub.vertex(7));
|
||||
res.push_back(cub.vertex(4));
|
||||
res.push_back(cub.vertex(5));
|
||||
}
|
||||
else if(has_on(pl, cub.vertex(2))
|
||||
&& has_on(pl, cub.vertex(1))
|
||||
&& has_on(pl, cub.vertex(0)))
|
||||
{
|
||||
res.push_back(cub.vertex(2));
|
||||
res.push_back(cub.vertex(1));
|
||||
res.push_back(cub.vertex(0));
|
||||
res.push_back(cub.vertex(3));
|
||||
}
|
||||
return result_type(std::forward<Poly>(res));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Poly filtered_points;
|
||||
filter_points(points, filtered_points);
|
||||
|
||||
//adjacent to a vertex
|
||||
if(filtered_points.size() == 1)
|
||||
{
|
||||
return result_type(std::forward<Point_3>(filtered_points.front()));
|
||||
}
|
||||
|
||||
//get intersections between pl and each face -> line. Foreach line, creates segment with points. Then use helper_function to recover polygon.
|
||||
typedef typename Intersection_traits<K,
|
||||
CGAL::Plane_3<K>,
|
||||
CGAL::Plane_3<K> >::result_type Pl_pl_type;
|
||||
|
||||
std::vector<Line_3> plane_intersections;
|
||||
Pl_pl_type pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0),
|
||||
cub.vertex(1),
|
||||
cub.vertex(5)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0),
|
||||
cub.vertex(3),
|
||||
cub.vertex(4)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0),
|
||||
cub.vertex(1),
|
||||
cub.vertex(3)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7),
|
||||
cub.vertex(6),
|
||||
cub.vertex(1)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7),
|
||||
cub.vertex(4),
|
||||
cub.vertex(3)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7),
|
||||
cub.vertex(6),
|
||||
cub.vertex(4)));
|
||||
if(const Line_3* line = boost::get<Line_3>(&*pl_inter)){
|
||||
plane_intersections.push_back(*line);
|
||||
}
|
||||
|
||||
std::list<Segment_3> tmp_segs;
|
||||
for(const auto& line : plane_intersections)
|
||||
{
|
||||
bool first_found = false;
|
||||
Point_3 first_p;
|
||||
typename K::Has_on_3 has_on;
|
||||
for(const auto &p : filtered_points)
|
||||
{
|
||||
if(has_on(line, p))
|
||||
{
|
||||
if(!first_found)
|
||||
{
|
||||
first_found = true;
|
||||
first_p = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_segs.emplace_back(first_p, p);
|
||||
break;
|
||||
}
|
||||
case ON_POSITIVE_SIDE:
|
||||
{
|
||||
all_in = false;
|
||||
// check for intersection of the edge
|
||||
if (orientations[next_id] == ON_NEGATIVE_SIDE)
|
||||
{
|
||||
ids.push_back(inter_pt_index(current_id, next_id, edge_id));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_ORIENTED_BOUNDARY:
|
||||
{
|
||||
all_in = all_out = false;
|
||||
ids.push_back(current_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (ids.size())
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
std::vector<Point_3> res({ corners[ids[0]],
|
||||
corners[ids[1]],
|
||||
corners[ids[2]],
|
||||
corners[ids[3]] });
|
||||
return result_type(res);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (start_id == -1) start_id = ids[0];
|
||||
add_neighbor(ids[0], ids[1]);
|
||||
add_neighbor(ids[1], ids[0]);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
solo_id = ids[0];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(tmp_segs.size() < 3)
|
||||
return result_type();
|
||||
if (all_in || all_out) return boost::none;
|
||||
if (start_id == -1) return { result_type(corners[solo_id]) };
|
||||
|
||||
std::list<Point_3> tmp_pts;
|
||||
fill_points_list(tmp_segs,tmp_pts);
|
||||
|
||||
Poly res;
|
||||
for(const auto& p : tmp_pts)
|
||||
res.push_back(p);
|
||||
|
||||
if(res.size() == 3){
|
||||
typename K::Triangle_3 tr(res[0], res[1], res[2]);
|
||||
return result_type(std::forward<typename K::Triangle_3>(tr));
|
||||
}
|
||||
else
|
||||
{
|
||||
return result_type(std::forward<Poly>(res));
|
||||
}
|
||||
int prv_id = -1;
|
||||
int cur_id = start_id;
|
||||
std::vector<Point_3> res;
|
||||
res.reserve(6);
|
||||
do {
|
||||
res.push_back(corners[cur_id]);
|
||||
int nxt_id = neighbor_ids[cur_id][0] == prv_id
|
||||
? neighbor_ids[cur_id][1]
|
||||
: neighbor_ids[cur_id][0];
|
||||
if (nxt_id == -1 || nxt_id == start_id){
|
||||
if(res.size() == 2){
|
||||
typename K::Segment_3 seg(res[0], res[1]);
|
||||
return result_type(seg);
|
||||
}
|
||||
if(res.size() == 3){
|
||||
typename K::Triangle_3 tr(res[0], res[1], res[2]);
|
||||
return result_type(tr);
|
||||
}
|
||||
return result_type(res);
|
||||
}
|
||||
prv_id = cur_id;
|
||||
cur_id = nxt_id;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
template <class K>
|
||||
|
|
|
|||
|
|
@ -32,101 +32,170 @@ template <class K>
|
|||
typename Intersection_traits<K, typename K::Tetrahedron_3, typename K::Plane_3>::result_type
|
||||
intersection(
|
||||
const typename K::Tetrahedron_3 &tet,
|
||||
const typename K::Plane_3 &pl,
|
||||
const K&)
|
||||
const typename K::Plane_3 &plane,
|
||||
const K& k)
|
||||
{
|
||||
typedef typename Intersection_traits<K,
|
||||
typename K::Tetrahedron_3,
|
||||
typename K::Plane_3>::result_type result_type;
|
||||
typedef typename K::Point_3 Point_3;
|
||||
typedef typename K::Triangle_3 Triangle_3;
|
||||
typedef typename Intersection_traits<K, typename K::Tetrahedron_3, typename K::Plane_3>::result_type result_type;
|
||||
typename K::Oriented_side_3 oriented_side = k.oriented_side_3_object();
|
||||
|
||||
typedef typename Intersection_traits<K,
|
||||
typename K::Triangle_3,
|
||||
typename K::Plane_3>::result_type Inter_type;
|
||||
std::vector<Point_3> corners(4);
|
||||
corners.reserve(8); // 4 corners + up to 4 polygon points
|
||||
corners[0] = tet[0];
|
||||
corners[1] = tet[1];
|
||||
corners[2] = tet[2];
|
||||
corners[3] = tet[3];
|
||||
|
||||
typedef typename K::Segment_3 Segment_3;
|
||||
Inter_type intersections[4];
|
||||
int p_id = -1;
|
||||
std::vector<typename K::Point_3> points;
|
||||
std::vector<Segment_3> segments;
|
||||
for(int i = 0; i < 4; ++i)
|
||||
const std::array<CGAL::Oriented_side, 4> orientations { {
|
||||
oriented_side(plane, corners[0]),
|
||||
oriented_side(plane, corners[1]),
|
||||
oriented_side(plane, corners[2]),
|
||||
oriented_side(plane, corners[3])
|
||||
} };
|
||||
|
||||
// description of faces of the bbox
|
||||
constexpr std::array<int, 12> face_indices
|
||||
{ { 0, 1, 2,
|
||||
0, 1, 3,
|
||||
1, 2, 3,
|
||||
2, 0, 3 } };
|
||||
|
||||
constexpr std::array<int, 12> edge_indices
|
||||
{ { 0, 1, 2,
|
||||
0, 3, 5,
|
||||
1, 4, 3,
|
||||
2, 5, 4 } };
|
||||
|
||||
std::array<int, 12> edge_ipt_id;
|
||||
edge_ipt_id.fill(-1);
|
||||
|
||||
auto inter_pt_index =
|
||||
[&plane, &corners, &edge_ipt_id](int i, int j, int edge_id)
|
||||
{
|
||||
const typename K::Triangle_3 triangle(tet.vertex((i+1)%4),
|
||||
tet.vertex((i+2)%4),
|
||||
tet.vertex((i+3)%4));
|
||||
intersections[i] = typename K::Intersect_3()(pl, triangle);
|
||||
if(intersections[i]){
|
||||
if(const typename K::Triangle_3* tr = boost::get<typename K::Triangle_3>(&*intersections[i]))
|
||||
if (edge_ipt_id[edge_id]==-1)
|
||||
{
|
||||
edge_ipt_id[edge_id] = static_cast<int> (corners.size());
|
||||
corners.push_back(typename K::Construct_plane_line_intersection_point_3()
|
||||
(plane, corners[i], corners[j]));
|
||||
}
|
||||
|
||||
return edge_ipt_id[edge_id];
|
||||
};
|
||||
|
||||
bool all_in = true;
|
||||
bool all_out = true;
|
||||
|
||||
std::vector<std::array<int,2>> neighbor_ids(8, {-1,-1});
|
||||
|
||||
auto add_neighbor = [&neighbor_ids](int i, int j)
|
||||
{
|
||||
if (neighbor_ids[i][0] == -1 ) {
|
||||
neighbor_ids[i][0] = j;
|
||||
}
|
||||
else {
|
||||
if (neighbor_ids[i][0]!=j && neighbor_ids[i][1]==-1)
|
||||
{
|
||||
typename K::Triangle_3 res = *tr;
|
||||
return result_type(std::forward<typename K::Triangle_3>(res));
|
||||
}
|
||||
else if( const Segment_3* s
|
||||
= boost::get<Segment_3>(&*intersections[i]))
|
||||
{
|
||||
segments.push_back(*s);
|
||||
}
|
||||
else if( const typename K::Point_3* p
|
||||
= boost::get<typename K::Point_3>(&*intersections[i]))
|
||||
{
|
||||
points.push_back(*p);
|
||||
p_id = i;
|
||||
neighbor_ids[i][1] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
CGAL_assertion(segments.size() != 1);
|
||||
};
|
||||
|
||||
switch(segments.size())
|
||||
int start_id = -1;
|
||||
int solo_id = -1;
|
||||
// for each face of the bbox, we look for intersection of the plane with its edges
|
||||
std::vector<int> ids;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if(p_id == -1)
|
||||
return result_type();
|
||||
else
|
||||
ids.clear();
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
typename K::Point_3 p
|
||||
= *boost::get<typename K::Point_3>(&*intersections[p_id]);
|
||||
|
||||
return result_type(std::forward<typename K::Point_3>(p));
|
||||
int current_id = face_indices[3 * i + k];
|
||||
int next_id = face_indices[3 * i + (k + 1) % 3];
|
||||
int edge_id = edge_indices[3 * i + k];
|
||||
|
||||
switch (orientations[current_id])
|
||||
{
|
||||
case ON_NEGATIVE_SIDE:
|
||||
{
|
||||
all_out = false;
|
||||
// check for intersection of the edge
|
||||
if (orientations[next_id] == ON_POSITIVE_SIDE)
|
||||
{
|
||||
ids.push_back(
|
||||
inter_pt_index(current_id, next_id, edge_id));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_POSITIVE_SIDE:
|
||||
{
|
||||
all_in = false;
|
||||
// check for intersection of the edge
|
||||
if (orientations[next_id] == ON_NEGATIVE_SIDE)
|
||||
{
|
||||
ids.push_back(inter_pt_index(current_id, next_id, edge_id));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_ORIENTED_BOUNDARY:
|
||||
{
|
||||
all_in = all_out = false;
|
||||
ids.push_back(current_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
return result_type(std::forward<typename K::Segment_3>(segments.back()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::set<typename K::Point_3> all_points;
|
||||
for (const auto& s : segments)
|
||||
|
||||
switch (ids.size())
|
||||
{
|
||||
all_points.insert(s.source());
|
||||
all_points.insert(s.target());
|
||||
}
|
||||
if(all_points.size() == 3)
|
||||
{
|
||||
auto p_it = all_points.begin();
|
||||
++p_it;
|
||||
typename K::Point_3 mid_point = *p_it;
|
||||
++p_it;
|
||||
typename K::Triangle_3 result(*all_points.begin(), mid_point, *p_it );
|
||||
return result_type(std::forward<typename K::Triangle_3>(result));
|
||||
}
|
||||
else //size = 4
|
||||
{
|
||||
std::list<Segment_3> segs(segments.begin(), segments.end());
|
||||
std::list<typename K::Point_3> tmp;
|
||||
fill_points_list(segs, tmp);
|
||||
std::vector<typename K::Point_3> res;
|
||||
for( const auto& p : tmp)
|
||||
res.push_back(p);
|
||||
return result_type(std::forward<std::vector<typename K::Point_3> >(res));
|
||||
case 3:
|
||||
{
|
||||
Triangle_3 res(corners[ids[0]],
|
||||
corners[ids[1]],
|
||||
corners[ids[2]]);
|
||||
return result_type(res);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (start_id == -1) start_id = ids[0];
|
||||
add_neighbor(ids[0], ids[1]);
|
||||
add_neighbor(ids[1], ids[0]);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
solo_id = ids[0];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
CGAL_assertion(false);
|
||||
return result_type();
|
||||
|
||||
if (all_in || all_out) return boost::none;
|
||||
if (start_id == -1) return { result_type(corners[solo_id]) };
|
||||
|
||||
int prv_id = -1;
|
||||
int cur_id = start_id;
|
||||
std::vector<Point_3> res;
|
||||
res.reserve(4);
|
||||
do {
|
||||
res.push_back(corners[cur_id]);
|
||||
int nxt_id = neighbor_ids[cur_id][0] == prv_id
|
||||
? neighbor_ids[cur_id][1]
|
||||
: neighbor_ids[cur_id][0];
|
||||
if (nxt_id == -1 || nxt_id == start_id){
|
||||
if(res.size() == 2){
|
||||
typename K::Segment_3 seg(res[0], res[1]);
|
||||
return result_type(seg);
|
||||
}
|
||||
if(res.size() == 3){
|
||||
typename K::Triangle_3 tr(res[0], res[1], res[2]);
|
||||
return result_type(tr);
|
||||
}
|
||||
return result_type(res);
|
||||
}
|
||||
prv_id = cur_id;
|
||||
cur_id = nxt_id;
|
||||
} while (true);
|
||||
|
||||
}
|
||||
|
||||
template <class K>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
|
||||
typedef EPICK::Point_3 Point;
|
||||
|
||||
int main()
|
||||
{
|
||||
EPICK::Plane_3 pl(Point(0, 0, 0), Point(1, 0, 0), Point(0, 1, 0));
|
||||
|
||||
std::vector<Point> pts;
|
||||
pts.push_back(Point(-10,-10,-10));
|
||||
pts.push_back(Point(10,10,10));
|
||||
CGAL::Bbox_3 cub = CGAL::bbox_3(pts.begin(), pts.end());
|
||||
|
||||
auto result = intersection(cub,pl);
|
||||
|
||||
const std::vector<Point>* res = boost::get <std::vector<Point> >(&*result);
|
||||
for (Point p : *res) {
|
||||
std::cout << p << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -672,7 +672,8 @@ struct Test {
|
|||
P(0,1,0));
|
||||
|
||||
check_intersection (tet, Pl(P(0,0.5,0), P(1,0.5,-5), P(0.5,0.5,0.5)),
|
||||
Tr(P(0.5,0.5,0), P(0,0.5,0), P(0,0.5,0.5)));
|
||||
Tr(P(0, 0.5, 0), P(0.5,0.5,0), P(0,0.5,0.5)));
|
||||
|
||||
Pl pl(P(0,0.9,0), P(0.9,0,0), P(0.9,0.01,0.06));
|
||||
|
||||
typedef typename CGAL::Intersection_traits<K,
|
||||
|
|
@ -907,7 +908,7 @@ struct Test {
|
|||
|
||||
//edge
|
||||
check_intersection (cub, Pl(P(1,1,1), P(1,2,1), P(1.5,0,0)),
|
||||
S(P(1,2,1), P(1,1,1)));
|
||||
S(P(1,1,1), P(1,2,1)));
|
||||
|
||||
|
||||
//face
|
||||
|
|
@ -924,6 +925,7 @@ struct Test {
|
|||
assert(p.x() == 1);
|
||||
}
|
||||
res = CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(2,2,2)));
|
||||
|
||||
poly = boost::get<std::vector<P> >(&*res);
|
||||
assert(poly != nullptr);
|
||||
assert(poly->size() == 4);
|
||||
|
|
@ -940,8 +942,8 @@ struct Test {
|
|||
check_intersection (cub, Pl(P(2, 1.66, 2),
|
||||
P(1.66,2,2),
|
||||
P(2,2,1.66)),
|
||||
Tr(P(2, 2, 1.66),
|
||||
P(1.66,2,2),
|
||||
Tr(P(1.66,2,2),
|
||||
P(2, 2, 1.66),
|
||||
P(2,1.66,2)));
|
||||
|
||||
//other edge
|
||||
|
|
@ -1100,7 +1102,7 @@ struct Test {
|
|||
|
||||
//edge
|
||||
check_intersection (cub, Pl(P(1,1,1), P(1,2,1), P(1.5,0,0)),
|
||||
S(P(1,2,1), P(1,1,1)));
|
||||
S(P(1,1,1), P(1,2,1)));
|
||||
//face
|
||||
typedef typename CGAL::Intersection_traits<K,
|
||||
typename K::Plane_3,
|
||||
|
|
@ -1126,8 +1128,8 @@ struct Test {
|
|||
check_intersection (cub, Pl(P(2, 1.66, 2),
|
||||
P(1.66,2,2),
|
||||
P(2,2,1.66)),
|
||||
Tr(P(2, 2, 1.66),
|
||||
P(1.66,2,2),
|
||||
Tr(P(1.66,2,2),
|
||||
P(2, 2, 1.66),
|
||||
P(2,1.66,2)));
|
||||
|
||||
//random
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
namespace CGAL{
|
||||
namespace Polygon_mesh_processing {
|
||||
|
|
@ -48,24 +49,6 @@ namespace Polygon_mesh_processing {
|
|||
namespace internal
|
||||
{
|
||||
|
||||
template <class Geom_traits, class Plane_3, class Point_3>
|
||||
int
|
||||
inter_pt_index(int i, int j,
|
||||
const Plane_3& plane,
|
||||
std::vector<Point_3>& points,
|
||||
std::map<std::pair<int,int>, int>& id_map)
|
||||
{
|
||||
std::pair<std::map<std::pair<int,int>, int>::iterator, bool> res =
|
||||
id_map.insert(std::make_pair(make_sorted_pair(i,j),
|
||||
static_cast<int> (points.size())));
|
||||
if(res.second)
|
||||
points.push_back(
|
||||
typename Geom_traits::Construct_plane_line_intersection_point_3()
|
||||
(plane, points[i], points[j]));
|
||||
|
||||
return res.first->second;
|
||||
}
|
||||
|
||||
template <class Plane_3,
|
||||
class TriangleMesh,
|
||||
class NamedParameters>
|
||||
|
|
@ -106,19 +89,42 @@ clip_to_bbox(const Plane_3& plane,
|
|||
}};
|
||||
|
||||
// description of faces of the bbox
|
||||
std::array<int, 24> face_indices =
|
||||
{{ 0, 1, 2, 3,
|
||||
2, 1, 5, 6,
|
||||
3, 2, 6, 7,
|
||||
1, 0, 4, 5,
|
||||
4, 0, 3, 7,
|
||||
6, 5, 4, 7 }};
|
||||
constexpr std::array<int, 24> face_indices
|
||||
{ { 0, 1, 2, 3,
|
||||
2, 1, 5, 6,
|
||||
3, 2, 6, 7,
|
||||
1, 0, 4, 5,
|
||||
4, 0, 3, 7,
|
||||
6, 5, 4, 7 } };
|
||||
|
||||
constexpr std::array<int, 24> edge_indices
|
||||
{ { 0, 1, 2, 3,
|
||||
1, 4, 5, 6,
|
||||
2, 6, 7, 8,
|
||||
0, 9, 10, 4,
|
||||
9, 3, 8, 11,
|
||||
5, 10, 11, 7 } };
|
||||
|
||||
std::array<int, 12> edge_ipt_id;
|
||||
edge_ipt_id.fill(-1);
|
||||
|
||||
auto inter_pt_index =
|
||||
[&plane, &corners, &edge_ipt_id](int i, int j, int edge_id)
|
||||
{
|
||||
if (edge_ipt_id[edge_id]==-1)
|
||||
{
|
||||
edge_ipt_id[edge_id] = static_cast<int> (corners.size());
|
||||
corners.push_back(typename Geom_traits::Construct_plane_line_intersection_point_3()
|
||||
(plane, corners[i], corners[j]));
|
||||
}
|
||||
|
||||
return edge_ipt_id[edge_id];
|
||||
};
|
||||
|
||||
std::map<std::pair<int,int>, int> id_map;
|
||||
std::vector< std::vector<int> > output_faces(6);
|
||||
bool all_in = true;
|
||||
bool all_out = true;
|
||||
std::set<int> in_point_ids; // to collect the set of points in the clipped bbox
|
||||
std::bitset<14> in_point_bits; // to collect the set of points in the clipped bbox
|
||||
|
||||
// for each face of the bbox, we look for intersection of the plane with its edges
|
||||
for(int i=0; i<6; ++i)
|
||||
|
|
@ -127,6 +133,7 @@ clip_to_bbox(const Plane_3& plane,
|
|||
{
|
||||
int current_id = face_indices[4*i + k];
|
||||
int next_id = face_indices[4*i + (k+1)%4];
|
||||
int edge_id = edge_indices[4 * i + k];
|
||||
|
||||
switch(orientations[ current_id ])
|
||||
{
|
||||
|
|
@ -135,13 +142,13 @@ clip_to_bbox(const Plane_3& plane,
|
|||
all_out=false;
|
||||
// point on or on the negative side
|
||||
output_faces[i].push_back(current_id);
|
||||
in_point_ids.insert(output_faces[i].back());
|
||||
in_point_bits.set(output_faces[i].back());
|
||||
// check for intersection of the edge
|
||||
if(orientations[ next_id ] == ON_POSITIVE_SIDE)
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map));
|
||||
in_point_ids.insert(output_faces[i].back());
|
||||
inter_pt_index(current_id, next_id, edge_id));
|
||||
in_point_bits.set(output_faces[i].back());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -152,15 +159,15 @@ clip_to_bbox(const Plane_3& plane,
|
|||
if(orientations[ next_id ] == ON_NEGATIVE_SIDE)
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map));
|
||||
in_point_ids.insert(output_faces[i].back());
|
||||
inter_pt_index(current_id, next_id, edge_id));
|
||||
in_point_bits.set(output_faces[i].back());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_ORIENTED_BOUNDARY:
|
||||
{
|
||||
output_faces[i].push_back(current_id);
|
||||
in_point_ids.insert(output_faces[i].back());
|
||||
in_point_bits.set(output_faces[i].back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -182,11 +189,14 @@ clip_to_bbox(const Plane_3& plane,
|
|||
typedef typename graph_traits::face_descriptor face_descriptor;
|
||||
|
||||
std::map<int, vertex_descriptor> out_vertices;
|
||||
for(int i : in_point_ids)
|
||||
for(int i=0; i<14;++i)
|
||||
{
|
||||
vertex_descriptor v = add_vertex(tm_out);
|
||||
out_vertices.insert(std::make_pair(i, v));
|
||||
put(vpm_out, v, corners[i]);
|
||||
if (in_point_bits.test(i))
|
||||
{
|
||||
vertex_descriptor v = add_vertex(tm_out);
|
||||
out_vertices.insert(std::make_pair(i, v));
|
||||
put(vpm_out, v, corners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::map< std::pair<int,int>, halfedge_descriptor> hedge_map;
|
||||
|
|
|
|||
Loading…
Reference in New Issue