diff --git a/Surface_modeling/doc/Surface_modeling/PackageDescription.txt b/Surface_modeling/doc/Surface_modeling/PackageDescription.txt index 837b98b44d7..ba870f072b3 100644 --- a/Surface_modeling/doc/Surface_modeling/PackageDescription.txt +++ b/Surface_modeling/doc/Surface_modeling/PackageDescription.txt @@ -19,7 +19,5 @@ \cgalPkgDemo{Edit plugin of the Polyhedron demo,polyhedron_3.zip} \cgalPkgShortInfoEnd \cgalPkgDescriptionEnd - -\todo change translate and rotate_and_translate to apply on the current position? */ diff --git a/Surface_modeling/doc/Surface_modeling/Surface_modeling.txt b/Surface_modeling/doc/Surface_modeling/Surface_modeling.txt index 5ad50a16428..9d3bdb7a5f0 100644 --- a/Surface_modeling/doc/Surface_modeling/Surface_modeling.txt +++ b/Surface_modeling/doc/Surface_modeling/Surface_modeling.txt @@ -94,13 +94,11 @@ it is better to use an individual deformation object for each connected componen \subsection Deform_section Deformation The deformation of the surface mesh is triggered by the displacement of the control vertices. -This is done by setting the final position of the control vertices, or setting an affine transformation -to be applied to a control vertex or a range of control vertices. +This is done by setting the target position of the control vertices (directly or by using an affine transformation +to be applied to a control vertex or a range of control vertices). -Note that the rotation and translation are always applied on the original positions of the control vertices. Hence, -they are not cumulative (i.e. any call to `Deform_mesh::rotate_and_translate()`, `Deform_mesh::translate()`, or `Deform_mesh::set_target_position()` -overrides the previous call). In particular, in an interactive deformation session, the user is responsible for composing the -affine transformations. The rationale for this choice is increase the numerical stability of the affine transformations. +Note that a rotation or a translation of a control vertex is always applied on its last target position set: +they are cumulative. The deformation of the mesh happens when calling the function `Deform_mesh::deform()`. The number of optimization iterations varies depending on whether the user choose a fixed number of iterations or a stop criteria based on the energy variation. @@ -131,7 +129,7 @@ Deformation results when running example \ref Example_1 : `deform_1.off` and `de \cgalFigureEnd \subsubsection Example_2 Using Affine Transformation on Range of Vertices -In this example, we use the functions `translate()` and `rotate_and_translate()` on a range of control vertices. +In this example, we use the functions `translate()` and `rotate()` on a range of control vertices. \cgalExample{Surface_modeling/k_ring_roi_translate_rotate_example.cpp} diff --git a/Surface_modeling/examples/Surface_modeling/k_ring_roi_translate_rotate_example.cpp b/Surface_modeling/examples/Surface_modeling/k_ring_roi_translate_rotate_example.cpp index d67d96d7339..e5509ad3a7a 100644 --- a/Surface_modeling/examples/Surface_modeling/k_ring_roi_translate_rotate_example.cpp +++ b/Surface_modeling/examples/Surface_modeling/k_ring_roi_translate_rotate_example.cpp @@ -98,14 +98,10 @@ int main() deform_mesh.preprocess(); //// DEFORM SECTION //// - deform_mesh.translate(controls_1_map.begin(), controls_1_map.end(), Eigen::Vector3d(0,0,1)); - // overrides any previous call - Eigen::Quaternion quad(0.92, 0, 0, -0.38); - Eigen::Vector3d vect(0, 0, 0); - deform_mesh.rotate_and_translate(controls_1_map.begin(), controls_1_map.end(), Deform_mesh::Point(0,0,0), quad, vect); - deform_mesh.rotate_and_translate(controls_2_map.begin(), controls_2_map.end(), Deform_mesh::Point(0,0,0), quad, vect); + deform_mesh.rotate(controls_1_map.begin(), controls_1_map.end(), Deform_mesh::Point(0,0,0), quad); + deform_mesh.rotate(controls_2_map.begin(), controls_2_map.end(), Deform_mesh::Point(0,0,0), quad); deform_mesh.deform(); @@ -113,6 +109,9 @@ int main() output << mesh; // save deformed mesh output.close(); + //restore the positions of the vertices + deform_mesh.reset(); + // Note that translate and rotate are not cumulative, // they just use original positions (positions at the time of construction) of the control verticess while calculating target positions deform_mesh.translate(controls_1_map.begin(), controls_1_map.end(), Eigen::Vector3d(0,0.30,0)); diff --git a/Surface_modeling/include/CGAL/Deform_mesh.h b/Surface_modeling/include/CGAL/Deform_mesh.h index e4539d03b13..0c100910a3f 100644 --- a/Surface_modeling/include/CGAL/Deform_mesh.h +++ b/Surface_modeling/include/CGAL/Deform_mesh.h @@ -530,9 +530,7 @@ public: } /** - * Sets the target position of `vd` by applying a translation of vertex `t` to its original position - * (that is its position at the time of the functor construction or after the last call to `overwrite_original_positions()`). - * \note A call to this function cancels the last call to `rotate_and_translate()`, `translate()`, or `set_target_position()` involving `vd`. + * Updates the target position of `vd` by applying a translation of vector `t` to its last target position. * * @tparam Vect is a 3D vector class, `Vect::operator[](int i)` with i=0,1 or 2 returns its coordinates * @@ -545,7 +543,7 @@ public: region_of_solution(); // we require ros ids, so if there is any need to preprocess of region of solution -do it. std::size_t v_id = ros_id(vd); - solution[v_id] = add_to_point(original[v_id], t); + solution[v_id] = add_to_point(solution[v_id], t); } /** @@ -565,15 +563,12 @@ public: for(; begin != end; ++begin) { std::size_t v_id = ros_id(*begin); - solution[v_id] = add_to_point(original[v_id], t); + solution[v_id] = add_to_point(solution[v_id], t); } } /** - * Sets the target position of `vd` by applying a rotation around `rotation_center` defined by the quaternion `quat`, followed by a - * translation by vector `t` to its original position (that is its position at the time of the functor construction or after - * the last call to `overwrite_original_positions()`). - * \note A call to this function cancels the last call to `rotate_and_translate()`, `translate()`, or `set_target_position()` involving `vd`. + * Updates the target position of `vd` by applying a rotation around `rotation_center` defined by the quaternion `quat` to its last target position. * * @tparam Quaternion is a quaternion class with `Vect operator*(Quaternion, Vect)` being defined and returns the product of a quaternion with a vector * @tparam Vect is a 3D vector class, `Vect(double x,double y, double z)` being a constructor available and `Vect::operator[](int i)` with i=0,1 or 2 returns its coordinates @@ -581,15 +576,14 @@ public: * @param vd a control vertex * @param rotation_center center of rotation * @param quat rotation holder quaternion - * @param t post translation vector */ template - void rotate_and_translate(vertex_descriptor vd, const Point& rotation_center, const Quaternion& quat, const Vect& t) + void rotate(vertex_descriptor vd, const Point& rotation_center, const Quaternion& quat) { region_of_solution(); // we require ros ids, so if there is any need to preprocess of region of solution -do it. std::size_t v_id = ros_id(vd); - Vect v = quat * sub_to_vector(original[v_id], rotation_center); + Vect v = quat * sub_to_vector(solution[v_id], rotation_center); const Point& rotated = add_to_point(rotation_center, v); solution[v_id] = Point(rotated[0] + t[0], rotated[1] + t[1], rotated[2] + t[2]); } @@ -605,23 +599,35 @@ public: * @param end past-the-end iterator of the range of vertices * @param rotation_center center of rotation * @param quat rotation holder quaternion - * @param t post translation vector */ template - void rotate_and_translate(InputIterator begin, InputIterator end, const Point& rotation_center, const Quaternion& quat, const Vect& t) + void rotate(InputIterator begin, InputIterator end, const Point& rotation_center, const Quaternion& quat) { region_of_solution(); // we require ros ids, so if there is any need to preprocess of region of solution -do it. for(; begin != end; ++begin) { std::size_t v_id = ros_id(*begin); - Vect v = quat * sub_to_vector(original[v_id], rotation_center); + Vect v = quat * sub_to_vector(solution[v_id], rotation_center); const Point& rotated = add_to_point(rotation_center, v); solution[v_id] = Point(rotated[0] + t[0], rotated[1] + t[1], rotated[2] + t[2]); } } /** - * Deforms the region-of-interest according to the deformation algorithm, using the target positions of each control vertex set by using `rotate_and_translate()`, `translate()`, or `set_target_position()`. + * Returns the target position of a control vertex. + * \param vd a control vertex + * \pre `is_roi(vd)` + */ + const Point& target_position(vertex_descriptor vd) + { + region_of_solution(); + + CGAL_precondition( is_roi(vd) ); + return solution[ ros_id(vd) ]; + } + + /** + * Deforms the region-of-interest according to the deformation algorithm, using the target positions of each control vertex set by using `rotate()`, `translate()`, or `set_target_position()`. * The points associated to each vertex of the input graph that are inside the region-of-interest are updated. The initial guess for solving the * deformation problem is using the points associated to the input graph before calling the function. * \note Nothing happens if `preprocess()` returns `false`. @@ -856,7 +862,7 @@ private: need_preprocess_region_of_solution = false; std::vector old_ros_id_map = ros_id_map; - std::vector old_rot_mtr = rot_mtr; + std::vector old_rot_mtr = rot_mtr; std::vector old_solution = solution; std::vector old_original = original;