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/Homogeneous_kernel/include/CGAL/Homogeneous/CircleH2.h $
11 // $Id: CircleH2.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 // Author(s)     : Sven Schoenherr
15 //                 Stefan Schirra
16 
17 #ifndef CGAL_CIRCLEH2_H
18 #define CGAL_CIRCLEH2_H
19 
20 #include <CGAL/Interval_nt.h>
21 #include <boost/tuple/tuple.hpp>
22 
23 namespace CGAL {
24 
25 template <class R_>
26 class CircleH2
27 {
28     typedef typename R_::FT                   FT;
29     typedef typename R_::RT                   RT;
30     typedef typename R_::Point_2              Point_2;
31 
32     typedef boost::tuple<Point_2, FT, Orientation>   Rep;
33     typedef typename R_::template Handle<Rep>::type  Base;
34 
35     Base base;
36 
37 public:
38     typedef R_                                    R;
39 
CircleH2()40     CircleH2() {}
41 
CircleH2(const Point_2 & p,const Point_2 & q,const Point_2 & r)42     CircleH2(const Point_2& p, const Point_2& q, const Point_2& r)
43     {
44       Orientation o = CGAL::orientation( p, q, r);
45       CGAL_kernel_precondition( o != COLLINEAR);
46 
47       Point_2    cp   = circumcenter( p, q, r);
48       FT         sq_r = squared_distance( p, cp);
49 
50       base = Rep(cp, sq_r, o);
51     }
52 
CircleH2(const Point_2 & p,const Point_2 & q,const Orientation & o)53     CircleH2(const Point_2& p, const Point_2& q, const Orientation& o)
54     {
55       CGAL_kernel_precondition( o != COLLINEAR);
56 
57       if ( p != q)
58       {
59          Point_2    cp   = midpoint( p, q);
60          FT         sq_r = squared_distance( cp, p);
61          base = Rep(cp, sq_r, o);
62       }
63       else
64          base = Rep(p, FT( 0), o);
65     }
66 
CircleH2(const Point_2 & cp,const FT & squared_radius,const Orientation & o)67     CircleH2(const Point_2& cp, const FT& squared_radius,
68              const Orientation& o)
69     {
70       CGAL_precondition( ( ! CGAL_NTS is_negative( squared_radius)) &&
71                          ( o != COLLINEAR ) );
72       base = Rep(cp, squared_radius, o);
73     }
74 
75     const Point_2 &
76     center() const;
77 
78     Orientation
79     orientation() const;
80 
81     const FT &
82     squared_radius() const;
83 
84     CircleH2<R>
85     opposite() const;
86 
87     Oriented_side
88     oriented_side(const Point_2& ) const;
89 
90     Bounded_side
91     bounded_side(const Point_2& ) const;
92 
93     bool  operator==( const CircleH2<R>& ) const;
94     bool  operator!=( const CircleH2<R>& ) const;
95     bool  has_on_positive_side(const Point_2& ) const;
96     bool  has_on_negative_side(const Point_2& ) const;
97     bool  has_on_boundary( const Point_2& ) const;
98     bool  has_on_bounded_side( const Point_2& ) const;
99     bool  has_on_unbounded_side(const Point_2&) const;
100     bool  is_degenerate() const;
101 
102     // bool  oriented_equal( const CircleH2<R>& ) const;
103     // bool  unoriented_equal( const CircleH2<R>& ) const;
104 };
105 
106 template <class R>
107 inline
108 const typename CircleH2<R>::Point_2 &
center()109 CircleH2<R>::center() const
110 { return get_pointee_or_identity(base).template get<0>(); }
111 
112 template <class R>
113 inline
114 const typename CircleH2<R>::FT &
squared_radius()115 CircleH2<R>::squared_radius() const
116 { return get_pointee_or_identity(base).template get<1>(); }
117 
118 template <class R>
119 CGAL_KERNEL_INLINE
120 CircleH2<R>
opposite()121 CircleH2<R>::opposite() const
122 {
123   return CircleH2<R>( center(),
124                           squared_radius(),
125                           CGAL::opposite( orientation() ) );
126 }
127 
128 template <class R>
129 inline
130 Orientation
orientation()131 CircleH2<R>::orientation() const
132 { return get_pointee_or_identity(base).template get<2>(); }
133 
134 template <class R>
135 CGAL_KERNEL_INLINE
136 Oriented_side
oriented_side(const typename CircleH2<R>::Point_2 & p)137 CircleH2<R>::oriented_side( const typename CircleH2<R>::Point_2& p) const
138 {
139   FT sq_dist = squared_distance( p, center() );
140   FT sq_rad  = squared_radius();
141   Comparison_result vgl = CGAL_NTS compare( sq_dist, sq_rad );
142   Oriented_side rel_pos = (vgl == LARGER ) ?
143                                    ON_NEGATIVE_SIDE :
144                                    ( (vgl == SMALLER ) ?
145                                           ON_POSITIVE_SIDE :
146                                           ON_ORIENTED_BOUNDARY);
147   if (orientation() == POSITIVE)
148   { return rel_pos; }
149   else       // NEGATIVE
150   { return CGAL::opposite( rel_pos ); }
151 }
152 
153 template <class R>
154 CGAL_KERNEL_INLINE
155 bool
has_on_positive_side(const typename CircleH2<R>::Point_2 & p)156 CircleH2<R>::has_on_positive_side(const typename CircleH2<R>::Point_2& p) const
157 {
158   if ( orientation() == POSITIVE )
159   { return (has_on_bounded_side(p) ); }
160   else
161   { return (has_on_unbounded_side(p) ); }
162 }
163 
164 template <class R>
165 CGAL_KERNEL_INLINE
166 bool
has_on_boundary(const typename CircleH2<R>::Point_2 & p)167 CircleH2<R>::has_on_boundary(const typename CircleH2<R>::Point_2& p) const
168 {
169   FT sq_dist = squared_distance( p, center() );
170   FT sq_rad  = squared_radius();
171   return ( sq_dist == sq_rad );
172 }
173 
174 template <class R>
175 CGAL_KERNEL_INLINE
176 bool
has_on_negative_side(const typename CircleH2<R>::Point_2 & p)177 CircleH2<R>::has_on_negative_side( const typename CircleH2<R>::Point_2&p) const
178 {
179   if ( orientation() == NEGATIVE )
180   {
181       return (has_on_bounded_side(p) );
182   }
183   else
184   {
185       return (has_on_unbounded_side(p) );
186   }
187 }
188 
189 template <class R>
190 CGAL_KERNEL_INLINE
191 Bounded_side
bounded_side(const typename CircleH2<R>::Point_2 & p)192 CircleH2<R>::bounded_side(const typename CircleH2<R>::Point_2& p) const
193 {
194   FT sq_dist = squared_distance( p, center() );
195   FT sq_rad  = squared_radius();
196   Comparison_result vgl = CGAL_NTS compare( sq_dist, sq_rad );
197   return  (vgl == LARGER ) ? ON_UNBOUNDED_SIDE :
198                                    ( (vgl == SMALLER ) ?
199                                           ON_BOUNDED_SIDE :
200                                           ON_BOUNDARY);
201 }
202 
203 template <class R>
204 CGAL_KERNEL_INLINE
205 bool
has_on_bounded_side(const typename CircleH2<R>::Point_2 & p)206 CircleH2<R>::has_on_bounded_side(const typename CircleH2<R>::Point_2& p) const
207 {
208   FT sq_dist = squared_distance( p, center() );
209   FT sq_rad  = squared_radius();
210   return ( sq_dist < sq_rad );
211 }
212 
213 template <class R>
214 CGAL_KERNEL_INLINE
215 bool
has_on_unbounded_side(const typename CircleH2<R>::Point_2 & p)216 CircleH2<R>::has_on_unbounded_side(const typename CircleH2<R>::Point_2&p) const
217 {
218   FT sq_dist = squared_distance( p, center() );
219   FT sq_rad  = squared_radius();
220   return ( sq_rad < sq_dist );
221 }
222 
223 template <class R>
224 inline
225 bool
is_degenerate()226 CircleH2<R>::is_degenerate() const
227 { return ( squared_radius() == FT(0) ); }
228 
229 template <class R>
230 CGAL_KERNEL_INLINE
231 bool
232 CircleH2<R>::operator==(const CircleH2<R>& c) const
233 {
234   return  ( center() == c.center() )
235         &&( squared_radius() == c.squared_radius() )
236         &&( orientation() == c.orientation() );
237 }
238 
239 template <class R>
240 inline
241 bool
242 CircleH2<R>::operator!=(const CircleH2<R>& c) const
243 { return !(*this == c); }
244 
245 } //namespace CGAL
246 
247 #endif // CGAL_CIRCLEH2_H
248