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