#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 // for viewportsBbox #include #include // the two base classes #include "ui_Stream_lines_2.h" #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Regular_grid_2 Regular_grid; typedef CGAL::Runge_kutta_integrator_2 Runge_kutta_integrator; typedef CGAL::Stream_lines_2 Stream_lines; typedef CGAL::Stream_lines_2::Stream_line_iterator_2 Stream_line_iterator; typedef CGAL::Stream_lines_2::Point_iterator_2 Point_iterator; typedef CGAL::Stream_lines_2::Point_2 Point_2; typedef CGAL::Stream_lines_2::Vector_2 Vector; typedef K::Iso_rectangle_2 Iso_rectangle_2; class MainWindow : public CGAL::Qt::DemosMainWindow, public Ui::Stream_lines_2 { Q_OBJECT private: Stream_lines * stream_lines; Runge_kutta_integrator * runge_kutta_integrator; Regular_grid * regular_grid; double density; double ratio; double integrating; int sampling; QGraphicsScene scene; CGAL::Qt::StreamLinesGraphicsItem * sli; CGAL::Qt::RegularGridVectorFieldGraphicsItem * rgi; public: MainWindow(); public Q_SLOTS: void on_actionLoadPoints_triggered(); void on_actionClear_triggered(); void on_actionSavePoints_triggered(); void on_actionRecenter_triggered(); virtual void open(QString fileName); private: void generate(); Q_SIGNALS: void changed(); }; MainWindow::MainWindow() : DemosMainWindow(), density(12.0), ratio(1.6), integrating(1.0), sampling(1) { setupUi(this); this->graphicsView->setAcceptDrops(false); // Manual handling of actions // QObject::connect(this->actionQuit, SIGNAL(triggered()), this, SLOT(close())); // // Setup the scene and the view // scene.setItemIndexMethod(QGraphicsScene::NoIndex); scene.setSceneRect(-100, -100, 100, 100); this->graphicsView->setScene(&scene); // Turn the vertical axis upside down this->graphicsView->transform().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_Stream_lines_2.html"); this->addAboutCGAL(); this->addRecentFiles(this->menuFile, this->actionQuit); connect(this, SIGNAL(openRecentFile(QString)), this, SLOT(open(QString))); } /* * 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() { Q_EMIT( changed()); } void MainWindow::generate() { stream_lines = new Stream_lines(*regular_grid, *runge_kutta_integrator, density, ratio, sampling); sli = new CGAL::Qt::StreamLinesGraphicsItem(stream_lines); rgi = new CGAL::Qt::RegularGridVectorFieldGraphicsItem(regular_grid); QObject::connect(this, SIGNAL(changed()), sli, SLOT(modelChanged())); rgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); rgi->setEdgesPen(QPen(Qt::gray, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); sli->setEdgesPen(QPen(Qt::blue, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); scene.addItem(sli); scene.addItem(rgi); on_actionRecenter_triggered(); Q_EMIT( changed()); } void MainWindow::on_actionLoadPoints_triggered() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open grid file"), "." ,tr("WKT files (*.wkt *.WKT)") ); if(! fileName.isEmpty()){ open(fileName); } } void MainWindow::open(QString fileName) { // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); std::ifstream ifs(qPrintable(fileName)); runge_kutta_integrator = new Runge_kutta_integrator(integrating); double iXSize, iYSize; iXSize = iYSize = 512; if(fileName.endsWith(".wkt", Qt::CaseInsensitive)) { std::vector > mp; int size= -1; do { std::vector ps; CGAL::IO::read_multi_point_WKT(ifs, ps); if(size == -1) size = static_cast(ps.size()); else if(ps.size() > 0 && size != static_cast(ps.size())) ps.resize(size); else if(ps.size() == 0) continue; mp.push_back(ps); }while(ifs.good() && !ifs.eof()); regular_grid = new Regular_grid(size, static_cast(mp.size()), iXSize, iYSize); /*fill the grid with the appropriate values*/ for (unsigned int i=0;i(size);++i) for (unsigned int j=0;jset_field(i, j, Vector(mp[j][i].x(), mp[j][i].y())); } } else{ unsigned int x_samples, y_samples; ifs >> x_samples; ifs >> y_samples; regular_grid = new Regular_grid(x_samples, y_samples, iXSize, iYSize); /*fill the grid with the appropriate values*/ for (unsigned int i=0;i> xval; ifs >> yval; regular_grid->set_field(i, j, Vector(xval, yval)); } } ifs.close(); // default cursor QApplication::restoreOverrideCursor(); this->addToRecentFiles(fileName); generate(); Q_EMIT( changed()); } void MainWindow::on_actionSavePoints_triggered() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save points"), ".", tr("WKT files (*.wkt *.WKT)")); if(! fileName.isEmpty()){ std::ofstream ofs(qPrintable(fileName)); std::vector >mp; mp.resize(regular_grid->get_dimension().second); for (int i=0;iget_dimension().first;++i) { mp[i].reserve(regular_grid->get_dimension().second); for (int j=0;jget_dimension().second;++j) { mp[i].push_back(Point_2(regular_grid->get_field(j,i).x(), regular_grid->get_field(j,i).y())); } CGAL::IO::write_multi_point_WKT(ofs, mp[i]); } ofs.close(); } } void MainWindow::on_actionRecenter_triggered() { this->graphicsView->setSceneRect(rgi->boundingRect()); this->graphicsView->fitInView(rgi->boundingRect(), Qt::KeepAspectRatio); } #include int main(int argc, char **argv) { QApplication app(argc, argv); app.setOrganizationDomain("geometryfactory.com"); app.setOrganizationName("GeometryFactory"); app.setApplicationName("Stream_lines_2 demo"); // Import resources from libCGAL (Qt6). // See https://doc.qt.io/qt-5/qdir.html#Q_INIT_RESOURCE CGAL_QT_INIT_RESOURCES; Q_INIT_RESOURCE(Stream_lines_2); MainWindow mainWindow; mainWindow.show(); return app.exec(); } #include "Stream_lines_2.moc"