diff --git a/Surface_mesh_approximation/doc/Surface_mesh_approximation/surface_mesh_approximation.txt b/Surface_mesh_approximation/doc/Surface_mesh_approximation/surface_mesh_approximation.txt
index b0a3e7c02a2..ae7ea809e94 100644
--- a/Surface_mesh_approximation/doc/Surface_mesh_approximation/surface_mesh_approximation.txt
+++ b/Surface_mesh_approximation/doc/Surface_mesh_approximation/surface_mesh_approximation.txt
@@ -60,10 +60,10 @@ Assuming a clustering partition of \f$n\f$ regions with errors \f$ \{E_k\}_{k=1\
- Hierarchical. \f$m\f$ seed facets are dispatched within the current partition, where each partition is refined with a number of proxies chosen in accordance to their fitting error:
- calculate total error \f$ E_{total} \f$, then average error \f$ E_{avg} = E_{total} / m \f$ (assuming that each new proxy shares the same amount of error)
- sort errors \f$ \{E_{min},\cdots,E_{max}\} \f$
- - from \f$ E_{min} \f$ to \f$ E_{max} \f$, we diffuse the error hierarchically one after another. More specifically, the number of proxies added to the \f$k\f$th region is proportional to its error given by the formula:
-\f[ nb\_to\_add\_k = rounded\_to\_nearest\_integer(E_k / E_{avg}), \f]
+ - from \f$ E_{min} \f$ to \f$ E_{max} \f$, we diffuse the error hierarchically one after another. More specifically, the number of proxies \f$N_k\f$ added to the \f$k\f$th region is proportional to its error:
+\f[ N_k = \lfloor E_k / E_{avg} + 0.5 \rfloor, \f]
and the remaining error is added to the next proxy error in order to keep the total error unchanged:
-\f[ E'_{k+1} = (E_k - nb\_to\_add\_k * E_{avg}) + E_{k+1}. \f]
+\f[ E'_{k+1} = (E_k - N_k * E_{avg}) + E_{k+1}. \f]
\cgalFigureBegin{seeding_method, seeding_method.png}
Comparison of seeding methods on the sphere-cube model. From left to right: initial partition (\f$ \mathcal{L}^{2,1} \f$ metrics and 20 proxies), add 5 proxy seeds (red facets) with random, incremental and hierarchical methods respectively.
diff --git a/Surface_mesh_approximation/include/CGAL/vsa_approximation.h b/Surface_mesh_approximation/include/CGAL/vsa_approximation.h
index 1acbb8cc87c..f592f84625c 100644
--- a/Surface_mesh_approximation/include/CGAL/vsa_approximation.h
+++ b/Surface_mesh_approximation/include/CGAL/vsa_approximation.h
@@ -545,59 +545,54 @@ public:
std::cerr << "#px " << m_proxies.size() << std::endl;
#endif
- const FT sum_error = compute_total_error();
- const FT avg_error = sum_error / FT(static_cast(num_proxies));
-
- std::vector px_error;
- for (std::size_t i = 0; i < m_proxies.size(); ++i)
- px_error.push_back(Proxy_error(i, m_proxies[i].err));
- // sort partition by error
- std::sort(px_error.begin(), px_error.end());
+ const double sum_error = CGAL::to_double(compute_total_error());
+ const double avg_error = sum_error / static_cast(num_proxies);
// number of proxies to be added to each region
std::vector num_to_add(m_proxies.size(), 0);
- if (avg_error == FT(0.0)) {
+ if (avg_error <= 0.0) {
// rare case on extremely regular geometry like a cube
#ifdef CGAL_SURFACE_MESH_APPROXIMATION_DEBUG
std::cerr << "zero error, diffuse w.r.t. number of facets" << std::endl;
#endif
- const FT avg_facet = FT(
- static_cast(num_faces(*m_ptm)) / static_cast(num_proxies));
- std::vector px_size(m_proxies.size(), FT(0.0));
+ const double avg_facet =
+ static_cast(num_faces(*m_ptm)) / static_cast(num_proxies);
+ std::vector px_size(m_proxies.size(), 0.0);
BOOST_FOREACH(face_descriptor f, faces(*m_ptm))
- px_size[get(m_fproxy_map, f)] += FT(1.0);
- FT residual(0.0);
+ px_size[get(m_fproxy_map, f)] += 1.0;
+ double residual = 0.0;
for (std::size_t i = 0; i < m_proxies.size(); ++i) {
- FT to_add = (residual + px_size[i]) / avg_facet;
- FT floor_to_add = FT(std::floor(CGAL::to_double(to_add)));
- FT q_to_add = FT(CGAL::to_double(
- ((to_add - floor_to_add) > FT(0.5)) ? (floor_to_add + FT(1.0)) : floor_to_add));
- residual = (to_add - q_to_add) * avg_facet;
- num_to_add[i] = static_cast(CGAL::to_double(q_to_add));
+ const double to_add = (residual + px_size[i]) / avg_facet;
+ const double to_add_round_up = std::floor(to_add + 0.5);
+ residual = (to_add - to_add_round_up) * avg_facet;
+ num_to_add[i] = static_cast(to_add_round_up);
}
}
else {
+ std::vector px_error;
+ for (std::size_t i = 0; i < m_proxies.size(); ++i)
+ px_error.push_back(Proxy_error(i, m_proxies[i].err));
+ // sort partition by error
+ std::sort(px_error.begin(), px_error.end());
+
// residual from previous proxy in range (-0.5, 0.5] * avg_error
- FT residual(0.0);
- BOOST_FOREACH(const Proxy_error &pxe, px_error) {
+ double residual = 0.0;
+ for (std::size_t i = 0; i < m_proxies.size(); ++i) {
// add error residual from previous proxy
// to_add maybe negative but greater than -0.5
- FT to_add = (residual + pxe.err) / avg_error;
- // floor_to_add maybe negative but no less than -1
- FT floor_to_add = FT(std::floor(CGAL::to_double(to_add)));
- FT q_to_add = FT(CGAL::to_double(
- ((to_add - floor_to_add) > FT(0.5)) ? (floor_to_add + FT(1.0)) : floor_to_add));
- residual = (to_add - q_to_add) * avg_error;
- num_to_add[pxe.px] = static_cast(CGAL::to_double(q_to_add));
+ const double to_add = (residual + CGAL::to_double(px_error[i].err)) / avg_error;
+ const double to_add_round_up = std::floor(to_add + 0.5);
+ residual = (to_add - to_add_round_up) * avg_error;
+ num_to_add[i] = static_cast(to_add_round_up);
}
- }
#ifdef CGAL_SURFACE_MESH_APPROXIMATION_DEBUG
- for (std::size_t i = 0; i < px_error.size(); ++i)
- std::cerr << "#px " << px_error[i].px
- << ", #error " << px_error[i].err
- << ", #num_to_add " << num_to_add[px_error[i].px] << std::endl;
+ for (std::size_t i = 0; i < px_error.size(); ++i)
+ std::cerr << "#px " << px_error[i].px
+ << ", #error " << px_error[i].err
+ << ", #num_to_add " << num_to_add[px_error[i].px] << std::endl;
#endif
+ }
std::size_t num_added = 0;
BOOST_FOREACH(face_descriptor f, faces(*m_ptm)) {