Merge remote-tracking branch 'MaelRL/Weights-v2.0-GF' into HEAD

This commit is contained in:
Sébastien Loriot 2022-11-08 17:05:55 +01:00
commit ac6f4c01b4
4 changed files with 134 additions and 114 deletions

View File

@ -86,8 +86,7 @@ struct Types_selectors;
template<typename TriangleMesh, typename VertexPointMap>
struct Types_selectors<TriangleMesh, VertexPointMap, CGAL::SPOKES_AND_RIMS>
{
typedef SC_on_the_fly_pmap<VertexPointMap> Wrapped_VertexPointMap;
typedef CGAL::Weights::Single_cotangent_weight<TriangleMesh, Wrapped_VertexPointMap> Weight_calculator;
typedef CGAL::Weights::Single_cotangent_weight<TriangleMesh> Weight_calculator;
struct ARAP_visitor
{
@ -107,8 +106,7 @@ struct Types_selectors<TriangleMesh, VertexPointMap, CGAL::SPOKES_AND_RIMS>
template<class TriangleMesh, typename VertexPointMap>
struct Types_selectors<TriangleMesh, VertexPointMap, CGAL::ORIGINAL_ARAP>
{
typedef SC_on_the_fly_pmap<VertexPointMap> Wrapped_VertexPointMap;
typedef CGAL::Weights::Cotangent_weight<TriangleMesh, Wrapped_VertexPointMap> Weight_calculator;
typedef CGAL::Weights::Cotangent_weight<TriangleMesh> Weight_calculator;
typedef typename Types_selectors<TriangleMesh, VertexPointMap, CGAL::SPOKES_AND_RIMS>::ARAP_visitor ARAP_visitor;
};
@ -116,8 +114,7 @@ struct Types_selectors<TriangleMesh, VertexPointMap, CGAL::ORIGINAL_ARAP>
template<class TriangleMesh, typename VertexPointMap>
struct Types_selectors<TriangleMesh, VertexPointMap, CGAL::SRE_ARAP>
{
typedef SC_on_the_fly_pmap<VertexPointMap> Wrapped_VertexPointMap;
typedef CGAL::Weights::Cotangent_weight<TriangleMesh, Wrapped_VertexPointMap> Weight_calculator;
typedef CGAL::Weights::Cotangent_weight<TriangleMesh> Weight_calculator;
class ARAP_visitor
{
@ -384,7 +381,7 @@ public:
vertex_index_map,
hedge_index_map,
vertex_point_map,
Weight_calculator(triangle_mesh, internal::SC_on_the_fly_pmap<Vertex_point_map>(vertex_point_map)))
Weight_calculator())
{ }
Surface_mesh_deformation(Triangle_mesh& triangle_mesh,
@ -437,9 +434,10 @@ public:
private:
void init()
{
typedef internal::SC_on_the_fly_pmap<Vertex_point_map> Wrapper;
hedge_weight.reserve(num_halfedges(m_triangle_mesh));
for(halfedge_descriptor he : halfedges(m_triangle_mesh))
hedge_weight.push_back(this->weight_calculator(he));
hedge_weight.push_back(this->weight_calculator(he, m_triangle_mesh, Wrapper(vertex_point_map)));
arap_visitor.init(m_triangle_mesh, vertex_point_map);
}
@ -823,6 +821,7 @@ public:
*/
void overwrite_initial_geometry()
{
typedef internal::SC_on_the_fly_pmap<Vertex_point_map> Wrapper;
if(roi.empty()) { return; } // no ROI to overwrite
region_of_solution(); // the roi should be preprocessed since we are using original_position vec
@ -843,13 +842,13 @@ public:
std::size_t id_e = id(he);
if(is_weight_computed[id_e]) { continue; }
hedge_weight[id_e] = weight_calculator(he);
hedge_weight[id_e] = weight_calculator(he, m_triangle_mesh, Wrapper(vertex_point_map));
is_weight_computed[id_e] = true;
halfedge_descriptor e_opp = opposite(he, m_triangle_mesh);
std::size_t id_e_opp = id(e_opp);
hedge_weight[id_e_opp] = weight_calculator(e_opp);
hedge_weight[id_e_opp] = weight_calculator(e_opp, m_triangle_mesh, Wrapper(vertex_point_map));
is_weight_computed[id_e_opp] = true;
}
}

View File

@ -147,44 +147,38 @@ typename Kernel::FT cotangent_weight(const CGAL::Point_3<Kernel>& p0,
// For border edges it returns zero.
// This version is currently used in:
// Surface_mesh_deformation -> Surface_mesh_deformation.h
template<typename PolygonMesh,
typename VertexPointMap,
typename GeomTraits = typename Kernel_traits<
typename boost::property_traits<VertexPointMap>::value_type>::type>
template<typename PolygonMesh>
class Single_cotangent_weight
{
using vertex_descriptor = typename boost::graph_traits<PolygonMesh>::vertex_descriptor;
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
using Point_ref = typename boost::property_traits<VertexPointMap>::reference;
using FT = typename GeomTraits::FT;
private:
const PolygonMesh& m_pmesh;
const VertexPointMap m_vpm;
const GeomTraits m_traits;
public:
Single_cotangent_weight(const PolygonMesh& pmesh,
const VertexPointMap vpm,
const GeomTraits& traits = GeomTraits())
: m_pmesh(pmesh), m_vpm(vpm), m_traits(traits)
{ }
decltype(auto) operator()(const halfedge_descriptor he) const
// Returns the cotangent of the opposite angle of the edge
// 0 for border edges (which does not have an opposite angle).
template <typename VPM>
auto operator()(halfedge_descriptor he,
PolygonMesh& pmesh,
VPM vpm)
{
if (is_border(he, m_pmesh))
using Point = typename boost::property_traits<VPM>::value_type;
using Point_ref = typename boost::property_traits<VPM>::reference;
using GeomTraits = typename Kernel_traits<Point>::type;
using FT = typename GeomTraits::FT;
if(is_border(he, pmesh))
return FT{0};
const vertex_descriptor v0 = target(he, m_pmesh);
const vertex_descriptor v1 = source(he, m_pmesh);
const vertex_descriptor v2 = target(next(he, m_pmesh), m_pmesh);
const vertex_descriptor v0 = target(he, pmesh);
const vertex_descriptor v1 = source(he, pmesh);
const vertex_descriptor v2 = target(next(he, pmesh), pmesh);
const Point_ref p0 = get(m_vpm, v0);
const Point_ref p1 = get(m_vpm, v1);
const Point_ref p2 = get(m_vpm, v2);
const Point_ref p0 = get(vpm, v0);
const Point_ref p1 = get(vpm, v1);
const Point_ref p2 = get(vpm, v2);
return cotangent_3(p0, p2, p1, m_traits);
return cotangent(p0, p2, p1);
}
};
@ -200,7 +194,7 @@ public:
// Surface_mesh_parameterizer -> Orbifold_Tutte_parameterizer_3.h (default version)
// Surface_mesh_skeletonization -> Mean_curvature_flow_skeletonization.h (clamped version)
template<typename PolygonMesh,
typename VertexPointMap,
typename VertexPointMap = typename GetVertexPointMap<PolygonMesh>::type,
typename GeomTraits = typename Kernel_traits<
typename boost::property_traits<VertexPointMap>::value_type>::type>
class Cotangent_weight
@ -208,11 +202,14 @@ class Cotangent_weight
using vertex_descriptor = typename boost::graph_traits<PolygonMesh>::vertex_descriptor;
using halfedge_descriptor = typename boost::graph_traits<PolygonMesh>::halfedge_descriptor;
using Point_ref = typename boost::property_traits<VertexPointMap>::reference;
using FT = typename GeomTraits::FT;
private:
const PolygonMesh& m_pmesh;
// These class members are used only when the constructor initializing them
// is used, but Surface_mesh_deformation has its own weight API locked
// by the concept SurfaceMeshDeformationWeights.
// A bit awkward, but better than duplicating code...
PolygonMesh* const* m_pmesh_ptr;
const VertexPointMap m_vpm;
const GeomTraits m_traits;
@ -220,39 +217,41 @@ private:
bool m_bound_from_below;
public:
Cotangent_weight(const PolygonMesh& pmesh,
const VertexPointMap vpm,
const GeomTraits& traits = GeomTraits(),
const bool use_clamped_version = false,
const bool bound_from_below = true)
: m_pmesh(pmesh), m_vpm(vpm), m_traits(traits),
m_use_clamped_version(use_clamped_version),
m_bound_from_below(bound_from_below)
Cotangent_weight()
: m_pmesh_ptr(nullptr), m_vpm(), m_traits(), m_use_clamped_version(false), m_bound_from_below(true)
{ }
decltype(auto) operator()(const halfedge_descriptor he) const
// Common API whether mesh/vpm/traits are initialized in the constructor,
// or passed in the operator()
template <typename VPM, typename GT>
FT operator()(const halfedge_descriptor he,
const PolygonMesh& pmesh,
const VPM vpm,
const GT& traits) const
{
if(is_border(he, m_pmesh))
using Point_ref = typename boost::property_traits<VPM>::reference;
if(is_border(he, pmesh))
return FT{0};
auto half_weight = [&] (const halfedge_descriptor he) -> FT
{
if(is_border(he, m_pmesh))
if(is_border(he, pmesh))
return FT{0};
const vertex_descriptor v0 = target(he, m_pmesh);
const vertex_descriptor v1 = source(he, m_pmesh);
const vertex_descriptor v2 = target(next(he, m_pmesh), m_pmesh);
const vertex_descriptor v0 = target(he, pmesh);
const vertex_descriptor v1 = source(he, pmesh);
const vertex_descriptor v2 = target(next(he, pmesh), pmesh);
const Point_ref p0 = get(m_vpm, v0);
const Point_ref p1 = get(m_vpm, v1);
const Point_ref p2 = get(m_vpm, v2);
const Point_ref p0 = get(vpm, v0);
const Point_ref p1 = get(vpm, v1);
const Point_ref p2 = get(vpm, v2);
FT weight = 0;
if (m_use_clamped_version)
weight = cotangent_3_clamped(p1, p2, p0, m_traits);
weight = cotangent_3_clamped(p1, p2, p0, traits);
else
weight = cotangent_3(p1, p2, p0, m_traits);
weight = cotangent_3(p1, p2, p0, traits);
if(m_bound_from_below)
weight = (CGAL::max)(FT(0), weight);
@ -260,9 +259,38 @@ public:
return weight / FT(2);
};
FT weight = half_weight(he) + half_weight(opposite(he, m_pmesh));
FT weight = half_weight(he) + half_weight(opposite(he, pmesh));
return weight;
}
// That is the API called by Surface_mesh_deformation
template <typename VPM>
FT operator()(const halfedge_descriptor he,
const PolygonMesh& pmesh,
const VPM vpm) const
{
using Point = typename boost::property_traits<VPM>::value_type;
using GT = typename Kernel_traits<Point>::type;
return this->operator()(he, pmesh, vpm, GT());
}
public:
// This is the "normal" API: give all info to the constructor, and operator()(halfedge)
Cotangent_weight(const PolygonMesh& pmesh,
const VertexPointMap vpm,
const GeomTraits& traits = GeomTraits(),
const bool use_clamped_version = false,
const bool bound_from_below = true)
: m_pmesh_ptr(&pmesh), m_vpm(vpm), m_traits(traits),
m_use_clamped_version(use_clamped_version),
m_bound_from_below(bound_from_below)
{ }
FT operator()(const halfedge_descriptor he) const
{
CGAL_precondition(m_pmesh_ptr != nullptr);
return this->operator()(he, *m_pmesh_ptr, m_vpm, m_traits);
}
};
// Undocumented cotangent weight class.

View File

@ -51,7 +51,7 @@ struct Cotangent_value_Meyer_impl
double operator()(vertex_descriptor v0,
vertex_descriptor v1,
vertex_descriptor v2,
const VertexPointMap& ppmap)
VertexPointMap ppmap)
{
typedef typename Kernel_traits<
typename boost::property_traits<VertexPointMap>::value_type >::Kernel::Vector_3 Vector;
@ -94,17 +94,17 @@ protected:
typedef typename boost::property_traits<Point_property_map>::value_type Point;
typedef typename Kernel_traits<Point>::Kernel::Vector_3 Vector;
PolygonMesh& pmesh_;
const PolygonMesh& pmesh_;
Point_property_map ppmap_;
public:
Cotangent_value_Meyer(PolygonMesh& pmesh_,
Cotangent_value_Meyer(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: pmesh_(pmesh_), ppmap_(vpmap_)
{ }
PolygonMesh& pmesh() { return pmesh_; }
Point_property_map& ppmap() { return ppmap_; }
const PolygonMesh& pmesh() { return pmesh_; }
Point_property_map ppmap() { return ppmap_; }
double operator()(vertex_descriptor v0,
vertex_descriptor v1,
@ -128,13 +128,13 @@ class Cotangent_value_Meyer_secure
Point_property_map ppmap_;
public:
Cotangent_value_Meyer_secure(PolygonMesh& pmesh_,
Cotangent_value_Meyer_secure(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: pmesh_(pmesh_), ppmap_(vpmap_)
{ }
PolygonMesh& pmesh() { return pmesh_; }
Point_property_map& ppmap() { return ppmap_; }
const PolygonMesh& pmesh() { return pmesh_; }
Point_property_map ppmap() { return ppmap_; }
double operator()(vertex_descriptor v0,
vertex_descriptor v1,
@ -165,13 +165,13 @@ class Cotangent_value_clamped : CotangentValue
Cotangent_value_clamped() { }
public:
Cotangent_value_clamped(PolygonMesh& pmesh_,
Cotangent_value_clamped(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -194,13 +194,13 @@ class Cotangent_value_clamped_2 : CotangentValue
Cotangent_value_clamped_2() { }
public:
Cotangent_value_clamped_2(PolygonMesh& pmesh_,
Cotangent_value_clamped_2(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -238,17 +238,16 @@ template<typename PolygonMesh,
typename CotangentValue = Cotangent_value_Meyer<PolygonMesh, VertexPointMap> >
class Cotangent_value_minimum_zero : CotangentValue
{
Cotangent_value_minimum_zero()
{ }
public:
Cotangent_value_minimum_zero(PolygonMesh& pmesh_,
Cotangent_value_minimum_zero() { }
Cotangent_value_minimum_zero(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -268,13 +267,13 @@ class Voronoi_area
: CotangentValue
{
public:
Voronoi_area(PolygonMesh& pmesh_,
Voronoi_area(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::in_edge_iterator in_edge_iterator;
@ -348,13 +347,13 @@ class Cotangent_value_area_weighted
Cotangent_value_area_weighted() { }
public:
Cotangent_value_area_weighted(PolygonMesh& pmesh_,
Cotangent_value_area_weighted(const PolygonMesh& pmesh_,
VertexPointMap vpmap_) :
CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -385,7 +384,7 @@ struct Cotangent_weight_impl
template<class VertexPointMap>
double operator()(halfedge_descriptor he,
PolygonMesh& pmesh,
const VertexPointMap& ppmap)
VertexPointMap ppmap)
{
const vertex_descriptor v0 = target(he, pmesh);
const vertex_descriptor v1 = source(he, pmesh);
@ -422,20 +421,20 @@ template<typename PolygonMesh,
class Cotangent_weight
: CotangentValue
{
public:
Cotangent_weight() { }
public:
Cotangent_weight(PolygonMesh& pmesh_,
Cotangent_weight(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
Cotangent_weight(PolygonMesh& pmesh_)
Cotangent_weight(const PolygonMesh& pmesh_)
: CotangentValue(pmesh_, get(CGAL::vertex_point, pmesh_))
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -512,13 +511,13 @@ class Single_cotangent_weight
Single_cotangent_weight() { }
public:
Single_cotangent_weight(PolygonMesh& pmesh_,
Single_cotangent_weight(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -557,13 +556,13 @@ class Cotangent_weight_with_triangle_area
Cotangent_weight_with_triangle_area() { }
public:
Cotangent_weight_with_triangle_area(PolygonMesh& pmesh_,
Cotangent_weight_with_triangle_area(const PolygonMesh& pmesh_,
VertexPointMap vpmap_)
: CotangentValue(pmesh_, vpmap_)
{ }
PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap& ppmap() { return CotangentValue::ppmap(); }
const PolygonMesh& pmesh() { return CotangentValue::pmesh(); }
VertexPointMap ppmap() { return CotangentValue::ppmap(); }
double operator()(halfedge_descriptor he)
{
@ -614,18 +613,16 @@ template<typename PolygonMesh,
typename VertexPointMap = typename boost::property_map<PolygonMesh, CGAL::vertex_point_t>::type>
class Mean_value_weight
{
// Mean_value_weight() {}
PolygonMesh& pmesh_;
const PolygonMesh& pmesh_;
VertexPointMap vpmap_;
public:
Mean_value_weight(PolygonMesh& pmesh_,
Mean_value_weight(const PolygonMesh& pmesh_,
VertexPointMap vpmap)
: pmesh_(pmesh_), vpmap_(vpmap)
{ }
PolygonMesh& pmesh() { return pmesh_; }
const PolygonMesh& pmesh() { return pmesh_; }
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -722,11 +719,11 @@ class Hybrid_weight
Hybrid_weight() { }
public:
Hybrid_weight(PolygonMesh& pmesh_)
Hybrid_weight(const PolygonMesh& pmesh_)
: primary(pmesh_), secondary(pmesh_)
{ }
PolygonMesh& pmesh() { return primary.pmesh(); }
const PolygonMesh& pmesh() { return primary.pmesh(); }
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
@ -751,14 +748,14 @@ public:
template<class PolygonMesh>
class Scale_dependent_weight_fairing
{
PolygonMesh& pmesh_;
const PolygonMesh& pmesh_;
public:
Scale_dependent_weight_fairing(PolygonMesh& pmesh_)
Scale_dependent_weight_fairing(const PolygonMesh& pmesh_)
: pmesh_(pmesh_)
{ }
PolygonMesh& pmesh() { return pmesh_; }
const PolygonMesh& pmesh() { return pmesh_; }
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -800,7 +797,7 @@ public:
Cotangent_weight_with_voronoi_area_fairing(PM& pmesh_,
VPMap vpmap_)
: voronoi_functor(pmesh_, vpmap_),
: voronoi_functor(pmesh_, vpmap_),
cotangent_functor(pmesh_, vpmap_)
{ }
@ -867,7 +864,7 @@ public:
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
Uniform_weight_fairing(PolygonMesh&) { }
Uniform_weight_fairing(const PolygonMesh&) { }
double w_ij(halfedge_descriptor /* e */) { return 1.0; }
double w_i(vertex_descriptor /* v_i */) { return 1.0; }

View File

@ -214,7 +214,6 @@ typename GeomTraits::Point_3 rotate_point_3(const double angle_rad,
const GeomTraits& traits)
{
using FT = typename GeomTraits::FT;
using Point_3 = typename GeomTraits::Point_3;
auto point_3 = traits.construct_point_3_object();
@ -274,7 +273,6 @@ typename GeomTraits::Point_2 to_2d(const typename GeomTraits::Vector_3& b1,
const GeomTraits& traits)
{
using FT = typename GeomTraits::FT;
using Point_2 = typename GeomTraits::Point_2;
using Vector_3 = typename GeomTraits::Vector_3;
auto dot_product_3 = traits.compute_scalar_product_3_object();
@ -447,7 +445,6 @@ typename GeomTraits::FT area_3(const typename GeomTraits::Point_3& p,
const typename GeomTraits::Point_3& r,
const GeomTraits& traits)
{
using FT = typename GeomTraits::FT;
using Point_2 = typename GeomTraits::Point_2;
using Point_3 = typename GeomTraits::Point_3;
using Vector_3 = typename GeomTraits::Vector_3;
@ -493,7 +490,6 @@ typename GeomTraits::FT positive_area_3(const typename GeomTraits::Point_3& p,
const typename GeomTraits::Point_3& r,
const GeomTraits& traits)
{
using FT = typename GeomTraits::FT;
using Get_sqrt = Get_sqrt<GeomTraits>;
auto sqrt = Get_sqrt::sqrt_object(traits);