Merge pull request #2350 from sloriot/SMS-fix_link_computation

Fix the link computation for edges on the border
This commit is contained in:
Laurent Rineau 2017-08-28 12:58:17 +02:00 committed by GitHub
commit dfa7481b76
13 changed files with 428 additions and 8 deletions

View File

@ -152,7 +152,7 @@ template<class VertexIdxMap
// counterclockwise around v0
halfedge_descriptor e02 = opposite(prev(v0_v1(),surface_mesh()), surface_mesh());
vertex_descriptor v, v2 =target(e02,surface_mesh());
vertex_descriptor v=target(e02,surface_mesh()), v2=v;
while(e02 != endleft) {
#ifdef CGAL_SMS_EDGE_PROFILE_ALWAYS_NEED_UNIQUE_VERTEX_IN_LINK
if (vertex_already_inserted.insert(v2).second)
@ -161,12 +161,14 @@ template<class VertexIdxMap
bool is_b = is_border(e02);
e02 = opposite(prev(e02,surface_mesh()), surface_mesh());
v = target(e02,surface_mesh());
if(! is_b){
if( !is_b )
mTriangles.push_back(Triangle(v,v0(),v2) ) ;
}
v2 = v;
}
if(v != vR() && (v!= vertex_descriptor())){
e02 = opposite(prev(v1_v0(),surface_mesh()), surface_mesh());
if(target(e02, surface_mesh())!=v ) // add the vertex if it is not added in the following loop
{
#ifdef CGAL_SMS_EDGE_PROFILE_ALWAYS_NEED_UNIQUE_VERTEX_IN_LINK
if (vertex_already_inserted.insert(v).second)
#endif
@ -174,8 +176,8 @@ template<class VertexIdxMap
}
// counterclockwise around v1
e02 = opposite(prev(v1_v0(),surface_mesh()), surface_mesh());
v2 = target(e02,surface_mesh());
v = v2;
while(e02 != endright) {
#ifdef CGAL_SMS_EDGE_PROFILE_ALWAYS_NEED_UNIQUE_VERTEX_IN_LINK
if (vertex_already_inserted.insert(v2).second)
@ -184,18 +186,22 @@ template<class VertexIdxMap
bool is_b = is_border(e02);
e02 = opposite(prev(e02,surface_mesh()), surface_mesh());
v = target(e02,surface_mesh());
if(! is_b){
if( !is_b ){
mTriangles.push_back(Triangle(v,v1(),v2) ) ;
}
v2 = v;
}
if(v != vL() && (v!= vertex_descriptor())){
if(mLink.empty() || //handle link of an isolated triangle
target(opposite(prev(v0_v1(),surface_mesh()), surface_mesh()), surface_mesh())!=v)
{
#ifdef CGAL_SMS_EDGE_PROFILE_ALWAYS_NEED_UNIQUE_VERTEX_IN_LINK
if (vertex_already_inserted.insert(v).second)
#endif
mLink.push_back(v);
}
CGAL_assertion(!mLink.empty());
}
} // namespace Surface_mesh_simplification

View File

@ -0,0 +1,38 @@
OFF
16 18 0
-12 -8 0
-9 -11 0
-10 -7 0
-10 -17 0
-9 -14 0
-12 -15 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 3 4 5
3 6 7 8
3 5 4 9
3 9 1 0
3 10 11 4
3 12 11 13
3 10 4 3
3 7 1 8
3 8 11 14
3 2 1 15
3 11 8 4
3 11 12 14
3 14 6 8
3 4 8 1
3 10 13 11
3 9 4 1
3 15 1 7

View File

@ -0,0 +1,37 @@
OFF
16 17 0
-12 -8 0
-9 -11 0
-10 -7 0
-10 -17 0
-9 -14 0
-12 -15 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 3 4 5
3 6 7 8
3 9 1 0
3 10 11 4
3 12 11 13
3 10 4 3
3 7 1 8
3 8 11 14
3 2 1 15
3 11 8 4
3 11 12 14
3 14 6 8
3 4 8 1
3 10 13 11
3 9 4 1
3 15 1 7

View File

@ -0,0 +1,36 @@
OFF
16 16 0
-12 -8 0
-9 -11 0
-10 -7 0
-10 -17 0
-9 -14 0
-12 -15 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 3 4 5
3 6 7 8
3 9 1 0
3 10 11 4
3 12 11 13
3 10 4 3
3 7 1 8
3 8 11 14
3 2 1 15
3 11 8 4
3 11 12 14
3 14 6 8
3 4 8 1
3 10 13 11
3 15 1 7

View File

@ -0,0 +1,31 @@
OFF
14 13 0
-12 -8 0
-9 -11 0
-10 -7 0
-9 -14 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 4 5 6
3 7 1 0
3 10 9 11
3 5 1 6
3 6 9 12
3 2 1 13
3 9 6 3
3 9 10 12
3 12 4 6
3 3 6 1
3 8 11 9
3 13 1 5

View File

@ -0,0 +1,36 @@
OFF
16 16 0
-12 -8 0
-9 -11 0
-10 -7 0
-10 -17 0
-9 -14 0
-12 -15 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 3 4 5
3 6 7 8
3 9 1 0
3 10 11 4
3 12 11 13
3 10 4 3
3 7 1 8
3 8 11 14
3 2 1 15
3 11 8 4
3 11 12 14
3 4 8 1
3 10 13 11
3 9 4 1
3 15 1 7

View File

@ -0,0 +1,34 @@
OFF
16 14 0
-12 -8 0
-9 -11 0
-10 -7 0
-10 -17 0
-9 -14 0
-12 -15 0
-3 -7 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 3 4 5
3 6 7 8
3 9 1 0
3 10 11 4
3 12 11 13
3 10 4 3
3 7 1 8
3 2 1 15
3 11 8 4
3 11 12 14
3 4 8 1
3 10 13 11
3 15 1 7

View File

@ -0,0 +1,23 @@
OFF
10 9 0
-9 -11 0
-10 -17 0
-9 -14 0
-12 -15 0
-5 -10 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
3 1 2 3
3 5 6 2
3 7 6 8
3 5 2 1
3 4 6 9
3 6 4 2
3 6 7 9
3 2 4 0
3 5 8 6

View File

@ -0,0 +1,28 @@
OFF
13 11 0
-12 -8 0
-9 -11 0
-10 -7 0
-9 -14 0
-6 -6 0
-5 -10 0
-13 -14 0
-8 -19 0
-6 -15 0
-2 -17 0
-4 -20 0
-2 -10 0
-9 -6 0
3 0 1 2
3 6 1 0
3 7 8 3
3 9 8 10
3 4 1 5
3 2 1 12
3 8 5 3
3 8 9 11
3 3 5 1
3 7 10 8
3 12 1 4

View File

@ -0,0 +1,10 @@
OFF
4 2 0
-9 -11 0
-9 -14 0
-5 -10 0
-6 -15 0
3 3 2 1
3 1 2 0

View File

@ -0,0 +1,8 @@
OFF
3 1 0
-9 -11 0
-9 -14 0
-5 -10 0
3 1 2 0

View File

@ -0,0 +1,11 @@
data_link/test01.off
data_link/test02.off
data_link/test03.off
data_link/test04.off
data_link/test05.off
data_link/test06.off
data_link/test07.off
data_link/test08.off
data_link/test09.off
data_link/test10.off
data/elephant.off

View File

@ -0,0 +1,122 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_profile.h>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <fstream>
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef CGAL::Surface_mesh_simplification::Edge_profile<Mesh> Profile;
void naive_all_triangles(Mesh::Halfedge_index h, Mesh& m, std::set<Mesh::Face_index>& triangles)
{
BOOST_FOREACH(Mesh::Halfedge_index hh, CGAL::halfedges_around_source(h, m))
{
if (!is_border(hh, m))
triangles.insert(face(hh,m));
}
BOOST_FOREACH(Mesh::Halfedge_index hh, CGAL::halfedges_around_target(h, m))
{
if (!is_border(hh, m))
triangles.insert(face(hh,m));
}
}
void naive_link_vertices(Mesh::Halfedge_index h, Mesh& m,
const std::set<Mesh::Face_index>& triangles,
std::set<Mesh::Vertex_index>& link_vertices)
{
BOOST_FOREACH(Mesh::Face_index f, triangles)
{
BOOST_FOREACH(Mesh::Halfedge_index h, CGAL::halfedges_around_face(halfedge(f, m), m))
{
link_vertices.insert(target(h, m));
}
}
link_vertices.erase( source(h, m) );
link_vertices.erase( target(h, m) );
}
struct A{};
boost::tuple<Mesh::Vertex_index, Mesh::Vertex_index, Mesh::Vertex_index>
make_canonical_tuple(Mesh::Vertex_index v1, Mesh::Vertex_index v2, Mesh::Vertex_index v3)
{
Mesh::Vertex_index vs[3]={v1, v2, v3};
std::sort(&vs[0], &vs[0]+3);
return boost::make_tuple(vs[0], vs[1], vs[2]);
}
boost::tuple<Mesh::Vertex_index, Mesh::Vertex_index, Mesh::Vertex_index>
make_canonical_tuple(const Profile::Triangle& t)
{
return make_canonical_tuple(t.v0, t.v1, t.v2);
}
boost::tuple<Mesh::Vertex_index, Mesh::Vertex_index, Mesh::Vertex_index>
make_canonical_tuple(Mesh::Face_index f, Mesh& m)
{
Mesh::Halfedge_index h=halfedge(f, m);
return make_canonical_tuple(source(h,m), target(h,m), target(next(h, m), m));
}
void test(const char* fname)
{
Mesh m;
std::ifstream input(fname);
assert( bool(input) );
input >> m;
assert(num_vertices(m)!=0);
A a;
BOOST_FOREACH(Mesh::Halfedge_index h, halfedges(m))
{
std::set<Mesh::Face_index> triangles;
naive_all_triangles(h, m, triangles);
Profile profile(h, m, a, get(boost::vertex_point, m), a, true);
if (CGAL::Euler::does_satisfy_link_condition(edge(h, m), m))
{
std::set<Mesh::Vertex_index> link_vertices;
naive_link_vertices(h, m, triangles, link_vertices);
assert( link_vertices.size()==profile.link().size() );
assert( std::set<Mesh::Vertex_index>(profile.link().begin(),
profile.link().end()).size()
== link_vertices.size() );
BOOST_FOREACH(const Mesh::Vertex_index& v, profile.link())
{
assert( link_vertices.count(v) == 1 );
}
}
assert(triangles.size() == profile.triangles().size());
std::set<boost::tuple<Mesh::Vertex_index, Mesh::Vertex_index, Mesh::Vertex_index> > triple_set;
BOOST_FOREACH(const Profile::Triangle& t, profile.triangles())
{
triple_set.insert( make_canonical_tuple(t) );
}
BOOST_FOREACH(Mesh::Face_index f, triangles)
{
assert( triple_set.count( make_canonical_tuple(f, m) ) == 1 );
}
}
}
int main(int argc, char** argv)
{
for (int i=1; i<argc; ++i)
{
std::cout << "Testing " << argv[i] << "\n";
test(argv[i]);
}
if (argc==1)
{
std::cout << "No file provided, nothing tested\n";
}
return 0;
}