Special case the circumcenter computation for few points

This commit is contained in:
Marc Glisse 2020-07-02 23:49:42 +02:00
parent abd53906c5
commit d6e39a16dc
1 changed files with 78 additions and 51 deletions

View File

@ -616,7 +616,36 @@ template <class R_> struct Construct_circumcenter : Store_kernel<R_> {
Point const& p0=*f;
int d = pd(p0);
if (d+1 == std::distance(f,e))
int k = static_cast<int>(std::distance(f,e));
if(k==1) return p0;
if(k==2){
typename Get_functor<R_, Midpoint_tag>::type mid(this->kernel());
return mid(p0, *++f);
}
if(k==3){
// Same equations as in the general case, but solved by hand (Cramer)
// (c-r).(p-r)=(p-r)²/2
// (c-r).(q-r)=(q-r)²/2
typedef typename Get_type<R_, Vector_tag>::type Vector;
typename Get_functor<R_, Squared_length_tag>::type sl(this->kernel());
typename Get_functor<R_, Scalar_product_tag>::type sp(this->kernel());
typename Get_functor<R_, Scaled_vector_tag>::type sv(this->kernel());
typename Get_functor<R_, Difference_of_points_tag>::type dp(this->kernel());
typename Get_functor<R_, Translated_point_tag>::type tp(this->kernel());
Iter f2=f;
Point const& q=*++f2;
Point const& r=*++f2;
Vector u = dp(p0, r);
Vector v = dp(q, r);
FT uv = sp(u, v);
FT u2 = sl(u);
FT v2 = sl(v);
FT den = 2 * (u2 * v2 - CGAL::square(uv));
FT a = (u2 - uv) * v2 / den;
FT b = (v2 - uv) * u2 / den;
return tp(tp(r, sv(u, a)), sv(v, b));
}
if (k == d+1)
{
// 2*(x-y).c == x^2-y^2
typedef typename LA::Square_matrix Matrix;
@ -641,9 +670,9 @@ template <class R_> struct Construct_circumcenter : Store_kernel<R_> {
//std::cout << "Sol: " << res << std::endl;
return cp(d,LA::vector_begin(res),LA::vector_end(res));
}
else
{
/*
/* The general case
*
* Matrix P=(p1, p2, ...) (each point as a column)
* Matrix Q=2*t(p2-p1,p3-p1, ...) (each vector as a line)
* Matrix M: QP, adding a line of 1 at the top
@ -660,7 +689,6 @@ template <class R_> struct Construct_circumcenter : Store_kernel<R_> {
typedef typename LAd::Square_matrix Matrix;
typedef typename LAd::Vector Vec;
typename Get_functor<R_, Scalar_product_tag>::type sp(this->kernel());
int k=static_cast<int>(std::distance(f,e));
Matrix m(k,k);
Vec b(k);
Vec l(k);
@ -696,7 +724,6 @@ template <class R_> struct Construct_circumcenter : Store_kernel<R_> {
return cp(LA::vector_begin(center),LA::vector_end(center));
}
}
};
}