// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Nef_S2/include/CGAL/Nef_S2/Normalizing.h $ // $Id: Normalizing.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Peter Hachenberger #ifndef CGAL_NORMALIZING_H #define CGAL_NORMALIZING_H #include #include #include #include #include #undef CGAL_NEF_DEBUG #define CGAL_NEF_DEBUG 307 #include #ifdef CCGAL_USE_LEDA #include #include #endif namespace CGAL { class Homogeneous_tag; class Cartesian_tag; template class Normalizing; template<> class Normalizing { public: template static void normalized(iterator begin, iterator end) { typedef typename std::iterator_traits::value_type RT; iterator i = begin; while(i!=end && *i == RT(0)) ++i; if(i==end) return; RT g = *i; for(iterator j=i+1; j!=end; ++j) g = (*j == 0 ? g : CGAL_NTS gcd(g,*j)); g=CGAL_NTS abs(g); for(; i!=end; ++i) *i = CGAL::integral_division(*i,g); } template static CGAL::Point_3 normalized(const CGAL::Point_3& p) { typedef typename R::RT RT; RT g = p.hw(); g = (p.hx() == 0 ? g : CGAL_NTS gcd(g,p.hx())); g = (p.hy() == 0 ? g : CGAL_NTS gcd(g,p.hy())); g = (p.hz() == 0 ? g : CGAL_NTS gcd(g,p.hz())); RT x = p.hx()/g; RT y = p.hy()/g; RT z = p.hz()/g; RT w = p.hw()/g; return typename R::Point_3(x,y,z,w); } template static CGAL::Sphere_point normalized(const CGAL::Sphere_point& p) { typedef typename R::RT RT; RT g = (p.x()==0) ? ((p.y()==0) ? ((p.z()==0) ? 1: p.z()): p.y()): p.x(); if(p.y() != 0) g = CGAL_NTS gcd(g,p.y()); if(p.z() != 0) g = CGAL_NTS gcd(g,p.z()); if(g<0) g = -g; RT x = p.x()/g; RT y = p.y()/g; RT z = p.z()/g; return CGAL::Sphere_point(x,y,z); } template static CGAL::Vector_3 normalized(const CGAL::Vector_3& p) { typedef typename R::RT RT; RT g = (p.hx()==0) ? ((p.hy()==0) ? ((p.hz()==0) ? 1: p.hz()): p.hy()): p.hx(); if(p.hy() != 0) g = CGAL_NTS gcd(g,p.hy()); if(p.hz() != 0) g = CGAL_NTS gcd(g,p.hz()); if(g<0) g = -g; RT x = p.hx()/g; RT y = p.hy()/g; RT z = p.hz()/g; return typename R::Vector_3(x,y,z); } template static CGAL::Sphere_direction normalized(const CGAL::Sphere_direction& c) { typename R::Plane_3 h = c.plane(); CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef typename R::RT RT; RT x = (h.a()==0) ? ((h.b()==0) ? ((h.c()==0) ? ((h.d()==0) ? 1 : h.d()) : h.c()) : h.b()) : h.a(); if(h.b() != 0) x = gcd(x,h.b()); if(h.c() != 0) x = gcd(x,h.c()); if(h.d() !=0) x = gcd(x,h.d()); x = CGAL_NTS abs(x); RT pa = h.a()/x; RT pb = h.b()/x; RT pc = h.c()/x; RT pd = h.d()/x; return CGAL::Sphere_direction(typename R::Plane_3(pa,pb,pc,pd)); } template static CGAL::Plane_3 normalized(const CGAL::Plane_3& h) { CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef typename R::RT RT; RT x = (h.a()==0) ? ((h.b()==0) ? ((h.c()==0) ? ((h.d()==0) ? 1 : h.d()) : h.c()) : h.b()) : h.a(); CGAL_NEF_TRACE("gcd... i"<<' '); if(h.b() != 0) x = CGAL_NTS gcd(x,h.b()); CGAL_NEF_TRACE(x<<' '); if(h.c() != 0) x = CGAL_NTS gcd(x,h.c()); CGAL_NEF_TRACE(x<<' '); if(h.d() !=0) x = CGAL_NTS gcd(x,h.d()); CGAL_NEF_TRACEN(x); x = CGAL_NTS abs(x); RT pa = h.a()/x; RT pb = h.b()/x; RT pc = h.c()/x; RT pd = h.d()/x; CGAL_NEF_TRACEN(" after normalizing " << typename R::Plane_3(pa,pb,pc,pd)); return typename R::Plane_3(pa,pb,pc,pd); } template static CGAL::Sphere_circle normalized(const CGAL::Sphere_circle& c) { typename R::Plane_3 h = c.plane(); CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef typename R::RT RT; RT x = (h.a()==0) ? ((h.b()==0) ? ((h.c()==0) ? ((h.d()==0) ? 1 : h.d()) : h.c()) : h.b()) : h.a(); if(h.b() != 0) x = CGAL_NTS gcd(x,h.b()); if(h.c() != 0) x = CGAL_NTS gcd(x,h.c()); if(h.d() !=0) x = CGAL_NTS gcd(x,h.d()); x = CGAL_NTS abs(x); RT pa = h.a()/x; RT pb = h.b()/x; RT pc = h.c()/x; RT pd = h.d()/x; return CGAL::Sphere_circle(typename R::Plane_3(pa,pb,pc,pd)); } }; template<> class Normalizing { public: template static CGAL::Point_3 normalized(const CGAL::Point_3& p) { return p; } template static CGAL::Vector_3 normalized(const CGAL::Vector_3& p) { return p; } template static CGAL::Sphere_point normalized(const CGAL::Sphere_point& p) { typedef typename R::RT RT; RT g = (p.hx() != 0 ? p.hx() : (p.hy() != 0 ? p.hy() : p.hz())); g = CGAL_NTS abs(g); RT x = p.hx()/g; RT y = p.hy()/g; RT z = p.hz()/g; return CGAL::Sphere_point(x,y,z); } template static CGAL::Sphere_direction normalized(const CGAL::Sphere_direction& c) { return c; } #ifdef CCGAL_USE_LEDA // specialization: Plane_3 < Cartesian < leda_rational > > static Plane_3 > normalized(Plane_3 >& h) { CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef leda_rational FT; FT x = (h.a()==0) ? ((h.b()==0) ? ((h.c()==0) ? ((h.d()==0) ? 1 : h.d()) : h.c()) : h.b()) : h.a(); x = CGAL_NTS abs(x); FT pa = h.a()/x; FT pb = h.b()/x; FT pc = h.c()/x; FT pd = h.d()/x; pa.normalize(); pb.normalize(); pc.normalize(); pd.normalize(); CGAL_NEF_TRACEN(" after normalizing " << CGAL::Plane_3 >(pa,pb,pc,pd)); return CGAL::Plane_3 >(pa,pb,pc,pd); } #endif template static CGAL::Plane_3 normalized(const CGAL::Plane_3& h,Tag_true) { CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef typename R::FT FT; typedef Fraction_traits FracTraits; typedef std::vector NV; typename FracTraits::Numerator_type num; typename FracTraits::Denominator_type denom; typename FracTraits::Decompose decomposer; typename FracTraits::Compose composer; NV vec; decomposer(h.a(),num,denom); vec.push_back(num); vec.push_back(denom); vec.push_back(denom); vec.push_back(denom); decomposer(h.b(),num,denom); vec[0]*=denom; vec[1]*=num; vec[2]*=denom; vec[3]*=denom; decomposer(h.c(),num,denom); vec[0]*=denom; vec[1]*=denom; vec[2]*=num; vec[3]*=denom; decomposer(h.d(),num,denom); vec[0]*=denom; vec[1]*=denom; vec[2]*=denom; vec[3]*=num; Normalizing:: normalized(vec.begin(),vec.end()); return typename R::Plane_3(composer(vec[0],1), composer(vec[1],1), composer(vec[2],1), composer(vec[3],1)); } template static CGAL::Plane_3 normalized(const CGAL::Plane_3& h,Tag_false) { CGAL_assertion(!(h.a()==0 && h.b()==0 && h.c()==0 && h.d()==0)); typedef typename R::FT FT; if (h.a()!=0) return typename R::Plane_3(FT(1),h.b()/h.a(),h.c()/h.a(),h.d()/h.a()); if (h.b()!=0) return typename R::Plane_3(h.a()/h.b(),FT(1),h.c()/h.b(),h.d()/h.b()); if (h.c()!=0) return typename R::Plane_3(h.a()/h.c(),h.b()/h.c(),FT(1),h.d()/h.c()); return typename R::Plane_3(h.a()/h.d(),h.b()/h.d(),h.c()/h.d(),FT(1)); } template static CGAL::Plane_3 normalized(const CGAL::Plane_3& h) { return normalized( h,typename Fraction_traits::Is_fraction() ); } template static CGAL::Sphere_circle normalized(CGAL::Sphere_circle& c) { return c; } }; /* template void normalized(iterator begin, iterator end) { Normalizing::normalized(begin, end); } */ template CGAL::Point_3 normalized(const CGAL::Point_3& p) { return Normalizing::normalized(p); } template CGAL::Sphere_point normalized(const CGAL::Sphere_point& p) { return Normalizing::normalized(p); } template CGAL::Vector_3 normalized(const CGAL::Vector_3& p) { return Normalizing::normalized(p); } template CGAL::Sphere_direction normalized(const CGAL::Sphere_direction& c) { return Normalizing::normalized(c); } template CGAL::Plane_3 normalized(const CGAL::Plane_3& h) { return Normalizing::normalized(h); } template CGAL::Sphere_circle normalized(const CGAL::Sphere_circle& c) { return Normalizing::normalized(c); } } //namespace CGAL #endif // CGAL_NORMALIZING_H