1 #include <boost/config.hpp>
2 #include <boost/version.hpp>
3 #include <fstream>
4 
5 // CGAL headers
6 #include <CGAL/Cartesian.h>
7 #include <CGAL/MP_Float.h>
8 #include <CGAL/Algebraic_kernel_for_circles_2_2.h>
9 #include <CGAL/Circular_kernel_2.h>
10 #include <CGAL/intersections.h>
11 #include <CGAL/Circular_kernel_2.h>
12 #include <CGAL/Object.h>
13 #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500)
14 #include <CGAL/IO/WKT.h>
15 #endif
16 
17 // Qt headers
18 #include <QtGui>
19 #include <QString>
20 #include <QActionGroup>
21 #include <QFileDialog>
22 #include <QInputDialog>
23 
24 // GraphicsView items and event filters (input classes)
25 #include <CGAL/Qt/GraphicsViewCircularArcInput.h>
26 #include "ArcsGraphicsItem.h"
27 
28 // the two base classes
29 #include "ui_Circular_kernel_2.h"
30 #include <CGAL/Qt/DemosMainWindow.h>
31 
32 typedef CGAL::Quotient<CGAL::MP_Float>                       NT;
33 typedef CGAL::Cartesian<NT>                                 Linear_k;
34 
35 typedef CGAL::Algebraic_kernel_for_circles_2_2<NT>          Algebraic_k;
36 typedef CGAL::Circular_kernel_2<Linear_k,Algebraic_k>       CircularKernel;
37 
38 typedef CircularKernel::Point_2                                 Point_2;
39 typedef CircularKernel::Segment_2                               Segment_2;
40 typedef CircularKernel::Line_arc_2                              Line_arc_2;
41 typedef CircularKernel::Circular_arc_2                          Circular_arc_2;
42 typedef CircularKernel::Circular_arc_point_2                    Circular_arc_point_2;
43 
44 
45 typedef CGAL::Qt::ArcsGraphicsItem<CircularKernel>                 ArcsGraphicsItem;
46 
47 
48 typedef std::vector<CGAL::Object>                           ArcContainer;
49 
50 class MainWindow :
51   public CGAL::Qt::DemosMainWindow,
52   public Ui::Circular_kernel_2
53 {
54   Q_OBJECT
55 
56 private:
57   ArcContainer arcs;
58   ArcContainer intersections;
59   QGraphicsScene scene;
60 
61   ArcsGraphicsItem * agi;
62 
63 
64   CGAL::Qt::GraphicsViewCircularArcInput<CircularKernel> * cai;
65 
66 public:
67   MainWindow();
68 
69 public Q_SLOTS:
70 
71   virtual void open(QString);
72 
73   void processInput(CGAL::Object o);
74 
75 
76   void on_actionInsertCircularArc_toggled(bool checked);
77 
78   void on_actionClear_triggered();
79 
80   void on_actionLoadLineAndCircularArcs_triggered();
81 
82   void on_actionRecenter_triggered();
83 
84 
85 Q_SIGNALS:
86   void changed();
87 };
88 
89 
MainWindow()90 MainWindow::MainWindow()
91   : DemosMainWindow()
92 {
93   setupUi(this);
94 
95   // Add a GraphicItem for the Circular triangulation
96   agi = new CGAL::Qt::ArcsGraphicsItem<CircularKernel>(arcs, intersections);
97 
98   agi->setIntersectionsPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
99 
100   QObject::connect(this, SIGNAL(changed()),
101                    agi, SLOT(modelChanged()));
102 
103   agi->setInputPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
104   scene.addItem(agi);
105   agi->hide();
106 
107   // Setup input handlers. They get events before the scene gets them
108   // and the input they generate is passed to the triangulation with
109   // the signal/slot mechanism
110   cai = new CGAL::Qt::GraphicsViewCircularArcInput<CircularKernel>(this, &scene);
111 
112   QObject::connect(cai, SIGNAL(generate(CGAL::Object)),
113                    this, SLOT(processInput(CGAL::Object)));
114 
115   // Manual handling of actions
116   //
117   QObject::connect(this->actionQuit, SIGNAL(triggered()),
118                    qApp, SLOT(quit()));
119 
120   // Check two actions
121   this->actionInsertCircularArc->setChecked(true);
122 
123   //
124   // Setup the scene and the view
125   //
126   scene.setItemIndexMethod(QGraphicsScene::NoIndex);
127   scene.setSceneRect(-100, -100, 100, 100);
128   this->graphicsView->setScene(&scene);
129 
130   // Uncomment the following line to get antialiasing by default.
131 //   actionUse_Antialiasing->setChecked(true);
132 
133   // Turn the vertical axis upside down
134   this->graphicsView->scale(1, -1);
135 
136   // The navigation adds zooming and translation functionality to the
137   // QGraphicsView
138   this->addNavigation(this->graphicsView);
139 
140   this->setupStatusBar();
141   this->setupOptionsMenu();
142   this->addAboutDemo(":/cgal/help/about_Circular_kernel_2.html");
143   this->addAboutCGAL();
144   this->addRecentFiles(this->menuFile, this->actionQuit);
145   connect(this, SIGNAL(openRecentFile(QString)),
146           this, SLOT(open(QString)));
147 }
148 
149 
150 void
processInput(CGAL::Object o)151 MainWindow::processInput(CGAL::Object o)
152 {
153   Circular_arc_2 ca;
154   Line_arc_2 la;
155   bool is_circular = false;
156 
157   if(assign(ca, o)){
158     is_circular = true;
159   } else if(! assign(la, o)){
160     std::cerr << "unknown object" << std::endl;
161     return;
162   }
163 
164   for(std::vector<CGAL::Object>::iterator it = arcs.begin(); it != arcs.end(); ++it){
165     Circular_arc_2 vca;
166     Line_arc_2 vla;
167     if(assign(vca, *it)){
168       if(is_circular){
169         CGAL::intersection(ca, vca, std::back_inserter(intersections));
170       } else {
171         CGAL::intersection(la, vca, std::back_inserter(intersections));
172       }
173     } else if(assign(vla, *it)){
174       if(is_circular){
175         CGAL::intersection(ca, vla, std::back_inserter(intersections));
176       } else {
177         CGAL::intersection(la, vla, std::back_inserter(intersections));
178       }
179     }
180   }
181   arcs.push_back(o);
182   Q_EMIT( changed());
183 }
184 
185 
186 /*
187  *  Qt Automatic Connections
188  *  https://doc.qt.io/qt-5/designer-using-a-ui-file.html#automatic-connections
189  *
190  *  setupUi(this) generates connections to the slots named
191  *  "on_<action_name>_<signal_name>"
192  */
193 
194 void
on_actionInsertCircularArc_toggled(bool checked)195 MainWindow::on_actionInsertCircularArc_toggled(bool checked)
196 {
197   if(checked){
198     scene.installEventFilter(cai);
199   } else {
200     scene.removeEventFilter(cai);
201   }
202 }
203 
204 void
on_actionClear_triggered()205 MainWindow::on_actionClear_triggered()
206 {
207   arcs.clear();
208   intersections.clear();
209   Q_EMIT( changed());
210 }
211 
212 void
on_actionLoadLineAndCircularArcs_triggered()213 MainWindow::on_actionLoadLineAndCircularArcs_triggered()
214 {
215   QString fileName = QFileDialog::getOpenFileName(this,
216                                                   tr("Open Line and Circular Arc File"),
217                                                   ".",
218                                                   tr("Edge files (*.arc)\n"
219                                                    #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500)
220                                                      "WKT files (*.wkt *.WKT)\n"
221                                                    #endif
222                                                      ));
223   if(! fileName.isEmpty()){
224     open(fileName);
225     this->addToRecentFiles(fileName);
226   }
227 }
228 
229 
230 void
open(QString fileName)231 MainWindow::open(QString fileName)
232 {
233     std::ifstream ifs(qPrintable(fileName));
234 
235     char c;
236     double x,y;
237     if(fileName.endsWith(".wkt", Qt::CaseInsensitive))
238     {
239 #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500)
240       //read pairs as Line_arc_2 and triplets as circular_arc_2
241       do
242       {
243         std::vector<Point_2> multi_points;
244         CGAL::IO::read_multi_point_WKT(ifs, multi_points);
245         if(multi_points.size() == 2)
246         {
247           Line_arc_2 la(Segment_2(multi_points[0],
248                         multi_points[1]));
249           for(std::vector<CGAL::Object>::iterator it = arcs.begin(); it != arcs.end(); ++it){
250             Circular_arc_2 vca;
251             Line_arc_2 vla;
252             if(assign(vca, *it)){
253               CGAL::intersection(la, vca, std::back_inserter(intersections));
254             } else if(assign(vla, *it)){
255               CGAL::intersection(la, vla, std::back_inserter(intersections));
256             }
257           }
258           arcs.push_back(make_object(la));
259         }
260         else if(multi_points.size() == 3)
261         {
262           Circular_arc_2 ca(multi_points[0],
263                             multi_points[1],
264                             multi_points[2]);
265           for(std::vector<CGAL::Object>::iterator it = arcs.begin(); it != arcs.end(); ++it){
266             Circular_arc_2 vca;
267             Line_arc_2 vla;
268             if(assign(vca, *it)){
269               CGAL::intersection(ca, vca, std::back_inserter(intersections));
270             } else if(assign(vla, *it)){
271               CGAL::intersection(ca, vla, std::back_inserter(intersections));
272             }
273           }
274           arcs.push_back(make_object(ca));
275         }
276         else if(multi_points.size()>0)
277         {
278           std::cerr<<"unreadable object."<<std::endl;
279         }
280       }while(ifs.good() && !ifs.eof());
281       ifs.close();
282 #endif
283     }
284     else
285     {
286       while(ifs >> c){
287         if(c == 's'){
288           ifs >> x >> y;
289           Point_2 p(x,y);
290           ifs >> x >> y;
291           Point_2 q(x,y);
292 
293           Line_arc_2 la(Segment_2(p,q));
294           for(std::vector<CGAL::Object>::iterator it = arcs.begin(); it != arcs.end(); ++it){
295             Circular_arc_2 vca;
296             Line_arc_2 vla;
297             if(assign(vca, *it)){
298               CGAL::intersection(la, vca, std::back_inserter(intersections));
299             } else if(assign(vla, *it)){
300               CGAL::intersection(la, vla, std::back_inserter(intersections));
301             }
302           }
303           arcs.push_back(make_object(la));
304         } else if(c == 'c'){
305           ifs >> x >> y;
306           Point_2 p(x,y);
307           ifs >> x >> y;
308           Point_2 q(x,y);
309           ifs >> x >> y;
310           Point_2 r(x,y);
311           Circular_arc_2 ca(p,q,r);
312           for(std::vector<CGAL::Object>::iterator it = arcs.begin(); it != arcs.end(); ++it){
313             Circular_arc_2 vca;
314             Line_arc_2 vla;
315             if(assign(vca, *it)){
316               CGAL::intersection(ca, vca, std::back_inserter(intersections));
317             } else if(assign(vla, *it)){
318               CGAL::intersection(ca, vla, std::back_inserter(intersections));
319             }
320           }
321           arcs.push_back(make_object(ca));
322         }
323       }
324     }
325     Q_EMIT( changed());
326 }
327 
328 void
on_actionRecenter_triggered()329 MainWindow::on_actionRecenter_triggered()
330 {
331   this->graphicsView->setSceneRect(agi->boundingRect());
332   this->graphicsView->fitInView(agi->boundingRect(), Qt::KeepAspectRatio);
333 }
334 
335 
336 #include "Circular_kernel_2.moc"
337 #include <CGAL/Qt/resources.h>
338 
main(int argc,char ** argv)339 int main(int argc, char **argv)
340 {
341   QApplication app(argc, argv);
342 
343   app.setOrganizationDomain("geometryfactory.com");
344   app.setOrganizationName("GeometryFactory");
345   app.setApplicationName("Circular_kernel_2 demo");
346 
347   // Import resources from libCGAL (Qt5).
348   CGAL_QT_INIT_RESOURCES;
349 
350   MainWindow mainWindow;
351   mainWindow.show();
352   return app.exec();
353 }
354