#include #include #include // CGAL headers #include #include #include #include // Qt headers #include #include #include #include #include // GraphicsView items and event filters (input classes) #include #include #if (! defined(BOOST_GCC) || BOOST_GCC >= 40500) #include #endif // the two base classes #include "ui_Spatial_searching_2.h" #include #include "NearestNeighbor.h" typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_2 Point_2; typedef K::Vector_2 Vector_2; typedef K::Segment_2 Segment_2; typedef K::Iso_rectangle_2 Iso_rectangle_2; typedef CGAL::Search_traits_2 TreeTraits; typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; typedef Neighbor_search::Tree Tree; typedef CGAL::Qt::NearestNeighbor NearestNeighbor; class MainWindow : public CGAL::Qt::DemosMainWindow, public Ui::Spatial_searching_2 { Q_OBJECT private: Tree tree; CGAL::Qt::Converter convert; QGraphicsScene scene; CGAL::Qt::PointsInKdTreeGraphicsItem * pgi; NearestNeighbor * nearest_neighbor; public: MainWindow(); template void on_actionGenerate_triggered() { QRectF rect = CGAL::Qt::viewportsBbox(&scene); CGAL::Qt::Converter convert; Iso_rectangle_2 isor = convert(rect); Point_2 center = CGAL::midpoint(isor[0], isor[2]); Vector_2 offset = center - CGAL::ORIGIN; double w = isor.xmax() - isor.xmin(); double h = isor.ymax() - isor.ymin(); double radius = (w::max)(), 1, &ok); if(!ok) { return; } // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); std::vector points; points.reserve(number_of_points); for(int i = 0; i < number_of_points; ++i){ points.push_back(*pg + offset); ++pg; } tree.insert(points.begin(), points.end()); // default cursor QApplication::restoreOverrideCursor(); Q_EMIT( changed()); } public Q_SLOTS: virtual void open(QString fileName); void N_changed(int i); void on_actionClear_triggered(); void on_actionLoadPoints_triggered(); void on_actionRecenter_triggered(); void on_actionGeneratePointsOnCircle_triggered(); void on_actionGeneratePointsInSquare_triggered(); void on_actionGeneratePointsInDisc_triggered(); void clear(); Q_SIGNALS: void changed(); }; MainWindow::MainWindow() : DemosMainWindow() { setupUi(this); this->graphicsView->setAcceptDrops(false); this->graphicsView->setCursor(Qt::CrossCursor); // Add a GraphicItem for the point set pgi = new CGAL::Qt::PointsInKdTreeGraphicsItem(&tree); QObject::connect(this, SIGNAL(changed()), pgi, SLOT(modelChanged())); pgi->setVerticesPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); scene.addItem(pgi); nearest_neighbor = new NearestNeighbor(&scene, &tree, this, this->nn->value()); nearest_neighbor->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); scene.installEventFilter(nearest_neighbor); // // Manual handling of actions // QObject::connect(this->nn, SIGNAL(valueChanged(int)), this, SLOT(N_changed(int))); QObject::connect(this->actionQuit, SIGNAL(triggered()), this, SLOT(close())); // // Setup the scene and the view // scene.setItemIndexMethod(QGraphicsScene::NoIndex); scene.setSceneRect(0, 0, 10, 10); this->graphicsView->setScene(&scene); this->graphicsView->setMouseTracking(true); // Uncomment the following line to get antialiasing by default. // actionUse_Antialiasing->setChecked(true); // Turn the vertical axis upside down this->graphicsView->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_Spatial_searching_2.html"); this->addAboutCGAL(); this->addRecentFiles(this->menuFile, this->actionQuit); connect(this, SIGNAL(openRecentFile(QString)), this, SLOT(open(QString))); } void MainWindow::N_changed(int i) { nearest_neighbor->setN(i); Q_EMIT( changed()); } /* * Qt Automatic Connections * https://doc.qt.io/qt-5/designer-using-a-ui-file.html#automatic-connections * * setupUi(this) generates connections to the slots named * "on__" */ void MainWindow::on_actionClear_triggered() { clear(); Q_EMIT( changed()); } void MainWindow::on_actionRecenter_triggered() { if(tree.empty()){ return; } this->graphicsView->setSceneRect(pgi->boundingRect()); this->graphicsView->fitInView(pgi->boundingRect(), Qt::KeepAspectRatio); } void MainWindow::on_actionGeneratePointsOnCircle_triggered() { typedef CGAL::Random_points_on_circle_2 Generator; on_actionGenerate_triggered(); } void MainWindow::on_actionGeneratePointsInSquare_triggered() { typedef CGAL::Random_points_in_square_2 Generator; on_actionGenerate_triggered(); } void MainWindow::on_actionGeneratePointsInDisc_triggered() { typedef CGAL::Random_points_in_disc_2 Generator; on_actionGenerate_triggered(); } void MainWindow::on_actionLoadPoints_triggered() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Points file"), ".", tr("CGAL files (*.pts.cgal);;" #if (! defined(BOOST_GCC) || BOOST_GCC >= 40500) "WKT files (*.wkt *.WKT);;" #endif "All files (*)")); if(! fileName.isEmpty()){ open(fileName); } } void MainWindow::open(QString fileName) { // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); std::ifstream ifs(qPrintable(fileName)); K::Point_2 p; std::vector points; if(fileName.endsWith(".wkt", Qt::CaseInsensitive)) { #if (! defined(BOOST_GCC) || BOOST_GCC >= 40500) CGAL::read_multi_point_WKT(ifs, points); #endif } else{ while(ifs >> p) { points.push_back(p); } } tree.insert(points.begin(), points.end()); // default cursor QApplication::restoreOverrideCursor(); this->addToRecentFiles(fileName); actionRecenter->trigger(); Q_EMIT( changed()); } void MainWindow::clear() { tree.clear(); } #include "Spatial_searching_2.moc" #include int main(int argc, char **argv) { QApplication app(argc, argv); app.setOrganizationDomain("geometryfactory.com"); app.setOrganizationName("GeometryFactory"); app.setApplicationName("Spatial_searching_2 demo"); // Import resources from libCGAL (Qt5). // See https://doc.qt.io/qt-5/qdir.html#Q_INIT_RESOURCE CGAL_QT_INIT_RESOURCES; Q_INIT_RESOURCE(Spatial_searching_2); MainWindow mainWindow; mainWindow.show(); mainWindow.on_actionRecenter_triggered(); return app.exec(); }