mirror of https://github.com/CGAL/cgal
Merge branch 'PMP-corefine_non_manifold' into master
This commit is contained in:
commit
68124448dc
|
|
@ -37,6 +37,20 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
namespace parameters
|
||||
{
|
||||
template <class Parameter, class NamedParameters>
|
||||
struct Is_default
|
||||
{
|
||||
typedef typename internal_np::Lookup_named_param_def <
|
||||
Parameter,
|
||||
NamedParameters,
|
||||
internal_np::Param_not_found > ::type NP_type;
|
||||
static const bool value = boost::is_same<NP_type, internal_np::Param_not_found>::value;
|
||||
typedef CGAL::Boolean_tag<value> type;
|
||||
};
|
||||
} // end of parameters namespace
|
||||
|
||||
// forward declarations to avoid dependency to Solver_interface
|
||||
template <typename FT, unsigned int dim>
|
||||
class Default_diagonalize_traits;
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ CGAL_add_named_parameter(halfedges_keeper_t, halfedges_keeper, halfedges_keeper)
|
|||
CGAL_add_named_parameter(volume_threshold_t, volume_threshold, volume_threshold)
|
||||
CGAL_add_named_parameter(dry_run_t, dry_run, dry_run)
|
||||
CGAL_add_named_parameter(do_not_modify_t, do_not_modify, do_not_modify)
|
||||
CGAL_add_named_parameter(non_manifold_feature_map_t, non_manifold_feature_map, non_manifold_feature_map)
|
||||
|
||||
// List of named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ void test(const NamedParameters& np)
|
|||
assert(get_parameter(np, CGAL::internal_np::do_simplify_border).v == 64);
|
||||
assert(get_parameter(np, CGAL::internal_np::do_not_modify).v == 65);
|
||||
assert(get_parameter(np, CGAL::internal_np::maximum_number_of_faces).v == 78910);
|
||||
assert(get_parameter(np, CGAL::internal_np::non_manifold_feature_map).v == 60);
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34);
|
||||
|
|
@ -207,6 +208,7 @@ void test(const NamedParameters& np)
|
|||
check_same_type<62>(get_parameter(np, CGAL::internal_np::halfedges_keeper));
|
||||
check_same_type<64>(get_parameter(np, CGAL::internal_np::do_simplify_border));
|
||||
check_same_type<78910>(get_parameter(np, CGAL::internal_np::maximum_number_of_faces));
|
||||
check_same_type<60>(get_parameter(np, CGAL::internal_np::non_manifold_feature_map));
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy));
|
||||
|
|
@ -325,6 +327,7 @@ int main()
|
|||
.throw_on_self_intersection(A<43>(43))
|
||||
.clip_volume(A<44>(44))
|
||||
.use_compact_clipper(A<45>(45))
|
||||
.non_manifold_feature_map(A<60>(60))
|
||||
.apply_per_connected_component(A<46>(46))
|
||||
.output_iterator(A<47>(47))
|
||||
.erase_all_duplicates(A<48>(48))
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ create_single_source_cgal_program( "corefinement_mesh_union.cpp" )
|
|||
create_single_source_cgal_program( "corefinement_mesh_union_and_intersection.cpp" )
|
||||
create_single_source_cgal_program( "corefinement_mesh_union_with_attributes.cpp" )
|
||||
create_single_source_cgal_program( "corefinement_polyhedron_union.cpp" )
|
||||
create_single_source_cgal_program( "corefine_non_manifold.cpp" )
|
||||
create_single_source_cgal_program( "random_perturbation_SM_example.cpp" )
|
||||
create_single_source_cgal_program( "corefinement_LCC.cpp")
|
||||
create_single_source_cgal_program( "detect_features_example.cpp" )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,232 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
#include <CGAL/Polygon_mesh_processing/stitch_borders.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef K::Point_3 P;
|
||||
typedef CGAL::Surface_mesh<P> Surface_mesh;
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
int main()
|
||||
{
|
||||
// polyline intersection with a non-manifold edge
|
||||
{
|
||||
std::cout << "running polyline test\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,4,0), P(0,4,0), tm1);
|
||||
CGAL::make_quad(P(0,-4,0), P(4,-4,0), P(4,0,0), P(0,0,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,4), P(0,0,4), tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,-4), P(0,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(2,3,-2), P(2,-2,-2), P(2,-2,2), P(2,3,2), tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
std::vector< std::vector<P> > polylines;
|
||||
PMP::surface_intersection(tm1, tm2, std::back_inserter(polylines), CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
//dump polylines
|
||||
std::ofstream output("intersection_polylines.cgal");
|
||||
for(const std::vector<P>& polyline : polylines)
|
||||
{
|
||||
output << polyline.size() << " ";
|
||||
std::copy(polyline.begin(), polyline.end(),std::ostream_iterator<P>(output," "));
|
||||
output << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// simple case with only one non-manifold edge
|
||||
{
|
||||
std::cout << "running corefinement test 1\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,4,0), P(0,4,0), tm1);
|
||||
CGAL::make_quad(P(0,-4,0), P(4,-4,0), P(4,0,0), P(0,0,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,4), P(0,0,4), tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,-4), P(0,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(2,3,-2), P(2,-2,-2), P(2,-2,2), P(2,3,2), tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
std::ofstream("t1_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t1_tm2_corefined.off") << tm2;
|
||||
}
|
||||
|
||||
// edge-edge intersection on a non-manifold edge
|
||||
{
|
||||
std::cout << "running corefinement test 2\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,4,0), P(0,4,0), tm1);
|
||||
CGAL::make_quad(P(0,-4,0), P(4,-4,0), P(4,0,0), P(0,0,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,4), P(0,0,4), tm1);
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,0,-4), P(0,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(2,2,-2), P(2,-2,-2), P(2,-2,2), P(2,2,2), tm2); //TODO: test me + also test splitting the diagonal
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
std::ofstream("t2_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t2_tm2_corefined.off") << tm2;
|
||||
}
|
||||
|
||||
// coplanar edge and non-manifold edge
|
||||
{
|
||||
std::cout << "running corefinement test 3\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(8,0,0), P(8,8,0), P(0,8,0), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(12,0,0), P(12,8,0), P(8,8,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,4), P(8,0,4), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,-4), P(8,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(6,1,0), P(14,3,0), P(13,7,4), P(5,5,0), tm2);
|
||||
CGAL::make_quad(P(6,1,0), P(5,5,0), P(5,5,2), P(6,1,3), tm2);
|
||||
PMP::stitch_borders(tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
std::ofstream("t3_tm1.off") << tm1;
|
||||
std::ofstream("t3_tm2.off") << tm2;
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
std::ofstream("t3_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t3_tm2_corefined.off") << tm2;
|
||||
}
|
||||
|
||||
//TODO: add more tests nm-edge on vertex, nm-edge vs nm-edge, ...
|
||||
|
||||
|
||||
// coplanar face and non-manifold edge
|
||||
{
|
||||
std::cout << "running corefinement test 4\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(8,0,0), P(8,8,0), P(0,8,0), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(12,0,0), P(12,8,0), P(8,8,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,4), P(8,0,4), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,-4), P(8,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(6,1,0), P(14,3,0), P(13,7,0), P(5,5,0), tm2);
|
||||
CGAL::make_quad(P(6,1,0), P(5,5,0), P(5,5,2), P(6,1,3), tm2);
|
||||
PMP::stitch_borders(tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
std::ofstream("t4_tm1.off") << tm1;
|
||||
std::ofstream("t4_tm2.off") << tm2;
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
std::ofstream("t4_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t4_tm2_corefined.off") << tm2;
|
||||
}
|
||||
//
|
||||
// // coplanar face and non-manifold edge and regular intersection with incident face
|
||||
{
|
||||
std::cout << "running corefinement test 5\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(4,0,0), P(4,8,0), P(0,8,0), tm1);
|
||||
CGAL::make_quad(P(4,0,0), P(12,0,0), P(12,8,0), P(4,8,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(4,0,0), P(4,8,0), P(4,8,4), P(4,0,4), tm1);
|
||||
CGAL::make_quad(P(4,0,0), P(4,8,0), P(4,8,-4), P(4,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(2,1,0), P(14,3,0), P(13,7,0), P(5,5,0), tm2);
|
||||
CGAL::make_quad(P(2,1,0), P(5,5,0), P(5,5,2), P(2,1,3), tm2);
|
||||
PMP::stitch_borders(tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
std::ofstream("t5_tm1.off") << tm1;
|
||||
std::ofstream("t5_tm2.off") << tm2;
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1));
|
||||
|
||||
std::ofstream("t5_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t5_tm2_corefined.off") << tm2;
|
||||
}
|
||||
|
||||
// coplanar face and 2 non-manifold edges
|
||||
{
|
||||
std::cout << "running corefinement test 6\n";
|
||||
Surface_mesh tm1;
|
||||
CGAL::make_quad(P(0,0,0), P(8,0,0), P(8,8,0), P(0,8,0), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(12,0,0), P(12,8,0), P(8,8,0), tm1);
|
||||
PMP::stitch_borders(tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,4), P(8,0,4), tm1);
|
||||
CGAL::make_quad(P(8,0,0), P(8,8,0), P(8,8,-4), P(8,0,-4), tm1);
|
||||
PMP::triangulate_faces(tm1);
|
||||
|
||||
Surface_mesh tm2;
|
||||
CGAL::make_quad(P(6,1,0), P(14,3,0), P(13,7,0), P(5,5,0), tm2);
|
||||
CGAL::make_quad(P(6,1,0), P(5,5,0), P(5,5,2), P(6,1,3), tm2);
|
||||
PMP::stitch_borders(tm2);
|
||||
CGAL::make_quad(P(6,1,0), P(5,5,0), P(5,5,-2), P(6,1,-3), tm2);
|
||||
CGAL::make_quad(P(6,1,0), P(5,5,0), P(3,5,0), P(3,1,0), tm2);
|
||||
PMP::triangulate_faces(tm2);
|
||||
|
||||
std::ofstream("t6_tm1.off") << tm1;
|
||||
std::ofstream("t6_tm2.off") << tm2;
|
||||
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_1(tm1, get(boost::vertex_point, tm1));
|
||||
PMP::Non_manifold_feature_map<Surface_mesh> nm_map_2(tm2, get(boost::vertex_point, tm2));
|
||||
|
||||
#if 0
|
||||
std::vector< std::vector<P> > polylines;
|
||||
PMP::surface_intersection(tm1, tm2, std::back_inserter(polylines),
|
||||
CGAL::parameters::non_manifold_feature_map(nm_map_1),
|
||||
CGAL::parameters::non_manifold_feature_map(nm_map_2));
|
||||
|
||||
//dump polylines
|
||||
std::ofstream output("intersection_polylines.cgal");
|
||||
for(const std::vector<P>& polyline : polylines)
|
||||
{
|
||||
output << polyline.size() << " ";
|
||||
std::copy(polyline.begin(), polyline.end(),std::ostream_iterator<P>(output," "));
|
||||
output << "\n";
|
||||
}
|
||||
#else
|
||||
PMP::corefine(tm1, tm2, CGAL::parameters::non_manifold_feature_map(nm_map_1),
|
||||
CGAL::parameters::non_manifold_feature_map(nm_map_2));
|
||||
|
||||
std::ofstream("t6_tm1_corefined.off") << tm1;
|
||||
std::ofstream("t6_tm2_corefined.off") << tm2;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) 2019 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
//
|
||||
//
|
||||
// Author(s) : Sebastien Loriot
|
||||
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_NON_MANIFOLD_FEATURE_MAP
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_NON_MANIFOLD_FEATURE_MAP
|
||||
|
||||
namespace CGAL {
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
//TODO: right now the base name parameter mechanism will make a deep copy, we probably want to avoid that
|
||||
template <class PolygonMesh>
|
||||
struct Non_manifold_feature_map
|
||||
{
|
||||
typedef boost::graph_traits<PolygonMesh> Graph_traits;
|
||||
typedef typename Graph_traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename Graph_traits::edge_descriptor edge_descriptor;
|
||||
typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor;
|
||||
typedef dynamic_edge_property_t<std::size_t> Edge_to_id_tag;
|
||||
typedef dynamic_vertex_property_t<std::size_t> Vertex_to_id_tag;
|
||||
typedef typename boost::property_map<PolygonMesh, Edge_to_id_tag>::type Edge_to_nm_id;
|
||||
typedef typename boost::property_map<PolygonMesh, Vertex_to_id_tag>::type Vertex_to_nm_id;
|
||||
Edge_to_nm_id e_nm_id;
|
||||
Vertex_to_nm_id v_nm_id;
|
||||
std::vector< std::vector<edge_descriptor> > non_manifold_edges;
|
||||
std::vector< std::vector<vertex_descriptor> > non_manifold_vertices;
|
||||
|
||||
Non_manifold_feature_map()
|
||||
{}
|
||||
|
||||
template <class Vpm>
|
||||
Non_manifold_feature_map(PolygonMesh& pm, Vpm vpm)
|
||||
: e_nm_id(get(Edge_to_id_tag(), pm))
|
||||
, v_nm_id(get(Vertex_to_id_tag(), pm))
|
||||
{
|
||||
typedef typename boost::property_traits<Vpm>::value_type Point_3;
|
||||
|
||||
// detect non-manifold vertices
|
||||
std::map<Point_3, std::vector<vertex_descriptor> > vertex_map;
|
||||
for(vertex_descriptor vd : vertices(pm))
|
||||
{
|
||||
put(v_nm_id, vd, std::size_t(-1)); // init map
|
||||
vertex_map[get(vpm, vd)].push_back(vd);
|
||||
}
|
||||
|
||||
for(std::pair< const Point_3,
|
||||
std::vector<vertex_descriptor> >& p : vertex_map)
|
||||
{
|
||||
if (p.second.size()!=1)
|
||||
{
|
||||
for (vertex_descriptor vd : p.second)
|
||||
put(v_nm_id, vd, non_manifold_vertices.size());
|
||||
non_manifold_vertices.resize(non_manifold_vertices.size()+1);
|
||||
// we steal the vertor from the map
|
||||
p.second.swap(non_manifold_vertices.back());
|
||||
}
|
||||
}
|
||||
|
||||
// detect non-manifold edges
|
||||
std::map< std::pair<Point_3, Point_3>, std::vector<edge_descriptor> > edge_map;
|
||||
for(edge_descriptor ed : edges(pm))
|
||||
{
|
||||
put(e_nm_id, ed, std::size_t(-1)); // init map
|
||||
|
||||
halfedge_descriptor hd = halfedge(ed, pm);
|
||||
|
||||
// an edge can be non-manifold only if both its vertices are non-manifold
|
||||
if ( get(v_nm_id, source(hd, pm))==std::size_t(-1) ||
|
||||
get(v_nm_id, target(hd, pm))==std::size_t(-1) ) continue;
|
||||
|
||||
const Point_3& src = get(vpm, source(ed, pm));
|
||||
const Point_3& tgt = get(vpm, target(ed, pm));
|
||||
// TODO: what to do with null edges?
|
||||
if (src > tgt)
|
||||
hd = opposite(hd, pm);
|
||||
edge_map[ make_sorted_pair(src, tgt) ].push_back(edge(hd,pm));
|
||||
}
|
||||
|
||||
for(std::pair< const std::pair<Point_3, Point_3>,
|
||||
std::vector<edge_descriptor> >& p : edge_map)
|
||||
{
|
||||
if (p.second.size()!=1)
|
||||
{
|
||||
for (edge_descriptor ed : p.second)
|
||||
put(e_nm_id, ed, non_manifold_edges.size());
|
||||
non_manifold_edges.resize(non_manifold_edges.size()+1);
|
||||
// we steal the vertor from the map
|
||||
p.second.swap(non_manifold_edges.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} } // end of CGAL::Polygon_mesh_processing
|
||||
|
||||
#endif
|
||||
|
|
@ -783,14 +783,23 @@ corefine( TriangleMesh& tm1,
|
|||
> ::type User_visitor;
|
||||
User_visitor uv(choose_parameter<User_visitor>(get_parameter(np1, internal_np::graph_visitor)));
|
||||
|
||||
static const bool handle_non_manifold_features =
|
||||
!parameters::Is_default<internal_np::non_manifold_feature_map_t, NamedParameters1>::value ||
|
||||
!parameters::Is_default<internal_np::non_manifold_feature_map_t, NamedParameters2>::value;
|
||||
|
||||
// surface intersection algorithm call
|
||||
typedef Corefinement::No_extra_output_from_corefinement<TriangleMesh> Ob;
|
||||
typedef Corefinement::Surface_intersection_visitor_for_corefinement<
|
||||
TriangleMesh, Vpm, Ob, Ecm, User_visitor> Algo_visitor;
|
||||
TriangleMesh, Vpm, Ob, Ecm, User_visitor, false, handle_non_manifold_features> Algo_visitor;
|
||||
Ob ob;
|
||||
Ecm ecm(tm1,tm2,ecm1,ecm2);
|
||||
Corefinement::Intersection_of_triangle_meshes<TriangleMesh, Vpm, Algo_visitor>
|
||||
functor(tm1, tm2, vpm1, vpm2, Algo_visitor(uv,ob,ecm,const_mesh_ptr));
|
||||
|
||||
// Fill non-manifold feature maps if provided
|
||||
functor.set_non_manifold_feature_map_1(parameters::get_parameter(np1, internal_np::non_manifold_feature_map));
|
||||
functor.set_non_manifold_feature_map_2(parameters::get_parameter(np2, internal_np::non_manifold_feature_map));
|
||||
|
||||
functor(CGAL::Emptyset_iterator(), throw_on_self_intersection, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -871,7 +871,7 @@ public:
|
|||
vpm1, vpm2,
|
||||
nodes) ) //p1==q2
|
||||
{
|
||||
CGAL_assertion( index_p1!=index_p2 || index_p1==Node_id((std::numeric_limits<Node_id>::max)()) );
|
||||
CGAL_assertion( index_p1!=index_p2 || index_p1==NID );
|
||||
coplanar_patches_of_tm1.set(patch_id_p1);
|
||||
coplanar_patches_of_tm2.set(patch_id_q2);
|
||||
bool q1_is_between_p1p2 = sorted_around_edge(
|
||||
|
|
@ -941,17 +941,17 @@ public:
|
|||
#endif //CGAL_COREFINEMENT_POLYHEDRA_DEBUG
|
||||
|
||||
CGAL_assertion(
|
||||
( index_p1 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm1,p1)): nodes.exact_node(index_p1) ) !=
|
||||
( index_q1 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm2,q1)): nodes.exact_node(index_q1) )
|
||||
( index_p1 == NID ? nodes.to_exact(get(vpm1,p1)): nodes.exact_node(index_p1) ) !=
|
||||
( index_q1 == NID ? nodes.to_exact(get(vpm2,q1)): nodes.exact_node(index_q1) )
|
||||
&&
|
||||
( index_p2 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm1,p2)): nodes.exact_node(index_p2) ) !=
|
||||
( index_q1 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm2,q1)): nodes.exact_node(index_q1) )
|
||||
( index_p2 == NID ? nodes.to_exact(get(vpm1,p2)): nodes.exact_node(index_p2) ) !=
|
||||
( index_q1 == NID ? nodes.to_exact(get(vpm2,q1)): nodes.exact_node(index_q1) )
|
||||
&&
|
||||
( index_p1 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm1,p1)): nodes.exact_node(index_p1) ) !=
|
||||
( index_q2 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm2,q2)): nodes.exact_node(index_q2) )
|
||||
( index_p1 == NID ? nodes.to_exact(get(vpm1,p1)): nodes.exact_node(index_p1) ) !=
|
||||
( index_q2 == NID ? nodes.to_exact(get(vpm2,q2)): nodes.exact_node(index_q2) )
|
||||
&&
|
||||
( index_p2 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm1,p2)): nodes.exact_node(index_p2) ) !=
|
||||
( index_q2 == Node_id((std::numeric_limits<Node_id>::max)()) ? nodes.to_exact(get(vpm2,q2)): nodes.exact_node(index_q2) )
|
||||
( index_p2 == NID ? nodes.to_exact(get(vpm1,p2)): nodes.exact_node(index_p2) ) !=
|
||||
( index_q2 == NID ? nodes.to_exact(get(vpm2,q2)): nodes.exact_node(index_q2) )
|
||||
);
|
||||
|
||||
bool q1_is_between_p1p2 = sorted_around_edge(
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ template< class TriangleMesh,
|
|||
class OutputBuilder_ = Default,
|
||||
class EdgeMarkMapBind_ = Default,
|
||||
class UserVisitor_ = Default,
|
||||
bool doing_autorefinement = false >
|
||||
bool doing_autorefinement = false,
|
||||
bool handle_non_manifold_features = false >
|
||||
class Surface_intersection_visitor_for_corefinement{
|
||||
//default template parameters
|
||||
typedef typename Default::Get<EdgeMarkMapBind_,
|
||||
|
|
@ -133,13 +134,14 @@ private:
|
|||
typedef boost::unordered_map<edge_descriptor,Node_ids> On_edge_map;
|
||||
//to keep the correspondance between node_id and vertex_handle in each mesh
|
||||
typedef std::vector<vertex_descriptor> Node_id_to_vertex;
|
||||
typedef std::map<TriangleMesh*, Node_id_to_vertex > Mesh_to_map_node;
|
||||
typedef std::map<const TriangleMesh*, Node_id_to_vertex > Mesh_to_map_node;
|
||||
//to handle coplanar halfedge of polyhedra that are full in the intersection
|
||||
typedef std::multimap<Node_id,halfedge_descriptor> Node_to_target_of_hedge_map;
|
||||
typedef std::map<TriangleMesh*,Node_to_target_of_hedge_map>
|
||||
Mesh_to_vertices_on_intersection_map;
|
||||
typedef boost::unordered_map<vertex_descriptor,Node_id> Vertex_to_node_id;
|
||||
typedef std::map<TriangleMesh*, Vertex_to_node_id> Mesh_to_vertex_to_node_id;
|
||||
typedef Non_manifold_feature_map<TriangleMesh> NM_features_map;
|
||||
// typedef for the CDT
|
||||
typedef typename Intersection_nodes<TriangleMesh,
|
||||
VertexPointMap, Predicates_on_constructions_needed>::Exact_kernel EK;
|
||||
|
|
@ -151,7 +153,7 @@ private:
|
|||
typedef typename CDT::Vertex_handle CDT_Vertex_handle;
|
||||
// data members
|
||||
private:
|
||||
// boost::dynamic_bitset<> non_manifold_nodes;
|
||||
boost::dynamic_bitset<> is_node_on_boundary; // indicate if a vertex is a border vertex in tm1 or tm2
|
||||
std::vector< std::vector<Node_id> > graph_of_constraints;
|
||||
boost::dynamic_bitset<> is_node_of_degree_one;
|
||||
//nb of intersection points between coplanar faces, see fixes XSL_TAG_CPL_VERT
|
||||
|
|
@ -165,6 +167,9 @@ private:
|
|||
|
||||
std::map< Node_id,std::set<Node_id> > coplanar_constraints;
|
||||
|
||||
// optional data members to handle non-manifold issues
|
||||
std::map<const TriangleMesh*, const NM_features_map*> non_manifold_feature_maps;
|
||||
|
||||
//data members that require initialization in the constructor
|
||||
UserVisitor& user_visitor;
|
||||
OutputBuilder& output_builder;
|
||||
|
|
@ -210,6 +215,70 @@ public:
|
|||
, const_mesh_ptr(const_mesh_ptr)
|
||||
{}
|
||||
|
||||
void
|
||||
set_non_manifold_feature_map(
|
||||
const TriangleMesh& tm,
|
||||
const NM_features_map& nm)
|
||||
{
|
||||
non_manifold_feature_maps[&tm] = &nm;
|
||||
}
|
||||
|
||||
void copy_nodes_ids_for_non_manifold_features()
|
||||
{
|
||||
static const constexpr std::size_t NM_NID((std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
for(const std::pair<const TriangleMesh*, const NM_features_map*>& tm_and_nm :
|
||||
non_manifold_feature_maps)
|
||||
{
|
||||
TriangleMesh* tm_ptr = const_cast<TriangleMesh*>(tm_and_nm.first);
|
||||
// update nodes on edges
|
||||
On_edge_map& on_edge_map = on_edge[tm_ptr];
|
||||
std::vector< std::pair<std::size_t, const Node_ids*> > edges_to_copy;
|
||||
for (const std::pair<const edge_descriptor, Node_ids>& ed_and_ids : on_edge_map)
|
||||
{
|
||||
std::size_t eid = get(tm_and_nm.second->e_nm_id, ed_and_ids.first);
|
||||
if (eid!=NM_NID)
|
||||
edges_to_copy.push_back(std::make_pair(eid,&(ed_and_ids.second)));
|
||||
}
|
||||
for(const std::pair<const std::size_t, const Node_ids*>& id_and_nodes : edges_to_copy)
|
||||
{
|
||||
const std::vector<edge_descriptor>& nm_edges =
|
||||
tm_and_nm.second->non_manifold_edges[id_and_nodes.first];
|
||||
CGAL_assertion( on_edge_map.count(nm_edges.front())==1 );
|
||||
|
||||
for (std::size_t i=1; i<nm_edges.size(); ++i)
|
||||
on_edge_map[nm_edges[i]] = *id_and_nodes.second;
|
||||
}
|
||||
|
||||
// update map vertex -> node_id
|
||||
Vertex_to_node_id& vertex_to_node_id = mesh_to_vertex_to_node_id[tm_ptr];
|
||||
Node_to_target_of_hedge_map& vertices_on_inter = mesh_to_vertices_on_inter[tm_ptr];
|
||||
|
||||
std::vector< std::pair<vertex_descriptor, Node_id> > vertices_to_add;
|
||||
for (const typename std::pair<const vertex_descriptor, Node_id>& vd_and_id
|
||||
: vertex_to_node_id)
|
||||
{
|
||||
std::size_t vid = get(tm_and_nm.second->v_nm_id, vd_and_id.first);
|
||||
if (vid!=NM_NID)
|
||||
vertices_to_add.push_back(std::make_pair(vd_and_id.first,vd_and_id.second));
|
||||
}
|
||||
|
||||
for(const std::pair<vertex_descriptor, Node_id>& vd_and_nid : vertices_to_add)
|
||||
{
|
||||
std::size_t vid = get(tm_and_nm.second->v_nm_id, vd_and_nid.first);
|
||||
for(vertex_descriptor vd : tm_and_nm.second->non_manifold_vertices[vid])
|
||||
{
|
||||
if (vd != vd_and_nid.first)
|
||||
{
|
||||
vertex_to_node_id.insert(std::make_pair(vd,vd_and_nid.second));
|
||||
output_builder.set_vertex_id(vd, vd_and_nid.second, *tm_ptr);
|
||||
vertices_on_inter.insert(std::make_pair(vd_and_nid.second,halfedge(vd,*tm_ptr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Graph_node>
|
||||
void annotate_graph(std::vector<Graph_node>& graph)
|
||||
{
|
||||
|
|
@ -218,14 +287,32 @@ public:
|
|||
is_node_of_degree_one.resize(nb_nodes);
|
||||
for(std::size_t node_id=0;node_id<nb_nodes;++node_id)
|
||||
{
|
||||
// if (non_manifold_nodes.test(node_id))
|
||||
// graph[node_id].make_terminal();
|
||||
graph_of_constraints[node_id].assign(
|
||||
graph[node_id].neighbors.begin(),
|
||||
graph[node_id].neighbors.end());
|
||||
|
||||
if (graph_of_constraints[node_id].size()==1)
|
||||
is_node_of_degree_one.set(node_id);
|
||||
|
||||
// mark every vertex on the boundary connected to another vertex by a non-boundary edge
|
||||
// The logic is somehow equivalent to what was done with the container `non_manifold_nodes`
|
||||
// that was used to split polylines at certains points. Non-manifold was used in the context
|
||||
// of the combinatorial map where the import inside the combinatorial map was possible (see broken_bound-[12].off)
|
||||
if (is_node_on_boundary.test(node_id))
|
||||
{
|
||||
// TODO: the commented condition is not restrictive enough. It only tests the vertices, not the edge used
|
||||
// to go from one vertex to the other. Right now we are marking too many norder vertices as
|
||||
// terminal than necessary. We cannot use mesh_to_node_id_to_vertex since it will be filled only
|
||||
// after the call to visitor.finalize() in the main algorithm
|
||||
// The current version of the code is correct but too many nodes are potentially
|
||||
// marked as terminal
|
||||
if (graph_of_constraints[node_id].size()==2 /* && (
|
||||
!is_node_on_boundary.test(graph_of_constraints[node_id][0]) ||
|
||||
!is_node_on_boundary.test(graph_of_constraints[node_id][1]) ) */ )
|
||||
{
|
||||
graph[node_id].make_terminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,33 +348,26 @@ public:
|
|||
CGAL_error_msg("This function should not be called");
|
||||
}
|
||||
|
||||
// The following code was used to split polylines at certains points.
|
||||
// Here manifold was used in the context of the combinatorial map where
|
||||
// the import inside the combinatorial map was possible (see broken_bound-[12].off)
|
||||
// I keep the code here for now as it could be use to detect non-manifold
|
||||
// situation of surfaces
|
||||
// void check_node_on_non_manifold_edge(
|
||||
// std::size_t node_id,
|
||||
// halfedge_descriptor h,
|
||||
// const TriangleMesh& tm)
|
||||
// {
|
||||
// if ( is_border_edge(h,tm) )
|
||||
// non_manifold_nodes.set(node_id);
|
||||
// }
|
||||
//
|
||||
// void check_node_on_non_manifold_vertex(
|
||||
// std::size_t node_id,
|
||||
// halfedge_descriptor h,
|
||||
// const TriangleMesh& tm)
|
||||
// {
|
||||
// //we turn around the hedge and check no halfedge is a border halfedge
|
||||
// for(halfedge_descriptor hc :halfedges_around_target(h,tm))
|
||||
// if ( is_border_edge(hc,tm) )
|
||||
// {
|
||||
// non_manifold_nodes.set(node_id);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
void check_node_on_boundary_edge_case(std::size_t node_id,
|
||||
halfedge_descriptor h,
|
||||
const TriangleMesh& tm)
|
||||
{
|
||||
if ( is_border_edge(h,tm) )
|
||||
is_node_on_boundary.set(node_id);
|
||||
}
|
||||
|
||||
void check_node_on_boundary_vertex_case(std::size_t node_id,
|
||||
halfedge_descriptor h,
|
||||
const TriangleMesh& tm)
|
||||
{
|
||||
//we turn around the hedge and check no halfedge is a border halfedge
|
||||
for(halfedge_descriptor hc :halfedges_around_target(h,tm))
|
||||
if ( is_border_edge(hc,tm) )
|
||||
{
|
||||
is_node_on_boundary.set(node_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//keep track of the fact that a polyhedron original vertex is a node
|
||||
void all_incident_faces_got_a_node_as_vertex(
|
||||
|
|
@ -327,7 +407,7 @@ public:
|
|||
bool is_target_coplanar,
|
||||
bool is_source_coplanar)
|
||||
{
|
||||
// non_manifold_nodes.resize(node_id+1);
|
||||
is_node_on_boundary.resize(node_id+1, false);
|
||||
|
||||
TriangleMesh* tm1_ptr = const_cast<TriangleMesh*>(&tm1);
|
||||
TriangleMesh* tm2_ptr = const_cast<TriangleMesh*>(&tm2);
|
||||
|
|
@ -344,7 +424,7 @@ public:
|
|||
case ON_EDGE: //Edge intersected by an edge
|
||||
{
|
||||
on_edge[tm2_ptr][edge(h_2,tm2)].push_back(node_id);
|
||||
// check_node_on_non_manifold_edge(node_id,h_2,tm2);
|
||||
check_node_on_boundary_edge_case(node_id,h_2,tm2);
|
||||
}
|
||||
break;
|
||||
case ON_VERTEX:
|
||||
|
|
@ -356,7 +436,7 @@ public:
|
|||
node_id_to_vertex.resize(node_id+1,Graph_traits::null_vertex());
|
||||
node_id_to_vertex[node_id]=target(h_2,tm2);
|
||||
all_incident_faces_got_a_node_as_vertex(h_2,node_id,*tm2_ptr);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_2,tm2);
|
||||
check_node_on_boundary_vertex_case(node_id,h_2,tm2);
|
||||
output_builder.set_vertex_id(target(h_2, tm2), node_id, tm2);
|
||||
}
|
||||
break;
|
||||
|
|
@ -380,7 +460,7 @@ public:
|
|||
all_incident_faces_got_a_node_as_vertex(h_1,node_id, *tm1_ptr);
|
||||
// register the vertex in the output builder
|
||||
output_builder.set_vertex_id(target(h_1, tm1), node_id, tm1);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_1,tm1);
|
||||
check_node_on_boundary_vertex_case(node_id,h_1,tm1);
|
||||
}
|
||||
else{
|
||||
if ( is_source_coplanar ){
|
||||
|
|
@ -394,12 +474,34 @@ public:
|
|||
all_incident_faces_got_a_node_as_vertex(h_1_opp,node_id, *tm1_ptr);
|
||||
// register the vertex in the output builder
|
||||
output_builder.set_vertex_id(source(h_1, tm1), node_id, tm1);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_1_opp,tm1);
|
||||
check_node_on_boundary_vertex_case(node_id,h_1_opp,tm1);
|
||||
}
|
||||
else{
|
||||
//handle intersection on principal edge
|
||||
typename std::map<const TriangleMesh*, const NM_features_map*>::iterator it_find =
|
||||
non_manifold_feature_maps.find(&tm1);
|
||||
if ( it_find != non_manifold_feature_maps.end() )
|
||||
{
|
||||
// update h_1 if it is not the canonical non-manifold edge
|
||||
// This is important to make sure intersection points on non-manifold
|
||||
// edges are all connected for the same edge so that the redistribution
|
||||
// on other edges does not overwrite some nodes.
|
||||
// This update might be required in case of EDGE-EDGE intersection or
|
||||
// COPLANAR intersection.
|
||||
const NM_features_map& nm_features_map_1 = *it_find->second;
|
||||
std::size_t eid1 = nm_features_map_1.non_manifold_edges.empty()
|
||||
? std::size_t(-1)
|
||||
: get(nm_features_map_1.e_nm_id, edge(h_1, tm1));
|
||||
|
||||
if (eid1 != std::size_t(-1))
|
||||
{
|
||||
if ( edge(h_1, tm1) != nm_features_map_1.non_manifold_edges[eid1].front() )
|
||||
h_1 = halfedge(nm_features_map_1.non_manifold_edges[eid1].front(), tm1);
|
||||
}
|
||||
}
|
||||
|
||||
on_edge[tm1_ptr][edge(h_1,tm1)].push_back(node_id);
|
||||
// check_node_on_non_manifold_edge(node_id,h_1,tm1);
|
||||
check_node_on_boundary_edge_case(node_id,h_1,tm1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -468,8 +570,9 @@ public:
|
|||
std::copy(begin,end,std::back_inserter(node_ids_array[it_id->second]));
|
||||
}
|
||||
|
||||
// Used by the autorefinement to re-set the id of nodes on the boundary of a
|
||||
// face since another vertex (inside a face or on another edge) might have
|
||||
// Used by the autorefinement and non-manifold edge handling to re-set
|
||||
// the id of nodes on the boundary of a face since another vertex
|
||||
// (inside a face or on another edge) might have
|
||||
// overwritten the vertex in node_id_to_vertex
|
||||
template <class Node_id_to_vertex>
|
||||
void update_node_id_to_vertex_map(Node_id_to_vertex& node_id_to_vertex,
|
||||
|
|
@ -559,7 +662,7 @@ public:
|
|||
// this condition ensures to consider only graph edges that are in
|
||||
// the same triangle
|
||||
if ( !points_on_triangle || it_vh!=id_to_CDT_vh.end() ){
|
||||
CGAL_assertion(doing_autorefinement || it_vh!=id_to_CDT_vh.end());
|
||||
CGAL_assertion(doing_autorefinement || handle_non_manifold_features || it_vh!=id_to_CDT_vh.end());
|
||||
if (it_vh==id_to_CDT_vh.end()) continue; // needed for autorefinement (interior nodes)
|
||||
cdt.insert_constraint(vh,it_vh->second);
|
||||
constrained_edges.push_back(std::make_pair(id,id_n));
|
||||
|
|
@ -599,14 +702,16 @@ public:
|
|||
const VertexPointMap& vpm1,
|
||||
const VertexPointMap& vpm2)
|
||||
{
|
||||
copy_nodes_ids_for_non_manifold_features();
|
||||
|
||||
nodes.all_nodes_created();
|
||||
|
||||
TriangleMesh* tm1_ptr = const_cast<TriangleMesh*>(&tm1);
|
||||
TriangleMesh* tm2_ptr = const_cast<TriangleMesh*>(&tm2);
|
||||
|
||||
std::map<TriangleMesh*, VertexPointMap> vpms;
|
||||
vpms[tm1_ptr] = vpm1;
|
||||
vpms[tm2_ptr] = vpm2;
|
||||
vpms.insert( std::make_pair(tm1_ptr, vpm1) );
|
||||
vpms.insert( std::make_pair(tm2_ptr, vpm2) );
|
||||
|
||||
vertex_descriptor null_vertex = Graph_traits::null_vertex();
|
||||
const Node_id nb_nodes = nodes.size();
|
||||
|
|
@ -635,15 +740,19 @@ public:
|
|||
// Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm];
|
||||
|
||||
Node_to_target_of_hedge_map& nodes_to_hedge=it->second;
|
||||
|
||||
// iterate on the vertices that are on the intersection between the input meshes
|
||||
for(typename Node_to_target_of_hedge_map::iterator
|
||||
it_node_2_hedge=nodes_to_hedge.begin();
|
||||
it_node_2_hedge!=nodes_to_hedge.end();
|
||||
++it_node_2_hedge)
|
||||
{
|
||||
Node_id node_id_of_first=it_node_2_hedge->first;
|
||||
// look for neighbors of the current node in the intersection graph
|
||||
std::vector<Node_id>& neighbors=graph_of_constraints[node_id_of_first];
|
||||
if ( !neighbors.empty() )
|
||||
{
|
||||
// for all neighbors look for input vertices that are also on the intersection
|
||||
for(Node_id node_id : neighbors)
|
||||
{
|
||||
//if already done for the opposite
|
||||
|
|
@ -661,7 +770,7 @@ public:
|
|||
target(it_node_2_hedge_two->second,tm) )
|
||||
{
|
||||
hedge=opposite(next(hedge,tm),tm);
|
||||
if (tm1_ptr==tm2_ptr && hedge==start)
|
||||
if ((doing_autorefinement || handle_non_manifold_features) && hedge==start)
|
||||
{
|
||||
++it_node_2_hedge_two; // we are using a multimap and
|
||||
// the halfedge we are looking for
|
||||
|
|
@ -825,7 +934,7 @@ public:
|
|||
f_vertices[1]=it_fb->second.vertices[1];
|
||||
f_vertices[2]=it_fb->second.vertices[2];
|
||||
update_face_indices(f_vertices,f_indices,vertex_to_node_id);
|
||||
if (doing_autorefinement)
|
||||
if (doing_autorefinement || handle_non_manifold_features)
|
||||
it_fb->second.update_node_id_to_vertex_map(node_id_to_vertex, tm);
|
||||
}
|
||||
else{
|
||||
|
|
@ -871,7 +980,7 @@ public:
|
|||
{
|
||||
id_to_CDT_vh.insert(
|
||||
std::make_pair(f_indices[ik],triangle_vertices[ik]));
|
||||
if (doing_autorefinement)
|
||||
if (doing_autorefinement || handle_non_manifold_features)
|
||||
// update the current vertex in node_id_to_vertex
|
||||
// to match the one of the face
|
||||
node_id_to_vertex[f_indices[ik]]=f_vertices[ik];
|
||||
|
|
@ -1040,7 +1149,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
nodes.finalize();
|
||||
nodes.finalize(mesh_to_node_id_to_vertex);
|
||||
|
||||
// additional operations
|
||||
output_builder(nodes,
|
||||
|
|
|
|||
|
|
@ -521,28 +521,38 @@ struct Patch_container{
|
|||
typedef typename GT::face_descriptor face_descriptor;
|
||||
|
||||
Patch_description<PolygonMesh>& patch=this->operator[](i);
|
||||
out << "OFF\n" << patch.interior_vertices.size() +
|
||||
patch.shared_edges.size();
|
||||
out << " " << patch.faces.size() << " 0\n";
|
||||
|
||||
std::stringstream ss;
|
||||
std::map<vertex_descriptor, int> vertexid;
|
||||
int id=0;
|
||||
for(vertex_descriptor vh : patch.interior_vertices)
|
||||
{
|
||||
vertexid[vh]=id++;
|
||||
out << get(vertex_point, pm, vh) << "\n";
|
||||
ss << get(vertex_point, pm, vh) << "\n";
|
||||
}
|
||||
|
||||
for(halfedge_descriptor hh : patch.shared_edges)
|
||||
{
|
||||
vertexid[target(hh, pm)]=id++;
|
||||
out << get(vertex_point, pm, target(hh, pm)) << "\n";
|
||||
if( vertexid.insert( std::make_pair(target(hh,pm), id) ).second )
|
||||
{
|
||||
ss << get(vertex_point, pm, target(hh, pm)) << "\n";
|
||||
++id;
|
||||
}
|
||||
if( vertexid.insert( std::make_pair(source(hh,pm), id) ).second )
|
||||
{
|
||||
ss << get(vertex_point, pm, source(hh, pm)) << "\n";
|
||||
++id;
|
||||
}
|
||||
}
|
||||
|
||||
out << "OFF\n" << id << " " << patch.faces.size() << " 0\n";
|
||||
out << ss.str();
|
||||
|
||||
for(face_descriptor f : patch.faces)
|
||||
{
|
||||
out << "3 " << vertexid[source(halfedge(f,pm),pm)] <<
|
||||
" " << vertexid[target(halfedge(f,pm),pm)] <<
|
||||
" " << vertexid[target(next(halfedge(f,pm),pm),pm)] << "\n";
|
||||
out << "3 " << vertexid.at(source(halfedge(f,pm),pm)) <<
|
||||
" " << vertexid.at(target(halfedge(f,pm),pm)) <<
|
||||
" " << vertexid.at(target(next(halfedge(f,pm),pm),pm)) << "\n";
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
@ -559,6 +569,16 @@ struct Patch_container{
|
|||
dump_patch(i, output);
|
||||
}
|
||||
}
|
||||
void dump_patches(std::string prefix)
|
||||
{
|
||||
for (std::size_t i=0;i <patches.size() ; ++i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << prefix << "-" << i << ".off";
|
||||
std::ofstream output(ss.str().c_str());
|
||||
dump_patch(i, output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class PolygonMesh,
|
||||
|
|
@ -1637,13 +1657,16 @@ void remove_unused_polylines(
|
|||
|
||||
do{
|
||||
|
||||
halfedge_descriptor tmp_start = h;
|
||||
halfedge_descriptor starter = h;
|
||||
while ( !is_border(h, tm) || is_border(opposite(h, tm), tm) )
|
||||
{
|
||||
h = opposite(next(h, tm), tm);
|
||||
if (tmp_start==h) break;
|
||||
if (starter==h) break; // it might happen that no update is required because
|
||||
// it is already closed thanks to another patch from tm'
|
||||
// (usually incident to coplanar patches)
|
||||
|
||||
}
|
||||
if( !is_border(h, tm) )
|
||||
if( !is_border(h, tm) || is_border(opposite(h, tm), tm) )
|
||||
{
|
||||
// nothing to do: the vertex has already been updated and is now in the middle of a patch kept.
|
||||
// This function can be called after the stitching of the patches kept, the vertex halfedge
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_of_coplanar_triangles_3.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_nodes.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/Corefinement/intersect_triangle_and_segment_3.h>
|
||||
#include <CGAL/Polygon_mesh_processing/Non_manifold_feature_map.h>
|
||||
#include <CGAL/utility.h>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
|
@ -98,9 +99,12 @@ struct Default_surface_intersection_visitor{
|
|||
// If we implement a predicate only test, we can get rid of it.
|
||||
static const bool Predicates_on_constructions_needed = doing_autorefinement;
|
||||
static const bool do_need_vertex_graph = false;
|
||||
void set_non_manifold_feature_map(
|
||||
const TriangleMesh&,
|
||||
const Non_manifold_feature_map<TriangleMesh>&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct Node_id_set {
|
||||
typedef std::size_t Node_id;
|
||||
|
||||
|
|
@ -187,12 +191,17 @@ class Intersection_of_triangle_meshes
|
|||
Node_visitor visitor;
|
||||
Faces_to_nodes_map f_to_node; //Associate a pair of triangles to their intersection points
|
||||
std::vector<Node_id> extra_terminal_nodes; //used only for autorefinement
|
||||
Non_manifold_feature_map<TriangleMesh> non_manifold_feature_map_1,
|
||||
non_manifold_feature_map_2;
|
||||
static const constexpr std::size_t NM_NID = (std::numeric_limits<std::size_t>::max)();
|
||||
CGAL_assertion_code(bool doing_autorefinement;)
|
||||
|
||||
// member functions
|
||||
void filter_intersections(const TriangleMesh& tm_f,
|
||||
const TriangleMesh& tm_e,
|
||||
const VertexPointMap& vpm_f,
|
||||
const VertexPointMap& vpm_e,
|
||||
const Non_manifold_feature_map<TriangleMesh>& non_manifold_feature_map,
|
||||
bool throw_on_self_intersection)
|
||||
{
|
||||
std::vector<Box> face_boxes, edge_boxes;
|
||||
|
|
@ -213,15 +222,38 @@ class Intersection_of_triangle_meshes
|
|||
|
||||
edge_boxes.reserve(num_edges(tm_e));
|
||||
edge_boxes_ptr.reserve(num_edges(tm_e));
|
||||
for(edge_descriptor ed : edges(tm_e))
|
||||
{
|
||||
halfedge_descriptor h=halfedge(ed,tm_e);
|
||||
edge_boxes.push_back( Box(
|
||||
get(vpm_e,source(h,tm_e)).bbox() +
|
||||
get(vpm_e,target(h,tm_e)).bbox(),
|
||||
h ) );
|
||||
edge_boxes_ptr.push_back( &edge_boxes.back() );
|
||||
}
|
||||
if (non_manifold_feature_map.non_manifold_edges.empty())
|
||||
// general manifold case
|
||||
for(edge_descriptor ed : edges(tm_e))
|
||||
{
|
||||
halfedge_descriptor h=halfedge(ed,tm_e);
|
||||
edge_boxes.push_back( Box(
|
||||
get(vpm_e,source(h,tm_e)).bbox() +
|
||||
get(vpm_e,target(h,tm_e)).bbox(),
|
||||
h ) );
|
||||
edge_boxes_ptr.push_back( &edge_boxes.back() );
|
||||
}
|
||||
else
|
||||
// non-manifold case
|
||||
for(edge_descriptor ed : edges(tm_e))
|
||||
{
|
||||
std::size_t eid=get(non_manifold_feature_map.e_nm_id, ed);
|
||||
halfedge_descriptor h=halfedge(ed,tm_e);
|
||||
// insert only one copy of a non-manifold edge
|
||||
if (eid!=NM_NID)
|
||||
{
|
||||
if (non_manifold_feature_map.non_manifold_edges[eid].front()!=ed)
|
||||
continue;
|
||||
else
|
||||
// make sure the halfedge used is consistant with stored one
|
||||
h = halfedge(non_manifold_feature_map.non_manifold_edges[eid].front(), tm_e);
|
||||
}
|
||||
edge_boxes.push_back( Box(
|
||||
get(vpm_e,source(h,tm_e)).bbox() +
|
||||
get(vpm_e,target(h,tm_e)).bbox(),
|
||||
h ) );
|
||||
edge_boxes_ptr.push_back( &edge_boxes.back() );
|
||||
}
|
||||
|
||||
/// \todo experiments different cutoff values
|
||||
std::ptrdiff_t cutoff = 2 * std::ptrdiff_t(
|
||||
|
|
@ -311,18 +343,34 @@ class Intersection_of_triangle_meshes
|
|||
get_or_create_node(const Cpl_inter_pt& ipt,
|
||||
Node_id& current_node,
|
||||
std::map<Key,Node_id>& coplanar_node_map,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2)
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_2,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2)
|
||||
{
|
||||
halfedge_descriptor h1=graph_traits::null_halfedge(),h2=h1;
|
||||
switch(ipt.type_1){
|
||||
case ON_VERTEX:
|
||||
h1=halfedge(target(ipt.info_1,tm1),tm1);
|
||||
{
|
||||
std::size_t vid1 = nm_features_map_1.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.v_nm_id, target(ipt.info_1,tm1));
|
||||
if (vid1==NM_NID)
|
||||
h1=halfedge(target(ipt.info_1,tm1),tm1);
|
||||
else
|
||||
h1=halfedge(nm_features_map_1.non_manifold_vertices[vid1][0],tm1);
|
||||
}
|
||||
break;
|
||||
case ON_EDGE :
|
||||
{
|
||||
h1=opposite(ipt.info_1,tm1);
|
||||
if (h1>ipt.info_1) h1=ipt.info_1;
|
||||
std::size_t eid1 = nm_features_map_1.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.e_nm_id, edge(ipt.info_1,tm1));
|
||||
if (eid1==NM_NID)
|
||||
h1=ipt.info_1;
|
||||
else
|
||||
h1=halfedge(nm_features_map_1.non_manifold_edges[eid1][0],tm1);
|
||||
h1=(std::max)(h1, opposite(h1, tm1));
|
||||
}
|
||||
break;
|
||||
case ON_FACE :
|
||||
|
|
@ -332,12 +380,26 @@ class Intersection_of_triangle_meshes
|
|||
}
|
||||
switch(ipt.type_2){
|
||||
case ON_VERTEX:
|
||||
h2=halfedge(target(ipt.info_2,tm2),tm2);
|
||||
{
|
||||
std::size_t vid2 = nm_features_map_2.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.v_nm_id, target(ipt.info_2,tm2));
|
||||
if (vid2==NM_NID)
|
||||
h2=halfedge(target(ipt.info_2,tm2),tm2);
|
||||
else
|
||||
h2=halfedge(nm_features_map_2.non_manifold_vertices[vid2][0],tm2);
|
||||
}
|
||||
break;
|
||||
case ON_EDGE :
|
||||
{
|
||||
h2=opposite(ipt.info_2,tm2);
|
||||
if (h2>ipt.info_2) h2=ipt.info_2;
|
||||
std::size_t eid2 = nm_features_map_2.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.e_nm_id, edge(ipt.info_2,tm2));
|
||||
if (eid2==NM_NID)
|
||||
h2=ipt.info_2;
|
||||
else
|
||||
h2=halfedge(nm_features_map_2.non_manifold_edges[eid2][0],tm2);
|
||||
h2=(std::max)(h2, opposite(h2, tm2));
|
||||
}
|
||||
break;
|
||||
case ON_FACE :
|
||||
|
|
@ -360,14 +422,14 @@ class Intersection_of_triangle_meshes
|
|||
}
|
||||
|
||||
void add_intersection_point_to_face_and_all_edge_incident_faces(face_descriptor f_1,
|
||||
halfedge_descriptor e_2,
|
||||
halfedge_descriptor h_2,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2,
|
||||
Node_id node_id)
|
||||
{
|
||||
if (!is_border(e_2, tm2))
|
||||
if (!is_border(h_2, tm2))
|
||||
{
|
||||
face_descriptor f_2 = face(e_2, tm2);
|
||||
face_descriptor f_2 = face(h_2, tm2);
|
||||
if(&tm1!=&tm2 || f_1!=f_2)
|
||||
{
|
||||
Face_pair face_pair = &tm1==&tm2 ? make_sorted_pair(f_1,f_2):
|
||||
|
|
@ -378,10 +440,10 @@ class Intersection_of_triangle_meshes
|
|||
f_to_node[Face_pair_and_int(face_pair,0)].insert(node_id);
|
||||
}
|
||||
}
|
||||
e_2 = opposite(e_2, tm2);
|
||||
if (!is_border(e_2, tm2))
|
||||
h_2 = opposite(h_2, tm2);
|
||||
if (!is_border(h_2, tm2))
|
||||
{
|
||||
face_descriptor f_2 = face(e_2, tm2);
|
||||
face_descriptor f_2 = face(h_2, tm2);
|
||||
if(&tm1!=&tm2 || f_1!=f_2)
|
||||
{
|
||||
Face_pair face_pair = &tm1==&tm2 ? make_sorted_pair(f_1,f_2):
|
||||
|
|
@ -462,6 +524,7 @@ class Intersection_of_triangle_meshes
|
|||
halfedge_descriptor f_2,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
Node_id node_id,
|
||||
bool is_new_node)
|
||||
{
|
||||
|
|
@ -472,42 +535,78 @@ class Intersection_of_triangle_meshes
|
|||
? stm_edge_to_ltm_faces
|
||||
: ltm_edge_to_stm_faces;
|
||||
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v_1,tm1))
|
||||
{
|
||||
add_intersection_point_to_face_and_all_edge_incident_faces(face(f_2,tm2),h_1,tm2,tm1,node_id);
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
if (it_ets!=tm1_edge_to_tm2_faces.end()) it_ets->second.erase(face(f_2,tm2));
|
||||
}
|
||||
std::vector<vertex_descriptor> tmp_vertices_1(1, target(v_1, tm1));
|
||||
|
||||
std::size_t vid1 = nm_features_map_1.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.v_nm_id, target(v_1, tm1));
|
||||
|
||||
const std::vector<vertex_descriptor>& vertices_1 = vid1==NM_NID
|
||||
? tmp_vertices_1
|
||||
: nm_features_map_1.non_manifold_vertices[vid1];
|
||||
for(vertex_descriptor v1 : vertices_1)
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v1,tm1))
|
||||
{
|
||||
add_intersection_point_to_face_and_all_edge_incident_faces(face(f_2,tm2),h_1,tm2,tm1,node_id);
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
if (it_ets!=tm1_edge_to_tm2_faces.end()) it_ets->second.erase(face(f_2,tm2));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_coplanar_case_VERTEX_EDGE(halfedge_descriptor v_1,
|
||||
halfedge_descriptor e_2,
|
||||
halfedge_descriptor h_2,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_2,
|
||||
Node_id node_id,
|
||||
bool is_new_node)
|
||||
{
|
||||
if(is_new_node)
|
||||
visitor.new_node_added(node_id,ON_VERTEX,e_2,v_1,tm2,tm1,false,false);
|
||||
visitor.new_node_added(node_id,ON_VERTEX,h_2,v_1,tm2,tm1,false,false);
|
||||
|
||||
Edge_to_faces& tm1_edge_to_tm2_faces = &tm1 <= &tm2
|
||||
? stm_edge_to_ltm_faces
|
||||
: ltm_edge_to_stm_faces;
|
||||
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v_1,tm1))
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
Face_set* fset = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_edge(node_id,fset,h_1,e_2,tm1,tm2);
|
||||
}
|
||||
std::vector<vertex_descriptor> tmp_vertices_1(1, target(v_1, tm1));
|
||||
|
||||
std::size_t vid1 = nm_features_map_1.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.v_nm_id, target(v_1, tm1));
|
||||
|
||||
const std::vector<vertex_descriptor>& vertices_1 = vid1==NM_NID
|
||||
? tmp_vertices_1
|
||||
: nm_features_map_1.non_manifold_vertices[vid1];
|
||||
|
||||
std::vector<edge_descriptor> tmp_edges_2(1, edge(h_2, tm2));
|
||||
|
||||
std::size_t eid2 = nm_features_map_2.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.e_nm_id, edge(h_2, tm2));
|
||||
|
||||
const std::vector<edge_descriptor>& edges_2 = eid2==NM_NID
|
||||
? tmp_edges_2
|
||||
: nm_features_map_2.non_manifold_edges[eid2];
|
||||
|
||||
for (vertex_descriptor v1 : vertices_1)
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v1,tm1))
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
Face_set* fset = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
for (edge_descriptor e2 : edges_2)
|
||||
cip_handle_case_edge(node_id,fset,h_1,halfedge(e2, tm2),tm1,tm2);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_coplanar_case_VERTEX_VERTEX(halfedge_descriptor v_1,
|
||||
halfedge_descriptor v_2,
|
||||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_2,
|
||||
Node_id node_id,
|
||||
bool is_new_node)
|
||||
{
|
||||
|
|
@ -518,13 +617,33 @@ class Intersection_of_triangle_meshes
|
|||
? stm_edge_to_ltm_faces
|
||||
: ltm_edge_to_stm_faces;
|
||||
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v_1,tm1))
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
Face_set* fset = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_vertex(node_id,fset,h_1,v_2,tm1,tm2);
|
||||
}
|
||||
std::vector<vertex_descriptor> tmp_vertices_1(1, target(v_1, tm1)),
|
||||
tmp_vertices_2(1, target(v_2, tm2));
|
||||
|
||||
std::size_t vid1 = nm_features_map_1.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.v_nm_id, target(v_1, tm1));
|
||||
|
||||
std::size_t vid2 = nm_features_map_2.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.v_nm_id, target(v_2, tm2));
|
||||
|
||||
const std::vector<vertex_descriptor>& vertices_1 = vid1==NM_NID
|
||||
? tmp_vertices_1
|
||||
: nm_features_map_1.non_manifold_vertices[vid1];
|
||||
const std::vector<vertex_descriptor>& vertices_2 = vid2==NM_NID
|
||||
? tmp_vertices_2
|
||||
: nm_features_map_2.non_manifold_vertices[vid2];
|
||||
|
||||
for (vertex_descriptor v1 : vertices_1)
|
||||
for(halfedge_descriptor h_1 :
|
||||
halfedges_around_target(v1,tm1))
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(h_1,tm1));
|
||||
Face_set* fset = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
for (vertex_descriptor v2 : vertices_2)
|
||||
cip_handle_case_vertex(node_id,fset,h_1,halfedge(v2, tm2),tm1,tm2);
|
||||
}
|
||||
}
|
||||
|
||||
void compute_intersection_of_coplanar_faces(
|
||||
|
|
@ -532,7 +651,9 @@ class Intersection_of_triangle_meshes
|
|||
const TriangleMesh& tm1,
|
||||
const TriangleMesh& tm2,
|
||||
const VertexPointMap& vpm1,
|
||||
const VertexPointMap& vpm2)
|
||||
const VertexPointMap& vpm2,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_2)
|
||||
{
|
||||
CGAL_assertion( &tm1 < &tm2 || &tm1==&tm2 );
|
||||
|
||||
|
|
@ -566,7 +687,7 @@ class Intersection_of_triangle_meshes
|
|||
Node_id node_id;
|
||||
bool is_new_node;
|
||||
std::tie(node_id, is_new_node) =
|
||||
get_or_create_node(ipt,current_node,coplanar_node_map,tm1,tm2);
|
||||
get_or_create_node(ipt,current_node,coplanar_node_map,nm_features_map_1,nm_features_map_2,tm1,tm2);
|
||||
cpln_nodes.push_back(node_id);
|
||||
|
||||
switch(ipt.type_1){
|
||||
|
|
@ -574,13 +695,13 @@ class Intersection_of_triangle_meshes
|
|||
{
|
||||
switch(ipt.type_2){
|
||||
case ON_VERTEX:
|
||||
handle_coplanar_case_VERTEX_VERTEX(ipt.info_1,ipt.info_2,tm1,tm2,node_id,is_new_node);
|
||||
handle_coplanar_case_VERTEX_VERTEX(ipt.info_1,ipt.info_2,tm1,tm2,nm_features_map_1,nm_features_map_2,node_id,is_new_node);
|
||||
break;
|
||||
case ON_EDGE:
|
||||
handle_coplanar_case_VERTEX_EDGE(ipt.info_1,ipt.info_2,tm1,tm2,node_id,is_new_node);
|
||||
handle_coplanar_case_VERTEX_EDGE(ipt.info_1,ipt.info_2,tm1,tm2,nm_features_map_1,nm_features_map_2,node_id,is_new_node);
|
||||
break;
|
||||
case ON_FACE:
|
||||
handle_coplanar_case_VERTEX_FACE(ipt.info_1,ipt.info_2,tm1,tm2,node_id,is_new_node);
|
||||
handle_coplanar_case_VERTEX_FACE(ipt.info_1,ipt.info_2,tm1,tm2,nm_features_map_1,node_id,is_new_node);
|
||||
break;
|
||||
default: CGAL_error_msg("Should not get there!");
|
||||
}
|
||||
|
|
@ -590,15 +711,33 @@ class Intersection_of_triangle_meshes
|
|||
{
|
||||
switch(ipt.type_2){
|
||||
case ON_VERTEX:
|
||||
handle_coplanar_case_VERTEX_EDGE(ipt.info_2,ipt.info_1,tm2,tm1,node_id,is_new_node);
|
||||
handle_coplanar_case_VERTEX_EDGE(ipt.info_2,ipt.info_1,tm2,tm1,nm_features_map_2,nm_features_map_1,node_id,is_new_node);
|
||||
break;
|
||||
case ON_EDGE:
|
||||
{
|
||||
std::vector<edge_descriptor> tmp_edges_1(1, edge(ipt.info_1,tm1)),
|
||||
tmp_edges_2(1, edge(ipt.info_2,tm2));
|
||||
std::size_t eid1 = nm_features_map_1.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_1.e_nm_id, edge(ipt.info_1, tm1));
|
||||
std::size_t eid2 = nm_features_map_2.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.e_nm_id, edge(ipt.info_2, tm2));
|
||||
const std::vector<edge_descriptor>& edges_1 = eid1==NM_NID
|
||||
? tmp_edges_1
|
||||
: nm_features_map_1.non_manifold_edges[eid1];
|
||||
const std::vector<edge_descriptor>& edges_2 = eid2==NM_NID
|
||||
? tmp_edges_2
|
||||
: nm_features_map_2.non_manifold_edges[eid2];
|
||||
if(is_new_node)
|
||||
visitor.new_node_added(node_id,ON_EDGE,ipt.info_1,ipt.info_2,tm1,tm2,false,false);
|
||||
typename Edge_to_faces::iterator it_ets=stm_edge_to_ltm_faces.find(edge(ipt.info_1,tm1));
|
||||
Face_set* fset = (it_ets!=stm_edge_to_ltm_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_edge(node_id,fset,ipt.info_1,ipt.info_2,tm1,tm2);
|
||||
visitor.new_node_added(node_id,ON_EDGE,halfedge(edges_1.front(), tm1),halfedge(edges_2.front(),tm2),tm1,tm2,false,false);
|
||||
for(edge_descriptor e1 : edges_1)
|
||||
for(edge_descriptor e2 : edges_2)
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=stm_edge_to_ltm_faces.find(e1);
|
||||
Face_set* fset = (it_ets!=stm_edge_to_ltm_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_edge(node_id,fset,halfedge(e1,tm1),halfedge(e2,tm2),tm1,tm2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: CGAL_error_msg("Should not get there!");
|
||||
|
|
@ -608,7 +747,7 @@ class Intersection_of_triangle_meshes
|
|||
case ON_FACE:
|
||||
{
|
||||
CGAL_assertion(ipt.type_2==ON_VERTEX);
|
||||
handle_coplanar_case_VERTEX_FACE(ipt.info_2,ipt.info_1,tm2,tm1,node_id,is_new_node);
|
||||
handle_coplanar_case_VERTEX_FACE(ipt.info_2,ipt.info_1,tm2,tm1,nm_features_map_2,node_id,is_new_node);
|
||||
}
|
||||
break;
|
||||
default: CGAL_error_msg("Should not get there!");
|
||||
|
|
@ -662,6 +801,8 @@ class Intersection_of_triangle_meshes
|
|||
const TriangleMesh& tm2,
|
||||
const VertexPointMap& vpm1,
|
||||
const VertexPointMap& vpm2,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_1,
|
||||
const Non_manifold_feature_map<TriangleMesh>& nm_features_map_2,
|
||||
Node_id& current_node)
|
||||
{
|
||||
typedef std::tuple<Intersection_type, halfedge_descriptor, bool,bool> Inter_type;
|
||||
|
|
@ -671,6 +812,7 @@ class Intersection_of_triangle_meshes
|
|||
it!=tm1_edge_to_tm2_faces.end();++it)
|
||||
{
|
||||
edge_descriptor e_1=it->first;
|
||||
|
||||
halfedge_descriptor h_1=halfedge(e_1,tm1);
|
||||
Face_set& fset=it->second;
|
||||
while (!fset.empty()){
|
||||
|
|
@ -682,18 +824,93 @@ class Intersection_of_triangle_meshes
|
|||
//handle degenerate case: one extremity of edge belong to f_2
|
||||
std::vector<halfedge_descriptor> all_edges;
|
||||
if ( std::get<3>(res) ) // is edge target in triangle plane
|
||||
std::copy(halfedges_around_target(h_1,tm1).first,
|
||||
halfedges_around_target(h_1,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
{
|
||||
if (!nm_features_map_1.non_manifold_edges.empty())
|
||||
{
|
||||
std::size_t vid1 = get(nm_features_map_1.v_nm_id, target(h_1, tm1));
|
||||
if (vid1 != NM_NID)
|
||||
{
|
||||
for (vertex_descriptor vd : nm_features_map_1.non_manifold_vertices[vid1])
|
||||
{
|
||||
std::copy(halfedges_around_target(vd,tm1).first,
|
||||
halfedges_around_target(vd,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
if (all_edges.front()!=h_1)
|
||||
{
|
||||
// restore expected property
|
||||
typename std::vector<halfedge_descriptor>::iterator pos =
|
||||
std::find(all_edges.begin(), all_edges.end(), h_1);
|
||||
CGAL_assertion(pos!=all_edges.end());
|
||||
std::swap(*pos, all_edges.front());
|
||||
}
|
||||
}
|
||||
else
|
||||
std::copy(halfedges_around_target(h_1,tm1).first,
|
||||
halfedges_around_target(h_1,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
else
|
||||
std::copy(halfedges_around_target(h_1,tm1).first,
|
||||
halfedges_around_target(h_1,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
else{
|
||||
if ( std::get<2>(res) ) // is edge source in triangle plane
|
||||
{
|
||||
if (!nm_features_map_1.non_manifold_edges.empty())
|
||||
{
|
||||
std::size_t vid1 = get(nm_features_map_1.v_nm_id, source(h_1, tm1));
|
||||
if (vid1 != NM_NID)
|
||||
{
|
||||
for (vertex_descriptor vd : nm_features_map_1.non_manifold_vertices[vid1])
|
||||
{
|
||||
std::copy(halfedges_around_source(vd,tm1).first,
|
||||
halfedges_around_source(vd,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
if (all_edges.front()!=h_1)
|
||||
{
|
||||
// restore expected property
|
||||
typename std::vector<halfedge_descriptor>::iterator pos =
|
||||
std::find(all_edges.begin(), all_edges.end(), h_1);
|
||||
CGAL_assertion(pos!=all_edges.end());
|
||||
std::swap(*pos, all_edges.front());
|
||||
}
|
||||
}
|
||||
else
|
||||
std::copy(halfedges_around_source(h_1,tm1).first,
|
||||
halfedges_around_source(h_1,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
else
|
||||
std::copy(halfedges_around_source(h_1,tm1).first,
|
||||
halfedges_around_source(h_1,tm1).second,
|
||||
std::back_inserter(all_edges));
|
||||
}
|
||||
else
|
||||
{
|
||||
all_edges.push_back(h_1);
|
||||
edge_descriptor e_1 = edge(h_1, tm1);
|
||||
if (!nm_features_map_1.non_manifold_edges.empty())
|
||||
{
|
||||
std::size_t eid1 = get(nm_features_map_1.e_nm_id, e_1);
|
||||
if (eid1 != NM_NID)
|
||||
{
|
||||
CGAL_assertion( nm_features_map_1.non_manifold_edges[eid1][0]==e_1 );
|
||||
for (std::size_t k=1;
|
||||
k<nm_features_map_1.non_manifold_edges[eid1].size();
|
||||
++k)
|
||||
{
|
||||
edge_descriptor e_1b = nm_features_map_1.non_manifold_edges[eid1][k];
|
||||
// note that the orientation of the halfedge pushed back is
|
||||
// not relevant for how it is used in the following
|
||||
all_edges.push_back(halfedge(e_1b, tm1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_precondition(all_edges[0]==h_1 || all_edges[0]==opposite(h_1,tm1));
|
||||
|
||||
// #ifdef USE_DETECTION_MULTIPLE_DEFINED_EDGES
|
||||
|
|
@ -726,7 +943,9 @@ class Intersection_of_triangle_meshes
|
|||
add_intersection_point_to_face_and_all_edge_incident_faces(f_2,*it_edge,tm2,tm1,node_id);
|
||||
//erase face from the list to test intersection with it_edge
|
||||
if ( it_edge==all_edges.begin() )
|
||||
{
|
||||
fset.erase(fset.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(*it_edge,tm1));
|
||||
|
|
@ -742,15 +961,35 @@ class Intersection_of_triangle_meshes
|
|||
Node_id node_id=++current_node;
|
||||
add_new_node(h_1,f_2,tm1,tm2,vpm1,vpm2,res);
|
||||
halfedge_descriptor h_2=std::get<1>(res);
|
||||
|
||||
std::size_t eid2 = nm_features_map_2.non_manifold_edges.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.e_nm_id, edge(h_2, tm2));
|
||||
|
||||
if (eid2!=NM_NID)
|
||||
h_2 = halfedge(nm_features_map_2.non_manifold_edges[eid2].front(), tm2);
|
||||
|
||||
visitor.new_node_added(node_id,ON_EDGE,h_1,h_2,tm1,tm2,std::get<3>(res),std::get<2>(res));
|
||||
for (;it_edge!=all_edges.end();++it_edge){
|
||||
if ( it_edge!=all_edges.begin() ){
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(*it_edge,tm1));
|
||||
Face_set* fset_bis = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_edge(node_id,fset_bis,*it_edge,h_2,tm1,tm2);
|
||||
if( eid2 == NM_NID )
|
||||
cip_handle_case_edge(node_id,fset_bis,*it_edge,h_2,tm1,tm2);
|
||||
else
|
||||
{
|
||||
for (edge_descriptor e2 : nm_features_map_2.non_manifold_edges[eid2])
|
||||
cip_handle_case_edge(node_id,fset_bis,*it_edge,halfedge(e2, tm2),tm1,tm2);
|
||||
}
|
||||
}
|
||||
else
|
||||
cip_handle_case_edge(node_id,&fset,*it_edge,h_2,tm1,tm2);
|
||||
{
|
||||
if( eid2 == NM_NID )
|
||||
cip_handle_case_edge(node_id,&fset,*it_edge,h_2,tm1,tm2);
|
||||
else
|
||||
for (edge_descriptor e2 : nm_features_map_2.non_manifold_edges[eid2])
|
||||
cip_handle_case_edge(node_id,&fset,*it_edge,halfedge(e2, tm2),tm1,tm2);
|
||||
}
|
||||
}
|
||||
} // end case ON_EDGE
|
||||
break;
|
||||
|
|
@ -762,14 +1001,27 @@ class Intersection_of_triangle_meshes
|
|||
nodes.add_new_node(get(vpm2, target(h_2,tm2))); //we use the original vertex to create the node
|
||||
//before it was ON_FACE but do not remember why, probably a bug...
|
||||
visitor.new_node_added(node_id,ON_VERTEX,h_1,h_2,tm1,tm2,std::get<3>(res),std::get<2>(res));
|
||||
|
||||
std::size_t vid2 = nm_features_map_2.non_manifold_vertices.empty()
|
||||
? NM_NID
|
||||
: get(nm_features_map_2.v_nm_id, target(h_2, tm2));
|
||||
|
||||
for (;it_edge!=all_edges.end();++it_edge){
|
||||
if ( it_edge!=all_edges.begin() ){
|
||||
typename Edge_to_faces::iterator it_ets=tm1_edge_to_tm2_faces.find(edge(*it_edge,tm1));
|
||||
Face_set* fset_bis = (it_ets!=tm1_edge_to_tm2_faces.end())?&(it_ets->second):nullptr;
|
||||
cip_handle_case_vertex(node_id,fset_bis,*it_edge,h_2,tm1,tm2);
|
||||
if( vid2 == NM_NID )
|
||||
cip_handle_case_vertex(node_id,fset_bis,*it_edge,h_2,tm1,tm2);
|
||||
else
|
||||
for (vertex_descriptor vd2 : nm_features_map_2.non_manifold_vertices[vid2])
|
||||
cip_handle_case_vertex(node_id,fset_bis,*it_edge,halfedge(vd2, tm2),tm1,tm2);
|
||||
}
|
||||
else
|
||||
cip_handle_case_vertex(node_id,&fset,*it_edge,h_2,tm1,tm2);
|
||||
if( vid2 == NM_NID )
|
||||
cip_handle_case_vertex(node_id,&fset,*it_edge,h_2,tm1,tm2);
|
||||
else
|
||||
for (vertex_descriptor vd2 : nm_features_map_2.non_manifold_vertices[vid2])
|
||||
cip_handle_case_vertex(node_id,&fset,*it_edge,halfedge(vd2, tm2),tm1,tm2);
|
||||
}
|
||||
} // end case ON_VERTEX
|
||||
break;
|
||||
|
|
@ -1098,7 +1350,7 @@ class Intersection_of_triangle_meshes
|
|||
}
|
||||
else{
|
||||
CGAL_assertion(segment.size()==1);
|
||||
isolated_point_seen=true;
|
||||
isolated_point_seen=true; // NOT TRUE CAN BE END POINT OF POLYLINE FALLING ONTO AN INPUT EDGE
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1284,6 +1536,20 @@ public:
|
|||
CGAL_assertion_code( doing_autorefinement=true; )
|
||||
}
|
||||
|
||||
// setting maps of non manifold features
|
||||
void set_non_manifold_feature_map_1(internal_np::Param_not_found){}
|
||||
void set_non_manifold_feature_map_2(internal_np::Param_not_found){}
|
||||
void set_non_manifold_feature_map_1(const Non_manifold_feature_map<TriangleMesh>& m)
|
||||
{
|
||||
non_manifold_feature_map_1=m;
|
||||
visitor.set_non_manifold_feature_map(nodes.tm1, non_manifold_feature_map_1);
|
||||
}
|
||||
void set_non_manifold_feature_map_2(const Non_manifold_feature_map<TriangleMesh>& m)
|
||||
{
|
||||
non_manifold_feature_map_2=m;
|
||||
visitor.set_non_manifold_feature_map(nodes.tm2, non_manifold_feature_map_2);
|
||||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
OutputIterator operator()(OutputIterator output,
|
||||
bool throw_on_self_intersection,
|
||||
|
|
@ -1296,18 +1562,18 @@ public:
|
|||
const VertexPointMap& vpm1=nodes.vpm1;
|
||||
const VertexPointMap& vpm2=nodes.vpm2;
|
||||
|
||||
filter_intersections(tm1, tm2, vpm1, vpm2, throw_on_self_intersection);
|
||||
filter_intersections(tm2, tm1, vpm2, vpm1, throw_on_self_intersection);
|
||||
filter_intersections(tm1, tm2, vpm1, vpm2, non_manifold_feature_map_2, throw_on_self_intersection);
|
||||
filter_intersections(tm2, tm1, vpm2, vpm1, non_manifold_feature_map_1, throw_on_self_intersection);
|
||||
|
||||
Node_id current_node((std::numeric_limits<Node_id>::max)());
|
||||
CGAL_assertion(current_node+1==0);
|
||||
|
||||
// TODO: handle non-manifold edges in coplanar
|
||||
#ifndef DO_NOT_HANDLE_COPLANAR_FACES
|
||||
//first handle coplanar triangles
|
||||
if (&tm1<&tm2)
|
||||
compute_intersection_of_coplanar_faces(current_node, tm1, tm2, vpm1, vpm2);
|
||||
compute_intersection_of_coplanar_faces(current_node, tm1, tm2, vpm1, vpm2, non_manifold_feature_map_1, non_manifold_feature_map_2);
|
||||
else
|
||||
compute_intersection_of_coplanar_faces(current_node, tm2, tm1, vpm2, vpm1);
|
||||
compute_intersection_of_coplanar_faces(current_node, tm2, tm1, vpm2, vpm1, non_manifold_feature_map_2, non_manifold_feature_map_1);
|
||||
visitor.set_number_of_intersection_points_from_coplanar_faces(current_node+1);
|
||||
if (!coplanar_faces.empty())
|
||||
visitor.input_have_coplanar_faces();
|
||||
|
|
@ -1322,8 +1588,11 @@ public:
|
|||
? stm_edge_to_ltm_faces
|
||||
: ltm_edge_to_stm_faces;
|
||||
|
||||
compute_intersection_points(tm1_edge_to_tm2_faces, tm1, tm2, vpm1, vpm2, current_node);
|
||||
compute_intersection_points(tm2_edge_to_tm1_faces, tm2, tm1, vpm2, vpm1, current_node);
|
||||
compute_intersection_points(tm1_edge_to_tm2_faces, tm1, tm2, vpm1, vpm2, non_manifold_feature_map_1, non_manifold_feature_map_2, current_node);
|
||||
compute_intersection_points(tm2_edge_to_tm1_faces, tm2, tm1, vpm2, vpm1, non_manifold_feature_map_2, non_manifold_feature_map_1, current_node);
|
||||
|
||||
nodes.check_no_duplicates();
|
||||
|
||||
if (!build_polylines){
|
||||
visitor.finalize(nodes,tm1,tm2,vpm1,vpm2);
|
||||
return output;
|
||||
|
|
@ -1369,7 +1638,7 @@ public:
|
|||
CGAL_assertion(current_node+1==0);
|
||||
|
||||
//first handle coplanar triangles
|
||||
compute_intersection_of_coplanar_faces(current_node, tm, tm, vpm, vpm);
|
||||
compute_intersection_of_coplanar_faces(current_node, tm, tm, vpm, vpm, non_manifold_feature_map_1, non_manifold_feature_map_1);
|
||||
if (!coplanar_faces.empty())
|
||||
visitor.input_have_coplanar_faces();
|
||||
|
||||
|
|
@ -1377,7 +1646,7 @@ public:
|
|||
|
||||
//compute intersection points of segments and triangles.
|
||||
//build the nodes of the graph and connectivity infos
|
||||
compute_intersection_points(stm_edge_to_ltm_faces, tm, tm, vpm, vpm, current_node);
|
||||
compute_intersection_points(stm_edge_to_ltm_faces, tm, tm, vpm, vpm, non_manifold_feature_map_1, non_manifold_feature_map_1, current_node);
|
||||
|
||||
if (!build_polylines){
|
||||
visitor.finalize(nodes,tm,tm,vpm,vpm);
|
||||
|
|
|
|||
|
|
@ -125,7 +125,13 @@ public:
|
|||
}
|
||||
|
||||
void all_nodes_created(){}
|
||||
void finalize() {}
|
||||
template <class Mesh_to_map_node>
|
||||
void finalize(const Mesh_to_map_node&) {}
|
||||
|
||||
void check_no_duplicates()
|
||||
{
|
||||
CGAL_assertion(nodes.size() == std::set<Point_3>(nodes.begin(), nodes.end()).size());
|
||||
}
|
||||
|
||||
}; // end specialization
|
||||
// Intersection_nodes<Polyhedron,Kernel,No_predicates_on_constructions,false>
|
||||
|
|
@ -158,7 +164,6 @@ private:
|
|||
Exact_to_double exact_to_double;
|
||||
Exact_kernel ek;
|
||||
Exact_kernel::Intersect_3 exact_intersection;
|
||||
std::vector<vertex_descriptor> tm1_vertices, tm2_vertices;
|
||||
const bool doing_autorefinement;
|
||||
public:
|
||||
const TriangleMesh &tm1, &tm2;
|
||||
|
|
@ -268,39 +273,45 @@ public:
|
|||
}
|
||||
|
||||
void all_nodes_created()
|
||||
{}
|
||||
|
||||
void call_put(const VertexPointMap& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh&)
|
||||
{
|
||||
tm1_vertices.resize(enodes.size(), GT::null_vertex());
|
||||
tm2_vertices.resize(enodes.size(), GT::null_vertex());
|
||||
put(vpm, vd, exact_to_double(enodes[i])); // Note this call is useless and only useful to see something in debug for intermediate results
|
||||
}
|
||||
|
||||
void call_put(const VertexPointMap& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh& tm)
|
||||
template <class Node_id_to_vertex>
|
||||
void finalize(const std::map<const TriangleMesh*, Node_id_to_vertex>& mesh_to_node_id_to_vertex)
|
||||
{
|
||||
put(vpm, vd, exact_to_double(enodes[i]));
|
||||
if (&tm1==&tm)
|
||||
if (!doing_autorefinement)
|
||||
{
|
||||
if ( tm1_vertices[i] == GT::null_vertex() )
|
||||
const Node_id_to_vertex& tm1_vertices = mesh_to_node_id_to_vertex.find(&tm1)->second;
|
||||
const Node_id_to_vertex& tm2_vertices = mesh_to_node_id_to_vertex.find(&tm2)->second;
|
||||
for (std::size_t i=0, e=enodes.size(); i!=e; ++i)
|
||||
{
|
||||
tm1_vertices[i] = vd;
|
||||
return;
|
||||
Point_3 pt = exact_to_double(enodes[i]);
|
||||
if ( tm1_vertices[i] != GT::null_vertex() )
|
||||
put(vpm1, tm1_vertices[i], pt);
|
||||
if ( tm2_vertices[i] != GT::null_vertex() )
|
||||
put(vpm2, tm2_vertices[i], pt);
|
||||
}
|
||||
}
|
||||
else{
|
||||
const Node_id_to_vertex& tm1_vertices = mesh_to_node_id_to_vertex.find(&tm1)->second;
|
||||
for (std::size_t i=0, e=enodes.size(); i!=e; ++i)
|
||||
{
|
||||
Point_3 pt = exact_to_double(enodes[i]);
|
||||
if ( tm1_vertices[i] != GT::null_vertex() )
|
||||
put(vpm1, tm1_vertices[i], pt);
|
||||
}
|
||||
if (doing_autorefinement)
|
||||
tm2_vertices[i] = vd;
|
||||
}
|
||||
else
|
||||
tm2_vertices[i] = vd;
|
||||
}
|
||||
|
||||
void finalize()
|
||||
void check_no_duplicates()
|
||||
{
|
||||
for (std::size_t i=0, e=enodes.size(); i!=e; ++i)
|
||||
{
|
||||
Point_3 pt = exact_to_double(enodes[i]);
|
||||
if ( tm1_vertices[i] != GT::null_vertex() )
|
||||
put(vpm1, tm1_vertices[i], pt);
|
||||
if ( tm2_vertices[i] != GT::null_vertex() )
|
||||
put(vpm2, tm2_vertices[i], pt);
|
||||
}
|
||||
CGAL_assertion(enodes.size() == std::set<typename Exact_kernel::Point_3>(enodes.begin(), enodes.end()).size());
|
||||
}
|
||||
|
||||
}; // end specialization
|
||||
// Intersection_nodes<Polyhedron,Kernel,Predicates_on_constructions,false>
|
||||
|
||||
|
|
@ -413,9 +424,16 @@ public:
|
|||
}
|
||||
|
||||
void all_nodes_created(){}
|
||||
void finalize() {}
|
||||
|
||||
template <class Node_id_to_vertex>
|
||||
void finalize(const std::map<const TriangleMesh*, Node_id_to_vertex>&)
|
||||
{}
|
||||
|
||||
|
||||
void check_no_duplicates()
|
||||
{
|
||||
CGAL_assertion(nodes.size() == std::set<Point_3>(nodes.begin(), nodes.end()).size());
|
||||
}
|
||||
}; // end specialization
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1774,6 +1774,11 @@ surface_intersection(const TriangleMesh& tm1,
|
|||
|
||||
Corefinement::Intersection_of_triangle_meshes<TriangleMesh,Vpm>
|
||||
functor(tm1, tm2, vpm1, vpm2);
|
||||
|
||||
// Fill non-manifold feature maps if provided
|
||||
functor.set_non_manifold_feature_map_1(parameters::get_parameter(np1, internal_np::non_manifold_feature_map));
|
||||
functor.set_non_manifold_feature_map_2(parameters::get_parameter(np2, internal_np::non_manifold_feature_map));
|
||||
|
||||
return functor(polyline_output, throw_on_self_intersection, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue