Merge pull request #1628 from MaelRL/PMP-Fix_self_intersections

Fixed self intersection tests
This commit is contained in:
Laurent Rineau 2016-12-02 11:34:38 +01:00
commit 9bb29f0c75
5 changed files with 39071 additions and 51 deletions

View File

@ -29,6 +29,8 @@
#include <CGAL/intersections.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/Kernel/global_functions_3.h>
#include <vector>
#include <exception>
#include <boost/foreach.hpp>
@ -97,16 +99,34 @@ struct Intersect_facets
do_intersect_3_functor(kernel.do_intersect_3_object())
{ }
void operator()(const Box* b,
const Box* c) const
void operator()(const Box* b, const Box* c) const
{
halfedge_descriptor h = halfedge(b->info(),m_tmesh);
halfedge_descriptor h = halfedge(b->info(), m_tmesh);
halfedge_descriptor opp_h;
// check for shared egde --> no intersection
if(face(opposite(h,m_tmesh),m_tmesh) == c->info() ||
face(opposite(next(h,m_tmesh),m_tmesh),m_tmesh) == c->info() ||
face(opposite(next(next(h,m_tmesh),m_tmesh),m_tmesh),m_tmesh) == c->info())
return;
// check for shared egde
for(unsigned int i=0; i<3; ++i){
opp_h = opposite(h, m_tmesh);
if(face(opp_h, m_tmesh) == c->info()){
// there is an intersection if the four points are coplanar and
// the triangles overlap
if(CGAL::coplanar(get(m_vpmap, target(h, m_tmesh)),
get(m_vpmap, target(next(h, m_tmesh), m_tmesh)),
get(m_vpmap, source(h, m_tmesh)),
get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) &&
CGAL::coplanar_orientation(get(m_vpmap, source(h, m_tmesh)),
get(m_vpmap, target(h, m_tmesh)),
get(m_vpmap, target(next(h, m_tmesh), m_tmesh)),
get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)))
== CGAL::POSITIVE){
*m_iterator_wrapper++ = std::make_pair(b->info(), c->info());
return;
} else { // there is a shared edge but no intersection
return;
}
}
h = next(h, m_tmesh);
}
// check for shared vertex --> maybe intersection, maybe not
halfedge_descriptor g = halfedge(c->info(),m_tmesh);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
OFF
4 2 0
0 0 0
1 0 0
0 1 0
1 1 0
3 0 1 2
3 0 2 3

View File

@ -1,5 +1,7 @@
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
@ -11,56 +13,109 @@
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;
typedef CGAL::Exact_predicates_exact_constructions_kernel Epec;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;
typedef CGAL::Exact_predicates_exact_constructions_kernel Epec;
template <typename K>
int
test_self_intersections(const char* filename)
test_self_intersections(const char* filename, const bool expected)
{
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
std::ifstream input(filename);
Polyhedron poly;
if ( !input || !(input >> poly) ){
std::cerr << "Error: can not read file.";
if ( !input || !(input >> poly) ) {
std::cerr << "Error: cannot read file: " << filename << std::endl;
return 1;
}
std::cout << "Reading file: " << filename << std::endl;
CGAL::Timer timer;
timer.start();
std::vector<std::pair<face_descriptor, face_descriptor> > intersected_tris;
CGAL::Polygon_mesh_processing::self_intersections
(poly,
std::back_inserter(intersected_tris),
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, poly)));
CGAL::Polygon_mesh_processing::self_intersections(
poly,
std::back_inserter(intersected_tris),
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, poly)));
bool intersecting_1 = !intersected_tris.empty();
assert(!intersecting_1);
std::cerr << "Self-intersection test took " << timer.time() << " sec." << std::endl;
std::cerr << intersected_tris.size() << " pairs of triangles intersect." << std::endl;
std::cout << "Self-intersection test took " << timer.time() << " sec." << std::endl;
std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl;
timer.reset();
bool intersecting_2 =
CGAL::Polygon_mesh_processing::does_self_intersect(poly,
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, poly)));
bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(poly,
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, poly)));
std::cout << "does_self_intersect test took " << timer.time() << " sec." << std::endl;
std::cout << (intersecting_2 ? "There is a self-intersection." :
"There are no self-intersections.") << std::endl;
assert(intersecting_1 == intersecting_2);
assert(intersecting_1 == expected);
std::cout << filename << " passed the tests." << std::endl << std::endl;
std::cerr << "does_self_intersect test took " << timer.time() << " sec." << std::endl;
std::cerr
<< (intersecting_2 ? "There is a self-intersection." : "There are no self-intersections.")
<< std::endl;
return 0;
}
int main(int argc, char** argv)
{
// If file(s) are provided, the associated expected result must also be provided.
// Note that this expected value is a Boolean that is passed in command line
// with either 'true' or 'false' (but not integers), that is for example:
// > self_intersection_polyhedron_test data/U.off false
// First test ----------------------------------------------------------------
bool expected = false;
const char* filename = (argc > 1) ? argv[1] : "data/elephant.off";
int r = test_self_intersections<Epic>(filename);
r += test_self_intersections<Epec>(filename);
if(argc > 1) {
assert(argc > 2);
std::stringstream ss(argv[2]);
ss >> std::boolalpha >> expected;
assert(!ss.fail()); // make sure that argv[2] is either 'true' or 'false'
}
std::cout << "First test (Epic):" << std::endl;
int r = test_self_intersections<Epic>(filename, expected);
std::cout << "First test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
// Second test ---------------------------------------------------------------
expected = true;
filename = (argc > 3) ? argv[3] : "data/mannequin-devil.off";
if(argc > 3) {
assert(argc > 4);
std::stringstream ss(argv[4]);
ss >> std::boolalpha >> expected;
assert(!ss.fail());
}
std::cout << "Second test (Epic):" << std::endl;
r += test_self_intersections<Epic>(filename, expected);
std::cout << "Second test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
// Third test ----------------------------------------------------------------
expected = true;
filename = (argc > 5) ? argv[5] : "data/overlapping_triangles.off";
if(argc > 5) {
assert(argc > 6);
std::stringstream ss(argv[6]);
ss >> std::boolalpha >> expected;
assert(!ss.fail());
}
std::cout << "Third test (Epic):" << std::endl;
r += test_self_intersections<Epic>(filename, expected);
std::cout << "Third test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
return r;
}

View File

@ -1,51 +1,120 @@
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;
typedef CGAL::Exact_predicates_exact_constructions_kernel Epec;
int main(int argc, char** argv)
template <typename K>
int
test_self_intersections(const char* filename, const bool expected)
{
const char* filename = (argc > 1) ? argv[1] : "data/elephant.off";
typedef CGAL::Surface_mesh<typename K::Point_3> Mesh;
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
std::ifstream input(filename);
Mesh m;
if ( !input || !(input >> m) ){
std::cerr << "Error: can not read file.";
if ( !input || !(input >> m) ) {
std::cerr << "Error: cannot read file: " << filename << std::endl;
return 1;
}
std::cout << "Reading file: " << filename << std::endl;
CGAL::Timer timer;
timer.start();
std::vector<std::pair<face_descriptor, face_descriptor> > intersected_tris;
CGAL::Polygon_mesh_processing::self_intersections(m,
CGAL::Polygon_mesh_processing::self_intersections(
m,
std::back_inserter(intersected_tris),
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m)));
bool intersecting_1 = !intersected_tris.empty();
assert(!intersecting_1);
std::cerr << "self_intersections test took " << timer.time() << " sec." << std::endl;
std::cerr << intersected_tris.size() << " pairs of triangles are intersecting." << std::endl;
std::cout << "self_intersections test took " << timer.time() << " sec." << std::endl;
std::cout << intersected_tris.size() << " pairs of triangles are intersecting." << std::endl;
timer.reset();
bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m,
CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m)));
assert(intersecting_1 == intersecting_2);
std::cerr << "does_self_intersect test took " << timer.time() << " sec." << std::endl;
std::cerr
<< (intersecting_2 ? "There is a self-intersection." : "There are no self-intersections.")
<< std::endl;
std::cout << "does_self_intersect test took " << timer.time() << " sec." << std::endl;
std::cout << (intersecting_2 ? "There is a self-intersection." :
"There are no self-intersections.") << std::endl;
assert(intersecting_1 == intersecting_2);
assert(intersecting_1 == expected);
std::cout << filename << " passed the tests." << std::endl << std::endl;
return 0;
}
int main(int argc, char** argv)
{
// If file(s) are provided, the associated expected result must also be provided.
// Note that this expected value is a Boolean that is passed in command line
// with either 'true' or 'false' (and not integers), that is for example:
// > self_intersection_surface_mesh_test data/U.off false
// First test ----------------------------------------------------------------
bool expected = false;
const char* filename = (argc > 1) ? argv[1] : "data/elephant.off";
if(argc > 1) {
assert(argc > 2);
std::stringstream ss(argv[2]);
ss >> std::boolalpha >> expected;
assert(!ss.fail()); // make sure that argv[2] is either 'true' or 'false'
}
std::cout << "First test (Epic):" << std::endl;
int r = test_self_intersections<Epic>(filename, expected);
std::cout << "First test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
// Second test ---------------------------------------------------------------
expected = true;
filename = (argc > 3) ? argv[3] : "data/mannequin-devil.off";
if(argc > 3) {
assert(argc > 4);
std::stringstream ss(argv[4]);
ss >> std::boolalpha >> expected;
assert(!ss.fail());
}
std::cout << "Second test (Epic):" << std::endl;
r += test_self_intersections<Epic>(filename, expected);
std::cout << "Second test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
// Third test ----------------------------------------------------------------
expected = true;
filename = (argc > 5) ? argv[5] : "data/overlapping_triangles.off";
if(argc > 5) {
assert(argc > 6);
std::stringstream ss(argv[6]);
ss >> std::boolalpha >> expected;
assert(!ss.fail());
}
std::cout << "Third test (Epic):" << std::endl;
r += test_self_intersections<Epic>(filename, expected);
std::cout << "Third test (Epec):" << std::endl;
r += test_self_intersections<Epec>(filename, expected);
return r;
}