mirror of https://github.com/CGAL/cgal
468 lines
14 KiB
C++
468 lines
14 KiB
C++
// Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// 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.
|
|
//
|
|
// $Source$
|
|
// $Revision$ $Date$
|
|
// $Name$
|
|
//
|
|
// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
|
|
#ifndef CGAL_EXTENDED_HOMOGENEOUS_3_H
|
|
#define CGAL_EXTENDED_HOMOGENEOUS_3_H
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <CGAL/Homogeneous.h>
|
|
#include <CGAL/Point_3.h>
|
|
// #include <CGAL/Line_3_Line_3_intersection.h>
|
|
#include <CGAL/squared_distance_3.h>
|
|
#include <CGAL/number_utils.h>
|
|
#include <CGAL/Nef_2/Nef_polynomial.h>
|
|
#undef _DEBUG
|
|
#define _DEBUG 5
|
|
#include <CGAL/Nef_3/debug.h>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
template <class T> class Extended_homogeneous_3;
|
|
|
|
template <class RT_>
|
|
class Extended_homogeneous_3 : public
|
|
CGAL::Homogeneous< CGAL::Nef_polynomial<RT_> > {
|
|
|
|
public:
|
|
|
|
typedef CGAL::Homogeneous< CGAL::Nef_polynomial<RT_> > Base;
|
|
typedef Extended_homogeneous_3<RT_> Self;
|
|
|
|
typedef CGAL::Homogeneous<RT_> Standard_kernel;
|
|
|
|
typedef RT_ Standard_RT;
|
|
|
|
typedef typename Standard_kernel::FT Standard_FT;
|
|
|
|
typedef typename Standard_kernel::Point_3 Standard_point_3;
|
|
|
|
typedef typename Standard_kernel::Segment_3 Standard_segment_3;
|
|
|
|
typedef typename Standard_kernel::Line_3 Standard_line_3;
|
|
|
|
typedef typename Standard_kernel::Ray_3 Standard_ray_3;
|
|
|
|
typedef typename Standard_kernel::Aff_transformation_3
|
|
Standard_aff_transformation_3;
|
|
|
|
typedef typename Base::RT RT;
|
|
|
|
typedef typename Base::Point_3 Point_3;
|
|
|
|
typedef typename Base::Segment_3 Segment_3;
|
|
|
|
typedef typename Base::Line_3 Line_3;
|
|
|
|
enum Point_type { ERROR=0,
|
|
STANDARD=1,
|
|
SWFCORNER, NWFCORNER, NEFCORNER, SEFCORNER,
|
|
SWBCORNER, NWBCORNER, NEBCORNER, SEBCORNER,
|
|
BOTTOMFFRAME, TOPFFRAME, RIGHTFFRAME, LEFTFFRAME,
|
|
BOTTOMBFRAME, TOPBFRAME, RIGHTBFRAME, LEFTBFRAME,
|
|
SWFRAME, NWFRAME, NEFRAME, SEFRAME,
|
|
BOTTOMPLANE, TOPPLANE, RIGHTPLANE, LEFTPLANE, FRONTPLANE, BACKPLANE};
|
|
|
|
|
|
public:
|
|
static Point_3 epoint(const Standard_RT& m1, const Standard_RT& n1,
|
|
const Standard_RT& m2, const Standard_RT& n2,
|
|
const Standard_RT& m3, const Standard_RT& n3,
|
|
const Standard_RT& n4)
|
|
{ return Point_3(RT(n1,m1),RT(n2,m2),RT(n3,m3),RT(n4));}
|
|
|
|
|
|
|
|
/* Vorsicht> vereinfacht, da Ortsvektor nicht mit einbezogen */
|
|
Point_3 construct_point(const Standard_line_3& l, Point_type& t) const
|
|
{
|
|
Point_3 res = epoint(l.dx(),0,l.dy(),0,l.dz(),0);
|
|
t = (Point_type) determine_type(res);
|
|
return res;
|
|
}
|
|
|
|
|
|
template <class Forward_iterator>
|
|
void determine_frame_radius(Forward_iterator start, Forward_iterator end,
|
|
Standard_RT& R0) const
|
|
{
|
|
Standard_RT R, mx, nx, my, ny, mz, nz;
|
|
while ( start != end ) {
|
|
Point_3 p = *start++;
|
|
if ( is_standard(p) ) {
|
|
R = CGAL_NTS max(CGAL_NTS abs(p.hx()[0])/p.hw()[0],
|
|
CGAL_NTS max(CGAL_NTS abs(p.hy()[0])/p.hw()[0],
|
|
CGAL_NTS abs(p.hz()[0])/p.hw()[0]));
|
|
}
|
|
else
|
|
{
|
|
RT rx = CGAL_NTS abs(p.hx()), ry = CGAL_NTS abs(p.hy()), rz = CGAL_NTS abs(p.hz());
|
|
mx = ( rx.degree()>0 ? rx[1] : Standard_RT(0) ); nx = rx[0];
|
|
my = ( ry.degree()>0 ? ry[1] : Standard_RT(0) ); ny = ry[0];
|
|
mz = ( rz.degree()>0 ? rz[1] : Standard_RT(0) ); nz = rz[0];
|
|
|
|
if ( mx > my ) R = CGAL_NTS abs((ny-nx)/(mx-my));
|
|
else if ( mx < my ) R = CGAL_NTS abs((nx-ny)/(my-mx));
|
|
else /* mx == my */ R = CGAL_NTS abs(nx-ny)/(2*p.hw()[0]);
|
|
if ( mx > mz ) R = CGAL_NTS max(R, CGAL_NTS abs((nz-nx)/(mx-mz)));
|
|
else if ( mx < mz) R = CGAL_NTS max(R, CGAL_NTS abs((nx-nz)/(mz-mx)));
|
|
else R = CGAL_NTS max(R, CGAL_NTS abs(nx-ny)/(2*p.hw()[0]));
|
|
}
|
|
R0 = CGAL_NTS max(R+1,R0);
|
|
}
|
|
}
|
|
|
|
|
|
Point_3 construct_point(const Standard_point_3& p) const
|
|
{ return Point_3(p.hx(), p.hy(), p.hz(), p.hw()); }
|
|
|
|
Point_3 construct_point(const Standard_point_3& p1,
|
|
const Standard_point_3& p2,
|
|
const Standard_point_3& p3,
|
|
Point_type& t) const
|
|
{ return construct_point(Standard_line_3(p1,p2,p3),t); }
|
|
|
|
Point_3 construct_point(const Standard_line_3& l) const
|
|
{ Point_type dummy; return construct_point(l,dummy); }
|
|
|
|
Point_3 construct_point(const Standard_point_3& p1,
|
|
const Standard_point_3& p2,
|
|
const Standard_point_3& p3) const
|
|
{ return construct_point(Standard_line_3(p1,p2,p3)); }
|
|
|
|
Point_3 construct_opposite_point(const Standard_line_3& l) const
|
|
{ Point_type dummy; return construct_point(l.opposite(),dummy); }
|
|
|
|
|
|
static Point_type type(const Point_3& p)
|
|
{
|
|
CGAL_assertion(p.hx().degree()>=0 && p.hy().degree()>=0 && p.hz().degree()>=0 );
|
|
CGAL_assertion(p.hw().degree()==0);
|
|
|
|
if (p.hx().degree() == 0 && p.hy().degree() == 0 && p.hz().degree() == 0)
|
|
return STANDARD;
|
|
|
|
RT r[3];
|
|
r[0] = p.hx();
|
|
r[1] = p.hy();
|
|
r[2] = p.hz();
|
|
|
|
int s[3];
|
|
for(int i=0;i<3;i++) {
|
|
s[i] = CGAL_NTS sign(r[i]);
|
|
if(s[i] < 0) r[i] = -r[i];
|
|
}
|
|
|
|
int on_frame = 1;
|
|
int ref = 0;
|
|
for(int i=1,bit = 2;i<3;++i) {
|
|
if(r[i]>r[ref]){
|
|
on_frame = bit;
|
|
ref = i;
|
|
}
|
|
else if(r[i]==r[ref])
|
|
on_frame += bit;
|
|
bit*=2;
|
|
}
|
|
|
|
switch(on_frame)
|
|
{
|
|
case 7:
|
|
CGAL_assertion(r[0]==r[1]);
|
|
CGAL_assertion(r[1]==r[2]);
|
|
|
|
if(s[0]>0)
|
|
if(s[1]>0)
|
|
if(s[2]>0) return NEFCORNER;
|
|
else return SEFCORNER;
|
|
else
|
|
if(s[2]>0) return NEBCORNER;
|
|
else return SEBCORNER;
|
|
else
|
|
if(s[1]>0)
|
|
if(s[2]>0) return NWFCORNER;
|
|
else return SWFCORNER;
|
|
else
|
|
if(s[2]>0) return NWBCORNER;
|
|
else return SWBCORNER;
|
|
break;
|
|
|
|
case 6:
|
|
CGAL_assertion(r[2]==r[1]);
|
|
CGAL_assertion(r[2]>r[0]);
|
|
|
|
if(s[1]>0)
|
|
if(s[2]>0) return TOPFFRAME;
|
|
else return BOTTOMFFRAME;
|
|
else
|
|
if(s[2]>0) return TOPBFRAME;
|
|
else return BOTTOMBFRAME;
|
|
break;
|
|
|
|
case 5:
|
|
CGAL_assertion(r[2]==r[0]);
|
|
CGAL_assertion(r[2]>r[1]);
|
|
|
|
if(s[0]>0)
|
|
if(s[2]>0) return NEFRAME;
|
|
else return SEFRAME;
|
|
else
|
|
if(s[2]>0) return NWFRAME;
|
|
else return SWFRAME;
|
|
break;
|
|
|
|
case 4:
|
|
CGAL_assertion(r[2]>r[0]);
|
|
CGAL_assertion(r[2]>r[1]);
|
|
|
|
if(s[2]>0) return TOPPLANE;
|
|
else return BOTTOMPLANE;
|
|
break;
|
|
|
|
case 3:
|
|
CGAL_assertion(r[1]==r[0]);
|
|
CGAL_assertion(r[1]>r[2]);
|
|
|
|
if(s[0]>0)
|
|
if(s[1]>0) return RIGHTFFRAME;
|
|
else return LEFTFFRAME;
|
|
else
|
|
if(s[1]>0) return RIGHTBFRAME;
|
|
else return LEFTBFRAME;
|
|
break;
|
|
|
|
case 2:
|
|
CGAL_assertion(r[1]>r[0]);
|
|
CGAL_assertion(r[1]>r[2]);
|
|
|
|
if(s[1]>0) return FRONTPLANE;
|
|
else return BACKPLANE;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
CGAL_assertion(r[0]>r[1]);
|
|
CGAL_assertion(r[0]>r[2]);
|
|
|
|
if(s[0]>0) return RIGHTPLANE;
|
|
else return LEFTPLANE;
|
|
|
|
break;
|
|
|
|
default:
|
|
CGAL_assertion_msg(0,"EPoint type not correct!");
|
|
return ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
static bool is_standard(const Point_3& p)
|
|
{ return (type(p)==STANDARD); }
|
|
|
|
Standard_point_3 standard_point(const Point_3& p) const
|
|
{ CGAL_assertion(type(p)==STANDARD);
|
|
CGAL_assertion(p.hw() > RT(0));
|
|
return Standard_point_3(p.hx()[0],p.hy()[0],p.hz()[0],p.hw()[0]);
|
|
}
|
|
|
|
Standard_line_3 standard_line(const Point_3& p) const
|
|
{ CGAL_assertion(type(p)!=STANDARD);
|
|
RT hx = p.hx(), hy = p.hy(), hz = p.hz(), hw = p.hw();
|
|
Standard_RT dx,dy,dz;
|
|
if (hx.degree()>0) dx=hx[1]; else dx=0;
|
|
if (hy.degree()>0) dy=hy[1]; else dy=0;
|
|
if (hz.degree()>0) dz=hz[1]; else dz=0;
|
|
Standard_point_3 p0(hx[0],hy[0],hz[0],hw[0]);
|
|
Standard_point_3 p1(hx[0]+dx,hy[0]+dy,hz[0]+dz,hw[0]);
|
|
return Standard_line_3(p0,p1);
|
|
}
|
|
|
|
Standard_ray_3 standard_ray(const Point_3& p) const
|
|
{ CGAL_assertion(type(p)!=STANDARD);
|
|
Standard_line_3 l = standard_line(p);
|
|
Standard_point_3 q = l.point(0);
|
|
return Standard_ray_3(q,l);
|
|
}
|
|
|
|
Point_3 NEF() const { return construct_point(Standard_line_3( 1, 1, 1,0)); }
|
|
Point_3 SEF() const { return construct_point(Standard_line_3( 1, 1,-1,0)); }
|
|
Point_3 NWF() const { return construct_point(Standard_line_3(-1, 1, 1,0)); }
|
|
Point_3 SWF() const { return construct_point(Standard_line_3(-1, 1,-1,0)); }
|
|
Point_3 NEB() const { return construct_point(Standard_line_3( 1,-1, 1,0)); }
|
|
Point_3 SEB() const { return construct_point(Standard_line_3( 1,-1,-1,0)); }
|
|
Point_3 NWB() const { return construct_point(Standard_line_3(-1,-1, 1,0)); }
|
|
Point_3 SWB() const { return construct_point(Standard_line_3(-1,-1,-1,0)); }
|
|
|
|
|
|
// Line_3 upper() const { return construct_line(NW(),NE()); }
|
|
// Line_3 lower() const { return construct_line(SW(),SE()); }
|
|
// Line_3 left() const { return construct_line(SW(),NW()); }
|
|
// Line_3 right() const { return construct_line(SE(),NE()); }
|
|
|
|
|
|
Point_3 source(const Segment_3& s) const
|
|
{ typename Base::Construct_vertex_3 _source = construct_vertex_3_object();
|
|
return _source(s,0); }
|
|
|
|
Point_3 target(const Segment_3& s) const
|
|
{ typename Base::Construct_vertex_3 _target = construct_vertex_3_object();
|
|
return _target(s,1); }
|
|
|
|
Segment_3 construct_segment(const Point_3& p, const Point_3& q) const
|
|
{ typename Base::Construct_segment_3 _segment =
|
|
construct_segment_3_object();
|
|
return _segment(p,q); }
|
|
|
|
void simplify(Point_3& p) const
|
|
{ TRACEN("simplify("<<p<<")");
|
|
RT x=p.hx(), y=p.hy(), z=p.hz(), w=p.hw();
|
|
RT common = x.is_zero() ? z : gcd(x,z);
|
|
common = y.is_zero() ? common : gcd(common,y);
|
|
common = gcd(common,w);
|
|
p = Point_3(x/common,y/common,z/common,w/common);
|
|
TRACEN("canceled="<<p);
|
|
}
|
|
|
|
Line_3 construct_line(const Standard_line_3& l) const
|
|
{ return Line_3(l.point(1),l.point(2)); }
|
|
|
|
Line_3 construct_line(const Point_3& p1, const Point_3& p2) const
|
|
{ return Line_3(p1,p2); }
|
|
|
|
int orientation(const Segment_3& s, const Point_3& p) const
|
|
{ typename Base::Orientation_3 _orientation =
|
|
orientation_3_object();
|
|
return static_cast<int> ( _orientation(source(s),target(s),p) );
|
|
}
|
|
|
|
int orientation(const Point_3& p1, const Point_3& p2, const Point_3& p3) const
|
|
{ typename Base::Orientation_3 _orientation =
|
|
orientation_3_object();
|
|
return static_cast<int> ( _orientation(p1,p2,p3) );
|
|
}
|
|
|
|
bool left_turn(const Point_3& p1, const Point_3& p2, const Point_3& p3)
|
|
const
|
|
{ return orientation(p1,p2,p3) > 0; }
|
|
|
|
bool is_degenerate(const Segment_3& s) const
|
|
{ typename Base::Is_degenerate_3 _is_degenerate =
|
|
is_degenerate_3_object();
|
|
return _is_degenerate(s);
|
|
}
|
|
|
|
int compare_xyz(const Point_3& p1, const Point_3& p2) const
|
|
{
|
|
typename Base::Compare_xyz_3 _compare_xyz = compare_xyz_3_object();
|
|
return static_cast<int>( _compare_xyz(p1,p2) );
|
|
}
|
|
|
|
int compare_x(const Point_3& p1, const Point_3& p2) const
|
|
{ typename Base::Compare_x_3 _compare_x =
|
|
compare_x_3_object();
|
|
return static_cast<int>( _compare_x(p1,p2) );
|
|
}
|
|
|
|
int compare_y(const Point_3& p1, const Point_3& p2) const
|
|
{ typename Base::Compare_y_3 _compare_y =
|
|
compare_y_3_object();
|
|
return static_cast<int>( _compare_y(p1,p2) );
|
|
}
|
|
|
|
int compare_z(const Point_3& p1, const Point_3& p2) const
|
|
{ typename Base::Compare_z_3 _compare_z =
|
|
compare_z_3_object();
|
|
return static_cast<int>( _compare_z(p1,p2) );
|
|
}
|
|
|
|
Point_3 intersection(
|
|
const Segment_3& s1, const Segment_3& s2) const
|
|
{ typename Base::Intersect_3 _intersect =
|
|
intersect_3_object();
|
|
typename Base::Construct_line_3 _line =
|
|
construct_line_3_object();
|
|
Point_3 p;
|
|
CGAL::Object result =
|
|
_intersect(_line(s1),_line(s2));
|
|
if ( !CGAL::assign(p, result) )
|
|
CGAL_assertion_msg(false,"intersection: no intersection.");
|
|
simplify(p);
|
|
return p;
|
|
}
|
|
|
|
bool strictly_ordered_along_line(
|
|
const Point_3& p1, const Point_3& p2, const Point_3& p3) const
|
|
{ typename Base::Are_strictly_ordered_along_line_3 _ordered =
|
|
are_strictly_ordered_along_line_3_object();
|
|
return _ordered(p1,p2,p3);
|
|
}
|
|
|
|
bool contains(const Segment_3& s, const Point_3& p) const
|
|
{ typename Base::Has_on_3 _contains = has_on_3_object();
|
|
return _contains(s,p);
|
|
}
|
|
|
|
bool first_pair_closer_than_second(
|
|
const Point_3& p1, const Point_3& p2,
|
|
const Point_3& p3, const Point_3& p4) const
|
|
{ return ( squared_distance(p1,p2) < squared_distance(p3,p4) ); }
|
|
|
|
/*
|
|
void scale_first_by_second(RT& r1, RT& r2, RT& r3, RT& w) const
|
|
{ CGAL_assertion(w.degree()==0&&w!=RT(0)&& r2[1]!=Standard_RT(0));
|
|
Standard_RT w_res = w[0]*r2[1];
|
|
int sm2 = CGAL_NTS sign(r2[1]);
|
|
RT r2_res = RT(Standard_RT(0),sm2 * w_res);
|
|
RT r1_res = RT(r2[1]*r1[0]-r1[1]*r2[0], w[0]*r1[1]*sm2);
|
|
r1 = r1_res; r2 = r2_res; w = w_res;
|
|
}
|
|
|
|
|
|
Point_3 transform(const Point_3& p,
|
|
const Standard_aff_transformation_3& t) const
|
|
{
|
|
RT tpx = t.homogeneous(0,0)*p.hx() + t.homogeneous(0,1)*p.hy() +
|
|
t.homogeneous(0,2)*p.hz()+t.homogeneous(0,3)*p.hw();
|
|
RT tpy = t.homogeneous(1,0)*p.hx() + t.homogeneous(1,1)*p.hy() +
|
|
t.homogeneous(1,2)*p.hz()+t.homogeneous(1,3)*p.hw();
|
|
RT tpw = t.homogeneous(2,2)*p.hw();
|
|
if ( is_standard(p) ) {
|
|
Point_3 res(tpx,tpy,tpz,tpw); simplify(res);
|
|
return res;
|
|
}
|
|
RT tpxa = CGAL_NTS abs(tpx);
|
|
RT tpya = CGAL_NTS abs(tpy);
|
|
RT tpza = CGAL_NTS abs(tpz);
|
|
?? if ( tpxa > tpya ) {
|
|
?? scale_first_by_second(tpy,tpx,tpw);
|
|
?? } else { // tpxa <= tpya
|
|
?? scale_first_by_second(tpx,tpy,tpw);
|
|
}
|
|
Point_3 res(tpx,tpy,tpz, tpw); simplify(res);
|
|
return res;
|
|
}
|
|
*/
|
|
|
|
const char* output_identifier() const { return "Extended_homogeneous"; }
|
|
|
|
|
|
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
#endif // CGAL_EXTENDED_HOMOGENEOUS_3_H
|