mirror of https://github.com/CGAL/cgal
Merge smooth_areas and smooth_angles, rework AABB tree, document everything
This commit is contained in:
parent
9942669dd1
commit
22bd8a943b
|
|
@ -83,6 +83,10 @@ CGAL_add_named_parameter(output_iterator_t, output_iterator, output_iterator)
|
|||
CGAL_add_named_parameter(erase_all_duplicates_t, erase_all_duplicates, erase_all_duplicates)
|
||||
CGAL_add_named_parameter(require_same_orientation_t, require_same_orientation, require_same_orientation)
|
||||
CGAL_add_named_parameter(use_safety_constraints_t, use_safety_constraints, use_safety_constraints)
|
||||
CGAL_add_named_parameter(use_angle_smoothing_t, use_angle_smoothing, use_angle_smoothing)
|
||||
CGAL_add_named_parameter(use_area_smoothing_t, use_area_smoothing, use_area_smoothing)
|
||||
CGAL_add_named_parameter(use_Delaunay_flips_t, use_Delaunay_flips, use_Delaunay_flips)
|
||||
CGAL_add_named_parameter(do_project_t, do_project, do_project)
|
||||
|
||||
// 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)
|
||||
|
|
@ -91,7 +95,6 @@ CGAL_add_named_parameter(get_placement_policy_t, get_placement_policy, get_place
|
|||
//to be documented
|
||||
CGAL_add_named_parameter(face_normal_t, face_normal, face_normal_map)
|
||||
CGAL_add_named_parameter(random_seed_t, random_seed, random_seed)
|
||||
CGAL_add_named_parameter(do_project_t, do_project, do_project)
|
||||
CGAL_add_named_parameter(tolerance_map_t, tolerance_map, tolerance_map)
|
||||
|
||||
//internal
|
||||
|
|
|
|||
|
|
@ -88,9 +88,12 @@ void test(const NamedParameters& np)
|
|||
assert(get_param(np, CGAL::internal_np::erase_all_duplicates).v == 48);
|
||||
assert(get_param(np, CGAL::internal_np::require_same_orientation).v == 49);
|
||||
assert(get_param(np, CGAL::internal_np::use_bool_op_to_clip_surface).v == 50);
|
||||
assert(get_param(np, CGAL::internal_np::use_angle_smoothing).v == 51);
|
||||
assert(get_param(np, CGAL::internal_np::use_area_smoothing).v == 52);
|
||||
assert(get_param(np, CGAL::internal_np::use_safety_constraints).v == 53);
|
||||
assert(get_param(np, CGAL::internal_np::use_bool_op_to_clip_surface).v == 54);
|
||||
assert(get_param(np, CGAL::internal_np::use_safety_constraints).v == 56);
|
||||
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
assert(get_param(np, CGAL::internal_np::get_cost_policy).v == 34);
|
||||
assert(get_param(np, CGAL::internal_np::get_placement_policy).v == 35);
|
||||
|
|
@ -171,8 +174,12 @@ void test(const NamedParameters& np)
|
|||
check_same_type<48>(get_param(np, CGAL::internal_np::erase_all_duplicates));
|
||||
check_same_type<49>(get_param(np, CGAL::internal_np::require_same_orientation));
|
||||
check_same_type<50>(get_param(np, CGAL::internal_np::use_bool_op_to_clip_surface));
|
||||
check_same_type<51>(get_param(np, CGAL::internal_np::use_angle_smoothing));
|
||||
check_same_type<52>(get_param(np, CGAL::internal_np::use_area_smoothing));
|
||||
check_same_type<53>(get_param(np, CGAL::internal_np::use_Delaunay_flips));
|
||||
check_same_type<54>(get_param(np, CGAL::internal_np::use_safety_constraints));
|
||||
check_same_type<56>(get_param(np, CGAL::internal_np::use_safety_constraints));
|
||||
7
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
check_same_type<34>(get_param(np, CGAL::internal_np::get_cost_policy));
|
||||
check_same_type<35>(get_param(np, CGAL::internal_np::get_placement_policy));
|
||||
|
|
@ -246,16 +253,19 @@ int main()
|
|||
.weight_calculator(A<39>(39))
|
||||
.preserve_genus(A<40>(40))
|
||||
.verbosity_level(A<41>(41))
|
||||
.use_binary_mode(A<51>(51))
|
||||
.projection_functor(A<42>(42))
|
||||
.throw_on_self_intersection(A<43>(43))
|
||||
.clip_volume(A<44>(44))
|
||||
.use_compact_clipper(A<45>(45))
|
||||
.use_bool_op_to_clip_surface(A<50>(50))
|
||||
.apply_per_connected_component(A<46>(46))
|
||||
.output_iterator(A<47>(47))
|
||||
.erase_all_duplicates(A<48>(48))
|
||||
.require_same_orientation(A<52>(52))
|
||||
.require_same_orientation(A<49>(49))
|
||||
.use_bool_op_to_clip_surface(A<50>(50))
|
||||
.use_binary_mode(A<51>(51))
|
||||
.use_angle_smoothing_t(A<52>(52))
|
||||
.use_area_smoothing_t(A<53>(53))
|
||||
.use_Delaunay_flips_t(A<54>(54))
|
||||
.use_safety_constraints(A<56>(56))
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ Release date: September 2019
|
|||
### Polygon Mesh Processing
|
||||
- Added the function `CGAL::Polygon_mesh_processing::centroid()` which computes
|
||||
the centroid of a closed triangle mesh.
|
||||
- Added the mesh smoothing functions `smooth_areas()` and `smooth_angles()`, which can be used to
|
||||
improve the quality of triangle elements based on geometric characteristics.
|
||||
- Added the mesh smoothing function `smooth()`, which can be used to
|
||||
improve the quality of triangle elements based on various geometric characteristics.
|
||||
- Added the shape smoothing function `smooth_along_curvature_flow()`, which can be used to
|
||||
smooth the surface of a triangle mesh, using the mean curvature flow to perform noise removal.
|
||||
|
||||
|
|
|
|||
|
|
@ -391,11 +391,52 @@ if orientation should matter when determining whether two faces are duplicates.
|
|||
<b>Default:</b> `false`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_angle_smoothing_t} \anchor PMP_use_angle_smoothing
|
||||
Parameter used in the function `smooth()` to indicate if angle-based smoothing should be used.
|
||||
When this type of smoothing is used, the algorithm attempts to equalize angles incident to each vertex.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_area_smoothing_t} \anchor PMP_use_area_smoothing
|
||||
Parameter used in the function `smooth()` to indicate if area-based smoothing should be used.
|
||||
When this type of smoothing is used, the algorithm attempts to equalize the areas of the triangles
|
||||
incident to each vertex. Since this can create elongated triangles, a second phase uses Delaunay-based
|
||||
flips to recover good shapes, unless specified otherwise (see below).
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_Delaunay_flips_t} \anchor PMP_use_Delaunay_flips
|
||||
Parameter used in the function `smooth()` to indicate if Delaunay-based flips should be used
|
||||
after area-based smoothing has been performed. A user wishing to preserve combinatorial information
|
||||
can set this parameter to `false`, but the mesh might have elongated elements.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_safety_constraints} \anchor PMP_use_safety_constraints
|
||||
Parameter used in the functions `smooth_angles()` and `smooth_areas()` to indicate
|
||||
if some sanity checks should be used to decide if the move of a vertex should be applied or rejected.
|
||||
These sanity checks consists of checking that no face incident to the vertex becomes inverted
|
||||
and that the minimum angle of the incident faces is not decreased by the move.
|
||||
Parameter used in the function `smooth()` to indicate if some sanity checks should be used to decide
|
||||
if the move of a vertex should be applied or rejected. These sanity checks consists of checking that
|
||||
no face incident to the vertex becomes inverted and that the minimum angle of the incident faces
|
||||
is not decreased by the move.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_safety_constraints} \anchor PMP_use_safety_constraints
|
||||
Parameter used in the function `smooth()` to indicate if some sanity checks should be used to decide
|
||||
if the move of a vertex should be applied or rejected. These sanity checks consists of checking that
|
||||
no face incident to the vertex becomes inverted and that the minimum angle of the incident faces
|
||||
is not decreased by the move.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
|
|
|
|||
|
|
@ -96,8 +96,7 @@ and provides a list of the parameters that are used in this package.
|
|||
\cgalCRPSection{Meshing Functions}
|
||||
- `CGAL::Polygon_mesh_processing::fair()`
|
||||
- `CGAL::Polygon_mesh_processing::refine()`
|
||||
- `CGAL::Polygon_mesh_processing::smooth_angles()`
|
||||
- `CGAL::Polygon_mesh_processing::smooth_areas()`
|
||||
- `CGAL::Polygon_mesh_processing::smooth()`
|
||||
- `CGAL::Polygon_mesh_processing::smooth_along_curvature_flow()`
|
||||
- `CGAL::Polygon_mesh_processing::triangulate_face()`
|
||||
- `CGAL::Polygon_mesh_processing::triangulate_faces()`
|
||||
|
|
|
|||
|
|
@ -130,8 +130,8 @@ While mesh smoothing is achieved by improving the quality of triangles based on
|
|||
shape smoothing is designed to be \e intrinsic, depending as little as possible on the discretization
|
||||
and smoothing the shape alone without optimizing the shape of the triangles.
|
||||
|
||||
- Mesh smoothing: `CGAL::Polygon_mesh_processing::smooth_angles()` moves vertices so that angles between incident edges equalize,
|
||||
and `CGAL::Polygon_mesh_processing::smooth_areas()` moves vertices so that areas of adjacent triangles tend to equalize.
|
||||
- Mesh smoothing: `CGAL::Polygon_mesh_processing::smooth()` moves vertices to optimize geometry around each vertex:
|
||||
it can try to equalize the angles between incident edges, or (and) move vertices so that areas of adjacent triangles tend to equalize.
|
||||
Border vertices are considered constrained and do not move at any step of the procedure. No vertices are inserted at any time.
|
||||
Angle and area smoothing algorithms are based on Surazhsky and Gotsman \cgalCite{cgal:sg-hqct-04}.
|
||||
Since area smoothing considers only areas as a smoothing criterion, it may result in long and skinny
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ if (EIGEN3_FOUND)
|
|||
create_single_source_cgal_program( "hole_filling_example_SM.cpp" )
|
||||
create_single_source_cgal_program( "refine_fair_example.cpp")
|
||||
create_single_source_cgal_program( "shape_smoothing_example.cpp")
|
||||
create_single_source_cgal_program( "mesh_smoothing_example.cpp")
|
||||
|
||||
endif(EIGEN3_FOUND)
|
||||
|
||||
create_single_source_cgal_program( "self_intersections_example.cpp" )
|
||||
|
|
@ -98,7 +100,6 @@ create_single_source_cgal_program( "corefinement_LCC.cpp")
|
|||
create_single_source_cgal_program( "hole_filling_example_LCC.cpp" )
|
||||
create_single_source_cgal_program( "detect_features_example.cpp" )
|
||||
create_single_source_cgal_program( "manifoldness_repair_example.cpp" )
|
||||
create_single_source_cgal_program( "mesh_smoothing_example.cpp")
|
||||
create_single_source_cgal_program( "repair_polygon_soup_example.cpp" )
|
||||
|
||||
set(SuiteSparse_USE_LAPACK_BLAS ON)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#define CGAL_PMP_SMOOTHING_VERBOSE
|
||||
#define CGAL_PMP_SMOOTHING_DEBUG
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
|
|
@ -16,7 +13,7 @@ namespace PMP = CGAL::Polygon_mesh_processing;
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* filename = argc > 1 ? argv[1] : "data/grid.off";
|
||||
const char* filename = argc > 1 ? argv[1] : "data/mech-holes-shark.off";
|
||||
std::ifstream input(filename);
|
||||
|
||||
Mesh mesh;
|
||||
|
|
@ -26,27 +23,27 @@ int main(int argc, char** argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const unsigned int repeat = 1;
|
||||
const unsigned int nb_iterations = 50;
|
||||
|
||||
for(unsigned int t=0 ; t<repeat; ++t)
|
||||
std::set<Mesh::Vertex_index> constrained_vertices;
|
||||
for(Mesh::Vertex_index v : vertices(mesh))
|
||||
{
|
||||
#if 0
|
||||
// std::cout << "Smooth areas..." << std::endl;
|
||||
// PMP::smooth_areas(mesh, PMP::parameters::number_of_iterations(nb_iterations)
|
||||
// .use_safety_constraints(false));
|
||||
|
||||
std::cout << "Smooth angles..." << std::endl;
|
||||
PMP::smooth_angles(mesh, PMP::parameters::number_of_iterations(nb_iterations)
|
||||
.use_safety_constraints(false));
|
||||
#else
|
||||
PMP::smooth(mesh, PMP::parameters::number_of_iterations(nb_iterations)
|
||||
.use_safety_constraints(false));
|
||||
#endif
|
||||
if(is_border(v, mesh))
|
||||
constrained_vertices.insert(v);
|
||||
}
|
||||
|
||||
std::cout << "Constraining: " << constrained_vertices.size() << " border vertices" << std::endl;
|
||||
|
||||
const unsigned int nb_iterations = 5;
|
||||
CGAL::Boolean_property_map<std::set<Mesh::Vertex_index> > vcmap(constrained_vertices);
|
||||
|
||||
std::cout << "Smoothing... (" << nb_iterations << " iterations)" << std::endl;
|
||||
PMP::smooth(mesh, PMP::parameters::number_of_iterations(nb_iterations)
|
||||
.use_safety_constraints(false) // authorize all moves
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
|
||||
std::ofstream output("mesh_smoothed.off");
|
||||
output << mesh;
|
||||
|
||||
std::cout << "Done!" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ public:
|
|||
}
|
||||
|
||||
ceres::Solver::Options options;
|
||||
options.minimizer_progress_to_stdout = true;
|
||||
// options.minimizer_progress_to_stdout = true;
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(options, &problem, &summary);
|
||||
// std::cout << summary.BriefReport() << "\n";
|
||||
|
|
@ -462,16 +462,6 @@ class Mesh_smoother
|
|||
typedef typename boost::property_traits<VertexPointMap>::reference Point_ref;
|
||||
typedef typename GeomTraits::FT FT;
|
||||
typedef typename GeomTraits::Vector_3 Vector;
|
||||
typedef typename GeomTraits::Segment_3 Segment;
|
||||
typedef typename GeomTraits::Triangle_3 Triangle;
|
||||
|
||||
typedef std::vector<Triangle> Triangle_list;
|
||||
typedef std::pair<halfedge_descriptor, halfedge_descriptor> He_pair;
|
||||
|
||||
typedef std::vector<Triangle> Triangle_container;
|
||||
typedef CGAL::AABB_triangle_primitive<GeomTraits, typename Triangle_container::iterator> AABB_Primitive;
|
||||
typedef CGAL::AABB_traits<GeomTraits, AABB_Primitive> AABB_Traits;
|
||||
typedef CGAL::AABB_tree<AABB_Traits> Tree;
|
||||
|
||||
public:
|
||||
Mesh_smoother(TriangleMesh& pmesh,
|
||||
|
|
@ -482,8 +472,6 @@ public:
|
|||
mesh_(pmesh), vpmap_(vpmap), vcmap_(vcmap), traits_(traits)
|
||||
{}
|
||||
|
||||
~Mesh_smoother() { delete tree_ptr_; }
|
||||
|
||||
public:
|
||||
template<typename FaceRange>
|
||||
void set_vertex_range(const FaceRange& face_range)
|
||||
|
|
@ -511,20 +499,6 @@ public:
|
|||
CGAL_precondition(degen_faces.empty());
|
||||
|
||||
set_vertex_range(face_range);
|
||||
|
||||
input_triangles_.clear();
|
||||
input_triangles_.reserve(face_range.size());
|
||||
|
||||
for(face_descriptor f : face_range)
|
||||
{
|
||||
halfedge_descriptor h = halfedge(f, mesh_);
|
||||
input_triangles_.push_back(traits_.construct_triangle_3_object()(get(vpmap_, source(h, mesh_)),
|
||||
get(vpmap_, target(h, mesh_)),
|
||||
get(vpmap_, target(next(h, mesh_), mesh_))));
|
||||
}
|
||||
|
||||
tree_ptr_ = new Tree(input_triangles_.begin(), input_triangles_.end());
|
||||
tree_ptr_->accelerate_distance_queries();
|
||||
}
|
||||
|
||||
// generic optimizer, the move is computed by 'Optimizer'
|
||||
|
|
@ -611,7 +585,8 @@ public:
|
|||
return moved_points;
|
||||
}
|
||||
|
||||
void project_to_surface()
|
||||
template <typename AABBTree>
|
||||
void project_to_surface(const AABBTree& tree)
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_DEBUG
|
||||
std::cout << "Projecting back to the surface" << std::endl;
|
||||
|
|
@ -623,7 +598,7 @@ public:
|
|||
continue;
|
||||
|
||||
Point_ref p_query = get(vpmap_, v);
|
||||
const Point projected = tree_ptr_->closest_point(p_query);
|
||||
const Point projected = tree.closest_point(p_query);
|
||||
put(vpmap_, v, projected);
|
||||
}
|
||||
}
|
||||
|
|
@ -724,9 +699,7 @@ private:
|
|||
VertexConstraintMap vcmap_;
|
||||
GeomTraits traits_;
|
||||
|
||||
Tree* tree_ptr_;
|
||||
std::vector<vertex_descriptor> vrange_;
|
||||
Triangle_container input_triangles_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
|||
|
|
@ -39,124 +39,18 @@ namespace Polygon_mesh_processing {
|
|||
|
||||
/*!
|
||||
* \ingroup PMP_meshing_grp
|
||||
* smoothes a triangulated region of a polygon mesh using angle-based criteria.
|
||||
* This function improves the angles of triangle faces by iteratively moving non-constrained vertices.
|
||||
* Optionally, the points are reprojected to the input surface after each iteration.
|
||||
*
|
||||
* @tparam TriangleMesh model of `MutableFaceGraph`.
|
||||
* @tparam FaceRange range of `boost::graph_traits<TriangleMesh>::%face_descriptor`,
|
||||
model of `Range`. Its iterator type is `ForwardIterator`.
|
||||
* @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters".
|
||||
* \short smoothes a triangulated region of a polygon mesh.
|
||||
*
|
||||
* @param tmesh a polygon mesh with triangulated surface patches to be smoothed.
|
||||
* @param faces the range of triangular faces defining one or several surface patches to be smoothed.
|
||||
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below.
|
||||
* This function attempts to make the triangle angle and area distributions as uniform as possible
|
||||
* by moving (non-constrained) vertices.
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamBegin{number_of_iterations} the number of iterations for the
|
||||
* sequence of the smoothing iterations performed (default is 1).
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{vertex_is_constrained_map} a property map containing the
|
||||
* constrained-or-not status of each vertex of `tmesh`. A constrained vertex
|
||||
* cannot be modified at all during smoothing.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{do_project} if `true` (default value), points are projected to the initial surface
|
||||
* after each iteration.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{vertex_point_map} the property map with the points associated
|
||||
* to the vertices of `tmesh`. Instance of a class model of `ReadWritePropertyMap`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{geom_traits} a geometric traits class instance, model of `Kernel`.
|
||||
* Exact constructions kernels are not supported by this function.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
* Angle-based smoothing does not change the combinatorial information of the mesh. Area-based smoothing
|
||||
* might change the combinatorial information, unless specified otherwise. It is also possible
|
||||
* to make the smoothing algorithm "safer" by rejecting moves that, when applied, would worsen the
|
||||
* quality of the mesh, e.g. that would decrease the value of the smallest angle around a vertex or
|
||||
* create self-intersections.
|
||||
*
|
||||
* @pre `tmesh` does not contain any degenerate faces
|
||||
*/
|
||||
template<typename TriangleMesh, typename FaceRange, typename NamedParameters>
|
||||
void smooth_angles(const FaceRange& faces,
|
||||
TriangleMesh& tmesh,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<TriangleMesh, NamedParameters>::type GeomTraits;
|
||||
typedef typename GetVertexPointMap<TriangleMesh, NamedParameters>::type VertexPointMap;
|
||||
typedef typename boost::lookup_named_param_def<internal_np::vertex_is_constrained_t,
|
||||
NamedParameters,
|
||||
Constant_property_map<vertex_descriptor, bool> // default
|
||||
> ::type VCMap;
|
||||
|
||||
typedef internal::Angle_smoother<TriangleMesh, VertexPointMap, GeomTraits> Angle_optimizer;
|
||||
typedef internal::Mesh_smoother<Angle_optimizer, TriangleMesh,
|
||||
VertexPointMap, VCMap, GeomTraits> Angle_smoother;
|
||||
|
||||
if(std::begin(faces) == std::end(faces))
|
||||
return;
|
||||
|
||||
using boost::choose_param;
|
||||
using boost::get_param;
|
||||
|
||||
// named parameters
|
||||
GeomTraits gt = choose_param(get_param(np, internal_np::geom_traits),
|
||||
GeomTraits());
|
||||
VertexPointMap vpmap = choose_param(get_param(np, internal_np::vertex_point),
|
||||
get_property_map(CGAL::vertex_point, tmesh));
|
||||
VCMap vcmap = choose_param(get_param(np, internal_np::vertex_is_constrained),
|
||||
Constant_property_map<vertex_descriptor, bool>());
|
||||
|
||||
std::size_t nb_iterations = choose_param(get_param(np, internal_np::number_of_iterations), 1);
|
||||
const bool do_project = choose_param(get_param(np, internal_np::do_project), true);
|
||||
const bool use_safety_constraints = choose_param(get_param(np, internal_np::use_safety_constraints), true);
|
||||
|
||||
Angle_smoother smoother(tmesh, vpmap, vcmap, gt);
|
||||
|
||||
smoother.init_smoothing(faces);
|
||||
|
||||
for(std::size_t i=0; i<nb_iterations; ++i)
|
||||
{
|
||||
smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
true /*apply all moves at once*/,
|
||||
use_safety_constraints /*check if the min angle is improved*/);
|
||||
|
||||
if(do_project)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
|
||||
std::cerr << "Can't do re-projection, there are self-intersections in the mesh!\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
smoother.project_to_surface();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FaceRange, typename TriangleMesh>
|
||||
void smooth_angles(const FaceRange& face_range, TriangleMesh& tmesh)
|
||||
{
|
||||
smooth_angles(face_range, tmesh, parameters::all_default());
|
||||
}
|
||||
|
||||
template <typename TriangleMesh, typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
|
||||
void smooth_angles(TriangleMesh& tmesh, const CGAL_PMP_NP_CLASS& np)
|
||||
{
|
||||
smooth_angles(faces(tmesh), tmesh, np);
|
||||
}
|
||||
|
||||
template<typename TriangleMesh>
|
||||
void smooth_angles(TriangleMesh& tmesh)
|
||||
{
|
||||
smooth_angles(faces(tmesh), tmesh, parameters::all_default());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup PMP_meshing_grp
|
||||
* smoothes a triangulated region of a polygon mesh using area-based criteria.
|
||||
* This function tries to make the triangle area distribution as uniform as possible
|
||||
* by moving non-constrained vertices.
|
||||
* Optionally, the points are reprojected after each iteration.
|
||||
*
|
||||
* @tparam TriangleMesh model of `MutableFaceGraph`.
|
||||
|
|
@ -169,131 +63,52 @@ void smooth_angles(TriangleMesh& tmesh)
|
|||
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below.
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamBegin{use_angle_based_smoothing} Boolean value to indicate whether angle-based smoothing should be used.
|
||||
* Default is `true`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{use_area_based_smoothing} Boolean value to indicate whether area-based smoothing should be used.
|
||||
* Default is `true`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{number_of_iterations} the number of iterations for the
|
||||
* sequence of the smoothing iterations performed (default is 1).
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{use_safety_constraints} if `true`, vertex moves that would worsen the mesh
|
||||
* are ignored. Default is `false`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{use_Delaunay_flips} if `true` (default value), area-based smoothing will be completed
|
||||
* by a phase of Delaunay-based edge-flips to prevent the creation of elongated triangles.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{do_project} if `true` (default value), points are projected onto the initial surface
|
||||
* after each iteration.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{vertex_is_constrained_map} a property map containing the
|
||||
* constrained-or-not status of each vertex of `tmesh`. A constrained vertex
|
||||
* cannot be modified at all during smoothing.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{edge_is_constrained_map} a property map containing the
|
||||
* constrained-or-not status of each edge of `tmesh`. A constrained edge cannot be flipped.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{vertex_point_map} the property map with the points associated
|
||||
* to the vertices of `tmesh`. Instance of a class model of `ReadWritePropertyMap`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{geom_traits} a geometric traits class instance, model of `Kernel`.
|
||||
* Exact constructions kernels are not supported by this function.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{number_of_iterations} the number of iterations for the
|
||||
* sequence of the smoothing iterations performed (default is 1).
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{vertex_is_constrained_map} a property map containing the
|
||||
* constrained-or-not status of each vertex of `tmesh`. A constrained vertex
|
||||
* cannot be modified at all during smoothing.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{do_project} if `true` (default value), points are projected to the initial surface after each iteration.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* @warning The third party libraries Ceres (and Eigen) are required to use the area-based smoothing.
|
||||
*
|
||||
* @pre `tmesh` does not contain any degenerate faces
|
||||
*/
|
||||
template<typename TriangleMesh, typename FaceRange, typename NamedParameters>
|
||||
void smooth_areas(const FaceRange faces,
|
||||
TriangleMesh& tmesh,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::edge_descriptor edge_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<TriangleMesh, NamedParameters>::type GeomTraits;
|
||||
typedef typename GetVertexPointMap<TriangleMesh, NamedParameters>::type VertexPointMap;
|
||||
|
||||
typedef typename boost::lookup_named_param_def<internal_np::vertex_is_constrained_t,
|
||||
NamedParameters,
|
||||
Constant_property_map<vertex_descriptor, bool> // default
|
||||
> ::type VCMap;
|
||||
typedef typename boost::lookup_named_param_def<internal_np::edge_is_constrained_t,
|
||||
NamedParameters,
|
||||
Constant_property_map<edge_descriptor, bool> // default
|
||||
> ::type ECMap;
|
||||
|
||||
typedef internal::Area_smoother<TriangleMesh, VertexPointMap, GeomTraits> Area_optimizer;
|
||||
typedef internal::Mesh_smoother<Area_optimizer, TriangleMesh,
|
||||
VertexPointMap, VCMap, GeomTraits> Area_smoother;
|
||||
|
||||
typedef internal::Delaunay_edge_flipper<TriangleMesh, VertexPointMap,
|
||||
ECMap, GeomTraits> Delaunay_flipper;
|
||||
|
||||
if(std::begin(faces) == std::end(faces))
|
||||
return;
|
||||
|
||||
using boost::choose_param;
|
||||
using boost::get_param;
|
||||
|
||||
// named parameters
|
||||
GeomTraits gt = choose_param(get_param(np, internal_np::geom_traits),
|
||||
GeomTraits());
|
||||
VertexPointMap vpmap = choose_param(get_param(np, internal_np::vertex_point),
|
||||
get_property_map(CGAL::vertex_point, tmesh));
|
||||
VCMap vcmap = choose_param(get_param(np, internal_np::vertex_is_constrained),
|
||||
Constant_property_map<vertex_descriptor, bool>());
|
||||
|
||||
std::size_t nb_iterations = choose_param(get_param(np, internal_np::number_of_iterations), 1);
|
||||
const bool do_project = choose_param(get_param(np, internal_np::do_project), true);
|
||||
const bool use_safety_constraints = choose_param(get_param(np, internal_np::use_safety_constraints), true);
|
||||
const bool use_Delaunay_flips = choose_param(get_param(np, internal_np::use_delaunay_triangulation), true);
|
||||
|
||||
Area_smoother smoother(tmesh, vpmap, vcmap, gt);
|
||||
|
||||
smoother.init_smoothing(faces);
|
||||
|
||||
for(std::size_t i=0; i<nb_iterations; ++i)
|
||||
{
|
||||
smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
false /*apply moves as soon as they're calculated*/,
|
||||
false /*do not enforce a minimum angle improvement*/);
|
||||
|
||||
if(do_project)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
|
||||
std::cerr << "Can't do re-projection, there are self-intersections in the mesh!\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
smoother.project_to_surface();
|
||||
}
|
||||
}
|
||||
|
||||
if(use_Delaunay_flips)
|
||||
{
|
||||
ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained),
|
||||
Constant_property_map<edge_descriptor, bool>(false));
|
||||
|
||||
Delaunay_flipper delaunay_flipper(tmesh, vpmap, ecmap, gt);
|
||||
delaunay_flipper(faces);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FaceRange, typename TriangleMesh>
|
||||
void smooth_areas(const FaceRange& face_range, TriangleMesh& tmesh)
|
||||
{
|
||||
smooth_areas(face_range, tmesh, parameters::all_default());
|
||||
}
|
||||
|
||||
template <typename TriangleMesh, typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
|
||||
void smooth_areas(TriangleMesh& tmesh, const CGAL_PMP_NP_CLASS& np)
|
||||
{
|
||||
smooth_areas(faces(tmesh), tmesh, np);
|
||||
}
|
||||
|
||||
template<typename TriangleMesh>
|
||||
void smooth_areas(TriangleMesh& tmesh)
|
||||
{
|
||||
smooth_areas(faces(tmesh), tmesh, parameters::all_default());
|
||||
}
|
||||
|
||||
// do both
|
||||
template<typename TriangleMesh, typename FaceRange, typename NamedParameters>
|
||||
void smooth(const FaceRange& faces,
|
||||
TriangleMesh& tmesh,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::edge_descriptor edge_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<TriangleMesh, NamedParameters>::type GeomTraits;
|
||||
typedef typename GetVertexPointMap<TriangleMesh, NamedParameters>::type VertexPointMap;
|
||||
|
|
@ -317,6 +132,14 @@ void smooth(const FaceRange& faces,
|
|||
typedef internal::Mesh_smoother<Angle_optimizer, TriangleMesh,
|
||||
VertexPointMap, VCMap, GeomTraits> Angle_smoother;
|
||||
|
||||
typedef typename GeomTraits::Triangle_3 Triangle;
|
||||
typedef std::vector<Triangle> Triangle_container;
|
||||
|
||||
typedef CGAL::AABB_triangle_primitive<GeomTraits,
|
||||
typename Triangle_container::iterator> AABB_Primitive;
|
||||
typedef CGAL::AABB_traits<GeomTraits, AABB_Primitive> AABB_Traits;
|
||||
typedef CGAL::AABB_tree<AABB_Traits> Tree;
|
||||
|
||||
if(std::begin(faces) == std::end(faces))
|
||||
return;
|
||||
|
||||
|
|
@ -331,66 +154,100 @@ void smooth(const FaceRange& faces,
|
|||
VCMap vcmap = choose_param(get_param(np, internal_np::vertex_is_constrained),
|
||||
Constant_property_map<vertex_descriptor, bool>());
|
||||
|
||||
const bool use_angle_smoothing = choose_param(get_param(np, internal_np::use_angle_smoothing), true);
|
||||
const bool use_area_smoothing = choose_param(get_param(np, internal_np::use_area_smoothing), true);
|
||||
|
||||
if(!use_angle_smoothing && !use_area_smoothing)
|
||||
std::cerr << "Warning: called PMP::smooth() but no smoothing method is being used" << std::endl;
|
||||
|
||||
std::size_t nb_iterations = choose_param(get_param(np, internal_np::number_of_iterations), 1);
|
||||
const bool do_project = choose_param(get_param(np, internal_np::do_project), true);
|
||||
const bool use_safety_constraints = choose_param(get_param(np, internal_np::use_safety_constraints), true);
|
||||
const bool use_Delaunay_flips = choose_param(get_param(np, internal_np::use_delaunay_triangulation), false);
|
||||
const bool use_Delaunay_flips = choose_param(get_param(np, internal_np::use_Delaunay_flips), false);
|
||||
|
||||
// Construct the AABB tree (if needed for reprojection)
|
||||
std::vector<Triangle> input_triangles;
|
||||
|
||||
if(do_project)
|
||||
{
|
||||
input_triangles.reserve(faces.size());
|
||||
|
||||
for(face_descriptor f : faces)
|
||||
{
|
||||
halfedge_descriptor h = halfedge(f, tmesh);
|
||||
input_triangles.push_back(gt.construct_triangle_3_object()(get(vpmap, source(h, tmesh)),
|
||||
get(vpmap, target(h, tmesh)),
|
||||
get(vpmap, target(next(h, tmesh), tmesh))));
|
||||
}
|
||||
}
|
||||
|
||||
Tree aabb_tree(input_triangles.begin(), input_triangles.end());
|
||||
aabb_tree.accelerate_distance_queries();
|
||||
|
||||
// Setup the working ranges and check some preconditions
|
||||
Area_smoother area_smoother(tmesh, vpmap, vcmap, gt);
|
||||
Angle_smoother angle_smoother(tmesh, vpmap, vcmap, gt);
|
||||
|
||||
area_smoother.init_smoothing(faces);
|
||||
angle_smoother.init_smoothing(faces);
|
||||
if(use_area_smoothing)
|
||||
area_smoother.init_smoothing(faces);
|
||||
|
||||
if(use_angle_smoothing)
|
||||
angle_smoother.init_smoothing(faces);
|
||||
|
||||
for(std::size_t i=0; i<nb_iterations; ++i)
|
||||
{
|
||||
// First apply area smoothing...
|
||||
area_smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
false /*apply moves as soon as they're calculated*/,
|
||||
false /*do not enforce a minimum angle improvement*/);
|
||||
if(do_project)
|
||||
if(use_area_smoothing)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
// First apply area smoothing...
|
||||
area_smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
false /*apply moves as soon as they're calculated*/,
|
||||
false /*do not enforce a minimum angle improvement*/);
|
||||
if(do_project)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
|
||||
std::cerr << "Can't do re-projection, there are self-intersections in the mesh!\n";
|
||||
std::cerr << "Cannot re-project as there are self-intersections in the mesh!\n";
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
area_smoother.project_to_surface(aabb_tree);
|
||||
}
|
||||
|
||||
area_smoother.project_to_surface();
|
||||
}
|
||||
if(use_Delaunay_flips)
|
||||
{
|
||||
ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained),
|
||||
Constant_property_map<edge_descriptor, bool>(false));
|
||||
|
||||
if(use_Delaunay_flips)
|
||||
{
|
||||
ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained),
|
||||
Constant_property_map<edge_descriptor, bool>(false));
|
||||
|
||||
Delaunay_flipper delaunay_flipper(tmesh, vpmap, ecmap, gt);
|
||||
delaunay_flipper(faces);
|
||||
Delaunay_flipper delaunay_flipper(tmesh, vpmap, ecmap, gt);
|
||||
delaunay_flipper(faces);
|
||||
}
|
||||
}
|
||||
|
||||
// ... then angle smoothing
|
||||
angle_smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
true /*apply all moves at once*/,
|
||||
use_safety_constraints /*check if the min angle is improved*/);
|
||||
|
||||
if(do_project)
|
||||
if(use_angle_smoothing)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
|
||||
std::cerr << "Can't do re-projection, there are self-intersections in the mesh!\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
angle_smoother.optimize(use_safety_constraints /*check for bad faces*/,
|
||||
true /*apply all moves at once*/,
|
||||
use_safety_constraints /*check if the min angle is improved*/);
|
||||
|
||||
angle_smoother.project_to_surface();
|
||||
if(do_project)
|
||||
{
|
||||
if(use_safety_constraints && does_self_intersect(tmesh))
|
||||
{
|
||||
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
|
||||
std::cerr << "Can't do re-projection, there are self-intersections in the mesh!\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
angle_smoother.project_to_surface(aabb_tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename FaceRange, typename TriangleMesh>
|
||||
void smooth(const FaceRange& face_range, TriangleMesh& tmesh)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
|||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
template <typename Mesh>
|
||||
void read_mesh(const char* filename,
|
||||
Mesh& mesh)
|
||||
void read_mesh(const char* filename, Mesh& mesh)
|
||||
{
|
||||
std::ifstream input(filename);
|
||||
|
||||
|
|
@ -47,8 +46,9 @@ void test_angle_smoothing(const char* filename)
|
|||
Mesh mesh;
|
||||
read_mesh(filename, mesh);
|
||||
|
||||
PMP::smooth_angles(mesh);
|
||||
PMP::smooth_angles(mesh, CGAL::parameters::number_of_iterations(10));
|
||||
PMP::smooth(mesh);
|
||||
PMP::smooth(mesh, CGAL::parameters::number_of_iterations(10)
|
||||
.use_area_smoothing(false));
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
|
|
@ -57,8 +57,9 @@ void test_area_smoothing(const char* filename)
|
|||
Mesh mesh;
|
||||
read_mesh(filename, mesh);
|
||||
|
||||
PMP::smooth_areas(mesh);
|
||||
PMP::smooth_areas(mesh, CGAL::parameters::number_of_iterations(10));
|
||||
PMP::smooth(mesh);
|
||||
PMP::smooth(mesh, CGAL::parameters::number_of_iterations(10)
|
||||
.use_angle_smoothing(false));
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
|
|
@ -67,7 +68,8 @@ void test_angle_smoothing_without_projection(const char* filename)
|
|||
Mesh mesh;
|
||||
read_mesh(filename, mesh);
|
||||
|
||||
PMP::smooth_angles(mesh, CGAL::parameters::do_project(false));
|
||||
PMP::smooth(mesh, CGAL::parameters::do_project(false)
|
||||
.use_area_smoothing(false));
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
|
|
@ -76,7 +78,8 @@ void test_area_smoothing_without_projection(const char* filename)
|
|||
Mesh mesh;
|
||||
read_mesh(filename, mesh);
|
||||
|
||||
PMP::smooth_areas(mesh, CGAL::parameters::do_project(false));
|
||||
PMP::smooth(mesh, CGAL::parameters::do_project(false)
|
||||
.use_angle_smoothing(false));
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
|
|
@ -88,32 +91,25 @@ void test_constrained_vertices(const char* filename)
|
|||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typename boost::property_map<Mesh, CGAL::vertex_point_t>::type vpmap = get(CGAL::vertex_point, mesh);
|
||||
|
||||
double x_init, y_init, z_init;
|
||||
std::set<vertex_descriptor> selected_vertices;
|
||||
std::map<vertex_descriptor, Point> initial_positions;
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
{
|
||||
if(!is_border(v, mesh))
|
||||
{
|
||||
selected_vertices.insert(v);
|
||||
x_init = get(vpmap, v).x();
|
||||
y_init = get(vpmap, v).y();
|
||||
z_init = get(vpmap, v).z();
|
||||
initial_positions[v] = get(vpmap, v);
|
||||
}
|
||||
}
|
||||
|
||||
CGAL::Boolean_property_map<std::set<vertex_descriptor> > vcmap(selected_vertices);
|
||||
|
||||
PMP::smooth_angles(mesh, CGAL::parameters::vertex_is_constrained_map(vcmap));
|
||||
PMP::smooth_areas(mesh, CGAL::parameters::vertex_is_constrained_map(vcmap));
|
||||
PMP::smooth(mesh, CGAL::parameters::vertex_is_constrained_map(vcmap));
|
||||
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
{
|
||||
if(!is_border(v, mesh))
|
||||
{
|
||||
assert(x_init == get(vpmap, v).x());
|
||||
assert(y_init == get(vpmap, v).y());
|
||||
assert(z_init == get(vpmap, v).z());
|
||||
}
|
||||
assert(initial_positions.at(v) == get(vpmap, v));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,19 +191,21 @@ public Q_SLOTS:
|
|||
}
|
||||
else
|
||||
{
|
||||
smooth_angles(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
smooth(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_area_smoothing(false));
|
||||
}
|
||||
}
|
||||
else if(use_area_smoothing)
|
||||
{
|
||||
smooth_areas(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_delaunay_triangulation(use_Delaunay_flips)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
smooth(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_delaunay_triangulation(use_Delaunay_flips)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_angle_smoothing(false));
|
||||
}
|
||||
|
||||
poly_item->invalidateOpenGLBuffers();
|
||||
|
|
@ -219,22 +221,28 @@ public Q_SLOTS:
|
|||
if(use_angle_smoothing)
|
||||
{
|
||||
if(use_area_smoothing)
|
||||
{
|
||||
smooth(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
}
|
||||
else
|
||||
smooth_angles(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
{
|
||||
smooth(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_area_smoothing(false));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
smooth_areas(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
smooth(pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_angle_smoothing(false));
|
||||
}
|
||||
}
|
||||
else // some faces exist in the selection
|
||||
|
|
@ -250,18 +258,20 @@ public Q_SLOTS:
|
|||
}
|
||||
else
|
||||
{
|
||||
smooth_angles(selection_item->selected_facets, pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
smooth(selection_item->selected_facets, pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_area_smoothing(false));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
smooth_areas(selection_item->selected_facets, pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap));
|
||||
smooth(selection_item->selected_facets, pmesh, parameters::do_project(projection)
|
||||
.number_of_iterations(nb_iter)
|
||||
.use_safety_constraints(use_safety_measures)
|
||||
.vertex_is_constrained_map(vcmap)
|
||||
.use_angle_smoothing(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue