Files
cgal/Cartesian_kernel/include/CGAL/constructions/kernel_ftC3.h
T
Sébastien Loriot a443f85a52 fix the determinism of the computation of point and base vectors
possibly will return true in case the evaluation lead to true or false
as possible values. If the exact value is computed or interval refined,
false could be the true value which has a consequence will give a
different result for point or base vector.
2018-03-16 14:33:51 +01:00

900 lines
29 KiB
C++

// Copyright (c) 2000
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Herve Bronnimann, Mariette Yvinec
#ifndef CGAL_CONSTRUCTIONS_KERNEL_FTC3_H
#define CGAL_CONSTRUCTIONS_KERNEL_FTC3_H
#include <CGAL/determinant.h>
#include <CGAL/number_utils.h>
namespace CGAL {
template < class FT >
CGAL_KERNEL_INLINE
void
midpointC3( const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
FT &x, FT &y, FT &z)
{
x = (px + qx) / 2;
y = (py + qy) / 2;
z = (pz + qz) / 2;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z,
FT &x, FT &y, FT &z)
{
FT w2 = 1 - w1;
x = w1 * p1x + w2 * p2x;
y = w1 * p1y + w2 * p2y;
z = w1 * p1z + w2 * p2z;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z, const FT &w2,
FT &x, FT &y, FT &z)
{
FT sum = w1 + w2;
CGAL_kernel_assertion(sum != 0);
x = (w1 * p1x + w2 * p2x) / sum;
y = (w1 * p1y + w2 * p2y) / sum;
z = (w1 * p1z + w2 * p2z) / sum;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z, const FT &w2,
const FT &p3x, const FT &p3y, const FT &p3z,
FT &x, FT &y, FT &z)
{
FT w3 = 1 - w1 - w2;
x = w1 * p1x + w2 * p2x + w3 * p3x;
y = w1 * p1y + w2 * p2y + w3 * p3y;
z = w1 * p1z + w2 * p2z + w3 * p3z;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z, const FT &w2,
const FT &p3x, const FT &p3y, const FT &p3z, const FT &w3,
FT &x, FT &y, FT &z)
{
FT sum = w1 + w2 + w3;
CGAL_kernel_assertion(sum != 0);
x = (w1 * p1x + w2 * p2x + w3 * p3x) / sum;
y = (w1 * p1y + w2 * p2y + w3 * p3y) / sum;
z = (w1 * p1z + w2 * p2z + w3 * p3z) / sum;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z, const FT &w2,
const FT &p3x, const FT &p3y, const FT &p3z, const FT &w3,
const FT &p4x, const FT &p4y, const FT &p4z,
FT &x, FT &y, FT &z)
{
FT w4 = 1 - w1 - w2 - w3;
x = w1 * p1x + w2 * p2x + w3 * p3x + w4 * p4x;
y = w1 * p1y + w2 * p2y + w3 * p3y + w4 * p4y;
z = w1 * p1z + w2 * p2z + w3 * p3z + w4 * p4z;
}
template < class FT >
void
barycenterC3(const FT &p1x, const FT &p1y, const FT &p1z, const FT &w1,
const FT &p2x, const FT &p2y, const FT &p2z, const FT &w2,
const FT &p3x, const FT &p3y, const FT &p3z, const FT &w3,
const FT &p4x, const FT &p4y, const FT &p4z, const FT &w4,
FT &x, FT &y, FT &z)
{
FT sum = w1 + w2 + w3 + w4;
CGAL_kernel_assertion(sum != 0);
x = (w1 * p1x + w2 * p2x + w3 * p3x + w4 * p4x) / sum;
y = (w1 * p1y + w2 * p2y + w3 * p3y + w4 * p4y) / sum;
z = (w1 * p1z + w2 * p2z + w3 * p3z + w4 * p4z) / sum;
}
template < class FT >
void
centroidC3( const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz,
const FT &sx, const FT &sy, const FT &sz,
FT &x, FT &y, FT &z)
{
x = (px + qx + rx + sx) / 4;
y = (py + qy + ry + sy) / 4;
z = (pz + qz + rz + sz) / 4;
}
template < class FT >
void
centroidC3( const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz,
FT &x, FT &y, FT &z)
{
x = (px + qx + rx) / 3;
y = (py + qy + ry) / 3;
z = (pz + qz + rz) / 3;
}
template < class FT >
CGAL_KERNEL_MEDIUM_INLINE
FT
squared_radiusC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz,
const FT &sx, const FT &sy, const FT &sz)
{
// Translate p to origin to simplify the expression.
FT qpx = qx-px;
FT qpy = qy-py;
FT qpz = qz-pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) + CGAL_NTS square(qpz);
FT rpx = rx-px;
FT rpy = ry-py;
FT rpz = rz-pz;
FT rp2 = CGAL_NTS square(rpx) + CGAL_NTS square(rpy) + CGAL_NTS square(rpz);
FT spx = sx-px;
FT spy = sy-py;
FT spz = sz-pz;
FT sp2 = CGAL_NTS square(spx) + CGAL_NTS square(spy) + CGAL_NTS square(spz);
FT num_x = determinant(qpy,qpz,qp2,
rpy,rpz,rp2,
spy,spz,sp2);
FT num_y = determinant(qpx,qpz,qp2,
rpx,rpz,rp2,
spx,spz,sp2);
FT num_z = determinant(qpx,qpy,qp2,
rpx,rpy,rp2,
spx,spy,sp2);
FT den = determinant(qpx,qpy,qpz,
rpx,rpy,rpz,
spx,spy,spz);
CGAL_kernel_assertion( ! CGAL_NTS is_zero(den) );
return (CGAL_NTS square(num_x) + CGAL_NTS square(num_y)
+ CGAL_NTS square(num_z)) / CGAL_NTS square(2 * den);
}
template < class FT >
CGAL_KERNEL_MEDIUM_INLINE
FT
squared_radiusC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &sx, const FT &sy, const FT &sz)
{
// Translate s to origin to simplify the expression.
FT psx = px-sx;
FT psy = py-sy;
FT psz = pz-sz;
FT ps2 = CGAL_NTS square(psx) + CGAL_NTS square(psy) + CGAL_NTS square(psz);
FT qsx = qx-sx;
FT qsy = qy-sy;
FT qsz = qz-sz;
FT qs2 = CGAL_NTS square(qsx) + CGAL_NTS square(qsy) + CGAL_NTS square(qsz);
FT rsx = psy*qsz-psz*qsy;
FT rsy = psz*qsx-psx*qsz;
FT rsz = psx*qsy-psy*qsx;
FT num_x = ps2 * determinant(qsy,qsz,rsy,rsz)
- qs2 * determinant(psy,psz,rsy,rsz);
FT num_y = ps2 * determinant(qsx,qsz,rsx,rsz)
- qs2 * determinant(psx,psz,rsx,rsz);
FT num_z = ps2 * determinant(qsx,qsy,rsx,rsy)
- qs2 * determinant(psx,psy,rsx,rsy);
FT den = determinant(psx,psy,psz,
qsx,qsy,qsz,
rsx,rsy,rsz);
CGAL_kernel_assertion( den != 0 );
return (CGAL_NTS square(num_x) + CGAL_NTS square(num_y)
+ CGAL_NTS square(num_z)) / CGAL_NTS square(2 * den);
}
template <class FT>
CGAL_KERNEL_MEDIUM_INLINE
void
plane_from_pointsC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz,
FT &pa, FT &pb, FT &pc, FT &pd)
{
FT rpx = px-rx;
FT rpy = py-ry;
FT rpz = pz-rz;
FT rqx = qx-rx;
FT rqy = qy-ry;
FT rqz = qz-rz;
// Cross product rp * rq
pa = rpy*rqz - rqy*rpz;
pb = rpz*rqx - rqz*rpx;
pc = rpx*rqy - rqx*rpy;
pd = - pa*rx - pb*ry - pc*rz;
}
template <class FT>
CGAL_KERNEL_MEDIUM_INLINE
void
plane_from_point_directionC3(const FT &px, const FT &py, const FT &pz,
const FT &dx, const FT &dy, const FT &dz,
FT &pa, FT &pb, FT &pc, FT &pd)
{
// d is the normal direction
pa = dx; pb = dy; pc = dz; pd = -dx*px - dy*py - dz*pz;
}
template <class FT>
CGAL_KERNEL_MEDIUM_INLINE
void
point_on_planeC3(const FT &pa, const FT &pb, const FT &pc, const FT &pd,
FT &x, FT &y, FT &z)
{
x = y = z = 0;
FT abs_pa = CGAL::abs(pa);
FT abs_pb = CGAL::abs(pb);
FT abs_pc = CGAL::abs(pc);
// to avoid badly defined point with an overly large coordinate when
// the plane is almost orthogonal to one axis, we use the largest
// scalar coordinate instead of always using the first non-null
if (abs_pa >= abs_pb && abs_pa >= abs_pc)
x = -pd/pa;
else if (abs_pb >= abs_pa && abs_pb >= abs_pc)
y = -pd/pb;
else
z = -pd/pc;
}
template <class FT>
CGAL_KERNEL_MEDIUM_INLINE
void
projection_planeC3(const FT &pa, const FT &pb, const FT &pc, const FT &pd,
const FT &px, const FT &py, const FT &pz,
FT &x, FT &y, FT &z)
{
// the equation of the plane is Ax+By+Cz+D=0
// the normal direction is (A,B,C)
// the projected point is p-lambda(A,B,C) where
// A(x-lambda A) + B(y-lambda B) + C(z-lambda C) + D = 0
FT num = pa*px + pb*py + pc*pz + pd;
FT den = pa*pa + pb*pb + pc*pc;
FT lambda = num / den;
x = px - lambda * pa;
y = py - lambda * pb;
z = pz - lambda * pc;
}
template < class FT >
CGAL_KERNEL_INLINE
FT
squared_distanceC3( const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz)
{
return CGAL_NTS square(px-qx) + CGAL_NTS square(py-qy) +
CGAL_NTS square(pz-qz);
}
template < class FT >
CGAL_KERNEL_INLINE
FT
squared_radiusC3( const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz)
{
return squared_distanceC3(px, py, pz, qx, qy, qz) / 4;
}
template < class FT >
CGAL_KERNEL_INLINE
FT
scaled_distance_to_directionC3(const FT &pa, const FT &pb, const FT &pc,
const FT &px, const FT &py, const FT &pz)
{
return pa*px + pb*py + pc*pz;
}
template < class FT >
CGAL_KERNEL_INLINE
FT
scaled_distance_to_planeC3(
const FT &pa, const FT &pb, const FT &pc, const FT &pd,
const FT &px, const FT &py, const FT &pz)
{
return pa*px + pb*py + pc*pz + pd;
}
template < class FT >
CGAL_KERNEL_INLINE
FT
scaled_distance_to_planeC3(
const FT &ppx, const FT &ppy, const FT &ppz,
const FT &pqx, const FT &pqy, const FT &pqz,
const FT &prx, const FT &pry, const FT &prz,
const FT &px, const FT &py, const FT &pz)
{
return determinant(ppx-px,ppy-py,ppz-pz,
pqx-px,pqy-py,pqz-pz,
prx-px,pry-py,prz-pz);
}
template < class FT >
CGAL_KERNEL_INLINE
void
bisector_of_pointsC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
FT &a, FT &b, FT &c, FT &d)
{
a = 2*(px - qx);
b = 2*(py - qy);
c = 2*(pz - qz);
d = CGAL_NTS square(qx) + CGAL_NTS square(qy) + CGAL_NTS square(qz)
- CGAL_NTS square(px) - CGAL_NTS square(py) - CGAL_NTS square(pz);
}
template < class FT >
void
bisector_of_planesC3(const FT &pa, const FT &pb, const FT &pc, const FT &pd,
const FT &qa, const FT &qb, const FT &qc, const FT &qd,
FT &a, FT &b, FT &c, FT &d)
{
// We normalize the equations of the 2 planes, and we then add them.
FT n1 = CGAL_NTS sqrt(CGAL_NTS square(pa) + CGAL_NTS square(pb) +
CGAL_NTS square(pc));
FT n2 = CGAL_NTS sqrt(CGAL_NTS square(qa) + CGAL_NTS square(qb) +
CGAL_NTS square(qc));
a = n2 * pa + n1 * qa;
b = n2 * pb + n1 * qb;
c = n2 * pc + n1 * qc;
d = n2 * pd + n1 * qd;
// Care must be taken for the case when this produces a degenerate line.
if (a == 0 && b == 0 && c == 0) {
a = n2 * pa - n1 * qa;
b = n2 * pb - n1 * qb;
c = n2 * pc - n1 * qc;
d = n2 * pd - n1 * qd;
}
}
template < class FT >
FT
squared_areaC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz)
{
// Compute vectors pq and pr, then the cross product,
// then 1/4 of its squared length.
FT dqx = qx-px;
FT dqy = qy-py;
FT dqz = qz-pz;
FT drx = rx-px;
FT dry = ry-py;
FT drz = rz-pz;
FT vx = dqy*drz-dqz*dry;
FT vy = dqz*drx-dqx*drz;
FT vz = dqx*dry-dqy*drx;
return (CGAL_NTS square(vx) + CGAL_NTS square(vy) + CGAL_NTS square(vz))/4;
}
template <class FT>
void
determinants_for_weighted_circumcenterC3(
const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw,
FT &num_x, FT &num_y, FT &num_z, FT& den)
{
// translate origin to p
// and compute determinants for weighted_circumcenter and
// circumradius
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz) - qw + pw;
FT rpx = rx - px;
FT rpy = ry - py;
FT rpz = rz - pz;
FT rp2 = CGAL_NTS square(rpx) + CGAL_NTS square(rpy) +
CGAL_NTS square(rpz) - rw + pw;
FT spx = sx - px;
FT spy = sy - py;
FT spz = sz - pz;
FT sp2 = CGAL_NTS square(spx) + CGAL_NTS square(spy) +
CGAL_NTS square(spz) - sw + pw;
num_x = determinant(qpy,qpz,qp2,
rpy,rpz,rp2,
spy,spz,sp2);
num_y = determinant(qpx,qpz,qp2,
rpx,rpz,rp2,
spx,spz,sp2);
num_z = determinant(qpx,qpy,qp2,
rpx,rpy,rp2,
spx,spy,sp2);
den = determinant(qpx,qpy,qpz,
rpx,rpy,rpz,
spx,spy,spz);
}
template <class FT>
void
determinants_for_circumcenterC3(const FT &px, const FT &py, const FT &pz,
const FT &qx, const FT &qy, const FT &qz,
const FT &rx, const FT &ry, const FT &rz,
const FT &sx, const FT &sy, const FT &sz,
FT &num_x, FT &num_y, FT &num_z, FT& den)
{
// translate origin to p
// and compute determinants for weighted_circumcenter and
// circumradius
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz);
FT rpx = rx - px;
FT rpy = ry - py;
FT rpz = rz - pz;
FT rp2 = CGAL_NTS square(rpx) + CGAL_NTS square(rpy) +
CGAL_NTS square(rpz);
FT spx = sx - px;
FT spy = sy - py;
FT spz = sz - pz;
FT sp2 = CGAL_NTS square(spx) + CGAL_NTS square(spy) +
CGAL_NTS square(spz);
num_x = determinant(qpy,qpz,qp2,
rpy,rpz,rp2,
spy,spz,sp2);
num_y = determinant(qpx,qpz,qp2,
rpx,rpz,rp2,
spx,spz,sp2);
num_z = determinant(qpx,qpy,qp2,
rpx,rpy,rp2,
spx,spy,sp2);
den = determinant(qpx,qpy,qpz,
rpx,rpy,rpz,
spx,spy,spz);
}
template < class FT>
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw,
FT &x, FT &y, FT &z)
{
// this function computes the weighted circumcenter point only
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
sx, sy, sz, sw,
num_x, num_y, num_z,den);
CGAL_assertion( ! CGAL_NTS is_zero(den) );
FT inv = FT(1)/(FT(2) * den);
x = px + num_x*inv;
y = py - num_y*inv;
z = pz + num_z*inv;
}
template < class FT>
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw,
FT &x, FT &y, FT &z, FT &w)
{
// this function computes the weighted circumcenter point
// and the squared weighted circumradius
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
sx, sy, sz, sw,
num_x, num_y, num_z, den);
CGAL_assertion( ! CGAL_NTS is_zero(den) );
FT inv = FT(1)/(FT(2) * den);
x = px + num_x*inv;
y = py - num_y*inv;
z = pz + num_z*inv;
w = (CGAL_NTS square(num_x) + CGAL_NTS square(num_y) + CGAL_NTS square(num_z))
* CGAL_NTS square(inv) - pw;
}
template< class FT >
FT
squared_radius_orthogonal_sphereC3(
const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw)
{
// this function computes the squared weighted circumradius only
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
sx, sy, sz, sw,
num_x, num_y, num_z,den);
CGAL_assertion( ! CGAL_NTS is_zero(den) );
FT inv = FT(1)/(FT(2) * den);
return (CGAL_NTS square(num_x) + CGAL_NTS square(num_y) + CGAL_NTS square(num_z))
* CGAL_NTS square(inv) - pw;
}
template <class FT>
void
determinants_for_weighted_circumcenterC3(
const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
FT &num_x, FT &num_y, FT &num_z, FT &den)
{
// translate origin to p and compute determinants for weighted_circumcenter
// and circumradius
// Translate s to origin to simplify the expression.
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz) - qw + pw;
FT rpx = rx - px;
FT rpy = ry - py;
FT rpz = rz - pz;
FT rp2 = CGAL_NTS square(rpx) + CGAL_NTS square(rpy) +
CGAL_NTS square(rpz) - rw + pw;
FT sx = qpy*rpz - qpz*rpy;
FT sy = qpz*rpx - qpx*rpz;
FT sz = qpx*rpy - qpy*rpx;
// The following determinants can be developped and simplified.
//
// FT num_x = determinant(qpy,qpz,qp2,
// rpy,rpz,rp2,
// sy,sz,FT(0));
// FT num_y = determinant(qpx,qpz,qp2,
// rpx,rpz,rp2,
// sx,sz,FT(0));
// FT num_z = determinant(qpx,qpy,qp2,
// rpx,rpy,rp2,
// sx,sy,FT(0));
num_x = qp2 * determinant(rpy,rpz,sy,sz)
- rp2 * determinant(qpy,qpz,sy,sz);
num_y = qp2 * determinant(rpx,rpz,sx,sz)
- rp2 * determinant(qpx,qpz,sx,sz);
num_z = qp2 * determinant(rpx,rpy,sx,sy)
- rp2 * determinant(qpx,qpy,sx,sy);
den = determinant(qpx,qpy,qpz,
rpx,rpy,rpz,
sx,sy,sz);
}
template < class FT >
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
FT &x, FT &y, FT &z)
{
// this function computes the weighted circumcenter point only
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
num_x, num_y, num_z, den);
CGAL_assertion( den != FT(0) );
FT inv = FT(1) / (FT(2) * den);
x = px + num_x*inv;
y = py - num_y*inv;
z = pz + num_z*inv;
}
template < class FT >
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
FT &x, FT &y, FT &z, FT &w)
{
// this function computes the weighted circumcenter and
// the weighted squared circumradius
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
num_x, num_y, num_z, den);
CGAL_assertion( den != FT(0) );
FT inv = FT(1) / (FT(2) * den);
x = px + num_x*inv;
y = py - num_y*inv;
z = pz + num_z*inv;
w = (CGAL_NTS square(num_x) + CGAL_NTS square(num_y) + CGAL_NTS square(num_z))
*CGAL_NTS square(inv) - pw;
}
template< class FT >
CGAL_MEDIUM_INLINE
FT
squared_radius_smallest_orthogonal_sphereC3(
const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw)
{
// this function computes the weighted squared circumradius only
// Translate p to origin and compute determinants
FT num_x, num_y, num_z, den;
determinants_for_weighted_circumcenterC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
num_x, num_y, num_z, den);
CGAL_assertion( den != FT(0) );
FT inv = FT(1)/(FT(2) * den);
return (CGAL_NTS square(num_x) + CGAL_NTS square(num_y) + CGAL_NTS square(num_z))
* CGAL_NTS square(inv) - pw;
}
template < class FT >
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
FT &x, FT &y, FT &z)
{
// this function computes the weighted circumcenter point only
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz);
FT inv = FT(1) / (FT(2) * qp2);
FT alpha = 1 / FT(2) + (pw-qw) * inv;
x = px + alpha * qpx;
y = py + alpha * qpy;
z = pz + alpha * qpz;
}
template < class FT >
void
weighted_circumcenterC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
FT &x, FT &y, FT &z, FT &w)
{
// this function computes the weighted circumcenter point and
// the weighted circumradius
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz);
FT inv = FT(1) / (FT(2) * qp2);
FT alpha = 1 / FT(2) + (pw-qw) * inv;
x = px + alpha * qpx;
y = py + alpha * qpy;
z = pz + alpha * qpz;
w = CGAL_NTS square(alpha) * qp2 - pw;
}
template< class FT >
CGAL_MEDIUM_INLINE
FT
squared_radius_smallest_orthogonal_sphereC3(
const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw)
{
// this function computes the weighted circumradius only
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz);
FT inv = FT(1) / (FT(2) * qp2);
FT alpha = 1 / FT(2) + (pw-qw) * inv;
return CGAL_NTS square(alpha)*qp2 - pw;
}
template< class FT >
FT
power_productC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw)
{
// computes the power product of two weighted points
FT qpx = qx - px;
FT qpy = qy - py;
FT qpz = qz - pz;
FT qp2 = CGAL_NTS square(qpx) + CGAL_NTS square(qpy) +
CGAL_NTS square(qpz);
return qp2 - pw - qw ;
}
template < class RT , class We>
void
radical_axisC3(const RT &px, const RT &py, const RT &pz, const We & /* pw */,
const RT &qx, const RT &qy, const RT &qz, const We & /* qw */,
const RT &rx, const RT &ry, const RT &rz, const We & /* rw */,
RT &a, RT &b, RT& c )
{
RT dqx=qx-px, dqy=qy-py, dqz=qz-pz, drx=rx-px, dry=ry-py, drz=rz-pz;
//il manque des tests...
a = RT(1)*determinant(dqy, dqz, dry, drz);
b = - RT(1)*determinant(dqx, dqz, drx, drz);
c = RT(1)*determinant(dqx, dqy, drx, dry);
}
// function used in critical_squared_radiusC3
// power ( t, tw) with respect to
// circle orthogonal (p,pw), (q,qw), (r,rw), (s,sw)
template < class FT>
FT
power_to_orthogonal_sphereC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw,
const FT &tx, const FT &ty, const FT &tz, const FT &tw)
{
//to get the value of the determinant
// We translate the points so that t becomes the origin.
FT dpx = px - tx;
FT dpy = py - ty;
FT dpz = pz - tz;
FT dpt = CGAL_NTS square(dpx) + CGAL_NTS square(dpy) +
CGAL_NTS square(dpz) - pw + tw ;
FT dqx = qx - tx;
FT dqy = qy - ty;
FT dqz = qz - tz;
FT dqt = CGAL_NTS square(dqx) + CGAL_NTS square(dqy) +
CGAL_NTS square(dqz) - qw + tw;
FT drx = rx - tx;
FT dry = ry - ty;
FT drz = rz - tz;
FT drt = CGAL_NTS square(drx) + CGAL_NTS square(dry) +
CGAL_NTS square(drz) - rw + tw;
FT dsx = sx - tx;
FT dsy = sy - ty;
FT dsz = sz - tz;
FT dst = CGAL_NTS square(dsx) + CGAL_NTS square(dsy) +
CGAL_NTS square(dsz) - sw + tw;
return determinant(dpx, dpy, dpz, dpt,
dqx, dqy, dqz, dqt,
drx, dry, drz, drt,
dsx, dsy, dsz, dst);
}
// compute the critical weight tw
// where weighted point t is orthogonal to weighted points p, q,r,s
template < class FT>
FT
power_distance_to_power_sphereC3(const FT &px, const FT &py, const FT &pz, const FT &pw,
const FT &qx, const FT &qy, const FT &qz, const FT &qw,
const FT &rx, const FT &ry, const FT &rz, const FT &rw,
const FT &sx, const FT &sy, const FT &sz, const FT &sw,
const FT &tx, const FT &ty, const FT &tz, const FT & )
{
// the 5x5 det is a linear function of tw ff(tw)= ff(0) + tw ff(1)
// the critical value for tw is - ff(0)/( ff(1) - ff(0))
FT ff0 = power_to_orthogonal_sphereC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
sx, sy, sz, sw,
tx, ty, tz, FT(0));
FT ff1 = power_to_orthogonal_sphereC3(px, py, pz, pw,
qx, qy, qz, qw,
rx, ry, rz, rw,
sx, sy, sz, sw,
tx, ty, tz, FT(1));
return -ff0/(ff1 - ff0);
}
// I will use this to test if the radial axis of three spheres
// intersect the triangle formed by the centers.
// // resolution of the system (where we note c the center)
// // | dc^2 = cw + rw
// // | (dp-dc)^2 = pw + cw
// // | (dq-dc)^2 = qw + cw
// // | dc = Lamdba*dp + Mu*dq
// FT FT2(2);
// FT dpx = px-rx;
// FT dpy = py-ry;
// FT dpz = pz-rz;
// FT dp = CGAL_NTS square(dpx)+CGAL_NTS square(dpy)+CGAL_NTS square(dpz);
// FT dpp = dp-pw+rw;
// FT dqx = qx-rx;
// FT dqy = qy-ry;
// FT dqz = qz-rz;
// FT dq = CGAL_NTS square(dqx)+CGAL_NTS square(dqy)+CGAL_NTS square(dqz);
// FT dqq = dq-qw+rw;
// FT dpdq = dpx*dqx+dpy*dqy+dpz*dqz;
// FT denom = FT2*(dp*dq-CGAL_NTS square(dpdq));
// FT Lambda = (dpp*dq-dqq*dpdq)/denom;
// FT Mu = (dqq*dp-dpp*dpdq)/denom;
// return (CGAL_NTS square(Lambda)*dp+CGAL_NTS square(Mu)*dq
// + FT2*Lambda*Mu*dpdq - rw);
} //namespace CGAL
#endif // CGAL_CONSTRUCTIONS_KERNEL_FTC3_H