// Copyright (c) 1997-2002 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $Source: /CVSROOT/CGAL/Packages/Alpha_shapes_2/demo/Alpha_shapes_2/alpha_shapes_2.C,v $ // $Revision: 1.9.4.1 $ $Date: 2004/12/18 16:54:01 $ // $Name: $ // // Author(s) : Radu Ursu // if QT is not installed, a message will be issued in runtime. #ifndef CGAL_USE_QT #include int main(int, char*) { std::cout << "Sorry, this demo needs QT." << std::endl; return 0; } #else //Application headers #include "cgal_types.h" #include "Qt_widget_toolbar.h" #include "Qt_widget_toolbar_layers.h" //Qt_widget headers #include #include #include #include #include //STL headers #include #include #include #include //Qt headers #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const QString my_title_string(" Alpha_shapes_2 Demo with" " CGAL Qt_widget"); //Global variables Delaunay tr1; CGALPointlist L; std::list LW; Alpha_shape A; Alpha_shape_w AW; int current_state; double alpha_index; //this is the alpha value for //the alpha_shape double mult; //this is used to compute the real value from //the slide QImage image; Coord_type xmin, ymin, xmax, ymax; class Layout_widget : public QWidget{ public: Layout_widget(QWidget *parent, const char *name=0): QWidget(parent, name) { QBoxLayout *topLayout = new QVBoxLayout( this, 5); QBoxLayout *topLayout1 = new QHBoxLayout( topLayout, 5); slider = new QSlider(0, 10000, 1, 10, Qt::Vertical, this, "slider1"); label = new QLabel(this, "label"); label->setText("The current alpha value: 0.001"); //QBoxLayout *bottomLayout = new QVBoxLayout( topLayout ); widget = new CGAL::Qt_widget(this); topLayout1->addWidget(widget); topLayout1->addWidget(slider); topLayout->addWidget(label); //topLayout->addLayout(topLayout1); } ~Layout_widget(){} CGAL::Qt_widget* get_qt_widget(){return widget;} QSlider* get_slider(){return slider;} QLabel* get_label(){return label;} private: CGAL::Qt_widget *widget; QSlider *slider; QLabel *label; }; class MyWindow : public QMainWindow { Q_OBJECT public: MyWindow(int w, int h) { Layout_widget *cwidget = new Layout_widget(this, "Main_layout"); widget = cwidget->get_qt_widget(); slider = cwidget->get_slider(); label = cwidget->get_label(); setCentralWidget(cwidget); //create a timer for checking if somthing changed QTimer *timer = new QTimer( this ); connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) ); timer->start( 200, FALSE ); // file menu QPopupMenu * file = new QPopupMenu( this ); menuBar()->insertItem( "&File", file ); file->insertItem("&New", this, SLOT(new_instance()), CTRL+Key_N); file->insertItem("New &Window", this, SLOT(new_window()), CTRL+Key_W); file->insertSeparator(); file->insertItem("&Load Triangulation", this, SLOT(load_triangulation()), CTRL+Key_L); file->insertItem("&Save Triangulation", this, SLOT(save_triangulation()), CTRL+Key_S); file->insertSeparator(); file->insertItem("&Load Image", this, SLOT(load_image()), CTRL+Key_I); file->insertSeparator(); file->insertItem("Print", widget, SLOT(print_to_ps()), CTRL+Key_P); file->insertSeparator(); file->insertItem( "&Close", this, SLOT(close()), CTRL+Key_X ); file->insertItem( "&Quit", qApp, SLOT( closeAllWindows() ), CTRL+Key_Q ); // drawing menu QPopupMenu * edit = new QPopupMenu( this ); menuBar()->insertItem( "&Edit", edit ); edit->insertItem("&Generate Triangulation", this, SLOT(gen_tr()), CTRL+Key_G ); edit->insertItem("&Change Alpha", this, SLOT(change_alpha()), CTRL+Key_C ); edit->insertItem("C&rust", this, SLOT(show_crust()), CTRL+Key_R ); edit->insertItem("&Weighted Alpha Shape", this, SLOT(show_weighted()), CTRL+Key_B); // help menu QPopupMenu * help = new QPopupMenu( this ); menuBar()->insertItem( "&Help", help ); help->insertItem("How To", this, SLOT(howto()), Key_F1); help->insertSeparator(); help->insertItem("&About", this, SLOT(about()), CTRL+Key_A ); help->insertItem("About &Qt", this, SLOT(aboutQt()) ); //the standard toolbar stoolbar = new CGAL::Qt_widget_standard_toolbar (widget, this, "ST"); //the new input layers toolbar newtoolbar = new Tools_toolbar(widget, this, &tr1, &A); //the new drawing layers toolbar vtoolbar = new Layers_toolbar(widget, this, &tr1, &A, &image); *widget << CGAL::LineWidth(2) << CGAL::BackgroundColor (CGAL::BLACK); resize(w,h); widget->set_window(-1, 1, -1, 1); widget->setMouseTracking(TRUE); //connect the widget to the main function that receives the objects connect(widget, SIGNAL(new_cgal_object(CGAL::Object)), this, SLOT(get_new_object(CGAL::Object))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(slider_changed(int))); //application flag stuff old_state = 0; alpha_index = 0.001; mult = 1; A.set_alpha(alpha_index); }; ~MyWindow() { }; void init_coordinates(){ xmin = -1; xmax = 1; ymin = -1; ymax = 1; } private: void something_changed(){current_state++;}; public slots: void new_instance() { widget->lock(); widget->clear(); tr1.clear(); A.clear();AW.clear(); L.clear();LW.clear(); stoolbar->clear_history(); widget->set_window(-1.1, 1.1, -1.1, 1.1); // set the Visible Area to the Interval widget->unlock(); something_changed(); } void howto(){ QString home; home = "help/index.html"; CGAL::Qt_help_window *help = new CGAL::Qt_help_window(home, ".", 0, "help viewer"); help->resize(400, 400); help->setCaption("Demo HowTo"); help->show(); } void load_image(){ QString s( QFileDialog::getOpenFileName( QString::null, "Image files (*.bmp) (*.jpg)", this ) ); if ( s.isEmpty() ) return; QImage img(s); image = img; something_changed(); } void show_crust(){ Delaunay T(tr1); Face_iterator f; typedef std::set point_set; point_set s; for (f=T.faces_begin(); f!=T.faces_end(); ++f) s.insert( T.dual(f) ); widget->lock(); point_set::iterator p; for (p=s.begin(); p!=s.end(); ++p) T.insert(*p); Edge_iterator e; for (e=T.edges_begin(); e!=T.edges_end(); ++e) { Face_handle f=(*e).first; int i=(*e).second; bool s1=s.find(f->vertex(f->ccw(i))->point())==s.end(); bool s2=s.find(f->vertex(f->cw(i))->point())==s.end(); if (s1&&s2) *widget << CGAL::YELLOW << T.segment(e); } widget->unlock(); } void show_weighted(){ AW.set_alpha(alpha_index); *widget << CGAL::LineWidth(2) << CGAL::GRAY; widget->lock(); *widget << AW; widget->unlock(); } private slots: void get_new_object(CGAL::Object obj) { Point_2 p; Wpoint wp; if(CGAL::assign(p,obj)) { wp = Wpoint(p); tr1.insert(p); LW.push_back(wp); L.push_back(p); A.clear(); A.make_alpha_shape(L.begin(), L.end()); AW.make_alpha_shape(LW.begin(), LW.end()); A.set_alpha(alpha_index); something_changed(); } }; void about() { QMessageBox::about( this, my_title_string, "This is a demo for Alpha Shapes,\n" "Copyright CGAL @2002"); }; void aboutQt() { QMessageBox::aboutQt( this, my_title_string ); } void new_window(){ MyWindow *ed = new MyWindow(500, 500); ed->setCaption("Layer"); if(tr1.number_of_vertices() > 1){ Vertex_iterator it = tr1.vertices_begin(); xmin = xmax = (*it).point().x(); ymin = ymax = (*it).point().y(); while(it != tr1.vertices_end()) { L.push_back((*it).point()); if(xmin > (*it).point().x()) xmin = (*it).point().x(); if(xmax < (*it).point().x()) xmax = (*it).point().x(); if(ymin > (*it).point().y()) ymin = (*it).point().y(); if(ymax < (*it).point().y()) ymax = (*it).point().y(); it++; } } ed->stoolbar->clear_history(); ed->widget->set_window(xmin, xmax, ymin, ymax); ed->show(); something_changed(); } void change_alpha() { bool ok = FALSE; double result = QInputDialog::getDouble( tr( "Please enter a decimal number" ), "alpha > 0:", alpha_index, 0, 2147483647, 4, &ok, this ); if ( ok ){ alpha_index = result; if(mult < result) mult = result; slider->setValue(static_cast(result*10000/mult)); A.set_alpha(alpha_index); label->setText(QString("The current alpha value: ") + QString::number(alpha_index)); widget->redraw(); } } void timerDone() { if(old_state!=current_state){ widget->redraw(); old_state = current_state; } } void gen_tr() { tr1.clear(); L.clear(); LW.clear(); A.clear(); AW.clear(); Wpoint pw; CGAL::Random_points_in_disc_2 g(0.2); for(int count=0; count<200; count++) { tr1.insert(*g); pw = Wpoint(*g); L.push_back(*g++); LW.push_back(pw); } { CGAL::Random_points_on_circle_2 g(0.3); for(int count=0; count<100; count++) { tr1.insert(*g); pw = Wpoint(*g); L.push_back(*g++); LW.push_back(pw); } } { CGAL::Random_points_on_circle_2 g(0.45); for(int count=0; count<60; count++) { tr1.insert(*g); pw = Wpoint(*g); L.push_back(*g++); LW.push_back(pw); } } Vertex_iterator it = tr1.vertices_begin(); xmin = xmax = (*it).point().x(); ymin = ymax = (*it).point().y(); while(it != tr1.vertices_end()) { L.push_back((*it).point()); if(xmin > (*it).point().x()) xmin = (*it).point().x(); if(xmax < (*it).point().x()) xmax = (*it).point().x(); if(ymin > (*it).point().y()) ymin = (*it).point().y(); if(ymax < (*it).point().y()) ymax = (*it).point().y(); it++; } stoolbar->clear_history(); widget->set_window(xmin, xmax, ymin, ymax); A.make_alpha_shape(L.begin(), L.end()); AW.make_alpha_shape(LW.begin(), LW.end()); A.set_alpha(alpha_index); something_changed(); } void save_triangulation() { QString fileName = QFileDialog::getSaveFileName( "triangulation.cgal", "Cgal files (*.cgal)", this ); if ( !fileName.isNull() ) { // got a file name std::ofstream out(fileName); CGAL::set_ascii_mode(out); out << tr1 << std::endl; } } void load_triangulation() { QString s( QFileDialog::getOpenFileName( QString::null, "CGAL files (*.cgal)", this ) ); if ( s.isEmpty() ) return; tr1.clear(); A.clear(); L.clear(); std::ifstream in(s); CGAL::set_ascii_mode(in); in >> tr1; Vertex_iterator it = tr1.vertices_begin(); xmin = xmax = (*it).point().x(); ymin = ymax = (*it).point().y(); while(it != tr1.vertices_end()) { L.push_back((*it).point()); if(xmin > (*it).point().x()) xmin = (*it).point().x(); if(xmax < (*it).point().x()) xmax = (*it).point().x(); if(ymin > (*it).point().y()) ymin = (*it).point().y(); if(ymax < (*it).point().y()) ymax = (*it).point().y(); it++; } stoolbar->clear_history(); widget->set_window(xmin, xmax, ymin, ymax); A.make_alpha_shape(L.begin(), L.end()); A.set_alpha(alpha_index); something_changed(); } void slider_changed(int new_value) { alpha_index = 0.0001 * new_value * mult; label->setText(QString("The current alpha value: ") + QString::number(alpha_index)); A.set_alpha(alpha_index); A.set_mode(Alpha_shape::GENERAL); something_changed(); //widget->redraw(); } private: CGAL::Qt_widget *widget; CGAL::Qt_widget_standard_toolbar *stoolbar; Tools_toolbar *newtoolbar; Layers_toolbar *vtoolbar; int old_state; QSlider *slider; QLabel *label; }; #include "alpha_shapes_2.moc" int main(int argc, char **argv) { QApplication app( argc, argv ); MyWindow win(600, 600); // physical window size app.setMainWidget(&win); win.setCaption(my_title_string); win.setMouseTracking(TRUE); #if !defined(__POWERPC__) QPixmap cgal_icon = QPixmap((const char**)demoicon_xpm); win.setIcon(cgal_icon); #endif win.show(); win.init_coordinates(); current_state = -1; return app.exec(); } #endif // CGAL_USE_QT