1 // Copyright (c) 2000
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/Cartesian_kernel/include/CGAL/Cartesian/Tetrahedron_3.h $
11 // $Id: Tetrahedron_3.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
12 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
13 //
14 //
15 // Author(s)     : Andreas Fabri
16 
17 #ifndef CGAL_CARTESIAN_TETRAHEDRON_3_H
18 #define CGAL_CARTESIAN_TETRAHEDRON_3_H
19 
20 #include <CGAL/array.h>
21 #include <CGAL/Handle_for.h>
22 #include <CGAL/enum.h>
23 #include <vector>
24 #include <functional>
25 
26 namespace CGAL {
27 
28 template <class R_>
29 class TetrahedronC3
30 {
31   typedef typename R_::FT                   FT;
32   typedef typename R_::Point_3              Point_3;
33   typedef typename R_::Plane_3              Plane_3;
34   typedef typename R_::Tetrahedron_3        Tetrahedron_3;
35 
36   typedef std::array<Point_3, 4>          Rep;
37   typedef typename R_::template Handle<Rep>::type  Base;
38 
39   Base base;
40 
41 public:
42   typedef R_                                     R;
43 
TetrahedronC3()44   TetrahedronC3() {}
45 
TetrahedronC3(const Point_3 & p,const Point_3 & q,const Point_3 & r,const Point_3 & s)46   TetrahedronC3(const Point_3 &p, const Point_3 &q, const Point_3 &r,
47                 const Point_3 &s)
48     : base(CGAL::make_array(p, q, r, s)) {}
49 
50   const Point_3 &    vertex(int i) const;
51   const Point_3 &    operator[](int i) const;
52 
53   typename R::Boolean         operator==(const TetrahedronC3 &t) const;
54   typename R::Boolean         operator!=(const TetrahedronC3 &t) const;
55 
56   typename R::Orientation    orientation() const;
57   typename R::Oriented_side  oriented_side(const Point_3 &p) const;
58   typename R::Bounded_side   bounded_side(const Point_3 &p) const;
59 
60   typename R::Boolean         has_on_boundary(const Point_3 &p) const;
61   typename R::Boolean         has_on_positive_side(const Point_3 &p) const;
62   typename R::Boolean         has_on_negative_side(const Point_3 &p) const;
63   typename R::Boolean         has_on_bounded_side(const Point_3 &p) const;
64   typename R::Boolean         has_on_unbounded_side(const Point_3 &p) const;
65 
66   typename R::Boolean         is_degenerate() const;
67 };
68 
69 template < class R >
70 typename R::Boolean
71 TetrahedronC3<R>::
72 operator==(const TetrahedronC3<R> &t) const
73 {
74   if (CGAL::identical(base, t.base))
75       return true;
76   if (orientation() != t.orientation())
77       return false;
78 
79   std::vector< Point_3 > V1;
80   std::vector< Point_3 > V2;
81   typename std::vector< Point_3 >::iterator uniq_end1;
82   typename std::vector< Point_3 >::iterator uniq_end2;
83   int k;
84   for ( k=0; k < 4; k++) V1.push_back( vertex(k));
85   for ( k=0; k < 4; k++) V2.push_back( t.vertex(k));
86   typename R::Less_xyz_3 Less_object = R().less_xyz_3_object();
87   std::sort(V1.begin(), V1.end(), Less_object);
88   std::sort(V2.begin(), V2.end(), Less_object);
89   uniq_end1 = std::unique( V1.begin(), V1.end());
90   uniq_end2 = std::unique( V2.begin(), V2.end());
91   V1.erase( uniq_end1, V1.end());
92   V2.erase( uniq_end2, V2.end());
93   return V1 == V2;
94 }
95 
96 template < class R >
97 inline
98 typename R::Boolean
99 TetrahedronC3<R>::
100 operator!=(const TetrahedronC3<R> &t) const
101 {
102   return !(*this == t);
103 }
104 
105 template < class R >
106 const typename TetrahedronC3<R>::Point_3 &
107 TetrahedronC3<R>::
vertex(int i)108 vertex(int i) const
109 {
110   if (i<0) i=(i%4)+4;
111   else if (i>3) i=i%4;
112   switch (i)
113     {
114     case 0: return get_pointee_or_identity(base)[0];
115     case 1: return get_pointee_or_identity(base)[1];
116     case 2: return get_pointee_or_identity(base)[2];
117     default: return get_pointee_or_identity(base)[3];
118     }
119 }
120 
121 template < class R >
122 inline
123 const typename TetrahedronC3<R>::Point_3 &
124 TetrahedronC3<R>::
125 operator[](int i) const
126 {
127   return vertex(i);
128 }
129 
130 template < class R >
131 typename R::Orientation
132 TetrahedronC3<R>::
orientation()133 orientation() const
134 {
135   return R().orientation_3_object()(vertex(0), vertex(1),
136                                     vertex(2), vertex(3));
137 }
138 
139 template < class R >
140 typename R::Oriented_side
141 TetrahedronC3<R>::
oriented_side(const typename TetrahedronC3<R>::Point_3 & p)142 oriented_side(const typename TetrahedronC3<R>::Point_3 &p) const
143 {
144   typename R::Orientation o = orientation();
145   if (o != ZERO)
146     return enum_cast<Oriented_side>(bounded_side(p)) * o;
147 
148   CGAL_kernel_assertion (!is_degenerate());
149   return ON_ORIENTED_BOUNDARY;
150 }
151 
152 template < class R >
153 typename R::Bounded_side
154 TetrahedronC3<R>::
bounded_side(const typename TetrahedronC3<R>::Point_3 & p)155 bounded_side(const typename TetrahedronC3<R>::Point_3 &p) const
156 {
157   return R().bounded_side_3_object()
158                (static_cast<const typename R::Tetrahedron_3&>(*this), p);
159 }
160 
161 template < class R >
162 inline
163 typename R::Boolean
has_on_boundary(const typename TetrahedronC3<R>::Point_3 & p)164 TetrahedronC3<R>::has_on_boundary
165   (const typename TetrahedronC3<R>::Point_3 &p) const
166 {
167   return oriented_side(p) == ON_ORIENTED_BOUNDARY;
168 }
169 
170 template < class R >
171 inline
172 typename R::Boolean
has_on_positive_side(const typename TetrahedronC3<R>::Point_3 & p)173 TetrahedronC3<R>::has_on_positive_side
174   (const typename TetrahedronC3<R>::Point_3 &p) const
175 {
176   return oriented_side(p) == ON_POSITIVE_SIDE;
177 }
178 
179 template < class R >
180 inline
181 typename R::Boolean
has_on_negative_side(const typename TetrahedronC3<R>::Point_3 & p)182 TetrahedronC3<R>::has_on_negative_side
183   (const typename TetrahedronC3<R>::Point_3 &p) const
184 {
185   return oriented_side(p) == ON_NEGATIVE_SIDE;
186 }
187 
188 template < class R >
189 inline
190 typename R::Boolean
has_on_bounded_side(const typename TetrahedronC3<R>::Point_3 & p)191 TetrahedronC3<R>::has_on_bounded_side
192   (const typename TetrahedronC3<R>::Point_3 &p) const
193 {
194   return bounded_side(p) == ON_BOUNDED_SIDE;
195 }
196 
197 template < class R >
198 inline
199 typename R::Boolean
has_on_unbounded_side(const typename TetrahedronC3<R>::Point_3 & p)200 TetrahedronC3<R>::has_on_unbounded_side
201   (const typename TetrahedronC3<R>::Point_3 &p) const
202 {
203   return bounded_side(p) == ON_UNBOUNDED_SIDE;
204 }
205 
206 template < class R >
207 inline
208 typename R::Boolean
is_degenerate()209 TetrahedronC3<R>::is_degenerate() const
210 {
211   return orientation() == COPLANAR;
212 }
213 
214 } //namespace CGAL
215 
216 #endif // CGAL_CARTESIAN_TETRAHEDRON_3_H
217