1 // Copyright (c) 1999
2 // Utrecht University (The Netherlands),
3 // ETH Zurich (Switzerland),
4 // INRIA Sophia-Antipolis (France),
5 // Max-Planck-Institute Saarbruecken (Germany),
6 // and Tel-Aviv University (Israel).  All rights reserved.
7 //
8 // This file is part of CGAL (www.cgal.org)
9 //
10 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Kernel_23/include/CGAL/Direction_3.h $
11 // $Id: Direction_3.h 4e519a3 2021-05-05T13:15:37+02:00 Sébastien Loriot
12 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
13 //
14 //
15 // Author(s)     : Andreas Fabri, Stefan Schirra
16 
17 #ifndef CGAL_DIRECTION_3_H
18 #define CGAL_DIRECTION_3_H
19 
20 #include <CGAL/assertions.h>
21 #include <boost/type_traits/is_same.hpp>
22 #include <CGAL/Kernel/Return_base_tag.h>
23 #include <CGAL/kernel_assertions.h>
24 #include <CGAL/representation_tags.h>
25 #include <CGAL/Dimension.h>
26 #include <CGAL/IO/io.h>
27 
28 namespace CGAL {
29 
30 template <class R_>
31 class Direction_3 : public R_::Kernel_base::Direction_3
32 {
33   typedef typename R_::RT                    RT;
34   typedef typename R_::Vector_3              Vector_3;
35   typedef typename R_::Line_3                Line_3;
36   typedef typename R_::Ray_3                 Ray_3;
37   typedef typename R_::Segment_3             Segment_3;
38   typedef typename R_::Aff_transformation_3  Aff_transformation_3;
39 
40   typedef Direction_3                        Self;
41   CGAL_static_assertion((boost::is_same<Self, typename R_::Direction_3>::value));
42 
43 public:
44 
45   typedef Dimension_tag<3>  Ambient_dimension;
46   typedef Dimension_tag<0>  Feature_dimension;
47 
48   typedef typename R_::Kernel_base::Direction_3 Rep;
49 
rep()50   const Rep& rep() const
51   {
52     return *this;
53   }
54 
rep()55   Rep& rep()
56   {
57     return *this;
58   }
59 
60   typedef          R_                       R;
61 
Direction_3()62   Direction_3() {}
63 
Direction_3(const Rep & d)64   Direction_3(const Rep& d)
65     : Rep(d) {}
66 
Direction_3(const Vector_3 & v)67   explicit Direction_3(const Vector_3& v)
68     : Rep(typename R::Construct_direction_3()(Return_base_tag(), v)) {}
69 
Direction_3(const Line_3 & l)70   explicit Direction_3(const Line_3& l)
71     : Rep(typename R::Construct_direction_3()(Return_base_tag(), l)) {}
72 
Direction_3(const Ray_3 & r)73   explicit Direction_3(const Ray_3& r)
74     : Rep(typename R::Construct_direction_3()(Return_base_tag(), r)) {}
75 
Direction_3(const Segment_3 & s)76   explicit Direction_3(const Segment_3& s)
77     : Rep(typename R::Construct_direction_3()(Return_base_tag(), s)) {}
78 
Direction_3(const RT & hx,const RT & hy,const RT & hz)79   Direction_3(const RT& hx, const RT& hy, const RT& hz)
80     : Rep(typename R::Construct_direction_3()(Return_base_tag(), hx, hy, hz)) {}
81 
transform(const Aff_transformation_3 & t)82   Direction_3 transform(const Aff_transformation_3 &t) const
83   {
84     return t.transform(*this);
85   }
86 
87   Direction_3
88   operator-() const
89   {
90     return R().construct_opposite_direction_3_object()(*this);
91   }
92 
to_vector()93   Vector_3 to_vector() const
94   {
95     return R().construct_vector_3_object()(*this);
96   }
97 
vector()98   Vector_3 vector() const { return to_vector(); }
99 
100 
101   decltype(auto)
dx()102   dx() const
103   {
104     return R().compute_dx_3_object()(*this);
105   }
106 
107   decltype(auto)
dy()108   dy() const
109   {
110     return R().compute_dy_3_object()(*this);
111   }
112 
113   decltype(auto)
dz()114   dz() const
115   {
116     return R().compute_dz_3_object()(*this);
117   }
118 
119   decltype(auto)
delta(int i)120   delta(int i) const
121   {
122     CGAL_kernel_precondition( i >= 0 && i <= 2 );
123     if (i==0) return dx();
124     if (i==1) return dy();
125     return dz();
126   }
127 
128 };
129 
130 
131 template <class R >
132 std::ostream&
insert(std::ostream & os,const Direction_3<R> & d,const Cartesian_tag &)133 insert(std::ostream& os, const Direction_3<R>& d, const Cartesian_tag&)
134 {
135   typename R::Vector_3 v = d.to_vector();
136   switch(IO::get_mode(os)) {
137     case IO::ASCII :
138       return os << v.x() << ' ' << v.y()  << ' ' << v.z();
139     case IO::BINARY :
140       write(os, v.x());
141       write(os, v.y());
142       write(os, v.z());
143       return os;
144     default:
145       os << "DirectionC3(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
146       return os;
147   }
148 }
149 
150 template <class R >
151 std::ostream&
insert(std::ostream & os,const Direction_3<R> & d,const Homogeneous_tag &)152 insert(std::ostream& os, const Direction_3<R>& d, const Homogeneous_tag&)
153 {
154   switch(IO::get_mode(os))
155   {
156     case IO::ASCII :
157         return os << d.dx() << ' ' << d.dy() << ' ' << d.dz();
158     case IO::BINARY :
159         write(os, d.dx());
160         write(os, d.dy());
161         write(os, d.dz());
162         return os;
163     default:
164         return os << "DirectionH3(" << d.dx() << ", "
165                                     << d.dy() << ", "
166                                     << d.dz() << ')';
167   }
168 }
169 
170 template < class R >
171 std::ostream&
172 operator<<(std::ostream& os, const Direction_3<R>& d)
173 {
174   return insert(os, d, typename R::Kernel_tag() );
175 }
176 
177 
178 template <class R >
179 std::istream&
extract(std::istream & is,Direction_3<R> & d,const Cartesian_tag &)180 extract(std::istream& is, Direction_3<R>& d, const Cartesian_tag&)
181 {
182   typename R::FT x(0), y(0), z(0);
183   switch(IO::get_mode(is)) {
184     case IO::ASCII :
185       is >> IO::iformat(x) >> IO::iformat(y) >> IO::iformat(z);
186       break;
187     case IO::BINARY :
188       read(is, x);
189       read(is, y);
190       read(is, z);
191       break;
192     default:
193       is.setstate(std::ios::failbit);
194       std::cerr << "" << std::endl;
195       std::cerr << "Stream must be in ascii or binary mode" << std::endl;
196       break;
197   }
198   if (is)
199       d = Direction_3<R>(x, y, z);
200   return is;
201 }
202 
203 template <class R >
204 std::istream&
extract(std::istream & is,Direction_3<R> & d,const Homogeneous_tag &)205 extract(std::istream& is, Direction_3<R>& d, const Homogeneous_tag&)
206 {
207   typename R::RT x, y, z;
208   switch(IO::get_mode(is))
209   {
210     case IO::ASCII :
211         is >> IO::iformat(x) >> IO::iformat(y) >> IO::iformat(z);
212         break;
213     case IO::BINARY :
214         read(is, x);
215         read(is, y);
216         read(is, z);
217         break;
218     default:
219         is.setstate(std::ios::failbit);
220         std::cerr << "" << std::endl;
221         std::cerr << "Stream must be in ascii or binary mode" << std::endl;
222         break;
223   }
224   if (is)
225     d = Direction_3<R>(x, y, z);
226   return is;
227 }
228 
229 template < class R >
230 std::istream&
231 operator>>(std::istream& is, Direction_3<R>& d)
232 {
233   return extract(is, d, typename R::Kernel_tag() );
234 }
235 
236 } //namespace CGAL
237 
238 #endif // CGAL_DIRECTION_3_H
239