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