mirror of https://github.com/CGAL/cgal
Merge pull request #1628 from MaelRL/PMP-Fix_self_intersections
Fixed self intersection tests
This commit is contained in:
commit
9bb29f0c75
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue