// file : robustness.C // author(s) : Stefan Schirra, 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::cout << std::endl; return 0; } #else #include "cgal_types.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const QString my_title_string("Robustness Demo with" " CGAL Qt_widget"); //global flags and variables int current_state; std::vector double_segments, double_segments2; std::vector real_segments; std::vector float_segments, float_segments2; std::vector hfloat_segments, hfloat_segments2; std::vector hdouble_segments, hdouble_segments2; std::vector double_intersection_points; std::vector real_intersection_points; std::vector double_convex_hull; std::vector real_convex_hull; class show_intersection_points : public CGAL::Qt_widget_layer{ public: void draw(){ widget->lock(); *widget << CGAL::LineWidth(1) << CGAL::GREEN; std::vector::iterator dit = double_segments.begin(); while(dit!=double_segments.end()){ *widget << (*dit); dit++; } *widget << CGAL::LineWidth(1) << CGAL::BLUE; std::vector::iterator dit2 = double_segments2.begin(); while(dit2!=double_segments2.end()){ *widget << (*dit2); dit2++; } widget->unlock(); } }; class show_hull_of_intersection_points : public CGAL::Qt_widget_layer{ public: void draw(){ widget->lock(); *widget << CGAL::LineWidth(1) << CGAL::GREEN; std::vector::iterator dit = double_segments.begin(); while(dit!=double_segments.end()){ *widget << (*dit); dit++; } std::list Sl; if( double_convex_hull.size() > 1 ) { double_Point pakt,prev,pstart; std::vector::iterator it; it=double_convex_hull.begin(); prev= *it; pstart=prev; it++; for(; it != double_convex_hull.end(); ++it) { pakt = *it; Sl.push_back(double_Segment(prev,pakt)); prev=pakt; } Sl.push_back(double_Segment(pakt,pstart)); *widget << CGAL::BLUE; std::list::iterator its = Sl.begin(); while(its!=Sl.end()) { *widget << (*its++); } } std::vector::iterator dip = double_convex_hull.begin(); *widget << CGAL::PointStyle(CGAL::CROSS) << CGAL::LineWidth(2); *widget << CGAL::WHITE << CGAL::PointSize(8); while(dip!=double_convex_hull.end()){ *widget << (*dip); dip++; } if ( real_convex_hull.size() != double_convex_hull.size() ) { *widget <::iterator dble_it; std::vector::iterator real_it; real_it = real_convex_hull.begin(); for ( dble_it = double_convex_hull.begin(); dble_it != double_convex_hull.end(); ++dble_it ) { if ( (real_it == real_convex_hull.end()) || (( CGAL::squared_distance( *dble_it, double_Point( CGAL::to_double(real_it->x()), CGAL::to_double(real_it->y()) )) ) > 0.125 ) ) { *widget << *dble_it; } else { if ( real_it != real_convex_hull.end() ){ ++real_it; } } } } widget->unlock(); } }; class MyWindow : public QMainWindow { Q_OBJECT public: MyWindow(int w, int h){ widget = new CGAL::Qt_widget(this); setCentralWidget(widget); //create a timer for checking if somthing changed QTimer *timer = new QTimer( this ); connect( timer, SIGNAL(timeout()), this, SLOT(timer_done()) ); 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("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 * draw = new QPopupMenu( this ); menuBar()->insertItem( "&Draw", draw ); draw->insertItem("Convex &Hull of intersection points", this, SLOT(hull_points()), CTRL+Key_H ); draw->insertItem("&Intersection points on segments", this, SLOT(intersection_points()), CTRL+Key_I ); // 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"); *widget << CGAL::LineWidth(2) << CGAL::BackgroundColor (CGAL::BLACK); resize(w,h); widget->set_window(-1, 1, -1, 1); widget->setMouseTracking(TRUE); //application flag stuff old_state = 0; //layers widget->attach(&hull_layer); widget->attach(&int_points_layer); qte = new QTextBrowser(NULL, "INFO"); qte->setCaption("Information Window"); }; private: void something_changed(){current_state++;}; public slots: void new_instance() { widget->lock(); stoolbar->clear_history(); double_segments.clear(); real_segments.clear(); double_convex_hull.clear(); real_convex_hull.clear(); double_intersection_points.clear(); real_intersection_points.clear(); widget->set_window(-1.1, 1.1, -1.1, 1.1); // set the Visible Area to the Interval widget->unlock(); something_changed(); } private slots: 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 about() { QMessageBox::about( this, my_title_string, "This is a demo for Robustness\n" "Copyright CGAL @2003"); }; void aboutQt() { QMessageBox::aboutQt( this, my_title_string ); } void new_window(){ MyWindow *ed = new MyWindow(500, 500); ed->setCaption("Layer"); ed->stoolbar->clear_history(); ed->widget->set_window(-1.1, 1.1, -1.1, 1.1); ed->show(); something_changed(); } void timer_done() { if(old_state!=current_state){ widget->redraw(); old_state = current_state; } } void intersection_points(){ stoolbar->clear_history(); widget->set_window(-1.1, 1.1, -1.1, 1.1); gen_segments(); //computing using Cartesian CartesianFloat::Point_2 p; CartesianFloat::Intersect_2 intersection = CartesianFloat().intersect_2_object(); CGAL::Timer watch; int is_count = 0; int ol_count = 0; int bl_count = 0; watch.start(); for( std::vector::const_iterator i = float_segments.begin(); i != float_segments.end(); ++i) for( std::vector::const_iterator j = float_segments2.begin(); j != float_segments2.end(); ++j) { if ( CGAL::assign(p, intersection(*i,*j)) ) { is_count++; int ok1 = ( i->has_on(p)) ? 1 : 0; int ok2 = ( j->has_on(p)) ? 1 : 0; bl_count += ok1*ok2; ol_count += ok1+ok2; } } watch.stop(); QString s("%1"), s1("%1"); qte->resize(400, 300); qte->show(); qte->setText("INFORMATION Cartesian:"); s.setNum(is_count); qte->append("Intersection points found: " + s); s.setNum(bl_count); s1.setNum((double)bl_count/is_count * 100); qte->append(s + " of them (" + s1 + "%) lie on both segments."); s.setNum(2*is_count); s1.setNum(ol_count); qte->append("Out of the " + s + " point-on-segment tests, "); s.setNum((double)ol_count/is_count * 50); qte->append(s1 + "(" + s + "%) are positive."); s.setNum(watch.time()); qte->append("Computation time = " + s + " sec."); //computing using Cartesian CartesianDouble::Intersect_2 double_intersection = CartesianDouble().intersect_2_object(); double_Point pd; is_count = 0; ol_count = 0; bl_count = 0; watch.reset(); watch.start(); for( std::vector::const_iterator i = double_segments.begin(); i != double_segments.end(); ++i) for( std::vector::const_iterator j = double_segments2.begin(); j != double_segments2.end(); ++j) { if ( CGAL::assign(pd, double_intersection(*i,*j)) ) { is_count++; int ok1 = ( i->has_on(pd)) ? 1 : 0; int ok2 = ( j->has_on(pd)) ? 1 : 0; bl_count += ok1*ok2; ol_count += ok1+ok2; } } watch.stop(); qte->append("_____"); qte->append("INFORMATION Cartesian " + QString::null + "double>:"); s.setNum(is_count); qte->append("Intersection points found: " + s); s.setNum(bl_count); s1.setNum((double)bl_count/is_count * 100); qte->append(s + " of them (" + s1 + "%) lie on both segments."); s.setNum(2*is_count); s1.setNum(ol_count); qte->append("Out of the " + s + " point-on-segment tests, "); s.setNum((double)ol_count/is_count * 50); qte->append(s1 + "(" + s + "%) are positive."); s.setNum(watch.time()); qte->append("Computation time = " + s + " sec."); //computing using Homogeneous HomogeneousFloat::Intersect_2 hfloat_intersection = HomogeneousFloat().intersect_2_object(); HomogeneousFloat::Point_2 phf; is_count = 0; ol_count = 0; bl_count = 0; watch.reset(); watch.start(); for( std::vector::const_iterator i = hfloat_segments.begin(); i != hfloat_segments.end(); ++i) for( std::vector::const_iterator j = hfloat_segments2.begin(); j != hfloat_segments2.end(); ++j) { if ( CGAL::assign(phf, hfloat_intersection(*i,*j)) ) { is_count++; int ok1 = ( i->has_on(phf)) ? 1 : 0; int ok2 = ( j->has_on(phf)) ? 1 : 0; bl_count += ok1*ok2; ol_count += ok1+ok2; } } watch.stop(); qte->append("_____"); qte->append("INFORMATION Homogeneous float>:"); s.setNum(is_count); qte->append("Intersection points found: " + s); s.setNum(bl_count); s1.setNum((double)bl_count/is_count * 100); qte->append(s + " of them (" + s1 + "%) lie on both segments."); s.setNum(2*is_count); s1.setNum(ol_count); qte->append("Out of the " + s + " point-on-segment tests, "); s.setNum((double)ol_count/is_count * 50); qte->append(s1 + "(" + s + "%) are positive."); s.setNum(watch.time()); qte->append("Computation time = " + s + " sec."); hull_layer.deactivate(); int_points_layer.activate(); something_changed(); } void hull_points(){ stoolbar->clear_history(); widget->set_window(-1.1, 1.1, -1.1, 1.1); QString s("%1"); qte->resize(400, 300); qte->show(); qte->setText("INFORMATION:"); qte->append("We compute the intersection points of segments using exact" " and double arithmetic. Then we compute the convex hull of" " those. If there are points that are different in different" " arithmetic, we mark them by a red circle."); QProgressDialog progress( "Generating segments...", "Cancel computing", 60, NULL, "Compute random segments ...", true ); progress.setCaption("Progress bar"); progress.resize(200, 50); progress.setTotalSteps(60); progress.setProgress(10); progress.setMinimumDuration(0); progress.setLabelText("Compute random segments..."); gen_segments(); progress.setLabelText("Compute intersection points..."); progress.setProgress(20); double_convex_hull.clear(); real_convex_hull.clear(); double_intersection_points.clear(); real_intersection_points.clear(); CGAL::segment_intersection_points_2( double_segments.begin(), double_segments.end(), std::back_inserter( double_intersection_points), C_double() ); progress.setLabelText("Compute intersection points exact..."); progress.setProgress(30); CGAL::segment_intersection_points_2( real_segments.begin(), real_segments.end(), std::back_inserter( real_intersection_points), C_real() ); progress.setLabelText("Compute hull of intersection points..."); progress.setProgress(40); CGAL::convex_hull_points_2( double_intersection_points.begin(), double_intersection_points.end(), std::back_inserter( double_convex_hull)); progress.setProgress(50); progress.setLabelText("Compute hull of intersection points exact..."); CGAL::convex_hull_points_2( real_intersection_points.begin(), real_intersection_points.end(), std::back_inserter( real_convex_hull)); progress.setProgress(60); hull_layer.activate(); int_points_layer.deactivate(); something_changed(); } void gen_segments() { Source RS(1); Segment_iterator g( RS, RS); double_segments.clear(); real_segments.clear(); double_segments2.clear(); float_segments.clear(); float_segments2.clear(); hfloat_segments.clear(); hfloat_segments2.clear(); hdouble_segments.clear(); hdouble_segments2.clear(); CGAL::copy_n( g, 100, std::back_inserter( double_segments) ); CGAL::copy_n( g, 100, std::back_inserter( double_segments2) ); CGAL::Cartesian_converter converter; std::transform( double_segments.begin(), double_segments.end(), std::back_inserter( real_segments), converter ); CGAL::Cartesian_converter fconverter; std::transform(double_segments.begin(), double_segments.end(), std::back_inserter(float_segments), fconverter); std::transform(double_segments2.begin(), double_segments2.end(), std::back_inserter(float_segments2), fconverter); CGAL::Cartesian_double_to_Homogeneous< HomogeneousFloat::RT > hfconverter; std::transform(double_segments.begin(), double_segments.end(), std::back_inserter(hfloat_segments), hfconverter); std::transform(double_segments2.begin(), double_segments2.end(), std::back_inserter(hfloat_segments2), hfconverter); CGAL::Cartesian_double_to_Homogeneous hdconverter; std::transform(double_segments.begin(), double_segments.end(), std::back_inserter(hdouble_segments), hdconverter); std::transform(double_segments2.begin(), double_segments2.end(), std::back_inserter(hdouble_segments2), hdconverter); } private: CGAL::Qt_widget *widget; CGAL::Qt_widget_standard_toolbar *stoolbar; int old_state; show_hull_of_intersection_points hull_layer; show_intersection_points int_points_layer; QTextBrowser *qte; }; #include "robustness.moc" int main(int argc, char **argv) { QApplication app( argc, argv ); MyWindow widget(500,500); // physical window size app.setMainWidget(&widget); widget.setCaption(my_title_string); widget.setMouseTracking(TRUE); QPixmap cgal_icon = QPixmap((const char**)demoicon_xpm); widget.setIcon(cgal_icon); widget.show(); current_state = -1; return app.exec(); } #endif // CGAL_USE_QT