Merge remote-tracking branch 'cgal/releases/CGAL-4.14-branch' into HEAD

This commit is contained in:
Sébastien Loriot 2019-07-18 16:57:27 +02:00
commit 41ef56f8ad
4 changed files with 191 additions and 10 deletions

View File

@ -1109,8 +1109,9 @@ public:
// triangle which is tangent at its 3 vertices
// \todo improve this part which is not robust with a kernel
// with inexact constructions.
Bounded_side position = inside_tm2(midpoint(get(vpm1, source(h, tm1)),
get(vpm1, target(h, tm1)) ));
Bounded_side position = inside_tm2(centroid(get(vpm1, source(h, tm1)),
get(vpm1, target(h, tm1)),
get(vpm1, target(next(h, tm1), tm1)) ));
CGAL_assertion( position != ON_BOUNDARY);
if ( position == in_tm2 )
is_patch_inside_tm2.set(patch_id);
@ -1257,6 +1258,35 @@ public:
FaceIdMap,
Intersection_edge_map> Patches;
boost::unordered_set<vertex_descriptor> border_nm_vertices; // only used if used_to_clip_a_surface == true
if (used_to_clip_a_surface)
{
if (!is_tm1_closed)
{
// \todo Note a loop over vertex_to_node_id1 would be sufficient
// if we merge the patch-id of patches to be removed (that way
// non-manifold vertices would not be duplicated in interior
// vertices of patche)
// special code to handle non-manifold vertices on the boundary
BOOST_FOREACH (vertex_descriptor vd, vertices(tm1))
{
boost::optional<halfedge_descriptor> op_h = is_border(vd, tm1);
if (op_h == boost::none) continue;
halfedge_descriptor h = *op_h;
CGAL_assertion( target(h, tm1) == vd);
// check if the target of h is a non-manifold vertex
halfedge_descriptor nh = prev( opposite(h, tm1), tm1 );
while (!is_border( opposite(nh, tm1), tm1 ) )
{
nh = prev( opposite(nh, tm1), tm1 );
}
nh = opposite(nh, tm1);
if (next(h, tm1) != nh)
border_nm_vertices.insert(target(h, tm1));
}
}
}
//store the patch description in a container to avoid recomputing it several times
Patches patches_of_tm1( tm1, tm1_patch_ids, fids1, intersection_edges1, nb_patches_tm1),
patches_of_tm2( tm2, tm2_patch_ids, fids2, intersection_edges2, nb_patches_tm2);
@ -1606,6 +1636,86 @@ public:
}
}
}
// Code dedicated to the handling of non-manifold vertices
BOOST_FOREACH(vertex_descriptor vd, border_nm_vertices)
{
// first check if at least one incident patch will be kept
boost::unordered_set<std::size_t> id_p_rm;
bool all_removed=true;
BOOST_FOREACH(halfedge_descriptor h, halfedges_around_target(vd, tm1))
{
face_descriptor f = face(h, tm1);
if ( f != GT::null_face() )
{
const std::size_t p_id = tm1_patch_ids[ get(fids1, f) ];
if ( patches_to_remove.test(p_id) )
id_p_rm.insert(p_id);
else
all_removed=false;
}
}
if (all_removed)
id_p_rm.erase(id_p_rm.begin());
// remove the vertex from the interior vertices of patches to be removed
BOOST_FOREACH(std::size_t pid, id_p_rm)
patches_of_tm1[pid].interior_vertices.erase(vd);
// we now need to update the next/prev relationship induced by the future removal of patches
// that will not be updated after patch removal
if (!all_removed && !id_p_rm.empty())
{
typedef std::pair<halfedge_descriptor, halfedge_descriptor> Hedge_pair;
std::vector< Hedge_pair> hedges_to_link;
typename CGAL::Halfedge_around_target_iterator<TriangleMesh> hit, end;
boost::tie(hit,end) = halfedges_around_target(vd, tm1);
for(; hit!=end; ++hit)
{
// look for a border halfedge incident to the non-manifold vertex that will not be
// removed.
if ( !is_border(*hit, tm1) ||
patches_to_remove.test( tm1_patch_ids[ get(fids1, face(opposite(*hit, tm1), tm1)) ] ) )
{
continue;
}
// we have to fix only cases when the next halfedge is to be removed
halfedge_descriptor nh = next(*hit, tm1);
if ( !patches_to_remove.test( tm1_patch_ids[ get(fids1, face(opposite(nh, tm1), tm1)) ] ) )
continue;
halfedge_descriptor h = *hit;
// we are now looking for a potential next candidate halfedge
do{
++hit;
if (hit == end) break;
if ( is_border(*hit, tm1) )
{
if ( patches_to_remove.test( tm1_patch_ids[ get(fids1, face(opposite(*hit, tm1), tm1)) ] ) )
{
// we check if the next halfedge is a good next
nh = next(*hit, tm1);
if ( !patches_to_remove.test( tm1_patch_ids[ get(fids1, face(opposite(nh, tm1), tm1)) ] ) )
{
hedges_to_link.push_back( Hedge_pair(h, nh) );
break;
}
}
else
{
// we push-back the halfedge for the next round only if it was not the first
if (h != *cpp11::prev(hit))
--hit;
break;
}
}
}
while(true);
if (hit == end) break;
}
BOOST_FOREACH ( const Hedge_pair& p, hedges_to_link)
set_next(p.first, p.second, tm1);
}
}
}
#define CGAL_COREF_FUNCTION_CALL_DEF(BO_type) \

View File

@ -6,6 +6,7 @@
#include <iostream>
#include <fstream>
#include <sstream>
namespace PMP = CGAL::Polygon_mesh_processing;
namespace params = PMP::parameters;
@ -283,6 +284,49 @@ void test()
assert(is_valid_polygon_mesh(tm1));
CGAL::clear(tm1);
CGAL::clear(tm2);
// non-manifold border vertices
std::stringstream ss;
ss << "OFF\n 5 2 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 0 1 4\n3 1 2 3\n";
ss >> tm1;
PMP::clip(tm1, K::Plane_3(-1,0,0,2));
assert(vertices(tm1).size()==3);
CGAL::clear(tm1);
ss = std::stringstream();
ss << "OFF\n 7 4 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 3 5\n";
ss >> tm1;
CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1);
PMP::clip(tm1, K::Plane_3(-1,0,0,2));
assert(vertices(tm1).size()==6);
CGAL::clear(tm1);
ss = std::stringstream();
ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n";
ss >> tm1;
for (int i=0;i<3;++i)
CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1);
PMP::clip(tm1, K::Plane_3(-1,0,0,2));
assert(vertices(tm1).size()==7);
CGAL::clear(tm1);
ss = std::stringstream();
ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n";
ss >> tm1;
for (int i=0;i<3;++i)
CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1);
PMP::clip(tm1, K::Plane_3(0,1,0,0));
assert(vertices(tm1).size()==3);
CGAL::clear(tm1);
ss = std::stringstream();
ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n";
ss >> tm1;
for (int i=0;i<3;++i)
CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1);
PMP::clip(tm1, K::Plane_3(0,-1,0,0));
assert(vertices(tm1).size()==7);
CGAL::clear(tm1);
}
int main()

View File

@ -49,7 +49,13 @@ read_OBJ( std::istream& input,
faces.push_back( std::vector<std::size_t>() );
while(iss >> i)
{
faces.back().push_back(i-1);
if(i < 1)
{
faces.back().push_back(points.size()+i);//negative indices are relative references
}
else {
faces.back().push_back(i-1);
}
iss.ignore(256, ' ');
}
}

View File

@ -35,6 +35,34 @@ export INSTALLATION_DIR=""
export TESTSUITE_DIR=""
USE_LATEST_UNZIPPED=""
# ----------------------------------------------------------------------------------------
# Logging functions
# ----------------------------------------------------------------------------------------
log()
{
LOGFILE=${1}
shift
if [ -n "${CONSOLE_OUTPUT}" ]; then
printf "${*} ...\n"
fi
printf "\n-------------------------------------------------------\n" >> "${LOGFILE}"
printf " ${*} ...\n" >> "${LOGFILE}"
printf "\n-------------------------------------------------------\n" >> "${LOGFILE}"
}
log_done()
{
if [ -n "${CONSOLE_OUTPUT}" ]; then
printf \
" done\n-------------------------------------------------------\n"
fi
printf "\n-------------------------------------------------------\n" >> "${1}"
printf " **DONE**\n" >> "${1}"
printf "\n-------------------------------------------------------\n" >> "${1}"
}
# ----------------------------------------------------------------------------------------
# Downloads the file "LATEST" whose contents indicates which release to test
# ----------------------------------------------------------------------------------------
@ -202,13 +230,6 @@ else
exit 1
fi
if [ -n "${SCRIPTS_DIR}" ]; then
CGAL_DIR=`readlink "${CGAL_HOME}/CGAL-git"`
else
CGAL_DIR=`readlink "${CGAL_HOME}/CGAL-I"`
fi
source "${CGAL_DIR}/${SCRIPTS_DIR}developer_scripts/log.sh"
LOGS_DIR="${CGAL_HOME}/AUTOTEST_LOGS"
LOCK_FILE="${CGAL_HOME}/autotest_cgal_with_cmake.lock"