1 // Copyright (c) 1998,2003
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/Kernel/Wutils.h $
11 // $Id: Wutils.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)     : Geert-Jan Giezeman, Sylvain Pion
16 
17 #ifndef CGAL_KERNEL_WUTILS_H
18 #define CGAL_KERNEL_WUTILS_H
19 
20 #include <CGAL/representation_tags.h>
21 #include <CGAL/determinant.h>
22 #include <CGAL/Point_2.h>
23 #include <CGAL/Point_3.h>
24 
25 // Functions wmult() and wcross().
26 
27 namespace CGAL {
28 
29 namespace internal {
30 
31 template < typename Rep_Tag > struct wmult_tag;
32 
33 template <>
34 struct wmult_tag<Cartesian_tag>
35 {
36   template < typename RT >
37   const RT & operator()(const RT &a, const RT &) const
38   { return a; }
39 
40   template < typename RT >
41   const RT & operator()(const RT &a, const RT &, const RT &) const
42   { return a; }
43 
44   template < typename RT >
45   const RT & operator()(const RT &a, const RT &, const RT &, const RT &) const
46   { return a; }
47 
48   template < typename RT >
49   const RT & operator()(const RT &a, const RT &, const RT &, const RT &,
50                         const RT &) const
51   { return a; }
52 };
53 
54 template <>
55 struct wmult_tag<Homogeneous_tag>
56 {
57   template < typename RT >
58   RT operator()(const RT &a, const RT &w) const
59   { return a*w; }
60 
61   template < typename RT >
62   RT operator()(const RT &a, const RT &w1, const RT &w2) const
63   { return a*w1*w2; }
64 
65   template < typename RT >
66   RT operator()(const RT &a, const RT &w1, const RT &w2, const RT &w3) const
67   { return a*w1*w2*w3; }
68 
69   template < typename RT >
70   RT operator()(const RT &a, const RT &w1, const RT &w2, const RT &w3,
71                 const RT &w4) const
72   { return a*w1*w2*w3*w4; }
73 };
74 
75 template < typename K >
76 struct wmult_functor
77   : public wmult_tag<typename K::Rep_tag> {};
78 
79 
80 template < typename Rep_Tag > struct wmult_hw_tag;
81 
82 template <>
83 struct wmult_hw_tag<Cartesian_tag>
84 {
85   template < typename RT, typename T >
86   const RT & operator()(const RT &a, const T &) const
87   { return a; }
88 
89   template < typename RT, typename T >
90   const RT & operator()(const RT &a, const RT &, const T &) const
91   { return a; }
92 
93   template < typename RT, typename T >
94   const RT & operator()(const RT &a, const RT &, const RT &, const T &) const
95   { return a; }
96 
97   template < typename RT, typename T >
98   const RT & operator()(const RT &a, const RT &, const RT &, const RT &,
99                         const T &) const
100   { return a; }
101 };
102 
103 template <>
104 struct wmult_hw_tag<Homogeneous_tag>
105 {
106   template < typename RT, typename T >
107   RT operator()(const RT &a, const T &t) const
108   { return a*t.hw(); }
109 
110   template < typename RT, typename T >
111   RT operator()(const RT &a, const RT &w1, const T &t) const
112   { return a*w1*t.hw(); }
113 
114   template < typename RT, typename T >
115   RT operator()(const RT &a, const RT &w1, const RT &w2, const T &t) const
116   { return a*w1*w2*t.hw(); }
117 
118   template < typename RT, typename T >
119   RT operator()(const RT &a, const RT &w1, const RT &w2, const RT &w3,
120                 const T &t) const
121   { return a*w1*w2*w3*t.hw(); }
122 };
123 
124 
125 template < typename K >
126 struct wmult_hw_functor
127   : public wmult_hw_tag<typename K::Rep_tag> {};
128 
129 
130 template < typename Rep_Tag > struct wcross_tag_2;
131 
132 template <>
133 struct wcross_tag_2<Cartesian_tag>
134 {
135   template < typename Point_2 >
136   typename Point_2::R::RT operator()(const Point_2 &p,
137                                      const Point_2 &q,
138                                      const Point_2 &r) const
139   {
140     return (q.x()-p.x())*(r.y()-q.y()) - (q.y()-p.y())*(r.x()-q.x());
141   }
142 };
143 
144 template <>
145 struct wcross_tag_2<Homogeneous_tag>
146 {
147   template < typename Point_2 >
148   typename Point_2::R::RT operator()(const Point_2 &p,
149                                      const Point_2 &q,
150                                      const Point_2 &r) const
151   {
152     return determinant(p.hx(), q.hx(), r.hx(),
153                              p.hy(), q.hy(), r.hy(),
154                              p.hw(), q.hw(), r.hw());
155   }
156 };
157 
158 template < typename K >
159 struct wcross_functor_2
160   : public wcross_tag_2<typename K::Rep_tag> {};
161 
162 
163 template < typename Rep_Tag > struct wcross_tag_3;
164 
165 template <>
166 struct wcross_tag_3<Cartesian_tag>
167 {
168   template < typename Point_3 >
169   typename Point_3::R::Vector_3 operator()(const Point_3 &p,
170                                            const Point_3 &q,
171                                            const Point_3 &r) const
172   {
173     typedef typename Point_3::R::FT         FT;
174     typedef typename Point_3::R::Vector_3   Vector_3;
175     FT x = (q.y()-p.y())*(r.z()-q.z()) - (q.z()-p.z())*(r.y()-q.y());
176     FT y = (q.z()-p.z())*(r.x()-q.x()) - (q.x()-p.x())*(r.z()-q.z());
177     FT z = (q.x()-p.x())*(r.y()-q.y()) - (q.y()-p.y())*(r.x()-q.x());
178     return Vector_3(x, y, z);
179   }
180 };
181 
182 template <>
183 struct wcross_tag_3<Homogeneous_tag>
184 {
185   template < typename Point_3 >
186   typename Point_3::R::Vector_3 operator()(const Point_3 &p,
187                                            const Point_3 &q,
188                                            const Point_3 &r) const
189   {
190     typedef typename Point_3::R::RT         RT;
191     typedef typename Point_3::R::Vector_3   Vector_3;
192     RT x =  p.hy() * (q.hz()*r.hw() - q.hw()*r.hz() )
193           + p.hz() * (q.hw()*r.hy() - q.hy()*r.hw() )
194           + p.hw() * (q.hy()*r.hz() - q.hz()*r.hy() );
195     RT y =  p.hz() * (q.hx()*r.hw() - q.hw()*r.hx() )
196           + p.hx() * (q.hw()*r.hz() - q.hz()*r.hw() )
197           + p.hw() * (q.hz()*r.hx() - q.hx()*r.hz() );
198     RT z =  p.hx() * (q.hy()*r.hw() - q.hw()*r.hy() )
199           + p.hy() * (q.hw()*r.hx() - q.hx()*r.hw() )
200           + p.hw() * (q.hx()*r.hy() - q.hy()*r.hx() );
201     return Vector_3(x, y, z);
202   }
203 };
204 
205 template < typename K >
206 struct wcross_functor_3
207   : public wcross_tag_3<typename K::Rep_tag> {};
208 
209 } // end namespace internal
210 
211 
212 // wmult_hw() is like wmult(), except it calls .hw() on its last argument.
213 // This way, we can completely avoid creating FT(1) for Cartesian.
214 
215 template < typename K, typename T >
216 inline
217 typename K::RT
218 wmult_hw(K*, const typename K::RT &a,
219              const T &t)
220 {
221     return internal::wmult_hw_functor<K>()(a, t);
222 }
223 
224 template < typename K, typename T >
225 inline
226 typename K::RT
227 wmult_hw(K*, const typename K::RT &a,
228              const typename K::RT &w1,
229              const T &t)
230 {
231     return internal::wmult_hw_functor<K>()(a, w1, t);
232 }
233 
234 template < typename K, typename T >
235 inline
236 typename K::RT
237 wmult_hw(K*, const typename K::RT &a,
238              const typename K::RT &w1,
239              const typename K::RT &w2,
240              const T &t)
241 {
242     return internal::wmult_hw_functor<K>()(a, w1, w2, t);
243 }
244 
245 template < typename K, typename T >
246 inline
247 typename K::RT
248 wmult_hw(K*, const typename K::RT &a,
249              const typename K::RT &w1,
250              const typename K::RT &w2,
251              const typename K::RT &w3,
252              const T &t)
253 {
254     return internal::wmult_hw_functor<K>()(a, w1, w2, w3, t);
255 }
256 
257 
258 template < typename K >
259 inline
260 typename K::RT
261 wmult(K*, const typename K::RT &a,
262           const typename K::RT &w)
263 {
264     return internal::wmult_functor<K>()(a, w);
265 }
266 
267 template < typename K >
268 inline
269 typename K::RT
270 wmult(K*, const typename K::RT &a,
271           const typename K::RT &w1,
272           const typename K::RT &w2)
273 {
274     return internal::wmult_functor<K>()(a, w1, w2);
275 }
276 
277 template < typename K >
278 inline
279 typename K::RT
280 wmult(K*, const typename K::RT &a,
281           const typename K::RT &w1,
282           const typename K::RT &w2,
283           const typename K::RT &w3)
284 {
285     return internal::wmult_functor<K>()(a, w1, w2, w3);
286 }
287 
288 template < typename K >
289 inline
290 typename K::RT
291 wmult(K*, const typename K::RT &a,
292           const typename K::RT &w1,
293           const typename K::RT &w2,
294           const typename K::RT &w3,
295           const typename K::RT &w4)
296 {
297     return internal::wmult_functor<K>()(a, w1, w2, w3, w4);
298 }
299 
300 template < typename K >
301 inline
302 typename K::RT
303 wcross(K*, const Point_2<K> &p,
304            const Point_2<K> &q,
305            const Point_2<K> &r)
306 {
307     return internal::wcross_functor_2<K>()(p, q, r);
308 }
309 
310 template < typename K >
311 inline
312 typename K::Vector_3
313 wcross(const Point_3<K> &p,
314        const Point_3<K> &q,
315        const Point_3<K> &r)
316 {
317     return internal::wcross_functor_3<K>()(p, q, r);
318 }
319 
320 } //namespace CGAL
321 
322 #endif // CGAL_KERNEL_WUTILS_H
323