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/Kernel_23/include/CGAL/Line_2.h $
11 // $Id: Line_2.h 4e519a3 2021-05-05T13:15:37+02: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_LINE_2_H
18 #define CGAL_LINE_2_H
19 
20 #include <CGAL/assertions.h>
21 #include <boost/type_traits/is_same.hpp>
22 #include <CGAL/Kernel/Return_base_tag.h>
23 #include <CGAL/Dimension.h>
24 #include <CGAL/IO/io.h>
25 #include <CGAL/Kernel/mpl.h>
26 
27 namespace CGAL {
28 
29 template <class R_>
30 class Line_2 : public R_::Kernel_base::Line_2
31 {
32   typedef typename R_::RT                    RT;
33   typedef typename R_::FT                    FT;
34   typedef typename R_::Point_2               Point_2;
35   typedef typename R_::Segment_2             Segment_2;
36   typedef typename R_::Ray_2                 Ray_2;
37   typedef typename R_::Vector_2              Vector_2;
38   typedef typename R_::Direction_2           Direction_2;
39   typedef typename R_::Aff_transformation_2  Aff_transformation_2;
40   typedef typename R_::Kernel_base::Line_2   RLine_2;
41 
42   typedef Line_2                             Self;
43   CGAL_static_assertion((boost::is_same<Self, typename R_::Line_2>::value));
44 
45 public:
46 
47   typedef Dimension_tag<2>  Ambient_dimension;
48   typedef Dimension_tag<1>  Feature_dimension;
49 
50   typedef RLine_2 Rep;
51 
rep()52   const Rep& rep() const
53   {
54     return *this;
55   }
56 
rep()57   Rep& rep()
58   {
59     return *this;
60   }
61 
62   typedef  R_   R;
63 
Line_2()64   Line_2() {}
65 
Line_2(const RLine_2 & l)66   Line_2(const RLine_2& l)  // conversion impl -> interface class
67     : RLine_2(l) {}
68 
Line_2(const Point_2 & p,const Point_2 & q)69   Line_2(const Point_2 &p, const Point_2 &q)
70     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), p,q)) {}
71 
Line_2(const RT & a,const RT & b,const RT & c)72   Line_2(const RT &a, const RT &b, const RT &c)
73     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), a,b,c)) {}
74 
Line_2(const Segment_2 & s)75   explicit Line_2(const Segment_2& s)
76     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), s)) {}
77 
Line_2(const Ray_2 & r)78   explicit Line_2(const Ray_2& r)
79     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), r)) {}
80 
Line_2(const Point_2 & p,const Direction_2 & d)81   Line_2(const Point_2 &p, const Direction_2 &d)
82     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), p,d)) {}
83 
Line_2(const Point_2 & p,const Vector_2 & v)84   Line_2(const Point_2 &p, const Vector_2 &v)
85     : RLine_2(typename R::Construct_line_2()(Return_base_tag(), p,v)) {}
86 
87 
88   // FIXME : Use Qrt<> here.
a()89   RT a() const
90   {
91     return R().compute_a_2_object()(*this);
92   }
93 
b()94   RT b() const
95   {
96     return R().compute_b_2_object()(*this);
97   }
98 
c()99   RT c() const
100   {
101     return R().compute_c_2_object()(*this);
102   }
103 
104   Line_2
transform(const Aff_transformation_2 & t)105   transform(const Aff_transformation_2 &t) const
106   {
107     return Line_2(t.transform(point(0)),
108                   t.transform(direction()));
109   }
110 
111   Line_2
opposite()112   opposite() const
113   {
114     return R().construct_opposite_line_2_object()(*this);
115   }
116 
117   Direction_2
direction()118   direction() const
119   {
120     return R().construct_direction_2_object()(*this);
121   }
122 
123   Vector_2
to_vector()124   to_vector() const
125   {
126     return R().construct_vector_2_object()(*this);
127   }
128 
129   Line_2
perpendicular(const Point_2 & p)130   perpendicular(const Point_2 &p) const
131   {
132     return R().construct_perpendicular_line_2_object()(*this,p);
133   }
134 
135   Point_2
projection(const Point_2 & p)136   projection(const Point_2& p) const
137   {
138     return R().construct_projected_point_2_object()(*this,p);
139   }
140 
141   typename R::Boolean
is_horizontal()142   is_horizontal() const
143   {
144     return R().is_horizontal_2_object()(*this);
145   }
146 
147   typename R::Boolean
is_vertical()148   is_vertical() const
149   {
150     return R().is_vertical_2_object()(*this);
151   }
152 
153   typename R::Boolean
is_degenerate()154   is_degenerate() const
155   { return R().is_degenerate_2_object()(*this); }
156 
157   typename R::Oriented_side
oriented_side(const Point_2 & p)158   oriented_side(const Point_2 &p) const
159   {
160     return R().oriented_side_2_object()(*this,p);
161   }
162 
163   typename R::Boolean
has_on_boundary(const Point_2 & p)164   has_on_boundary(const Point_2 &p) const
165   {
166     return oriented_side(p) == ON_ORIENTED_BOUNDARY;
167   }
168 
169   typename R::Boolean
has_on_positive_side(const Point_2 & p)170   has_on_positive_side(const Point_2 &p) const
171   {
172     return oriented_side(p) == ON_POSITIVE_SIDE;
173   }
174 
175   typename R::Boolean
has_on_negative_side(const Point_2 & p)176   has_on_negative_side(const Point_2 &p) const
177   {
178     return oriented_side(p) == ON_NEGATIVE_SIDE;
179   }
180 
181   typename R::Boolean
has_on(const Point_2 & p)182   has_on(const Point_2 &p) const
183   {
184     return has_on_boundary(p);
185   }
186 
187   FT
x_at_y(const FT & y)188   x_at_y(const FT &y) const
189   {
190     return R().compute_x_at_y_2_object()(*this, y);
191   }
192 
193   FT
y_at_x(const FT & y)194   y_at_x(const FT &y) const
195   {
196     return R().compute_y_at_x_2_object()(*this, y);
197   }
198 
199   Point_2
point()200   point() const
201   {
202     return R().construct_point_2_object()(*this);
203   }
204 
205   Point_2
point(const int i)206   point(const int i) const
207   {
208     return R().construct_point_2_object()(*this, RT(i));
209   }
210 
211   Point_2
point(const typename First_if_different<RT,int,1>::Type & i)212   point(const typename First_if_different<RT, int, 1>::Type& i) const
213   {
214     return R().construct_point_2_object()(*this,i);
215   }
216 
217   Point_2
point(const typename First_if_different<const typename First_if_different<FT,RT,2>::Type,int>::Type & i)218   point(const typename First_if_different<
219                 const typename First_if_different<FT, RT, 2>::Type, int>::Type& i) const
220   {
221     return R().construct_point_2_object()(*this,i);
222   }
223 
224   typename R::Boolean
225   operator==(const Line_2 &l) const
226   {
227     return R().equal_2_object()(*this, l);
228   }
229 
230   typename R::Boolean
231   operator!=(const Line_2 &l) const
232   {
233     return !(*this == l);
234   }
235 
236 };
237 
238 
239 template <class R >
240 std::ostream&
insert(std::ostream & os,const Line_2<R> & l)241 insert(std::ostream& os, const Line_2<R>& l)
242 {
243     switch(IO::get_mode(os)) {
244     case IO::ASCII :
245         return os << l.a() << ' ' << l.b() << ' ' << l.c();
246     case IO::BINARY :
247         write(os, l.a());
248         write(os, l.b());
249         write(os, l.c());
250         return os;
251     default:
252         return os << "Line_2(" << l.a()
253                   << ", " << l.b() << ", " << l.c() <<')';
254     }
255 }
256 
257 template < class R >
258 std::ostream &
259 operator<<(std::ostream &os, const Line_2<R> &l)
260 {
261   return insert(os, l);
262 }
263 
264 
265 template <class R >
266 std::istream&
extract(std::istream & is,Line_2<R> & l)267 extract(std::istream& is, Line_2<R>& l)
268 {
269   typename R::RT a(0), b(0), c(0);
270     switch(IO::get_mode(is)) {
271     case IO::ASCII :
272         is >> IO::iformat(a) >> IO::iformat(b) >> IO::iformat(c);
273         break;
274     case IO::BINARY :
275         read(is, a);
276         read(is, b);
277         read(is, c);
278         break;
279     default:
280         is.setstate(std::ios::failbit);
281         std::cerr << "" << std::endl;
282         std::cerr << "Stream must be in ascii or binary mode" << std::endl;
283         break;
284     }
285     if (is)
286         l = Line_2<R>(a, b, c);
287     return is;
288 }
289 
290 
291 template < class R >
292 std::istream &
293 operator>>(std::istream &is, Line_2<R> &l)
294 {
295   return extract(is, l);
296 }
297 
298 } //namespace CGAL
299 
300 #endif  // CGAL_LINE_2_H
301