1 // Copyright (c) 2008, 2012, 2020 GeometryFactory Sarl (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
7 //
8 // Author(s): Ahmed Essam <theartful.ae@gmail.com>
9 
10 #ifndef CGAL_QT_GRAPHICS_VIEW_CURVE_INPUT_TYPED_H
11 #define CGAL_QT_GRAPHICS_VIEW_CURVE_INPUT_TYPED_H
12 
13 #include <CGAL/Object.h>
14 #include <boost/optional/optional_fwd.hpp>
15 #include <tuple>
16 #include <type_traits>
17 #include <vector>
18 
19 #include "Callback.h"
20 #include "CurveInputMethods.h"
21 #include "ForwardDeclarations.h"
22 #include "GraphicsSceneMixin.h"
23 #include "GraphicsViewCurveInput.h"
24 #include "PointSnapper.h"
25 
26 class QEvent;
27 
28 namespace demo_types
29 {
30 enum class TraitsType : int;
31 }
32 
33 namespace CGAL
34 {
35 namespace Qt
36 {
37 
38 template <typename ArrTraits_>
39 class CurveGeneratorBase
40 {
41 public:
42   using ArrTraits = ArrTraits_;
43   using Curve_2 = typename ArrTraits::Curve_2;
44   using Point_2 = CGAL::Qt::CurveInputMethod::Point_2;
45 
46   void setTraits(const ArrTraits* traits_);
47 
48   boost::optional<Curve_2>
49   generate(const std::vector<Point_2>& clickedPoints, CurveType type);
50 
51   virtual boost::optional<Curve_2>
generateSegment(const std::vector<Point_2> &)52   generateSegment(const std::vector<Point_2>&) { return {}; }
53   virtual boost::optional<Curve_2>
generateRay(const std::vector<Point_2> &)54   generateRay(const std::vector<Point_2>&) { return {}; }
55   virtual boost::optional<Curve_2>
generateLine(const std::vector<Point_2> &)56   generateLine(const std::vector<Point_2>&) { return {}; }
57   virtual boost::optional<Curve_2>
generatePolyline(const std::vector<Point_2> &)58   generatePolyline(const std::vector<Point_2>&) { return {}; }
59   virtual boost::optional<Curve_2>
generateCircle(const std::vector<Point_2> &)60   generateCircle(const std::vector<Point_2>&) { return {}; }
61   virtual boost::optional<Curve_2>
generateEllipse(const std::vector<Point_2> &)62   generateEllipse(const std::vector<Point_2>&) { return {}; }
63   virtual boost::optional<Curve_2>
generateThreePointCircularArc(const std::vector<Point_2> &)64   generateThreePointCircularArc(const std::vector<Point_2>&) { return {}; }
65   virtual boost::optional<Curve_2>
generateFivePointConicArc(const std::vector<Point_2> &)66   generateFivePointConicArc(const std::vector<Point_2>&) { return {}; }
67   virtual boost::optional<Curve_2>
generateBezier(const std::vector<Point_2> &)68   generateBezier(const std::vector<Point_2>&) { return {}; }
69 
70   const ArrTraits* traits;
71 };
72 
73 template <typename ArrTraits_>
74 struct CurveGenerator : public CurveGeneratorBase<ArrTraits_>
75 {
76 };
77 
78 template <typename Kernel_>
79 struct CurveGenerator<CGAL::Arr_segment_traits_2<Kernel_>> :
80     public CurveGeneratorBase<CGAL::Arr_segment_traits_2<Kernel_>>
81 {
82   using ArrTraits = CGAL::Arr_segment_traits_2<Kernel_>;
83   using Curve_2 = typename ArrTraits::Curve_2;
84   using Kernel = Kernel_;
85   using Super = CurveGeneratorBase<ArrTraits>;
86   using Point_2 = typename Super::Point_2;
87 
88   boost::optional<Curve_2>
89   generateSegment(const std::vector<Point_2>&) override;
90 };
91 
92 template <typename SegmentTraits>
93 struct CurveGenerator<CGAL::Arr_polyline_traits_2<SegmentTraits>> :
94     public CurveGeneratorBase<CGAL::Arr_polyline_traits_2<SegmentTraits>>
95 {
96   using ArrTraits = CGAL::Arr_polyline_traits_2<SegmentTraits>;
97   using Curve_2 = typename ArrTraits::Curve_2;
98   using Super = CurveGeneratorBase<ArrTraits>;
99   using Point_2 = typename Super::Point_2;
100 
101   boost::optional<Curve_2>
102   generatePolyline(const std::vector<Point_2>&) override;
103 };
104 
105 template <typename RatKernel, typename AlgKernel, typename NtTraits>
106 struct CurveGenerator<Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>> :
107     public CurveGeneratorBase<
108       Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>
109 {
110   using ArrTraits = Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>;
111   using Curve_2 = typename ArrTraits::Curve_2;
112   using Kernel = AlgKernel;
113   using Segment_2 = typename Kernel::Segment_2;
114   using Rat_FT = typename RatKernel::FT;
115   using Rat_point_2 = typename RatKernel::Point_2;
116   using Rat_segment_2 = typename RatKernel::Segment_2;
117   using Rat_circle_2 = typename RatKernel::Circle_2;
118   using Super = CurveGeneratorBase<ArrTraits>;
119   using Point_2 = typename Super::Point_2;
120 
121   boost::optional<Curve_2>
122   generateSegment(const std::vector<Point_2>&) override;
123   boost::optional<Curve_2> generateCircle(const std::vector<Point_2>&) override;
124   boost::optional<Curve_2>
125   generateEllipse(const std::vector<Point_2>&) override;
126   boost::optional<Curve_2>
127   generateThreePointCircularArc(const std::vector<Point_2>&) override;
128   boost::optional<Curve_2>
129   generateFivePointConicArc(const std::vector<Point_2>&) override;
130 };
131 
132 template <typename Kernel_>
133 struct CurveGenerator<CGAL::Arr_linear_traits_2<Kernel_>> :
134     public CurveGeneratorBase<CGAL::Arr_linear_traits_2<Kernel_>>
135 {
136   using Kernel = Kernel_;
137   using KernelPoint = typename Kernel::Point_2;
138   using ArrTraits = CGAL::Arr_linear_traits_2<Kernel>;
139   using Curve_2 = typename ArrTraits::Curve_2;
140   using Segment_2 = typename Kernel::Segment_2;
141   using Ray_2 = typename Kernel::Ray_2;
142   using Line_2 = typename Kernel::Line_2;
143   using Super = CurveGeneratorBase<ArrTraits>;
144   using Point_2 = typename Super::Point_2;
145 
146   boost::optional<Curve_2>
147   generateSegment(const std::vector<Point_2>&) override;
148   boost::optional<Curve_2> generateRay(const std::vector<Point_2>&) override;
149   boost::optional<Curve_2> generateLine(const std::vector<Point_2>&) override;
150 };
151 
152 template <typename Coefficient_>
153 struct CurveGenerator<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>> :
154     public CurveGeneratorBase<
155       CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>
156 {
157   using Coefficient = Coefficient_;
158   using ArrTraits = CGAL::Arr_algebraic_segment_traits_2<Coefficient>;
159   using X_monotone_curve_2 = typename ArrTraits::X_monotone_curve_2;
160   using Polynomial_2 = typename ArrTraits::Polynomial_2;
161   using Curve_2 = typename ArrTraits::Curve_2;
162   using Algebraic_real_1 = typename ArrTraits::Algebraic_real_1;
163   using Rational = typename Algebraic_real_1::Rational;
164   using RationalTraits = Rational_traits<Rational>;
165   using Super = CurveGeneratorBase<ArrTraits>;
166   using Point_2 = typename Super::Point_2;
167 
168   boost::optional<Curve_2> generateLine(const std::vector<Point_2>&) override;
169   boost::optional<Curve_2> generateCircle(const std::vector<Point_2>&) override;
170   boost::optional<Curve_2>
171   generateEllipse(const std::vector<Point_2>&) override;
172 
173 private:
174   boost::optional<Curve_2> generateEllipse_(const Point_2&, Rational, Rational);
175 };
176 
177 template <
178   typename RatKernel, typename AlgKernel, typename NtTraits,
179   typename BoundingTraits>
180 struct CurveGenerator<
181   Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits, BoundingTraits>> :
182     public CurveGeneratorBase<
183       Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits, BoundingTraits>>
184 {
185   using ArrTraits =
186     Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits, BoundingTraits>;
187   using Super = CurveGeneratorBase<ArrTraits>;
188   using Point_2 = typename Super::Point_2;
189   using Curve_2 = typename ArrTraits::Curve_2;
190 
191   boost::optional<Curve_2> generateBezier(const std::vector<Point_2>&) override;
192 };
193 
194 template <typename ArrTraits>
195 struct GraphicsViewCurveInputTypeHelper
196 {
197   using InputMethodTuple = std::tuple<>;
198 };
199 
200 template <typename Kernel_>
201 struct GraphicsViewCurveInputTypeHelper<CGAL::Arr_segment_traits_2<Kernel_>>
202 {
203   using InputMethodTuple = std::tuple<SegmentInputMethod>;
204 };
205 
206 template <typename SegmentTraits>
207 struct GraphicsViewCurveInputTypeHelper<
208   CGAL::Arr_polyline_traits_2<SegmentTraits>>
209 {
210   using InputMethodTuple = std::tuple<PolylineInputMethod>;
211 };
212 
213 template <typename Kernel_>
214 struct GraphicsViewCurveInputTypeHelper<CGAL::Arr_linear_traits_2<Kernel_>>
215 {
216   using InputMethodTuple =
217     std::tuple<SegmentInputMethod, RayInputMethod, LineInputMethod>;
218 };
219 
220 template <typename RatKernel, typename AlgKernel, typename NtTraits>
221 struct GraphicsViewCurveInputTypeHelper<
222   CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>
223 {
224   using InputMethodTuple = std::tuple<
225     SegmentInputMethod, CircleInputMethod, EllipseInputMethod,
226     ThreePointCircularInputMethod, FivePointConicInputMethod>;
227 };
228 
229 template <typename Coefficient_>
230 struct GraphicsViewCurveInputTypeHelper<
231   CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>
232 {
233   using InputMethodTuple =
234     std::tuple<LineInputMethod, CircleInputMethod, EllipseInputMethod>;
235 };
236 
237 template <
238   typename RatKernel, typename AlgKernel, typename NtTraits,
239   typename BoundingTraits>
240 struct GraphicsViewCurveInputTypeHelper<CGAL::Arr_Bezier_curve_traits_2<
241   RatKernel, AlgKernel, NtTraits, BoundingTraits>>
242 {
243   using InputMethodTuple = std::tuple<BezierInputMethod>;
244 };
245 
246 template <typename Arr_>
247 class GraphicsViewCurveInput :
248     public GraphicsViewCurveInputBase,
249     public CurveInputMethodCallback
250 {
251   using Self = GraphicsViewCurveInput<Arr_>;
252   using Arrangement = Arr_;
253   using ArrTraits = typename Arrangement::Geometry_traits_2;
254   using Curve_2 = typename Arrangement::Curve_2;
255   using InputMethodTuple =
256     typename GraphicsViewCurveInputTypeHelper<ArrTraits>::InputMethodTuple;
257   using Point_2 = CGAL::Qt::CurveInputMethod::Point_2;
258 
259 public:
260   GraphicsViewCurveInput(
261     Arrangement* arrangement_, QObject* parent, QGraphicsScene* scene);
262   void setCurveType(CurveType type) override;
263   void setPointSnapper(PointSnapperBase*) override;
264   void generate(CGAL::Object o) override;
265   void curveInputDoneEvent(
266     const std::vector<Point_2>& clickedPoints, CurveType type) override;
267 
268 private:
269   template <typename = ArrTraits>
270   void setDefaultInputMethod(std::true_type);
271   void setDefaultInputMethod(std::false_type);
272 
273   Arrangement* arrangement;
274   InputMethodTuple inputMethods;
275   CurveGenerator<ArrTraits> curveGenerator;
276 };
277 
278 } // namespace Qt
279 } // namespace CGAL
280 
281 #endif // CGAL_QT_GRAPHICS_VIEW_SEGMENT_INPUT_H
282