cgal/GraphicsView/demo/Triangulation_2/Delaunay_triangulation_2.cpp

330 lines
7.7 KiB
C++

#include <fstream>
// CGAL headers
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/point_generators_2.h>
// Qt headers
#include <QtGui>
#include <QString>
#include <QActionGroup>
#include <QFileDialog>
#include <QInputDialog>
// GraphicsView items and event filters (input classes)
#include "TriangulationCircumcircle.h"
#include "TriangulationMovingPoint.h"
#include <CGAL/Qt/GraphicsViewPolylineInput.h>
#include <CGAL/Qt/TriangulationGraphicsItem.h>
#include <CGAL/Qt/VoronoiGraphicsItem.h>
// the two base classes
#include "ui_Delaunay_triangulation_2.h"
#include <CGAL/Qt/DemosMainWindow.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef CGAL::Delaunay_triangulation_2<K> Delaunay;
class MainWindow :
public CGAL::Qt::DemosMainWindow,
public Ui::Delaunay_triangulation_2
{
Q_OBJECT
private:
Delaunay dt;
QGraphicsScene scene;
CGAL::Qt::TriangulationGraphicsItem<Delaunay> * dgi;
CGAL::Qt::VoronoiGraphicsItem<Delaunay> * vgi;
CGAL::Qt::TriangulationMovingPoint<Delaunay> * mp;
CGAL::Qt::GraphicsViewPolylineInput<K> * pi;
CGAL::Qt::TriangulationCircumcircle<Delaunay> *tcc;
public:
MainWindow();
public slots:
void processInput(CGAL::Object o);
void on_actionMovingPoint_toggled(bool checked);
void on_actionCircumcenter_toggled(bool checked);
void on_actionShowDelaunay_toggled(bool checked);
void on_actionShowVoronoi_toggled(bool checked);
void on_actionInsertPoint_toggled(bool checked);
void on_actionInsertRandomPoints_triggered();
void on_actionLoadPoints_triggered();
void on_actionSavePoints_triggered();
void on_actionClear_triggered();
void on_actionRecenter_triggered();
signals:
void changed();
};
MainWindow::MainWindow()
: DemosMainWindow()
{
setupUi(this);
// Add a GraphicItem for the Delaunay triangulation
dgi = new CGAL::Qt::TriangulationGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
dgi, SLOT(modelChanged()));
dgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(dgi);
// Add a GraphicItem for the Voronoi diagram
vgi = new CGAL::Qt::VoronoiGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
vgi, SLOT(modelChanged()));
vgi->setEdgesPen(QPen(Qt::blue, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(vgi);
vgi->hide();
// 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<K>(this, &scene, 1, false); // inputs
// points
QObject::connect(pi, SIGNAL(generate(CGAL::Object)),
this, SLOT(processInput(CGAL::Object)));
mp = new CGAL::Qt::TriangulationMovingPoint<Delaunay>(&dt, this);
// TriangulationMovingPoint<Delaunay> 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, SIGNAL(changed()));
tcc = new CGAL::Qt::TriangulationCircumcircle<Delaunay>(&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->actionInsertPoint);
ag->addAction(this->actionMovingPoint);
// Check two actions
this->actionInsertPoint->setChecked(true);
this->actionShowDelaunay->setChecked(true);
//
// Setup the scene and the view
//
scene.setItemIndexMethod(QGraphicsScene::NoIndex);
scene.setSceneRect(-100, -100, 100, 100);
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->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_Delaunay_triangulation_2.html");
this->addAboutCGAL();
}
void
MainWindow::processInput(CGAL::Object o)
{
std::list<Point_2> points;
if(CGAL::assign(points, o)){
if(points.size() == 1) {
dt.insert(points.front());
}
}
emit(changed());
}
/*
* Qt Automatic Connections
* http://doc.trolltech.com/4.4/designer-using-a-component.html#automatic-connections
*
* setupUi(this) generates connections to the slots named
* "on_<action_name>_<signal_name>"
*/
void
MainWindow::on_actionInsertPoint_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_actionCircumcenter_toggled(bool checked)
{
if(checked){
scene.installEventFilter(tcc);
tcc->show();
} else {
scene.removeEventFilter(tcc);
tcc->hide();
}
}
void
MainWindow::on_actionShowDelaunay_toggled(bool checked)
{
dgi->setDrawEdges(checked);
}
void
MainWindow::on_actionShowVoronoi_toggled(bool checked)
{
vgi->setVisible(checked);
}
void
MainWindow::on_actionClear_triggered()
{
dt.clear();
emit(changed());
}
void
MainWindow::on_actionInsertRandomPoints_triggered()
{
typedef CGAL::Creator_uniform_2<double,Point_2> Creator;
CGAL::Random_points_in_disc_2<Point_2,Creator> g( 100.0);
const int number_of_points =
QInputDialog::getInteger(this,
tr("Number of random points"),
tr("Enter number of random points"));
std::vector<Point_2> 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());
}
void
MainWindow::on_actionLoadPoints_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Points file"),
".");
if(! fileName.isEmpty()){
std::ifstream ifs(qPrintable(fileName));
K::Point_2 p;
std::vector<K::Point_2> points;
while(ifs >> p) {
points.push_back(p);
}
dt.insert(points.begin(), points.end());
actionRecenter->trigger();
emit(changed());
}
}
void
MainWindow::on_actionSavePoints_triggered()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Save points"),
".");
if(! fileName.isEmpty()){
std::ofstream ofs(qPrintable(fileName));
for(Delaunay::Finite_vertices_iterator
vit = dt.finite_vertices_begin(),
end = dt.finite_vertices_end();
vit!= end; ++vit)
{
ofs << vit->point() << std::endl;
}
}
}
void
MainWindow::on_actionRecenter_triggered()
{
this->graphicsView->setSceneRect(dgi->boundingRect());
this->graphicsView->fitInView(dgi->boundingRect(), Qt::KeepAspectRatio);
}
#include "Delaunay_triangulation_2.moc"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// Import resources from libCGALQt4.
// See http://doc.trolltech.com/4.4/qdir.html#Q_INIT_RESOURCE
Q_INIT_RESOURCE(File);
Q_INIT_RESOURCE(Triangulation_2);
Q_INIT_RESOURCE(Input);
Q_INIT_RESOURCE(Logos);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}