mirror of https://github.com/CGAL/cgal
implement API update
This commit is contained in:
parent
7e38151479
commit
88bb9570c0
|
|
@ -4,6 +4,7 @@
|
|||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/detect_features.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
|
@ -17,8 +18,7 @@ namespace PMP = CGAL::Polygon_mesh_processing;
|
|||
int main()
|
||||
{
|
||||
Surface_mesh sm;
|
||||
std::ifstream in("data/cube_quad.off");
|
||||
in >> sm;
|
||||
CGAL::IO::read_polygon_mesh(CGAL::data_file_path("meshes/cube_quad.off"), sm);
|
||||
|
||||
// triangulate faces;
|
||||
PMP::triangulate_faces(sm);
|
||||
|
|
@ -36,11 +36,12 @@ int main()
|
|||
assert(faces(sm).size()>100);
|
||||
|
||||
// decimate the mesh
|
||||
PMP::remesh_planar_patches(sm);
|
||||
std::ofstream("cube_decimated.off") << sm;
|
||||
Surface_mesh out;
|
||||
PMP::remesh_planar_patches(sm, out);
|
||||
std::ofstream("cube_decimated.off") << out;
|
||||
|
||||
// we should be back to 12 faces
|
||||
assert(faces(sm).size()==12);
|
||||
assert(faces(out).size()==12);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2018 GeometryFactory (France).
|
||||
// Copyright (c) 2018-2023 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Sebastien Loriot
|
||||
// Author(s) : Sébastien Loriot
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_REMESH_PLANAR_PATCHES_H
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_REMESH_PLANAR_PATCHES_H
|
||||
|
|
@ -27,19 +27,98 @@
|
|||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <unordered_map>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
#include <boost/iterator/function_output_iterator.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/// @todo remove Kernel_traits
|
||||
/// @todo function to move in PMP: retriangulate_planar_patches(in, out, vci, ecm, fccid, np) (pca is a np option)
|
||||
|
||||
|
||||
namespace CGAL{
|
||||
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
namespace Planar_segmentation{
|
||||
|
||||
template <class TriangleMeshOut, class VertexCornerMapOut>
|
||||
struct Triangle_index_tracker_base
|
||||
{
|
||||
typedef boost::graph_traits<TriangleMeshOut> GT;
|
||||
|
||||
Triangle_index_tracker_base(VertexCornerMapOut vertex_corner_map)
|
||||
: vertex_corner_map(vertex_corner_map)
|
||||
{}
|
||||
|
||||
decltype(auto)
|
||||
v2v_oi()
|
||||
{
|
||||
auto l = [this](const std::pair<std::size_t, typename GT::vertex_descriptor>& p)
|
||||
{
|
||||
put(vertex_corner_map, p.second, p.first);
|
||||
};
|
||||
return boost::make_function_output_iterator(l);
|
||||
}
|
||||
|
||||
VertexCornerMapOut vertex_corner_map;
|
||||
};
|
||||
|
||||
template <class TriangleMeshOut>
|
||||
struct Triangle_index_tracker_base<TriangleMeshOut, internal_np::Param_not_found>
|
||||
{
|
||||
typedef boost::graph_traits<TriangleMeshOut> GT;
|
||||
|
||||
Triangle_index_tracker_base(internal_np::Param_not_found) {}
|
||||
Emptyset_iterator v2v_oi() { return Emptyset_iterator(); }
|
||||
};
|
||||
|
||||
template <class TriangleMeshOut, class VertexCornerMapOut, class FacePatchMapOut>
|
||||
struct Triangle_index_tracker
|
||||
: public Triangle_index_tracker_base<TriangleMeshOut, VertexCornerMapOut>
|
||||
{
|
||||
typedef boost::graph_traits<TriangleMeshOut> GT;
|
||||
|
||||
Triangle_index_tracker(VertexCornerMapOut vertex_corner_map, FacePatchMapOut face_patch_map)
|
||||
: Triangle_index_tracker_base<TriangleMeshOut, VertexCornerMapOut>(vertex_corner_map)
|
||||
, face_patch_map(face_patch_map)
|
||||
{}
|
||||
|
||||
std::vector<std::size_t> triangle_ids;
|
||||
void new_triangle_added_to_patch(std::size_t i)
|
||||
{
|
||||
triangle_ids.push_back(i);
|
||||
}
|
||||
|
||||
void new_triangles_added_to_patch(std::size_t nb_triangles, std::size_t i)
|
||||
{
|
||||
triangle_ids.resize(triangle_ids.size()+nb_triangles, i);
|
||||
}
|
||||
|
||||
decltype(auto)
|
||||
f2f_oi()
|
||||
{
|
||||
auto l = [this](const std::pair<std::size_t, typename GT::face_descriptor>& p)
|
||||
{
|
||||
put(face_patch_map, p.second, triangle_ids[p.first]);
|
||||
};
|
||||
return boost::make_function_output_iterator(l);
|
||||
}
|
||||
|
||||
FacePatchMapOut face_patch_map;
|
||||
};
|
||||
|
||||
|
||||
template <class TriangleMeshOut, class VertexCornerMapOut>
|
||||
struct Triangle_index_tracker<TriangleMeshOut, VertexCornerMapOut, internal_np::Param_not_found>
|
||||
: public Triangle_index_tracker_base<TriangleMeshOut, VertexCornerMapOut>
|
||||
{
|
||||
Triangle_index_tracker(VertexCornerMapOut vertex_corner_map,internal_np::Param_not_found)
|
||||
: Triangle_index_tracker_base<TriangleMeshOut, VertexCornerMapOut>(vertex_corner_map)
|
||||
{}
|
||||
|
||||
void new_triangle_added_to_patch(std::size_t /*in_patch_id*/) {}
|
||||
void new_triangles_added_to_patch(std::size_t /*nb_triangles*/, std::size_t /*in_patch_id*/) {}
|
||||
|
||||
Emptyset_iterator f2f_oi() { return Emptyset_iterator(); }
|
||||
};
|
||||
|
||||
|
||||
inline std::size_t init_id()
|
||||
{
|
||||
return std::size_t(-1);
|
||||
|
|
@ -85,7 +164,8 @@ struct FaceInfo2
|
|||
bool in_domain() const { return m_in_domain==1; }
|
||||
};
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename VertexPointMap,
|
||||
typename edge_descriptor>
|
||||
bool is_edge_between_coplanar_faces(edge_descriptor e,
|
||||
|
|
@ -93,8 +173,7 @@ bool is_edge_between_coplanar_faces(edge_descriptor e,
|
|||
double coplanar_cos_threshold,
|
||||
const VertexPointMap& vpm)
|
||||
{
|
||||
typedef typename boost::property_traits<VertexPointMap>::value_type Point_3;
|
||||
typedef typename Kernel_traits<Point_3>::type K;
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef typename boost::property_traits<VertexPointMap>::reference Point_ref_3;
|
||||
if (is_border(e, tm)) return false;
|
||||
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor
|
||||
|
|
@ -108,12 +187,13 @@ bool is_edge_between_coplanar_faces(edge_descriptor e,
|
|||
return coplanar(p, q, r, s);
|
||||
else
|
||||
{
|
||||
typename K::Compare_dihedral_angle_3 pred;
|
||||
return pred(p, q, r, s, typename K::FT(coplanar_cos_threshold)) == CGAL::LARGER;
|
||||
typename Kernel::Compare_dihedral_angle_3 pred;
|
||||
return pred(p, q, r, s, typename Kernel::FT(coplanar_cos_threshold)) == CGAL::LARGER;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename VertexPointMap,
|
||||
typename halfedge_descriptor,
|
||||
typename EdgeIsConstrainedMap>
|
||||
|
|
@ -123,8 +203,7 @@ bool is_target_vertex_a_corner(halfedge_descriptor h,
|
|||
double coplanar_cos_threshold,
|
||||
const VertexPointMap& vpm)
|
||||
{
|
||||
typedef typename boost::property_traits<VertexPointMap>::value_type Point_3;
|
||||
typedef typename Kernel_traits<Point_3>::type K;
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef typename boost::graph_traits<TriangleMesh> graph_traits;
|
||||
|
||||
halfedge_descriptor h2 = graph_traits::null_halfedge();
|
||||
|
|
@ -150,12 +229,13 @@ bool is_target_vertex_a_corner(halfedge_descriptor h,
|
|||
return !collinear(p, q, r);
|
||||
else
|
||||
{
|
||||
typename K::Compare_angle_3 pred;
|
||||
return pred(p, q, r, typename K::FT(coplanar_cos_threshold))==CGAL::SMALLER;
|
||||
typename Kernel::Compare_angle_3 pred;
|
||||
return pred(p, q, r, typename Kernel::FT(coplanar_cos_threshold))==CGAL::SMALLER;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename VertexPointMap>
|
||||
void
|
||||
|
|
@ -168,12 +248,13 @@ mark_constrained_edges(
|
|||
for(typename boost::graph_traits<TriangleMesh>::edge_descriptor e : edges(tm))
|
||||
{
|
||||
if (!get(edge_is_constrained,e))
|
||||
if (!is_edge_between_coplanar_faces(e, tm, coplanar_cos_threshold, vpm))
|
||||
if (!is_edge_between_coplanar_faces<Kernel>(e, tm, coplanar_cos_threshold, vpm))
|
||||
put(edge_is_constrained, e, true);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename VertexPointMap,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename VertexCornerIdMap>
|
||||
|
|
@ -194,14 +275,14 @@ mark_corner_vertices(
|
|||
|
||||
if (is_init_id(get(vertex_corner_id, target(h, tm))))
|
||||
{
|
||||
if (is_target_vertex_a_corner(h, edge_is_constrained, tm, coplanar_cos_threshold, vpm))
|
||||
if (is_target_vertex_a_corner<Kernel>(h, edge_is_constrained, tm, coplanar_cos_threshold, vpm))
|
||||
put(vertex_corner_id, target(h, tm), corner_id++);
|
||||
else
|
||||
put(vertex_corner_id, target(h, tm), default_id());
|
||||
}
|
||||
if (is_init_id(get(vertex_corner_id, source(h, tm))))
|
||||
{
|
||||
if (is_target_vertex_a_corner(opposite(h, tm), edge_is_constrained, tm, coplanar_cos_threshold, vpm))
|
||||
if (is_target_vertex_a_corner<Kernel>(opposite(h, tm), edge_is_constrained, tm, coplanar_cos_threshold, vpm))
|
||||
put(vertex_corner_id, source(h, tm), corner_id++);
|
||||
else
|
||||
put(vertex_corner_id, source(h, tm), default_id());
|
||||
|
|
@ -301,7 +382,7 @@ template <typename Kernel>
|
|||
bool add_triangle_faces(const std::vector< std::pair<std::size_t, std::size_t> >& csts,
|
||||
typename Kernel::Vector_3 normal,
|
||||
const std::vector<typename Kernel::Point_3>& corners,
|
||||
std::vector<cpp11::array<std::size_t, 3> >& triangles)
|
||||
std::vector<std::array<std::size_t, 3> >& triangles)
|
||||
{
|
||||
typedef Projection_traits_3<Kernel> P_traits;
|
||||
typedef Triangulation_vertex_base_with_id_2<P_traits> Vb;
|
||||
|
|
@ -400,7 +481,8 @@ bool add_triangle_faces(const std::vector< std::pair<std::size_t, std::size_t> >
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename VertexCornerIdMap,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename FaceCCIdMap,
|
||||
|
|
@ -415,7 +497,7 @@ tag_corners_and_constrained_edges(TriangleMesh& tm,
|
|||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh> graph_traits;
|
||||
// mark constrained edges
|
||||
mark_constrained_edges(tm, edge_is_constrained, coplanar_cos_threshold, vpm);
|
||||
mark_constrained_edges<Kernel>(tm, edge_is_constrained, coplanar_cos_threshold, vpm);
|
||||
|
||||
// mark connected components (cc) delimited by constrained edges
|
||||
std::size_t nb_cc = Polygon_mesh_processing::connected_components(
|
||||
|
|
@ -435,40 +517,39 @@ tag_corners_and_constrained_edges(TriangleMesh& tm,
|
|||
}
|
||||
|
||||
std::size_t nb_corners =
|
||||
mark_corner_vertices(tm, edge_is_constrained, vertex_corner_id, coplanar_cos_threshold, vpm);
|
||||
mark_corner_vertices<Kernel>(tm, edge_is_constrained, vertex_corner_id, coplanar_cos_threshold, vpm);
|
||||
|
||||
return std::make_pair(nb_corners, nb_cc);
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMesh,
|
||||
typename VertexCornerIdMap,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename FaceCCIdMap,
|
||||
typename VertexPointMap,
|
||||
typename Point_3>
|
||||
typename IndexTracking>
|
||||
bool decimate_impl(const TriangleMesh& tm,
|
||||
std::pair<std::size_t, std::size_t>& nb_corners_and_nb_cc,
|
||||
VertexCornerIdMap& vertex_corner_id,
|
||||
EdgeIsConstrainedMap& edge_is_constrained,
|
||||
FaceCCIdMap& face_cc_ids,
|
||||
const VertexPointMap& vpm,
|
||||
std::vector< Point_3 >& corners,
|
||||
std::vector< cpp11::array<std::size_t, 3> >& out_triangles)
|
||||
std::vector< typename Kernel::Point_3 >& corners,
|
||||
std::vector< std::array<std::size_t, 3> >& out_triangles,
|
||||
IndexTracking& t_id_tracker)
|
||||
{
|
||||
typedef typename Kernel_traits<Point_3>::type K;
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef typename Kernel::Vector_3 Vector_3;
|
||||
typedef typename boost::graph_traits<TriangleMesh> graph_traits;
|
||||
typedef typename graph_traits::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename graph_traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits::face_descriptor face_descriptor;
|
||||
typedef std::pair<std::size_t, std::size_t> Id_pair;
|
||||
std::vector< typename K::Vector_3 > face_normals(nb_corners_and_nb_cc.second, NULL_VECTOR);
|
||||
|
||||
|
||||
/// @TODO this is rather drastic in particular if the mesh has almost none simplified faces
|
||||
/// TODO use add_faces?
|
||||
std::vector< Vector_3 > face_normals(nb_corners_and_nb_cc.second, NULL_VECTOR);
|
||||
|
||||
// compute the new mesh
|
||||
std::vector< std::vector< cpp11::array<std::size_t, 3> > > triangles_per_cc(nb_corners_and_nb_cc.second);
|
||||
std::vector< std::vector< std::array<std::size_t, 3> > > triangles_per_cc(nb_corners_and_nb_cc.second);
|
||||
boost::dynamic_bitset<> cc_to_handle(nb_corners_and_nb_cc.second);
|
||||
cc_to_handle.set();
|
||||
|
||||
|
|
@ -526,7 +607,7 @@ bool decimate_impl(const TriangleMesh& tm,
|
|||
cc_id < cc_to_handle.npos;
|
||||
cc_id = cc_to_handle.find_next(cc_id))
|
||||
{
|
||||
std::vector< cpp11::array<std::size_t, 3> >& triangles = triangles_per_cc[cc_id];
|
||||
std::vector< std::array<std::size_t, 3> >& triangles = triangles_per_cc[cc_id];
|
||||
triangles.clear();
|
||||
|
||||
std::vector< Id_pair >& csts = face_boundaries[cc_id];
|
||||
|
|
@ -551,10 +632,12 @@ bool decimate_impl(const TriangleMesh& tm,
|
|||
csts[0].second==csts[1].first ?
|
||||
csts[1].second:csts[1].first) );
|
||||
cc_to_handle.set(cc_id, 0);
|
||||
t_id_tracker.new_triangle_added_to_patch(cc_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (csts.size() > 3 && add_triangle_faces<K>(csts, face_normals[cc_id], corners, triangles))
|
||||
std::size_t prev_triangles_size=triangles.size();
|
||||
if (csts.size() > 3 && add_triangle_faces<Kernel>(csts, face_normals[cc_id], corners, triangles))
|
||||
cc_to_handle.set(cc_id, 0);
|
||||
else
|
||||
{
|
||||
|
|
@ -571,7 +654,8 @@ bool decimate_impl(const TriangleMesh& tm,
|
|||
std::size_t i = get(vertex_corner_id, v);
|
||||
if ( !is_corner_id(i) )
|
||||
{
|
||||
put(vertex_corner_id, v, nb_corners_and_nb_cc.first++);
|
||||
i = nb_corners_and_nb_cc.first++;
|
||||
put(vertex_corner_id, v, i);
|
||||
corners.push_back(get(vpm, v));
|
||||
new_corners.push_back(v);
|
||||
}
|
||||
|
|
@ -583,6 +667,7 @@ bool decimate_impl(const TriangleMesh& tm,
|
|||
triangles.push_back({ get(vertex_corner_id, source(h,tm)),
|
||||
get(vertex_corner_id, target(h,tm)),
|
||||
get(vertex_corner_id, target(next(h,tm), tm)) });
|
||||
t_id_tracker.new_triangle_added_to_patch(cc_id);
|
||||
}
|
||||
// reset flag for neighbor connected components only if interface has changed
|
||||
for (vertex_descriptor v : new_corners)
|
||||
|
|
@ -599,58 +684,75 @@ bool decimate_impl(const TriangleMesh& tm,
|
|||
}
|
||||
cc_to_handle.set(cc_id, 0);
|
||||
}
|
||||
t_id_tracker.new_triangles_added_to_patch(triangles.size()-prev_triangles_size, cc_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
while(cc_to_handle.any());
|
||||
|
||||
for (const std::vector<cpp11::array<std::size_t, 3>>& cc_trs : triangles_per_cc)
|
||||
for (const std::vector<std::array<std::size_t, 3>>& cc_trs : triangles_per_cc)
|
||||
out_triangles.insert(out_triangles.end(), cc_trs.begin(), cc_trs.end());
|
||||
|
||||
return all_patches_successfully_remeshed;
|
||||
}
|
||||
|
||||
template <typename TriangleMesh,
|
||||
template <typename Kernel,
|
||||
typename TriangleMeshIn,
|
||||
typename TriangleMeshOut,
|
||||
typename VertexCornerIdMap,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename FaceCCIdMap,
|
||||
typename VertexPointMap>
|
||||
bool decimate_impl(TriangleMesh& tm,
|
||||
typename VertexPointMapIn,
|
||||
typename VertexPointMapOut,
|
||||
typename VertexCornerMapOut,
|
||||
typename FacePatchMapOut>
|
||||
bool decimate_impl(const TriangleMeshIn& tm_in,
|
||||
TriangleMeshOut& tm_out,
|
||||
std::pair<std::size_t, std::size_t> nb_corners_and_nb_cc,
|
||||
VertexCornerIdMap& vertex_corner_id,
|
||||
EdgeIsConstrainedMap& edge_is_constrained,
|
||||
FaceCCIdMap& face_cc_ids,
|
||||
const VertexPointMap& vpm)
|
||||
const VertexPointMapIn& vpm_in,
|
||||
const VertexPointMapOut& vpm_out,
|
||||
VertexCornerMapOut vcorner_map_out,
|
||||
FacePatchMapOut fpatch_map_out)
|
||||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh> graph_traits;
|
||||
typedef typename boost::graph_traits<TriangleMeshIn> graph_traits;
|
||||
typedef typename graph_traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::property_traits<VertexPointMap>::value_type Point_3;
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
|
||||
Triangle_index_tracker<TriangleMeshOut, VertexCornerMapOut, FacePatchMapOut>
|
||||
t_id_tracker(vcorner_map_out, fpatch_map_out);
|
||||
|
||||
//collect corners
|
||||
std::vector< Point_3 > corners(nb_corners_and_nb_cc.first);
|
||||
for(vertex_descriptor v : vertices(tm))
|
||||
for(vertex_descriptor v : vertices(tm_in))
|
||||
{
|
||||
std::size_t i = get(vertex_corner_id, v);
|
||||
if ( is_corner_id(i) )
|
||||
corners[i]=get(vpm, v);
|
||||
{
|
||||
corners[i]=get(vpm_in, v);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< cpp11::array<std::size_t, 3> > triangles;
|
||||
bool remeshing_failed = decimate_impl(tm,
|
||||
nb_corners_and_nb_cc,
|
||||
vertex_corner_id,
|
||||
edge_is_constrained,
|
||||
face_cc_ids,
|
||||
vpm,
|
||||
corners,
|
||||
triangles);
|
||||
std::vector< std::array<std::size_t, 3> > triangles;
|
||||
bool remeshing_failed = decimate_impl<Kernel>(tm_in,
|
||||
nb_corners_and_nb_cc,
|
||||
vertex_corner_id,
|
||||
edge_is_constrained,
|
||||
face_cc_ids,
|
||||
vpm_in,
|
||||
corners,
|
||||
triangles,
|
||||
t_id_tracker);
|
||||
|
||||
if (!is_polygon_soup_a_polygon_mesh(triangles))
|
||||
return false;
|
||||
|
||||
//clear(tm);
|
||||
tm.clear_without_removing_property_maps();
|
||||
polygon_soup_to_polygon_mesh(corners, triangles, tm, parameters::all_default(), parameters::vertex_point_map(vpm));
|
||||
polygon_soup_to_polygon_mesh(corners, triangles, tm_out,
|
||||
parameters::vertex_to_vertex_output_iterator(t_id_tracker.v2v_oi()).
|
||||
face_to_face_output_iterator(t_id_tracker.f2f_oi()),
|
||||
parameters::vertex_point_map(vpm_out));
|
||||
return remeshing_failed;
|
||||
}
|
||||
|
||||
|
|
@ -811,7 +913,8 @@ void propagate_corner_status(
|
|||
}
|
||||
}
|
||||
|
||||
template <typename TriangleMeshRange,
|
||||
template <typename Kernel,
|
||||
typename TriangleMeshRange,
|
||||
typename MeshMap,
|
||||
typename VertexPointMap>
|
||||
bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes,
|
||||
|
|
@ -922,12 +1025,12 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes,
|
|||
|
||||
if (!mesh_has_non_manifold_vertices[mesh_id])
|
||||
nb_corners_and_nb_cc_all[mesh_id] =
|
||||
tag_corners_and_constrained_edges(tm,
|
||||
coplanar_cos_threshold,
|
||||
vertex_corner_id_maps[mesh_id],
|
||||
edge_is_constrained_maps[mesh_id],
|
||||
face_cc_ids_maps[mesh_id],
|
||||
vpms[mesh_id]);
|
||||
tag_corners_and_constrained_edges<Kernel>(tm,
|
||||
coplanar_cos_threshold,
|
||||
vertex_corner_id_maps[mesh_id],
|
||||
edge_is_constrained_maps[mesh_id],
|
||||
face_cc_ids_maps[mesh_id],
|
||||
vpms[mesh_id]);
|
||||
else
|
||||
{
|
||||
nb_corners_and_nb_cc_all[mesh_id]={0,1};
|
||||
|
|
@ -951,7 +1054,7 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes,
|
|||
// now call the decimation
|
||||
// storage of all new triangles and all corners
|
||||
std::vector< std::vector< Point_3 > > all_corners(nb_meshes);
|
||||
std::vector< std::vector< cpp11::array<std::size_t, 3> > > all_triangles(nb_meshes);
|
||||
std::vector< std::vector< std::array<std::size_t, 3> > > all_triangles(nb_meshes);
|
||||
bool res = true;
|
||||
std::vector<bool> to_be_processed(nb_meshes, true);
|
||||
bool loop_again;
|
||||
|
|
@ -1162,45 +1265,68 @@ void remesh_planar_patches(const TriangleMeshIn& tm_in,
|
|||
const NamedParametersIn& np_in = parameters::default_values(),
|
||||
const NamedParametersOut& np_out = parameters::default_values())
|
||||
{
|
||||
/*
|
||||
// typedef typename GetGeomTraits<TriangleMesh, NamedParameters>::type Traits;
|
||||
typedef typename GetVertexPointMap <TriangleMesh, NamedParameters>::type VPM;
|
||||
//TODO: demo plugin
|
||||
|
||||
typedef typename GetGeomTraits<TriangleMeshIn, NamedParametersIn>::type Traits;
|
||||
typedef typename GetVertexPointMap <TriangleMeshIn, NamedParametersIn>::const_type VPM_in;
|
||||
typedef typename GetVertexPointMap <TriangleMeshIn, NamedParametersOut>::type VPM_out;
|
||||
using parameters::choose_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
typedef typename boost::graph_traits<TriangleMesh> graph_traits;
|
||||
typedef typename boost::graph_traits<TriangleMeshIn> graph_traits;
|
||||
typedef typename graph_traits::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits::face_descriptor face_descriptor;
|
||||
|
||||
double coplanar_cos_threshold = choose_parameter(get_parameter(np, internal_np::cosinus_threshold), -1);
|
||||
double coplanar_cos_threshold = choose_parameter(get_parameter(np_in, internal_np::cosinus_threshold), -1);
|
||||
CGAL_precondition(coplanar_cos_threshold<0);
|
||||
|
||||
// initialize property maps
|
||||
typename boost::property_map<TriangleMesh, CGAL::dynamic_edge_property_t<bool> >::type edge_is_constrained = get(CGAL::dynamic_edge_property_t<bool>(), tm);
|
||||
for(edge_descriptor e : edges(tm))
|
||||
put(edge_is_constrained, e, false);
|
||||
// initialize property maps (fill user provided or user internal ones)
|
||||
typedef typename boost::property_map<TriangleMeshIn,
|
||||
dynamic_edge_property_t<bool> >::const_type Default_ECM;
|
||||
typedef typename boost::property_map<TriangleMeshIn,
|
||||
dynamic_vertex_property_t<std::size_t> >::const_type Default_VCM;
|
||||
typedef typename boost::property_map<TriangleMeshIn,
|
||||
dynamic_face_property_t<std::size_t> >::const_type Default_FCM;
|
||||
|
||||
typename boost::property_map<TriangleMesh, CGAL::dynamic_vertex_property_t<std::size_t> >::type vertex_corner_id = get(CGAL::dynamic_vertex_property_t<std::size_t>(), tm);
|
||||
for(vertex_descriptor v : vertices(tm))
|
||||
put(vertex_corner_id, v, Planar_segmentation::init_id());
|
||||
typename internal_np::Lookup_named_param_def< internal_np::edge_is_constrained_t,
|
||||
NamedParametersIn,
|
||||
Default_ECM>::type
|
||||
edge_is_constrained = choose_parameter<Default_ECM>(get_parameter(np_in, internal_np::edge_is_constrained),
|
||||
dynamic_edge_property_t<bool>(), tm_in);
|
||||
|
||||
typename boost::property_map<TriangleMesh, CGAL::dynamic_face_property_t<std::size_t> >::type face_cc_ids = get(CGAL::dynamic_face_property_t<std::size_t>(), tm);
|
||||
for(face_descriptor f : faces(tm))
|
||||
put(face_cc_ids, f, -1);
|
||||
typename internal_np::Lookup_named_param_def< internal_np::vertex_corner_map_t,
|
||||
NamedParametersIn,
|
||||
Default_VCM>::type
|
||||
vertex_corner_id = choose_parameter<Default_VCM>(get_parameter(np_in, internal_np::vertex_corner_map),
|
||||
dynamic_vertex_property_t<std::size_t>(), tm_in);
|
||||
|
||||
VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_property_map(vertex_point, tm));
|
||||
typename internal_np::Lookup_named_param_def< internal_np::face_patch_t,
|
||||
NamedParametersIn,
|
||||
Default_FCM>::type
|
||||
face_cc_ids = choose_parameter<Default_FCM>(get_parameter(np_in, internal_np::face_patch),
|
||||
dynamic_face_property_t<std::size_t>(), tm_in);
|
||||
|
||||
for(edge_descriptor e : edges(tm_in)) put(edge_is_constrained, e, false);
|
||||
for(vertex_descriptor v : vertices(tm_in)) put(vertex_corner_id, v, Planar_segmentation::init_id());
|
||||
for(face_descriptor f : faces(tm_in)) put(face_cc_ids, f, -1);
|
||||
|
||||
VPM_in vpm_in = choose_parameter(get_parameter(np_in, internal_np::vertex_point),
|
||||
get_const_property_map(vertex_point, tm_in));
|
||||
|
||||
VPM_out vpm_out = choose_parameter(get_parameter(np_out, internal_np::vertex_point),
|
||||
get_property_map(vertex_point, tm_out));
|
||||
|
||||
std::pair<std::size_t, std::size_t> nb_corners_and_nb_cc =
|
||||
Planar_segmentation::tag_corners_and_constrained_edges(tm, coplanar_cos_threshold, vertex_corner_id, edge_is_constrained, face_cc_ids, vpm);
|
||||
Planar_segmentation::decimate_impl(tm,
|
||||
nb_corners_and_nb_cc,
|
||||
vertex_corner_id,
|
||||
edge_is_constrained,
|
||||
face_cc_ids,
|
||||
vpm);
|
||||
*/
|
||||
Planar_segmentation::tag_corners_and_constrained_edges<Traits>(tm_in, coplanar_cos_threshold, vertex_corner_id, edge_is_constrained, face_cc_ids, vpm_in);
|
||||
Planar_segmentation::decimate_impl<Traits>(tm_in, tm_out,
|
||||
nb_corners_and_nb_cc,
|
||||
vertex_corner_id,
|
||||
edge_is_constrained,
|
||||
face_cc_ids,
|
||||
vpm_in, vpm_out,
|
||||
get_parameter(np_out, internal_np::vertex_corner_map),
|
||||
get_parameter(np_out, internal_np::face_patch));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -1280,7 +1406,8 @@ template <typename TriangleMeshIn,
|
|||
typename FacePatchMap,
|
||||
typename EdgeIsConstrainedMap,
|
||||
typename VertexCornerMap,
|
||||
typename NamedParameters = parameters::Default_named_parameters>
|
||||
typename NamedParametersIn = parameters::Default_named_parameters,
|
||||
typename NamedParametersOut = parameters::Default_named_parameters>
|
||||
bool remesh_almost_planar_patches(const TriangleMeshIn& tm_in,
|
||||
TriangleMeshOut& tm_out,
|
||||
std::size_t nb_patches,
|
||||
|
|
@ -1291,21 +1418,25 @@ bool remesh_almost_planar_patches(const TriangleMeshIn& tm_in,
|
|||
const NamedParametersIn& np_in = parameters::default_values(),
|
||||
const NamedParametersOut& np_out = parameters::default_values())
|
||||
{
|
||||
/*
|
||||
typedef typename GetVertexPointMap <TriangleMesh, NamedParameters>::type VPM;
|
||||
typedef typename GetGeomTraits<TriangleMeshIn, NamedParametersIn>::type Traits;
|
||||
typedef typename GetVertexPointMap <TriangleMeshIn, NamedParametersIn>::const_type VPM_in;
|
||||
typedef typename GetVertexPointMap <TriangleMeshIn, NamedParametersOut>::type VPM_out;
|
||||
using parameters::choose_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_property_map(vertex_point, tm));
|
||||
VPM_in vpm_in = choose_parameter(get_parameter(np_in, internal_np::vertex_point),
|
||||
get_const_property_map(vertex_point, tm_in));
|
||||
|
||||
return Planar_segmentation::decimate_impl(tm,
|
||||
std::make_pair(nb_corners, nb_patches),
|
||||
vertex_corner_map, ecm, face_patch_map, vpm);
|
||||
*/
|
||||
VPM_out vpm_out = choose_parameter(get_parameter(np_out, internal_np::vertex_point),
|
||||
get_property_map(vertex_point, tm_out));
|
||||
|
||||
return Planar_segmentation::decimate_impl<Traits>(tm_in, tm_out,
|
||||
std::make_pair(nb_corners, nb_patches),
|
||||
vertex_corner_map, ecm, face_patch_map, vpm_in, vpm_out,
|
||||
get_parameter(np_out, internal_np::vertex_corner_map),
|
||||
get_parameter(np_out, internal_np::face_patch));
|
||||
}
|
||||
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
// MeshMap must be a mutable lvalue pmap with Triangle_mesh as value_type
|
||||
template <typename TriangleMeshRange, typename MeshMap>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ int main()
|
|||
in >> sm;
|
||||
|
||||
// call the decimation function
|
||||
if (!PMP::remesh_planar_patches(sm))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out))
|
||||
{
|
||||
std::cerr << "ERROR: decimate failed to remesh some patches\n";
|
||||
OK=false;
|
||||
|
|
@ -46,9 +47,9 @@ int main()
|
|||
ss=std::stringstream();
|
||||
ss << "out" << i << ".off";
|
||||
std::ofstream out(ss.str().c_str());
|
||||
out << sm;
|
||||
out << out;
|
||||
std::cout << " output written to out" << i << ".off\n";
|
||||
assert(is_valid_polygon_mesh(sm));
|
||||
assert(is_valid_polygon_mesh(out));
|
||||
}
|
||||
// testing border non-manifold vertex: not working for now, test kept
|
||||
/*
|
||||
|
|
@ -81,11 +82,12 @@ int main()
|
|||
CGAL::Euler::remove_face(halfedge(f2, sm), sm);
|
||||
PMP::duplicate_non_manifold_vertices(sm);
|
||||
std::size_t nbv_before = vertices(sm).size();
|
||||
if (!PMP::remesh_planar_patches(sm))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out))
|
||||
std::cerr << "decimate failed to remesh some patches (expected)\n";
|
||||
assert(vertices(sm).size()<nbv_before);
|
||||
std::ofstream("nmd_m1.off") << std::setprecision(17) << sm;
|
||||
assert(is_valid_polygon_mesh(sm));
|
||||
assert(vertices(out).size()<nbv_before);
|
||||
std::ofstream("nmd_m1.off") << std::setprecision(17) << out;
|
||||
assert(is_valid_polygon_mesh(out));
|
||||
}
|
||||
// test duplicated vertex at patch interface
|
||||
{
|
||||
|
|
@ -98,11 +100,12 @@ int main()
|
|||
CGAL::Euler::remove_face(halfedge(f2, sm), sm);
|
||||
PMP::duplicate_non_manifold_vertices(sm);
|
||||
std::size_t nbv_before = vertices(sm).size();
|
||||
if (!PMP::remesh_planar_patches(sm))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out))
|
||||
std::cerr << "decimate failed to remesh some patches (expected)\n";
|
||||
assert(vertices(sm).size()<nbv_before);
|
||||
std::ofstream("nmdi_m1.off") << std::setprecision(17) << sm;
|
||||
assert(is_valid_polygon_mesh(sm));
|
||||
assert(vertices(out).size()<nbv_before);
|
||||
std::ofstream("nmdi_m1.off") << std::setprecision(17) << out;
|
||||
assert(is_valid_polygon_mesh(out));
|
||||
}
|
||||
assert(OK);
|
||||
|
||||
|
|
@ -117,7 +120,8 @@ int main()
|
|||
in >> sm;
|
||||
|
||||
// call the decimation function
|
||||
if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
{
|
||||
OK=false;
|
||||
std::cerr << "ERROR: decimate failed to remesh some patches\n";
|
||||
|
|
@ -125,9 +129,9 @@ int main()
|
|||
ss=std::stringstream();
|
||||
ss << "out_a" << i << ".off";
|
||||
std::ofstream out(ss.str().c_str());
|
||||
out << sm;
|
||||
out << out;
|
||||
std::cout << " output written to out_a" << i << ".off\n";
|
||||
assert(is_valid_polygon_mesh(sm));
|
||||
assert(is_valid_polygon_mesh(out));
|
||||
}
|
||||
|
||||
//testing decimation of meshes, preserving common interface
|
||||
|
|
@ -310,7 +314,8 @@ int main()
|
|||
std::cout << "decimate of data/decimation/sphere.off using approximate predicates\n";
|
||||
std::ifstream in("data/decimation/sphere.off");
|
||||
in >> sm;
|
||||
if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
std::cerr << "decimate failed to remesh some patches\n";
|
||||
}
|
||||
{
|
||||
|
|
@ -318,12 +323,13 @@ int main()
|
|||
std::cout << "decimate of data/decimation/sphere_selection.off using approximate predicates\n";
|
||||
std::ifstream in("data/decimation/sphere_selection.off");
|
||||
in >> sm;
|
||||
if (!PMP::remesh_planar_patches(sm, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
Surface_mesh out;
|
||||
if (!PMP::remesh_planar_patches(sm, out, CGAL::parameters::cosinus_threshold(-0.99)))
|
||||
std::cout << "decimate failed to remesh some patches (this is the expected behavior)\n";
|
||||
std::ofstream out("sphere_selection_app.off");
|
||||
out << sm;
|
||||
out << out;
|
||||
std::cout << "output written to sphere_selection_app.off\n";
|
||||
assert(is_valid_polygon_mesh(sm));
|
||||
assert(is_valid_polygon_mesh(out));
|
||||
}
|
||||
|
||||
assert(OK);
|
||||
|
|
|
|||
Loading…
Reference in New Issue