#include // CGAL headers #include #include #include // Qt headers #include #include #include #include #include // GraphicsView items and event filters (input classes) #include "TriangulationCircumcircle.h" #include "TriangulationMovingPoint.h" #include #include // the two base classes #include "ui_Constrained_Delaunay_triangulation_2.h" #include // forward declarations namespace CGAL { namespace Qt { template class ConstrainedTriangulationGraphicsItem; template class TriangulationMovingPoint; template class TriangulationCircumcircle; template class GraphicsViewPolylineInput; } // namespace Qt } // namespace CGAL typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_2 Point_2; typedef CGAL::Triangulation_vertex_base_2 Vertex_base; typedef CGAL::Constrained_triangulation_face_base_2 Face_base; typedef CGAL::Triangulation_data_structure_2 TDS; typedef CGAL::Exact_predicates_tag Itag; typedef CGAL::Constrained_Delaunay_triangulation_2 Delaunay; class MainWindow : public CGAL::Qt::DemosMainWindow, public Ui::Constrained_Delaunay_triangulation_2 { Q_OBJECT private: Delaunay dt; QGraphicsScene scene; CGAL::Qt::ConstrainedTriangulationGraphicsItem * dgi; CGAL::Qt::TriangulationMovingPoint * mp; CGAL::Qt::GraphicsViewPolylineInput * pi; CGAL::Qt::TriangulationCircumcircle *tcc; public: MainWindow(); private: template void insert_polyline(Iterator b, Iterator e) { Point_2 p, q; Delaunay::Vertex_handle vh, wh; Iterator it = b; vh = dt.insert(*it); p = *it; ++it; for(; it != e; ++it){ q = *it; if(p != q){ wh = dt.insert(*it); dt.insert_constraint(vh,wh); vh = wh; p = q; } else { std::cout << "duplicate point: " << p << std::endl; } } emit(changed()); } public slots: void processInput(CGAL::Object o); void on_actionMovingPoint_toggled(bool checked); void on_actionShowDelaunay_toggled(bool checked); void on_actionInsertPolyline_toggled(bool checked); void on_actionCircumcenter_toggled(bool checked); void on_actionClear_triggered(); void on_actionRecenter_triggered(); void on_actionLoadConstraints_triggered(); void loadConstraints(QString); void on_actionSaveConstraints_triggered(); void saveConstraints(QString); void on_actionInsertRandomPoints_triggered(); signals: void changed(); }; MainWindow::MainWindow() : DemosMainWindow() { setupUi(this); // Add a GraphicItem for the Delaunay triangulation dgi = new CGAL::Qt::ConstrainedTriangulationGraphicsItem(&dt); QObject::connect(this, SIGNAL(changed()), dgi, SLOT(modelChanged())); dgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); scene.addItem(dgi); // Setup input handlers. They get events before the scene gets them // and the input they generate is passed to the triangulation with // the signal/slot mechanism pi = new CGAL::Qt::GraphicsViewPolylineInput(this, &scene, 0, false); // inputs polylines which are not closed QObject::connect(pi, SIGNAL(generate(CGAL::Object)), this, SLOT(processInput(CGAL::Object))); mp = new CGAL::Qt::TriangulationMovingPoint(&dt, this); // TriangulationMovingPoint generates an empty Object() each // time the moving point moves. // The following connection is for the purpose of emitting changed(). QObject::connect(mp, SIGNAL(generate(CGAL::Object)), this, SLOT(processInput(CGAL::Object))); tcc = new CGAL::Qt::TriangulationCircumcircle(&scene, &dt, this); tcc->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); // // Manual handling of actions // QObject::connect(this->actionExit, SIGNAL(triggered()), this, SLOT(close())); // We put mutually exclusive actions in an QActionGroup QActionGroup* ag = new QActionGroup(this); ag->addAction(this->actionInsertPolyline); ag->addAction(this->actionMovingPoint); // Check two actions this->actionInsertPolyline->setChecked(true); this->actionShowDelaunay->setChecked(true); // // Setup the scene and the view // scene.setItemIndexMethod(QGraphicsScene::NoIndex); scene.setSceneRect(0,0, 100, 100); this->graphicsView->setScene(&scene); // Uncomment the following line to get antialiasing by default. // actionUse_Antialiasing->setChecked(true); // Turn the vertical axe upside down this->graphicsView->matrix().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView this->addNavigation(this->graphicsView); this->setupStatusBar(); this->setupOptionsMenu(); this->addAboutDemo(":/cgal/help/about_Constrained_Delaunay_triangulation_2.html"); this->addAboutCGAL(); } void MainWindow::processInput(CGAL::Object o) { std::list points; if(CGAL::assign(points, o)){ if(points.size() == 1) { dt.insert(points.front()); } else { insert_polyline(points.begin(), points.end()); } } emit(changed()); } void MainWindow::on_actionInsertPolyline_toggled(bool checked) { if(checked){ scene.installEventFilter(pi); } else { scene.removeEventFilter(pi); } } void MainWindow::on_actionMovingPoint_toggled(bool checked) { if(checked){ scene.installEventFilter(mp); } else { scene.removeEventFilter(mp); } } void MainWindow::on_actionShowDelaunay_toggled(bool checked) { dgi->setDrawEdges(checked); } void MainWindow::on_actionCircumcenter_toggled(bool checked) { if(checked){ scene.installEventFilter(tcc); this->graphicsView->setMouseTracking(true); tcc->show(); } else { scene.removeEventFilter(tcc); this->graphicsView->setMouseTracking(false); tcc->hide(); } } void MainWindow::on_actionClear_triggered() { dt.clear(); emit(changed()); } void MainWindow::on_actionLoadConstraints_triggered() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Constraint File"), ".", tr("Poly files (*.poly)\n" "Edge files (*.edg)")); if(! fileName.isEmpty()){ loadConstraints(fileName); } } void MainWindow::loadConstraints(QString fileName) { std::ifstream ifs(qPrintable(fileName)); std::list points; K::Point_2 p; while(ifs >> p) { points.push_back(p); } insert_polyline(points.begin(), points.end()); actionRecenter->trigger(); emit(changed()); } void MainWindow::on_actionRecenter_triggered() { this->graphicsView->setSceneRect(dgi->boundingRect()); this->graphicsView->fitInView(dgi->boundingRect(), Qt::KeepAspectRatio); } void MainWindow::on_actionSaveConstraints_triggered() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save Constraints"), ".", tr("Poly files (*.poly)\n" "Edge files (*.edg)")); if(! fileName.isEmpty()){ saveConstraints(fileName); } } void MainWindow::saveConstraints(QString fileName) { QMessageBox::warning(this, tr("saveConstraints"), tr("Not implemented!")); } void MainWindow::on_actionInsertRandomPoints_triggered() { typedef CGAL::Creator_uniform_2 Creator; CGAL::Random_points_in_disc_2 g( 100.0); const int number_of_points = QInputDialog::getInteger(this, tr("Number of random points"), tr("Enter number of random points")); std::vector points; points.reserve(number_of_points); for(int i = 0; i < number_of_points; ++i){ points.push_back(*g++); } dt.insert(points.begin(), points.end()); emit(changed()); } #include "Constrained_Delaunay_triangulation_2.moc" int main(int argc, char **argv) { QApplication app(argc, argv); // import resources from libCGALQt4 Q_INIT_RESOURCE(File); Q_INIT_RESOURCE(Triangulation_2); Q_INIT_RESOURCE(Input); Q_INIT_RESOURCE(Logos); MainWindow mainWindow; mainWindow.show(); return app.exec(); }