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/Plane_3.h $
11 // $Id: Plane_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_PLANE_3_H
18 #define CGAL_CARTESIAN_PLANE_3_H
19 
20 #include <CGAL/array.h>
21 #include <CGAL/Handle_for.h>
22 #include <CGAL/Cartesian/solve_3.h>
23 #include <CGAL/Cartesian/plane_constructions_3.h>
24 
25 namespace CGAL {
26 
27 template <class R_>
28 class PlaneC3
29 {
30   typedef typename R_::FT                   FT;
31   typedef typename R_::Point_2              Point_2;
32   typedef typename R_::Point_3              Point_3;
33   typedef typename R_::Vector_3             Vector_3;
34   typedef typename R_::Direction_3          Direction_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_::Plane_3              Plane_3;
39   typedef typename R_::Circle_3             Circle_3;
40   typedef typename R_::Construct_point_3    Construct_point_3;
41   typedef typename R_::Construct_point_2    Construct_point_2;
42 
43   typedef std::array<FT, 4>               Rep;
44   typedef typename R_::template Handle<Rep>::type  Base;
45 
46   Base base;
47 
48 public:
49 
50   typedef R_                                     R;
51 
PlaneC3()52   PlaneC3() {}
53 
PlaneC3(const Point_3 & p,const Point_3 & q,const Point_3 & r)54   PlaneC3(const Point_3 &p, const Point_3 &q, const Point_3 &r)
55   { *this = plane_from_points<R>(p, q, r); }
56 
PlaneC3(const Point_3 & p,const Direction_3 & d)57   PlaneC3(const Point_3 &p, const Direction_3 &d)
58   { *this = plane_from_point_direction<R>(p, d); }
59 
PlaneC3(const Point_3 & p,const Vector_3 & v)60   PlaneC3(const Point_3 &p, const Vector_3 &v)
61   { *this = plane_from_point_direction<R>(p, v.direction()); }
62 
PlaneC3(const FT & a,const FT & b,const FT & c,const FT & d)63   PlaneC3(const FT &a, const FT &b, const FT &c, const FT &d)
64     : base(CGAL::make_array(a, b, c, d)) {}
65 
PlaneC3(const Line_3 & l,const Point_3 & p)66   PlaneC3(const Line_3 &l, const Point_3 &p)
67   { *this = plane_from_points<R>(l.point(),
68                               l.point()+l.direction().to_vector(),
69                               p); }
70 
PlaneC3(const Segment_3 & s,const Point_3 & p)71   PlaneC3(const Segment_3 &s, const Point_3 &p)
72   { *this = plane_from_points<R>(s.start(), s.end(), p); }
73 
PlaneC3(const Ray_3 & r,const Point_3 & p)74   PlaneC3(const Ray_3 &r, const Point_3 &p)
75   { *this = plane_from_points<R>(r.start(), r.second_point(), p); }
76 
77   typename R::Boolean   operator==(const PlaneC3 &p) const;
78   typename R::Boolean   operator!=(const PlaneC3 &p) const;
79 
a()80   const FT & a() const
81   {
82       return get_pointee_or_identity(base)[0];
83   }
b()84   const FT & b() const
85   {
86       return get_pointee_or_identity(base)[1];
87   }
c()88   const FT & c() const
89   {
90       return get_pointee_or_identity(base)[2];
91   }
d()92   const FT & d() const
93   {
94       return get_pointee_or_identity(base)[3];
95   }
96 
97   Line_3       perpendicular_line(const Point_3 &p) const;
98   Plane_3      opposite() const;
99 
100   Point_3      point() const;
101   Point_3      projection(const Point_3 &p) const;
102   Vector_3     orthogonal_vector() const;
103   Direction_3  orthogonal_direction() const;
104   Vector_3     base1() const;
105   Vector_3     base2() const;
106 
107   Point_3      to_plane_basis(const Point_3 &p) const;
108 
109   Point_2      to_2d(const Point_3 &p) const;
110   Point_3      to_3d(const Point_2 &p) const;
111 
112   typename R::Oriented_side     oriented_side(const Point_3 &p) const;
113   typename R::Boolean           has_on_positive_side(const Point_3 &l) const;
114   typename R::Boolean           has_on_negative_side(const Point_3 &l) const;
has_on(const Point_3 & p)115   typename R::Boolean           has_on(const Point_3 &p) const
116   {
117     return oriented_side(p) == ON_ORIENTED_BOUNDARY;
118   }
has_on(const Line_3 & l)119   typename R::Boolean           has_on(const Line_3 &l) const
120   {
121     return has_on(l.point())
122        &&  has_on(l.point() + l.direction().to_vector());
123   }
has_on(const Circle_3 & circle)124   typename R::Boolean           has_on(const Circle_3 &circle) const
125   {
126     if(circle.squared_radius() != FT(0)) {
127       const Plane_3& p = circle.supporting_plane();
128       if(is_zero(a())) {
129         if(!is_zero(p.a())) return false;
130         if(is_zero(b())) {
131           if(!is_zero(p.b())) return false;
132           return c() * p.d() == d() * p.c();
133         }
134         return (p.c() * b() == c() * p.b()) &&
135                (p.d() * b() == d() * p.b());
136       }
137       return (p.b() * a() == b() * p.a()) &&
138              (p.c() * a() == c() * p.a()) &&
139              (p.d() * a() == d() * p.a());
140     } else return has_on(circle.center());
141   }
142 
143   typename R::Boolean           is_degenerate() const;
144 };
145 
146 template < class R >
147 CGAL_KERNEL_INLINE
148 typename R::Boolean
149 PlaneC3<R>::operator==(const PlaneC3<R> &p) const
150 {
151   if (CGAL::identical(base, p.base))
152       return true;
153   return equal_plane(*this, p);
154 }
155 
156 template < class R >
157 inline
158 typename R::Boolean
159 PlaneC3<R>::operator!=(const PlaneC3<R> &p) const
160 {
161   return !(*this == p);
162 }
163 
164 template < class R >
165 inline
166 typename PlaneC3<R>::Point_3
point()167 PlaneC3<R>::point() const
168 {
169   return point_on_plane(*this);
170 }
171 
172 template < class R >
173 inline
174 typename PlaneC3<R>::Point_3
175 PlaneC3<R>::
projection(const typename PlaneC3<R>::Point_3 & p)176 projection(const typename PlaneC3<R>::Point_3 &p) const
177 {
178   return projection_plane(p, *this);
179 }
180 
181 template < class R >
182 inline
183 typename PlaneC3<R>::Vector_3
orthogonal_vector()184 PlaneC3<R>::orthogonal_vector() const
185 {
186   return R().construct_orthogonal_vector_3_object()(*this);
187 }
188 
189 template < class R >
190 inline
191 typename PlaneC3<R>::Direction_3
orthogonal_direction()192 PlaneC3<R>::orthogonal_direction() const
193 {
194   return Direction_3(a(), b(), c());
195 }
196 
197 template < class R >
198 typename PlaneC3<R>::Vector_3
base1()199 PlaneC3<R>::base1() const
200 {
201   return R().construct_base_vector_3_object()(*this, 1);
202 }
203 
204 template < class R >
205 typename PlaneC3<R>::Vector_3
base2()206 PlaneC3<R>::base2() const
207 {
208   return R().construct_base_vector_3_object()(*this, 2);
209 }
210 
211 template < class R >
212 typename PlaneC3<R>::Point_3
213 PlaneC3<R>::
to_plane_basis(const typename PlaneC3<R>::Point_3 & p)214 to_plane_basis(const typename PlaneC3<R>::Point_3 &p) const
215 {
216   FT alpha, beta, gamma;
217   Construct_point_3 construct_point_3;
218   Cartesian_internal::solve(base1(), base2(), orthogonal_vector(), p - point(),
219         alpha, beta, gamma);
220 
221   return construct_point_3(alpha, beta, gamma);
222 }
223 
224 template < class R >
225 typename PlaneC3<R>::Point_2
226 PlaneC3<R>::
to_2d(const typename PlaneC3<R>::Point_3 & p)227 to_2d(const typename PlaneC3<R>::Point_3 &p) const
228 {
229   FT alpha, beta, gamma;
230   Construct_point_2 construct_point_2;
231 
232   Cartesian_internal::solve(base1(), base2(), orthogonal_vector(), p - point(),
233         alpha, beta, gamma);
234 
235   return construct_point_2(alpha, beta);
236 }
237 
238 template < class R >
239 inline
240 typename PlaneC3<R>::Point_3
241 PlaneC3<R>::
to_3d(const typename PlaneC3<R>::Point_2 & p)242 to_3d(const typename PlaneC3<R>::Point_2 &p) const
243 {
244   return R().construct_lifted_point_3_object()(*this, p);
245 }
246 
247 template < class R >
248 inline
249 typename PlaneC3<R>::Line_3
250 PlaneC3<R>::
perpendicular_line(const typename PlaneC3<R>::Point_3 & p)251 perpendicular_line(const typename PlaneC3<R>::Point_3 &p) const
252 {
253   return Line_3(p, orthogonal_direction());
254 }
255 
256 template < class R >
257 inline
258 typename PlaneC3<R>::Plane_3
opposite()259 PlaneC3<R>::opposite() const
260 {
261   return PlaneC3<R>(-a(), -b(), -c(), -d());
262 }
263 
264 template < class R >
265 inline
266 typename R::Oriented_side
267 PlaneC3<R>::
oriented_side(const typename PlaneC3<R>::Point_3 & p)268 oriented_side(const typename PlaneC3<R>::Point_3 &p) const
269 {
270   return side_of_oriented_plane(*this, p);
271 }
272 
273 template < class R >
274 inline
275 typename R::Boolean
276 PlaneC3<R>::
has_on_positive_side(const typename PlaneC3<R>::Point_3 & p)277 has_on_positive_side(const  typename PlaneC3<R>::Point_3 &p) const
278 {
279   return oriented_side(p) == ON_POSITIVE_SIDE;
280 }
281 
282 template < class R >
283 inline
284 typename R::Boolean
285 PlaneC3<R>::
has_on_negative_side(const typename PlaneC3<R>::Point_3 & p)286 has_on_negative_side(const  typename PlaneC3<R>::Point_3 &p) const
287 {
288   return oriented_side(p) == ON_NEGATIVE_SIDE;
289 }
290 
291 template < class R >
292 inline
293 typename R::Boolean
294 PlaneC3<R>::
is_degenerate()295 is_degenerate() const
296 { // FIXME : predicate
297   return CGAL_NTS is_zero(a()) && CGAL_NTS is_zero(b()) &&
298          CGAL_NTS is_zero(c());
299 }
300 
301 } //namespace CGAL
302 
303 #endif // CGAL_CARTESIAN_PLANE_3_H
304