From 2a3e9bac34bc4603a74e1decea76393edd99aed2 Mon Sep 17 00:00:00 2001 From: Iordan Iordanov Date: Tue, 22 Mar 2016 10:07:07 +0100 Subject: [PATCH] Modifications to Dehn's algorithm and reorganization of classes hierarchy (inheriting from Misha's classes) --- .../CMakeLists.txt | 8 +- ...perbolic_Delaunay_triangulation_2_demo.cpp | 153 +- ...odic_4_hyperbolic_triangulation_2_demo.cpp | 767 --- .../Delaunay_hyperbolic_triangulation_2.h | 625 --- .../include/CGAL/Hyperbolic_face_info_2.h | 81 - .../include/CGAL/Hyperbolic_octagon_group.h | 443 +- ...ic_4_Delaunay_hyperbolic_triangulation_2.h | 256 - .../Periodic_4_construct_hyperbolic_point_2.h | 6 +- ...perbolic_Delaunay_triangulation_traits_2.h | 249 +- .../Periodic_4_hyperbolic_triangulation_2.h | 4856 ----------------- ...eriodic_4_hyperbolic_triangulation_dummy.h | 243 - ...odic_4_hyperbolic_triangulation_traits_2.h | 123 - .../CGAL/Qt/HyperbolicPainterOstream.h | 8 +- .../Traits_with_hyperbolic_offsets_adaptor.h | 4 +- 14 files changed, 631 insertions(+), 7191 deletions(-) delete mode 100644 Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_triangulation_2_demo.cpp delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Delaunay_hyperbolic_triangulation_2.h delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_face_info_2.h delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_Delaunay_hyperbolic_triangulation_2.h delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_2.h delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_dummy.h delete mode 100644 Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h diff --git a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/CMakeLists.txt b/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/CMakeLists.txt index cb1cb5bc460..668f2c2fc19 100644 --- a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/CMakeLists.txt +++ b/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/CMakeLists.txt @@ -19,7 +19,7 @@ include(${CGAL_USE_FILE}) find_package(Qt5 QUIET COMPONENTS Widgets) -include_directories (BEFORE ../../include include ../../../Hyperbolic_triangulation_2/include) +include_directories (BEFORE ../../../Hyperbolic_triangulation_2/include ../../include include) # ui files, created with Qt Designer qt5_wrap_ui( uis Periodic_4_hyperbolic_triangulation_2.ui ) @@ -30,12 +30,6 @@ qt5_add_resources ( RESOURCE_FILES resources/Periodic_4_hyperbolic_triangulation # cpp files -add_executable ( Periodic_4_hyperbolic_triangulation_2_demo Periodic_4_hyperbolic_triangulation_2_demo.cpp ) -qt5_use_modules( Periodic_4_hyperbolic_triangulation_2_demo Widgets) -add_to_cached_list( CGAL_EXECUTABLE_TARGETS Periodic_4_hyperbolic_triangulation_2_demo ) -target_link_libraries( Periodic_4_hyperbolic_triangulation_2_demo ${CGAL_LIBRARIES} ${QT_LIBRARIES} ${CGAL_QT_LIBRARIES} ) - - add_executable ( Periodic_4_hyperbolic_Delaunay_triangulation_2_demo Periodic_4_hyperbolic_Delaunay_triangulation_2_demo.cpp ) qt5_use_modules( Periodic_4_hyperbolic_Delaunay_triangulation_2_demo Widgets) add_to_cached_list( CGAL_EXECUTABLE_TARGETS Periodic_4_hyperbolic_Delaunay_triangulation_2_demo ) diff --git a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_Delaunay_triangulation_2_demo.cpp b/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_Delaunay_triangulation_2_demo.cpp index 7201514d068..7d489ed731d 100644 --- a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_Delaunay_triangulation_2_demo.cpp +++ b/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_Delaunay_triangulation_2_demo.cpp @@ -4,15 +4,17 @@ #include #include #include -#include - +#include #include - -// to be deleted -#include -// - #include +// unique words +#include +#include +#include +// to be deleted (iiordano: why?) +#include +// for viewportsBbox +#include // Qt headers #include @@ -22,50 +24,42 @@ #include #include +// for filtering +#include #include // GraphicsView items and event filters (input classes) #include "CGAL/Qt/TriangulationCircumcircle.h" - #include "CGAL/Qt/TriangulationMovingPoint.h" #include "CGAL/Qt/TriangulationConflictZone.h" #include "CGAL/Qt/TriangulationRemoveVertex.h" #include "CGAL/Qt/TriangulationPointInputAndConflictZone.h" -//#include #include - -// store color -#include -// visualise color -#include - -// unique words -//#include -#include -#include - -#include - -// dummy points -//#include - -// for filtering -#include - -// for viewportsBbox -#include - -// the two base classes -#include "ui_Delaunay_triangulation_2.h" +#include // Visualise color +#include // Store color #include -#define OPTION_INSERT_DUMMY_POINTS 0 -#define OPTION_INSERT_FIELD_DUMMY_POINTS 0 + +#define OPTION_INSERT_DUMMY_POINTS 0 + + +// dummy points +#if OPTION_INSERT_DUMMY_POINTS == 1 + #include +#endif + +// the two base classes +#include "ui_Periodic_4_hyperbolic_Delaunay_triangulation_2.h" + + typedef CGAL::Exact_predicates_inexact_constructions_kernel InR; typedef CGAL::Exact_predicates_exact_constructions_kernel R; -typedef CGAL::Triangulation_hyperbolic_traits_2 K; + +typedef CGAL::Triangulation_hyperbolic_traits_2 THT2; +typedef CGAL::Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 + K; typedef K::Point_2 Point; // keep color typedef TranslationInfo Vb_info; @@ -73,12 +67,9 @@ typedef CGAL::Triangulation_vertex_base_with_info_2< Vb_info, K > Vb; typedef CGAL::Triangulation_face_base_with_info_2 Fb; -typedef CGAL::Delaunay_hyperbolic_triangulation_2< K, CGAL::Triangulation_data_structure_2 > +typedef CGAL::Periodic_4_hyperbolic_Delaunay_triangulation_2< K, CGAL::Triangulation_data_structure_2 > Delaunay; typedef Delaunay::Vertex_handle Vertex_handle; - - - struct PointsComparator { @@ -103,12 +94,12 @@ double PointsComparator::eps = 0.0001; string glabels[] = { "a", "\\bar{b}", "c", "\\bar{d}", "\\bar{a}", "b", "\\bar{c}", "d" }; -void recurr(vector& v, vector g, int depth = 1) { +void recurr(vector& v, vector g, int depth = 1) { if (depth > 1) { recurr(v, g, depth-1); - vector tmp; + vector tmp; vector tmpw; for (int i = 0; i < v.size(); i++) { tmp.push_back(v[i]); @@ -127,24 +118,24 @@ void recurr(vector& v, vector g, } -void my_unique_words(std::vector& p, Point input, int length) { - std::vector g; +void my_unique_words(std::vector& p, Point input, int depth) { + std::vector g; get_generators(g); - std::vector v; - recurr(v, g, length); - std::set s; + std::vector v; + recurr(v, g, depth); + std::set s; for (int i = 0; i < v.size(); i++) { s.insert( v[i] ); } - cout << "Original point and images: " << endl; - cout << input.x() << ", " << input.y() << endl; - for (set::iterator it = s.begin(); it != s.end(); it++) { - HyperbolicOctagonGroup m = *it; + //cout << "Original point and images: " << endl; + //cout << input.x() << ", " << input.y() << endl; + for (set::iterator it = s.begin(); it != s.end(); it++) { + Octagon_group m = *it; pair res; res = m.apply(to_double(input.x()), to_double(input.y())); - cout << res.first << ", " << res.second << endl; + //cout << res.first << ", " << res.second << endl; p.push_back( Point(res.first, res.second) ); } @@ -157,7 +148,7 @@ void apply_unique_words(std::vector& points, Point input = Point(0, 0), d cout << "apply_unique_words called with threshold = " << threshold << ", word_length = " << word_length << ", d = " << d << endl; - static vector unique_words; + static vector unique_words; static bool generated = false; if(generated == false) { generate_unique_words(unique_words, threshold, word_length); @@ -179,7 +170,7 @@ void apply_unique_words(std::vector& points, Point input = Point(0, 0), d void apply_unique_words_G(std::vector& points, Point input = Point(0, 0), double threshold = 6/*13.5*/, int word_length = 6/*20*/) { - static vector unique_words; + static vector unique_words; static bool generated = false; if(generated == false) { generate_unique_words(unique_words, threshold, word_length); @@ -221,12 +212,13 @@ void apply_unique_words_G(std::vector& points, Point input = Point(0, 0), class MainWindow : public CGAL::Qt::DemosMainWindow, - public Ui::Delaunay_triangulation_2 + public Ui::Periodic_4_hyperbolic_Delaunay_triangulation_2 { Q_OBJECT private: + int recursion_depth; int cidx; std::vector ccol; @@ -266,6 +258,8 @@ public slots: void on_actionInsertRandomPoints_triggered(); + void on_actionModifyDepth_triggered(); + void on_actionLoadPoints_triggered(); void on_actionSavePoints_triggered(); @@ -284,7 +278,7 @@ signals: MainWindow::MainWindow() : DemosMainWindow(), dt(K(1)) { - + recursion_depth = 1; cidx = 0; for (int i = 0; i < 10; i++) ccol.push_back(i); @@ -424,7 +418,6 @@ MainWindow::MainWindow() // // 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"); @@ -448,15 +441,6 @@ MainWindow::MainWindow() #endif - -#if OPTION_INSERT_FIELD_DUMMY_POINTS == 1 - -Point mypt(1. - sqrt(2.), 1. - sqrt(2.)); -processInput(make_object(mypt)); -emit(changed()); - -#endif - } @@ -483,7 +467,7 @@ MainWindow::processInput(CGAL::Object o) //delete vector points; //apply_unique_words(points, p, 4, 1, .998); - my_unique_words(points, p, 1); + my_unique_words(points, p, recursion_depth); points.push_back(p); Vertex_handle v; @@ -626,10 +610,6 @@ MainWindow::on_actionClear_triggered() void MainWindow::on_actionInsertRandomPoints_triggered() { - QRectF rect = CGAL::Qt::viewportsBbox(&scene); - CGAL::Qt::Converter convert; - //Circle_2 isor = convert(rect); - //CGAL::Random_points_in_disc_2 pg(1.0); bool ok = false; const int number_of_points = QInputDialog::getInt(this, @@ -647,8 +627,6 @@ MainWindow::on_actionInsertRandomPoints_triggered() // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); - //std::vector points; - //points.reserve(number_of_points); typedef CGAL::Exact_predicates_inexact_constructions_kernel GT; typedef GT::Point_2 Point_2; @@ -658,16 +636,35 @@ MainWindow::on_actionInsertRandomPoints_triggered() Hyperbolic_random_points_in_disc_2(pts, number_of_points); for(int i = 0; i < number_of_points; ++i){ - processInput(make_object(pts[i])); - //points.push_back(*pg++); + processInput(make_object(pts[i])); } - //dt.insert(points.begin(), points.end()); - // default cursor QApplication::restoreOverrideCursor(); emit(changed()); } +void +MainWindow::on_actionModifyDepth_triggered() +{ + bool ok = false; + const int result = + QInputDialog::getInt(this, + tr("Modify recursion depth"), + tr("Enter new recursion depth"), + recursion_depth, + 0, + 10, + 1, + &ok); + + if(!ok) { + return; + } + + recursion_depth = result; +} + + void MainWindow::on_actionLoadPoints_triggered() { @@ -757,7 +754,7 @@ int main(int argc, char **argv) app.setOrganizationDomain("geometryfactory.com"); app.setOrganizationName("GeometryFactory"); - app.setApplicationName("Delaunay_triangulation_2 demo"); + app.setApplicationName("Periodic_4_hyperbolic_Delaunay_triangulation_2 demo"); // Import resources from libCGALQt4. // See http://doc.trolltech.com/4.4/qdir.html#Q_INIT_RESOURCE diff --git a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_triangulation_2_demo.cpp b/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_triangulation_2_demo.cpp deleted file mode 100644 index 5170b58c3a5..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/demo/Periodic_4_hyperbolic_triangulation_2/Periodic_4_hyperbolic_triangulation_2_demo.cpp +++ /dev/null @@ -1,767 +0,0 @@ -#include - -// CGAL headers -#include -#include -#include -#include - -#include - -// to be deleted -#include -// - -#include - -// Qt headers -#include -#include -#include -#include -#include -#include - -#include - -// GraphicsView items and event filters (input classes) -#include "CGAL/Qt/TriangulationCircumcircle.h" - -#include "CGAL/Qt/TriangulationMovingPoint.h" -#include "CGAL/Qt/TriangulationConflictZone.h" -#include "CGAL/Qt/TriangulationRemoveVertex.h" -#include "CGAL/Qt/TriangulationPointInputAndConflictZone.h" -//#include -#include - -// store color -#include -// visualise color -#include - -// unique words -//#include -#include -#include - -#include - -// dummy points -//#include - -// for filtering -#include - -// for viewportsBbox -#include - -// the two base classes -#include "ui_Delaunay_triangulation_2.h" -#include - -#define OPTION_INSERT_DUMMY_POINTS 0 - - -typedef CGAL::Exact_predicates_inexact_constructions_kernel InR; -typedef CGAL::Exact_predicates_exact_constructions_kernel R; -typedef CGAL::Triangulation_hyperbolic_traits_2 K; -typedef K::Point_2 Point; -// keep color -typedef TranslationInfo Vb_info; -typedef CGAL::Triangulation_vertex_base_with_info_2< Vb_info, K > - Vb; -typedef CGAL::Triangulation_face_base_with_info_2 - Fb; -typedef CGAL::Delaunay_hyperbolic_triangulation_2< K, CGAL::Triangulation_data_structure_2 > - Delaunay; -typedef Delaunay::Vertex_handle Vertex_handle; - - - - -struct PointsComparator { - static double eps; - - bool operator() (const Point& l, const Point& r) const - { - if(l.x() < r.x() - eps) { - return true; - } - if(l.x() < r.x() + eps) { - if(l.y() < r.y() - eps) { - return true; - } - } - return false; - } -}; - -double PointsComparator::eps = 0.0001; - -string glabels[] = { "a", "\\bar{b}", "c", "\\bar{d}", "\\bar{a}", "b", "\\bar{c}", "d" }; - - -void recurr(vector& v, vector g, int depth = 1) { - if (depth > 1) { - - recurr(v, g, depth-1); - - vector tmp; - vector tmpw; - for (int i = 0; i < v.size(); i++) { - tmp.push_back(v[i]); - } - - for (int i = 0; i < tmp.size(); i++) { - for (int j = 0; j < g.size(); j++) { - v.push_back(tmp[i]*g[j]); - } - } - } else { - for (int i = 0; i < g.size(); i++) { - v.push_back(g[i]); - } - } -} - - -void my_unique_words(std::vector& p, Point input, int length) { - std::vector g; - get_generators(g); - std::vector v; - recurr(v, g, length); - std::set s; - - for (int i = 0; i < v.size(); i++) { - s.insert( v[i] ); - } - - cout << "Original point and images: " << endl; - cout << input.x() << ", " << input.y() << endl; - for (set::iterator it = s.begin(); it != s.end(); it++) { - HyperbolicOctagonGroup m = *it; - pair res; - res = m.apply(to_double(input.x()), to_double(input.y())); - cout << res.first << ", " << res.second << endl; - p.push_back( Point(res.first, res.second) ); - } - -} - - - -void apply_unique_words(std::vector& points, Point input = Point(0, 0), double threshold = 10, int word_length = 6, double d = .998) -{ - - cout << "apply_unique_words called with threshold = " << threshold << ", word_length = " << word_length << ", d = " << d << endl; - - static vector unique_words; - static bool generated = false; - if(generated == false) { - generate_unique_words(unique_words, threshold, word_length); - generated = true; - } - - //points.resize(unique_words.size()); - pair res; - for(size_t i = 0; i < unique_words.size(); i++) { - pair res; - res = unique_words[i].apply(to_double(input.x()), to_double(input.y())); - - double dist = res.first*res.first + res.second*res.second; - if(dist < d) { - points.push_back( Point(res.first, res.second) ); - } - } -} - -void apply_unique_words_G(std::vector& points, Point input = Point(0, 0), double threshold = 6/*13.5*/, int word_length = 6/*20*/) -{ - static vector unique_words; - static bool generated = false; - if(generated == false) { - generate_unique_words(unique_words, threshold, word_length); - generated = true; - - // to generate all words - /* - ofstream fwords("m_w"); - fwords << "local words;\nPrint(\"words!\\n\");\nwords := [\n"; - for(size_t i = 0; i < unique_words.size() - 1; i++) { - fwords << unique_words[i].label << "," < indices; - while(findices >> index) { - indices.push_back(index); - } - cout << "indices size " << indices.size() << endl; - - pair res; - for(size_t i = 0; i < indices.size(); i++) { - pair res; - if(indices[i] < unique_words.size() /*&& unique_words[indices[i]].length() < 13.*/) { - res = unique_words[indices[i]].apply(to_double(input.x()), to_double(input.y())); - points.push_back(Point(res.first, res.second)); - } - } - cout << "nb of points to insert " << points.size() << endl; -} - - -class MainWindow : - public CGAL::Qt::DemosMainWindow, - public Ui::Delaunay_triangulation_2 -{ - Q_OBJECT - -private: - - int cidx; - std::vector ccol; - - Delaunay dt; - QGraphicsEllipseItem * disk; - QGraphicsScene scene; - - CGAL::Qt::TriangulationGraphicsItem * dgi; - CGAL::Qt::VoronoiGraphicsItem * vgi; - - // for drawing Voronoi diagram of the orbit of the origin - CGAL::Qt::VoronoiGraphicsItem * origin_vgi; - - CGAL::Qt::TriangulationMovingPoint * mp; - CGAL::Qt::TriangulationConflictZone * cz; - CGAL::Qt::TriangulationRemoveVertex * trv; - CGAL::Qt::TriangulationPointInputAndConflictZone * pi; - CGAL::Qt::TriangulationCircumcircle * tcc; -public: - MainWindow(); - -public slots: - - void processInput(CGAL::Object o); - - void on_actionMovingPoint_toggled(bool checked); - - void on_actionShowConflictZone_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(); - - virtual void open(QString fileName); - -signals: - void changed(); -}; - - -MainWindow::MainWindow() - : DemosMainWindow(), dt(K(1)) -{ - - cidx = 0; - for (int i = 0; i < 10; i++) - ccol.push_back(i); - - setupUi(this); - - this->graphicsView->setAcceptDrops(false); - - // Add PoincarĂ© disk - qreal origin_x = 0, origin_y = 0, radius = 1, diameter = 2*radius; - qreal left_top_corner_x = origin_x - radius; - qreal left_top_corner_y = origin_y - radius; - qreal width = diameter, height = diameter; - - // set background - qreal eps = 0.01; - QGraphicsRectItem* rect = new QGraphicsRectItem(left_top_corner_x - eps, left_top_corner_y - eps, width + 2*eps, height + 2*eps); - rect->setPen(Qt::NoPen); - rect->setBrush(Qt::white); - scene.addItem(rect); - - // set disk - disk = new QGraphicsEllipseItem(left_top_corner_x, left_top_corner_y, width, height); - QPen pen; // creates a default pen - pen.setWidth(0); - //pen.setBrush(Qt::black); - pen.setBrush(QColor(200, 200, 0)); - disk->setPen(pen); - - scene.addItem(disk); - - // another input point, instead of the origin - - double phi = CGAL_PI / 8.; - double psi = CGAL_PI / 3.; - double rho = std::sqrt(cos(psi)*cos(psi) - sin(phi)*sin(phi)); - - Point origin = Point(0, 0); - const Point a(cos(phi)*cos(phi + psi)/rho, sin(phi)*cos(phi + psi)/rho); - - - // dt to form the octagon tessellation - vector origin_orbit; - apply_unique_words(origin_orbit, origin, 10, 6); - origin_orbit.push_back(Point(0, 0)); - // for(long i = 0; i < origin_orbit.size(); i++) { - // cout << origin_orbit[i] << endl; - // } - cout << "nb of points on the orbit of the origin: " << origin_orbit.size() << endl; - - Delaunay* dtO = new Delaunay(K(1)); - dtO->insert(origin_orbit.begin(), origin_orbit.end()); - - origin_vgi = new CGAL::Qt::VoronoiGraphicsItem(dtO); - origin_vgi->setVisible(true); - - QObject::connect(this, SIGNAL(changed()), - origin_vgi, SLOT(modelChanged())); - - QColor br(149, 179, 179); - origin_vgi->setEdgesPen(QPen(br, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - scene.addItem(origin_vgi); - - - // Add a GraphicItem for the Delaunay triangulation - dgi = new CGAL::Qt::TriangulationGraphicsItem(&dt); - - QObject::connect(this, SIGNAL(changed()), - dgi, SLOT(modelChanged())); - - dgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - dgi->setEdgesPen(QPen(QColor(200, 200, 0), 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - scene.addItem(dgi); - - // Add a GraphicItem for the Voronoi diagram - vgi = new CGAL::Qt::VoronoiGraphicsItem(&dt); - - QObject::connect(this, SIGNAL(changed()), - vgi, SLOT(modelChanged())); - - QColor brown(139, 69, 19); - vgi->setEdgesPen(QPen(brown, 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::TriangulationPointInputAndConflictZone(&scene, &dt, this ); - - QObject::connect(pi, SIGNAL(generate(CGAL::Object)), - this, SLOT(processInput(CGAL::Object))); - - mp = new CGAL::Qt::TriangulationMovingPoint(&dt, this); - // TriangulationMovingPoint emits a modelChanged() signal each - // time the moving point moves. - // The following connection is for the purpose of emitting changed(). - QObject::connect(mp, SIGNAL(modelChanged()), - this, SIGNAL(changed())); - - trv = new CGAL::Qt::TriangulationRemoveVertex(&dt, this); - QObject::connect(trv, SIGNAL(modelChanged()), - this, SIGNAL(changed())); - - tcc = new CGAL::Qt::TriangulationCircumcircle(&scene, &dt, this); - tcc->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - - cz = new CGAL::Qt::TriangulationConflictZone(&scene, &dt, this); - - // - // Manual handling of actions - // - - QObject::connect(this->actionQuit, 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); - ag->addAction(this->actionCircumcenter); - ag->addAction(this->actionShowConflictZone); - - // Check two actions - this->actionInsertPoint->setChecked(true); - this->actionShowDelaunay->setChecked(true); - - // // - // // Setup the scene and the view - // // - scene.setItemIndexMethod(QGraphicsScene::NoIndex); - scene.setSceneRect(left_top_corner_x, left_top_corner_y, width, height); - this->graphicsView->setScene(&scene); - this->graphicsView->setMouseTracking(true); - this->graphicsView->shear(230, 230); - - // // 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(); - - this->addRecentFiles(this->menuFile, this->actionQuit); - connect(this, SIGNAL(openRecentFile(QString)), - this, SLOT(open(QString))); - - -#if OPTION_INSERT_DUMMY_POINTS == 1 - - std::vector pts; - cout << "Inserting dummy points now! " << endl; - dt.insert_dummy_points(pts); - for (int i = 0; i < pts.size(); i++) { - processInput(make_object(pts[i])); - } - cout << "Dummy points inserted! " << endl; - emit(changed()); - -#endif - -} - - -void -MainWindow::processInput(CGAL::Object o) -{ - - typedef CGAL::Exact_predicates_inexact_constructions_kernel GT; - typedef GT::Point_2 Point_2; - Point_2 pp; - if (CGAL::assign(pp, o)) { - Point tmp(pp.x(), pp.y()); - o = make_object(tmp); - } - - Point p; - if(CGAL::assign(p, o)){ - QPointF qp(CGAL::to_double(p.x()), CGAL::to_double(p.y())); - - // note that if the point is on the boundary then the disk contains the point - if(disk->contains(qp)){ - //dt.insert(p); - - //delete - vector points; - //apply_unique_words(points, p, 4, 1, .998); - my_unique_words(points, p, 1); - - points.push_back(p); - Vertex_handle v; - for(size_t j = 0; j < points.size() ; j++) { - v = dt.insert(points[j]); - v->info().setColor(ccol[cidx]); - } - cidx = (cidx + 1) % ccol.size(); - // - } - // delete - else { - static double phi = CGAL_PI / 8.; - static double psi = CGAL_PI / 3.; - static double rho = std::sqrt(cos(psi)*cos(psi) - sin(phi)*sin(phi)); - - static Point origin = Point(0, 0); - static Point a(cos(phi)*cos(phi + psi)/rho, sin(phi)*cos(phi + psi)/rho); - static Point b((cos(psi)-sin(phi))/rho, 0.); - - static Point current_point_a = origin; - static Point current_point_b = origin; - static double dT = 0.05; - - static double dx_a = dT * CGAL::to_double(a.x()); - static double dy_a = dT * CGAL::to_double(a.y()); - current_point_a = Point(current_point_a.x() + dx_a, current_point_a.y() + dy_a); - if(current_point_a.x() > a.x()) { - current_point_a = origin; - } - - static double dx_b = dT * CGAL::to_double(b.x()); - static double dy_b = dT * CGAL::to_double(b.y()); - current_point_b = Point(current_point_b.x() + dx_b, current_point_b.y() + dy_b); - std::cout << current_point_b.x() << " : " << current_point_b.y() << std::endl; - if(current_point_b.x() > b.x()) { - current_point_b = origin; - } - - vector points; - - // current_point_b <-> current_point_b - Point current_point = current_point_a; - apply_unique_words(points, current_point); - points.push_back(current_point); - dt.clear(); - dt.insert(points.begin(), points.end()); - - } - - } - emit(changed()); - - cout << "v = " << dt.number_of_vertices() << ", f = " << dt.number_of_faces() << endl; - -} - - - - - -/* - * 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__" - */ -void -MainWindow::on_actionInsertPoint_toggled(bool checked) -{ - if(checked){ - scene.installEventFilter(pi); - scene.installEventFilter(trv); - } else { - scene.removeEventFilter(pi); - scene.removeEventFilter(trv); - } -} - - -void -MainWindow::on_actionMovingPoint_toggled(bool checked) -{ - - if(checked){ - scene.installEventFilter(mp); - } else { - scene.removeEventFilter(mp); - } -} - - -void -MainWindow::on_actionShowConflictZone_toggled(bool checked) -{ - - if(checked){ - scene.installEventFilter(cz); - } else { - scene.removeEventFilter(cz); - } -} - -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->setVisibleEdges(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() -{ - QRectF rect = CGAL::Qt::viewportsBbox(&scene); - CGAL::Qt::Converter convert; - //Circle_2 isor = convert(rect); - //CGAL::Random_points_in_disc_2 pg(1.0); - bool ok = false; - const int number_of_points = - QInputDialog::getInt(this, - tr("Number of random points"), - tr("Enter number of random points"), - 100, - 0, - std::numeric_limits::max(), - 1, - &ok); - - if(!ok) { - return; - } - - // wait cursor - QApplication::setOverrideCursor(Qt::WaitCursor); - //std::vector points; - //points.reserve(number_of_points); - - typedef CGAL::Exact_predicates_inexact_constructions_kernel GT; - typedef GT::Point_2 Point_2; - typedef GT::FT FT; - - vector pts; - Hyperbolic_random_points_in_disc_2(pts, number_of_points); - - for(int i = 0; i < number_of_points; ++i){ - processInput(make_object(pts[i])); - //points.push_back(*pg++); - } - //dt.insert(points.begin(), points.end()); - // default cursor - QApplication::restoreOverrideCursor(); - emit(changed()); -} - - -void -MainWindow::on_actionLoadPoints_triggered() -{ - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open Points file"), - "."); - if(! fileName.isEmpty()){ - open(fileName); - } -} - - -void -MainWindow::open(QString fileName) -{ - // wait cursor - QApplication::setOverrideCursor(Qt::WaitCursor); - std::ifstream ifs(qPrintable(fileName)); - - K::Point p; - std::vector points; - while(ifs >> p) { - points.push_back(p); - } - dt.insert(points.begin(), points.end()); - - // default cursor - QApplication::restoreOverrideCursor(); - this->addToRecentFiles(fileName); - actionRecenter->trigger(); - emit(changed()); - -} - -void -MainWindow::on_actionSavePoints_triggered() -{ -/* // dump points - 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; - } - } -*/ - - // take a snapshot - std::cout << "snapshot..."; - - const QRect viewerRect = graphicsView->mapFromScene(scene.sceneRect()).boundingRect(); - const QRect imageRect = QRect(QPoint(0, 0), viewerRect.size()); - - QImage snapshot(imageRect.size(), QImage::Format_ARGB32);//QImage::Format_ARGB32_Premultiplied - - QPainter painter(&snapshot); - painter.setRenderHint(QPainter::Antialiasing); - //painter.setRenderHint(QPainter::SmoothPixmapTransform); - - graphicsView->render(&painter, imageRect, viewerRect); - bool saved = snapshot.save("mysnap.png", "PNG", 100); - assert(saved == true); - - std::cout << "done" << std::endl; -} - - -void -MainWindow::on_actionRecenter_triggered() -{ - this->graphicsView->setSceneRect(dgi->boundingRect()); - this->graphicsView->fitInView(dgi->boundingRect(), Qt::KeepAspectRatio); -} - - -#include "Periodic_4_hyperbolic_triangulation_2_demo.moc" - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - app.setOrganizationDomain("geometryfactory.com"); - app.setOrganizationName("GeometryFactory"); - app.setApplicationName("Delaunay_triangulation_2 demo"); - - // 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(CGAL); - - MainWindow mainWindow; - mainWindow.show(); - - QStringList args = app.arguments(); - args.removeAt(0); - Q_FOREACH(QString filename, args) { - mainWindow.open(filename); - } - - return app.exec(); -} diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Delaunay_hyperbolic_triangulation_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Delaunay_hyperbolic_triangulation_2.h deleted file mode 100644 index 1e6b53060e2..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Delaunay_hyperbolic_triangulation_2.h +++ /dev/null @@ -1,625 +0,0 @@ -// Copyright (c) 2010 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. -// -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/candidate-packages/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h $ -// $Id: Delaunay_triangulation_2.h 57509 2010-07-15 09:14:09Z sloriot $ -// -// -// Author(s) : Mikhail Bogdanov - -#ifndef CGAL_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H -#define CGAL_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H - -#include -#include - -#include -#include - -namespace CGAL { - -class Hyperbolic_face_info_2 -{ -public: - Hyperbolic_face_info_2() : _is_finite_invisible(false), _invisible_edge(UCHAR_MAX) - { - } - - bool is_finite_invisible() const - { - return _is_finite_invisible; - } - - void set_finite_invisible(bool is_finite_invisible) - { - _is_finite_invisible = is_finite_invisible; - } - - // Supposed to be called before "get_invisible_edge" - bool has_invisible_edge() const - { - return _invisible_edge <= 2; - } - - // Higly recommended to call "has_invisible_edge" before - unsigned char get_invisible_edge() const - { - assert(_is_finite_invisible); - assert(_invisible_edge <= 2); - - return _invisible_edge; - } - - void set_invisible_edge(unsigned char invisible_edge) - { - assert(_is_finite_invisible); - assert(invisible_edge <= 2); - - _invisible_edge = invisible_edge; - } - -private: - // a face is invisible if its circumscribing circle intersects the circle at infinity - bool _is_finite_invisible; - - // defined only if the face is finite and invisible - unsigned char _invisible_edge; -}; - -template < class Gt, - class Tds = Triangulation_data_structure_2 < - Triangulation_vertex_base_2, - Triangulation_face_base_with_info_2 > > -class Delaunay_hyperbolic_triangulation_2 : public Delaunay_triangulation_2 -{ -public: - typedef Delaunay_hyperbolic_triangulation_2 Self; - typedef Delaunay_triangulation_2 Base; - - typedef Triangulation_face_base_with_info_2 Face_base; - typedef typename Face_base::Info Face_info; - - typedef typename Base::size_type size_type; - - typedef typename Base::Vertex_handle Vertex_handle; - typedef typename Base::Face_handle Face_handle; - typedef typename Base::Edge Edge; - -#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 - using Base::cw; - using Base::ccw; - using Base::geom_traits; -#endif - - typedef typename Base::Edge_circulator Edge_circulator; - typedef typename Base::Face_circulator Face_circulator; - typedef typename Base::Vertex_circulator Vertex_circulator; - - typedef typename Base::All_vertices_iterator All_vertices_iterator; - typedef typename Base::All_edges_iterator All_edges_iterator; - typedef typename Base::All_faces_iterator All_faces_iterator; - - typedef Gt Geom_traits; - typedef typename Geom_traits::FT FT; - typedef typename Geom_traits::Point_2 Point; - typedef typename Geom_traits::Segment_2 Segment; - - /* -#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 - using Triangulation::side_of_oriented_circle; - using Triangulation::circumcenter; - using Triangulation::collinear_between; - using Triangulation::test_dim_down; - using Triangulation::make_hole; - using Triangulation::fill_hole_delaunay; - using Triangulation::delete_vertex; -#endif -*/ - - Delaunay_hyperbolic_triangulation_2(const Gt& gt = Gt()) - : Delaunay_triangulation_2(gt) {} - - Delaunay_hyperbolic_triangulation_2( - const Delaunay_hyperbolic_triangulation_2 &tr) - : Delaunay_triangulation_2(tr) - { CGAL_triangulation_postcondition( this->is_valid() );} - - void mark_star(Vertex_handle v) const - { - if(!is_star_bounded(v)) { - mark_star_faces(v); - } - } - - Vertex_handle insert(const Point &p, - Face_handle start = Face_handle() ) - { - Vertex_handle v = Base::insert(p, start); - mark_star(v); - - return v; - } - - Vertex_handle insert(const Point& p, - typename Base::Locate_type lt, - Face_handle loc, int li ) - { - Vertex_handle v = Base::insert(p, lt, loc, li); - mark_star(v); - - return v; - } - -#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO - template < class InputIterator > - std::ptrdiff_t - insert( InputIterator first, InputIterator last, - typename boost::enable_if< - boost::is_base_of< - Point, - typename std::iterator_traits::value_type - > - >::type* = NULL - ) -#else - template < class InputIterator > - std::ptrdiff_t - insert(InputIterator first, InputIterator last) -#endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO - { - size_type n = Base::insert(first, last); - - mark_faces(); - - return n; - } - - //test version of insert function - -#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO - template < class InputIterator > - std::ptrdiff_t - insert2( InputIterator first, InputIterator last, - typename boost::enable_if< - boost::is_base_of< - Point, - typename std::iterator_traits::value_type - > - >::type* = NULL - ) -#else - template < class InputIterator > - std::ptrdiff_t - insert_2(InputIterator first, InputIterator last) -#endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO - { - size_type n = this->number_of_vertices(); - - spatial_sort(first, last, geom_traits()); - Face_handle f; - while(first != last) { - f = insert (*first++, f)->face(); - } - - return this->number_of_vertices() - n; - } - - bool is_infinite(Vertex_handle v) const - { - return Base::is_infinite(v); - } - - bool is_infinite(Face_handle f) const - { - return has_infinite_vertex(f) || is_finite_invisible(f); - } - - bool is_infinite(Face_handle f, int i) const - { - return has_infinite_vertex(f, i) || is_finite_invisible(f, i); - } - - bool is_infinite(const Edge& e) const - { - return is_infinite(e.first, e.second); - } - - bool is_infinite(const Edge_circulator& ec) const - { - return is_infinite(*ec); - } - - bool is_infinite(const All_edges_iterator& ei) const - { - return is_infinite(*ei); - } - -private: - - bool has_infinite_vertex(Face_handle f) const - { - return Base::is_infinite(f); - } - - bool has_infinite_vertex(Face_handle f, int i) const - { - return Base::is_infinite(f, i); - } - - bool has_infinite_vertex(const Edge& e) const - { - return Base::is_infinite(e); - } - - int get_finite_invisible_edge(Face_handle f) const - { - assert(is_finite_invisible(f)); - - return f->info().get_invisible_edge(); - } - - bool is_finite_invisible(Face_handle f) const - { - return f->info().is_finite_invisible(); - } - - bool is_finite_invisible(Face_handle f, int i) const - { - if(this->dimension() <= 1) { - return false; - } - - if(is_finite_invisible(f) && get_finite_invisible_edge(f) == i) { - return true; - } - - // another incident face and corresponding index - Face_handle f2 = f->neighbor(i); - int i2 = f2->index(f); - - if(is_finite_invisible(f2) && get_finite_invisible_edge(f2) == i2) { - return true; - } - - return false; - } - - bool is_finite_invisible(const Edge& e) const - { - return is_finite_invisible(e.first, e.second); - } - - // Depth-first search (dfs) and marking the finite invisible faces. - void mark_faces() const - { - if(this->dimension() <= 1) return; - - std::set visited_faces; - - // maintain a stack to be able to backtrack - // to the most recent faces which neighbors are not visited - std::stack backtrack; - - // start from a face with infinite vertex - Face_handle current = Base::infinite_face(); - - // mark it as visited - visited_faces.insert(current); - - // put the element whose neighbors we are going to explore. - backtrack.push(current); - - // test whether a face is finite invisible or not - Mark_face test(*this); - - Face_handle next; - Face_info face_info; - - while(!backtrack.empty()) { - // take a face - current = backtrack.top(); - - // start visiting the neighbors - int i = 0; - for(; i < 3; i++) { - next = current->neighbor(i); - - // if a neighbor is already visited, then stop going deeper - if(visited_faces.find(next) != visited_faces.end()) { - continue; - } - - visited_faces.insert(next); - mark_face(next, test); - - // go deeper if the neighbor is infinite - if(is_infinite(next)) { - backtrack.push(next); - break; - } - } - - // if all the neighbors are already visited, then remove "current" face. - if(i == 3) { - backtrack.pop(); - } - } - - } - - // check if a star is bounded by finite faces - // TODO: rename this function name - bool is_star_bounded(Vertex_handle v) const - { - if(this->dimension() <= 1) { - return true; - } - - Face_handle f = v->face(); - Face_handle next; - int i; - Face_handle start(f); - - Face_handle opposite_face; - - do { - i = f->index(v); - next = f->neighbor(ccw(i)); // turn ccw around v - - opposite_face = f->neighbor(i); - if(this->is_infinite(opposite_face)) { - return false; - } - - f = next; - } while(next != start); - - return true; - } - - //use the function: insert_and_give_new_faces? - - void mark_star_faces(Vertex_handle v) const - { - // TODO: think of it - if(this->dimension() <= 1) return; - - Mark_face test(*this); - - Face_handle f = v->face(); - Face_handle start(f), next; - int i; - do { - i = f->index(v); - next = f->neighbor(ccw(i)); // turn ccw around v - - mark_face(f, test); - - f = next; - } while(next != start); - return; - } - - template - void mark_face(const Face_handle& f, const Mark_face_test& test) const - { - f->info() = test(f); - } - - void mark_face(const Face_handle& f) const - { - Mark_face test(*this); - mark_face(f, test); - } - - class Mark_face - { - public: - Mark_face(const Self& tr) : - _tr(tr) - {} - - Face_info operator ()(const Face_handle& f) const - { - typedef typename Gt::Is_hyperbolic Is_hyperbolic; - - Face_info info; - if(_tr.has_infinite_vertex(f)) { - return info; - } - - Point p0 = f->vertex(0)->point(); - Point p1 = f->vertex(1)->point(); - Point p2 = f->vertex(2)->point(); - int ind = 0; - - Is_hyperbolic is_hyperbolic = _tr.geom_traits().Is_hyperbolic_object(); - if(is_hyperbolic(p0, p1, p2, ind) == false) { - - info.set_finite_invisible(true); - info.set_invisible_edge(ind); - - return info; - } - - return info; - } - - private: - - Mark_face(const Mark_face&); - Mark_face& operator= (const Mark_face&); - - const Self& _tr; - }; - -public: - // This class is used to generate the Finite_*_iterators. - class Infinite_hyperbolic_tester - { - const Self *t; - public: - Infinite_hyperbolic_tester() {} - Infinite_hyperbolic_tester(const Self *tr) : t(tr) {} - - bool operator()(const All_vertices_iterator & vit) const { - return t->is_infinite(vit); - } - bool operator()(const All_faces_iterator & fit) const { - return t->is_infinite(fit); - } - bool operator()(const All_edges_iterator & eit ) const { - return t->is_infinite(eit); - } - }; - - Infinite_hyperbolic_tester - infinite_hyperbolic_tester() const - { - return Infinite_hyperbolic_tester(this); - } - - //Finite faces iterator - - class Finite_faces_iterator - : public Filter_iterator - { - typedef Filter_iterator Base; - typedef Finite_faces_iterator Self; - public: - Finite_faces_iterator() : Base() {} - Finite_faces_iterator(const Base &b) : Base(b) {} - Self & operator++() { Base::operator++(); return *this; } - Self & operator--() { Base::operator--(); return *this; } - Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } - Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator const Face_handle() const { return Base::base(); } - }; - - Finite_faces_iterator - finite_faces_begin() const - { - if ( this->dimension() < 2 ) - return finite_faces_end(); - return CGAL::filter_iterator(this->all_faces_end(), - Infinite_hyperbolic_tester(this), - this->all_faces_begin() ); - } - - Finite_faces_iterator - finite_faces_end() const - { - return CGAL::filter_iterator(this->all_faces_end(), - Infinite_hyperbolic_tester(this) ); - } - - //Finite edges iterator - - typedef Filter_iterator - Finite_edges_iterator; - - Finite_edges_iterator - finite_edges_begin() const - { - if ( this->dimension() < 1 ) - return finite_edges_end(); - return CGAL::filter_iterator(this->all_edges_end(), - infinite_hyperbolic_tester(), - this->all_edges_begin()); - } - - Finite_edges_iterator - finite_edges_end() const - { - return CGAL::filter_iterator(this->all_edges_end(), - infinite_hyperbolic_tester() ); - } - - using Base::dual; - - Object - dual(const Finite_edges_iterator& ei) const - { - return this->dual(*ei); - } - - Object - dual(const Edge &e) const - { - CGAL_triangulation_precondition (!this->is_infinite(e)); - - if(this->dimension() == 1) { - const Point& p = (e.first)->vertex(cw(e.second))->point(); - const Point& q = (e.first)->vertex(ccw(e.second))->point(); - - // hyperbolic line - Segment line = this->geom_traits().construct_hyperbolic_bisector_2_object()(p,q); - return make_object(line); - } - - // incident faces - Face_handle f1 = e.first; - int i1 = e.second; - - Face_handle f2 = f1->neighbor(i1); - int i2 = f2->index(f1); - - // boths faces are infinite, but the incident edge is finite - if(is_infinite(f1) && is_infinite(f2)){ - const Point& p = (f1)->vertex(cw(i1))->point(); - const Point& q = (f1)->vertex(ccw(i1))->point(); - - // hyperbolic line - Segment line = this->geom_traits().construct_hyperbolic_bisector_2_object()(p,q); - return make_object(line); - } - - // both faces are finite - if(!is_infinite(f1) && !is_infinite(f2)) { - - Segment s = this->geom_traits().construct_segment_2_object() - (dual(f1),dual(f2)); - - return make_object(s); - } - - // one of the incident faces is infinite - Face_handle finite_face = f1; - int i = i1; - - if(is_infinite(f1)) { - finite_face = f2; - i = i2; - } - - const Point& p = finite_face->vertex(cw(i))->point(); - const Point& q = finite_face->vertex(ccw(i))->point(); - - // ToDo: Line or Segment? - // hyperbolic line and ray - Segment line = this->geom_traits().construct_hyperbolic_bisector_2_object()(p,q); - Segment ray = this->geom_traits().construct_ray_2_object()(dual(finite_face), line); - return make_object(ray); - } - -public: - void insert_dummy_points(std::vector& ); - -}; - -} //namespace CGAL - -#include - -#endif // CGAL_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_face_info_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_face_info_2.h deleted file mode 100644 index d5d51dca212..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_face_info_2.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2010 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. -// -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/candidate-packages/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h $ -// $Id: Delaunay_triangulation_2.h 57509 2010-07-15 09:14:09Z sloriot $ -// -// -// Author(s) : Mikhail Bogdanov - -#ifndef CGAL_DELAUNAY_HYPERBOLIC_FACE_INFO_2_H -#define CGAL_DELAUNAY_HYPERBOLIC_FACE_INFO_2_H - -#include -#include - -#include -#include - -namespace CGAL { - -class Hyperbolic_face_info_2 -{ -public: - Hyperbolic_face_info_2() : _is_finite_invisible(false), _invisible_edge(UCHAR_MAX) - { - } - - bool is_finite_invisible() const - { - return _is_finite_invisible; - } - - void set_finite_invisible(bool is_finite_invisible) - { - _is_finite_invisible = is_finite_invisible; - } - - // Supposed to be called before "get_invisible_edge" - bool has_invisible_edge() const - { - return _invisible_edge <= 2; - } - - // Higly recommended to call "has_invisible_edge" before - unsigned char get_invisible_edge() const - { - assert(_is_finite_invisible); - assert(_invisible_edge <= 2); - - return _invisible_edge; - } - - void set_invisible_edge(unsigned char invisible_edge) - { - assert(_is_finite_invisible); - assert(invisible_edge <= 2); - - _invisible_edge = invisible_edge; - } - -private: - // a face is invisible if its circumscribing circle intersects the circle at infinity - bool _is_finite_invisible; - - // defined only if the face is finite and invisible - unsigned char _invisible_edge; -}; - -} //namespace CGAL - -#endif // CGAL_DELAUNAY_HYPERBOLIC_FACE_INFO_2_H diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_octagon_group.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_octagon_group.h index 238fc726390..5fbdf3d7915 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_octagon_group.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Hyperbolic_octagon_group.h @@ -154,8 +154,9 @@ public: }; + template -Square_root_2_field Hyperbolic_octagon_group::factor = Square_root_2_field(-1, 1); +Square_root_2_field Hyperbolic_octagon_group::factor = Square_root_2_field(-1, 1); /*Square_root_2_field(-1, 1);*/ // just to give an order(ing) template @@ -207,57 +208,349 @@ ostream& operator<<(ostream& os, const Hyperbolic_octagon_group SqrtField; -typedef Hyperbolic_octagon_group HyperbolicOctagonGroup; -typedef HyperbolicOctagonGroup::Matrix_element Element; +typedef long long ll; +typedef Square_root_2_field Sqrt_field; +typedef Hyperbolic_octagon_group Octagon_group; +typedef pair Octagon_group_with_index; +typedef Octagon_group::Matrix_element Element; enum Direction { - G_A = 0, // 0 - G_InvB, // 1 - G_C, // 2 - G_InvD, // 3 - G_InvA, // 4 - G_B, // 5 - G_InvC, // 6 - G_D // 7 + DIRECTION_A = 0, // 0 + DIRECTION_B_BAR, // 1 + DIRECTION_C, // 2 + DIRECTION_D_BAR, // 3 + DIRECTION_A_BAR, // 4 + DIRECTION_B, // 5 + DIRECTION_C_BAR, // 6 + DIRECTION_D // 7 }; -void get_generators(vector& gens) + + +void get_generators(vector& gens) { // This is a in the matrix, equal to sqrt(2) + 1 - Element A = Element(SqrtField(1, 1), SqrtField(0, 0)); + Element A = Element(Sqrt_field(1, 1), Sqrt_field(0, 0)); // This vector holds all other elements, results of the exponentials for various k - vector B(8, Element(SqrtField(0, 0), SqrtField(0, 0))); + vector B(8, Element(Sqrt_field(0, 0), Sqrt_field(0, 0))); // Corrected ordering (initial ordering is present in backup file) - B[G_A] = A * Element(SqrtField( 0, 0), SqrtField( 0, -1)); - B[G_B] = A * Element(SqrtField( 1, 0), SqrtField(-1, 0)); - B[G_C] = A * Element(SqrtField( 0, 1), SqrtField( 0, 0)); - B[G_D] = A * Element(SqrtField( 1, 0), SqrtField( 1, 0)); - B[G_InvA] = A * Element(SqrtField( 0, 0), SqrtField( 0, 1)); - B[G_InvB] = A * Element(SqrtField(-1, 0), SqrtField( 1, 0)); - B[G_InvC] = A * Element(SqrtField( 0, -1), SqrtField( 0, 0)); - B[G_InvD] = A * Element(SqrtField(-1, 0), SqrtField(-1, 0)); + /* This here produces the correct ordering, and identity is given by g[G_A]*g[G_B]*g[G_C]*g[G_D]*g[G_InvA]*g[G_InvB]*g[G_InvC]*g[G_InvD] */ + B[DIRECTION_A] = A * Element(Sqrt_field( 0, 1), Sqrt_field( 0, 0)); + B[DIRECTION_B] = A * Element(Sqrt_field(-1, 0), Sqrt_field(-1, 0)); + B[DIRECTION_C] = A * Element(Sqrt_field( 0, 0), Sqrt_field( 0, 1)); + B[DIRECTION_D] = A * Element(Sqrt_field( 1, 0), Sqrt_field(-1, 0)); + B[DIRECTION_A_BAR] = A * Element(Sqrt_field( 0, -1), Sqrt_field( 0, 0)); + B[DIRECTION_B_BAR] = A * Element(Sqrt_field( 1, 0), Sqrt_field( 1, 0)); + B[DIRECTION_C_BAR] = A * Element(Sqrt_field( 0, 0), Sqrt_field( 0, -1)); + B[DIRECTION_D_BAR] = A * Element(Sqrt_field(-1, 0), Sqrt_field( 1, 0)); - string labels[8] = {string("a"), string("\\bar{b}"), string("c"), string("\\bar{d}"), string("\\bar{a}"), string("b"), string("\\bar{c}"), string("d")}; for(int i = 0; i < 8; i++) { - gens.push_back(HyperbolicOctagonGroup(A, B[i], labels[i])); + gens.push_back(Octagon_group(A, B[i], labels[i])); } } + + + + +/***************************************************************/ + + + + // Check whether two elements of the group are inverse of each other + bool Are_inverse(Octagon_group_with_index x, Octagon_group_with_index y) { + int idx = x.second % 4; + int idy = y.second % 4; + bool r = ((idx == idy) && (x.second != y.second)); + return r; + } + + + + // Recursively eliminate neighboring inverse elements present in the word + void Simplify_word(vector& w) { + vector t; + bool reduced = false; + int N = w.size(); + if (N > 0) { + for (int i = 0; i < N-1; i++) { + if (!Are_inverse(w[i], w[i+1])) { + t.push_back(w[i]); + } else { + reduced = true; + i++; + } + } + if (!Are_inverse(w[N-2], w[N-1])) { + t.push_back(w[N-1]); + } else { + reduced = true; + } + + if (reduced) { + Simplify_word(t); + } + + w = t; + } + } + + + // Checks whether y is the next element from x + bool Is_next(Octagon_group_with_index x, Octagon_group_with_index y) { + return (((y.second + 5) % 8) == x.second); + } + + + // Given a word, find the largest subsequence of consecutive elements it contains. + // The sequence itself is placed in 'seq', while the index at which it starts is + // the return argument of the function. + int Longest_sequence(vector& seq, vector const w) { + int start = 0; + int mstart = 0; + int end = 1; + int max = 1; + int len = 1; + vector tmp, mvec; + tmp.push_back(w[0]); + for (int i = 1; i < w.size(); i++) { + if ( Is_next( w[i], w[i-1] ) ) { + end++; + len++; + tmp.push_back(w[i]); + if (len > max) { + max = len; + mvec = tmp; + mstart = start; + } + } else { + tmp.clear(); + tmp.push_back(w[i]); + start = i; + end = i; + len = 0; + } + } + seq = mvec; + return mstart; + } + + + + Octagon_group_with_index Invert(Octagon_group_with_index x) { + Octagon_group y = x.first.inverse(); + int idx = (x.second + 4) % 8; + return Octagon_group_with_index(y, idx); + } + + + // Given a word, construct its inverse + void Invert(vector& w, vector const original) { + w.clear(); + for (int i = original.size() - 1; i >= 0; i--) { + w.push_back( Invert(original[i]) ); + } + } + + + // Computes and returns the next index in the identity element chain + int Next_index(int idx) { + return ( (idx + 5) % 8 ); + } + + + // Given a sequence of consecutive indices, return the complementary set of consecutive indices in mod 8. + // For instance, if start = 5 and end = 1, the output is the sequence 2, 3, 4 + void Get_complement_indices(vector& v, int begin, int end) { + vector tmp; + for (int i = Next_index(end); i != begin; i = Next_index(i)) { + tmp.push_back(i); + } + + for (int i = tmp.size() - 1; i >= 0; i--) { + v.push_back(tmp[i]); + } + } + + + int Inverse(int idx) { + return ((idx + 4) % 8); + } + + + // Given the start and end indices of a sequence of consecutive elements, construct the complementary sequence of elements + void Get_complement_word(vector& c, int start, int end) { + vector idx; + vector gens; + get_generators(gens); + + Get_complement_indices(idx, start, end); + + for (int i = idx.size()-1; i >= 0; i--) { + int ii = idx[i]; + c.push_back(Octagon_group_with_index(gens[ii], ii)); + } + } + + + // Given a word consisting of consecutive elements, construct its complementary word + void Get_complement_word(vector& c, vector w) { + if (w.size() > 0) { + Get_complement_word(c, w[0].second, w[w.size()-1].second); + } else { + c = w; + } + } + + + + + // Given a word, identifies the longest subword consisting of consecutive elements and substitutes + // it with its equivalent shorter word. The search is executed in both the original word and its + // inverse, and the substitution is made considering the longest subword from both cases. + bool Replace_subword(vector& w, vector original) { + + bool replaced = false; + + // Handle empty string case + if (original.size() == 0) { + return replaced; // false + } + + // Look for longest subword forward + vector lfwd; + int idxf = Longest_sequence(lfwd, original); + int Nf = lfwd.size(); + + // Get inverse of the original word + vector inv; + Invert(inv, original); + + // Look for longest subword backwards + vector lbwd; + int idxb = Longest_sequence(lbwd, inv); + int Nb = lbwd.size(); + + // Assign parameters based on results to homogenise the logic + vector word, sub; + bool is_inverse; + int N, idx; + //cout << "Nb = " << Nb << ", Nf = " << Nf << endl; + if (Nb > Nf) { + word = inv; + sub = lbwd; + idx = idxb; + is_inverse = true; + N = Nb; + } else { + word = original; + sub = lfwd; + idx = idxf; + is_inverse = false; + N = Nf; + } + + // Take care of sequences with length greater or equal to 8 -- each chain of length 8 + // is by default equal to the identity element and can be directly eliminated. + while (N >= 8) { + replaced = true; + vector ttt = word; + word.clear(); + for (int i = 0; i < idx; i++) { + word.push_back(ttt[i]); + } + for (int i = idx + 8; i < ttt.size(); i++) { + word.push_back(ttt[i]); + } + w = word; + + ttt = sub; + sub.clear(); + for (int i = 8; i < ttt.size(); i++) { + sub.push_back(ttt[i]); + } + N -= 8; + } + + // Dehn's algorithm substitutes only chains longer that half-circle. + // Considering equality may lead to infinite loop -- the equivalent + // of a chain with length 4 is also a chain of length 4, so the + // substitution becomes cyclic. + if (N > 4) { + replaced = true; + vector cmpl; + Get_complement_word(cmpl, sub); + + vector tmp; + Invert(tmp, cmpl); + cmpl = tmp; + + for (int i = 0; i < idx; i++) { + w.push_back(word[i]); + } + for (int i = 0; i < cmpl.size(); i++) { + w.push_back(cmpl[i]); + } + for (int i = N + idx; i < word.size(); i++) { + w.push_back(word[i]); + } + } + + // If we have been working with the inverse of the original, the result has to be inverted. + if (is_inverse) { + vector tmp; + Invert(tmp, w); + w = tmp; + } + + return replaced; + } + + + + // Applies Dehn's algorithm to a given word. The result is the equivalent ireducible word + // of the original. The boolean return argument of the function indicates whether the + // resulting equivalent irreducible word is the identity element or not. + bool Apply_Dehn(vector& w, vector const original) { + bool is_identity = false; + vector tmp; + tmp = original; + + while (tmp.size() > 0) { + Simplify_word(tmp); + vector sub; + bool replaced = Replace_subword(sub, tmp); + if (!replaced) { + w = tmp; + return false; + } + tmp = sub; + } + + w = tmp; + + return true; + } + + + +/**************************************************************/ + + + // a, \bar{b}, c, \bar{d}, \bar{a}, b, \bar{c}, d -vector gens; +vector gens; -bool IsCanonical(const HyperbolicOctagonGroup& m); +bool IsCanonical(const Octagon_group& m); -void generate_words( set& words, vector& prev, int depth, double threshold ) +void generate_words( set& words, vector& prev, int depth, double threshold ) { if (depth == 1) { for(int i = 0; i < 8; i++) { @@ -267,10 +560,10 @@ void generate_words( set& words, vector els; + vector els; generate_words( words, els, depth - 1, threshold); - HyperbolicOctagonGroup temp = HyperbolicOctagonGroup(Element(), Element()); + Octagon_group temp = Octagon_group(Element(), Element()); ll size = els.size(); bool is_new = false; for(ll k = 0; k < size; k++) { @@ -290,13 +583,13 @@ void generate_words( set& words, vector true C = right - left; return C == C.abs(); } -void dfs(const HyperbolicOctagonGroup& m, set& visited) +void dfs(const Octagon_group& m, set& visited) { assert(IsCanonical(m)); visited.insert(m); - HyperbolicOctagonGroup candidate = m; + Octagon_group candidate = m; for(int i = 0; i < 8; i++) { candidate = gens[i]*m*gens[(i + 4) % 8]; if(IsCanonical(candidate) == true && visited.find(candidate) == visited.end()) { @@ -331,33 +624,33 @@ void dfs(const HyperbolicOctagonGroup& m, set& visited) } } -// map, m = Aux * origin * Aux^{-1} -void dfs_with_info(const pair& new_pair, - map & visited) +// map, m = Aux * origin * Aux^{-1} +void dfs_with_info(const pair& new_pair, + map & visited) { assert(IsCanonical(new_pair.first)); visited.insert(new_pair); - const HyperbolicOctagonGroup& current = new_pair.first; - const HyperbolicOctagonGroup& current_factor = new_pair.second; - HyperbolicOctagonGroup candidate = current, candidate_factor = current_factor; + const Octagon_group& current = new_pair.first; + const Octagon_group& current_factor = new_pair.second; + Octagon_group candidate = current, candidate_factor = current_factor; for(int i = 0; i < 8; i++) { candidate = gens[i]*current*gens[(i + 4) % 8]; if(IsCanonical(candidate) == true && visited.find(candidate) == visited.end()) { candidate_factor = gens[i]*current_factor; - dfs_with_info(pair(candidate, candidate_factor), visited); + dfs_with_info(pair(candidate, candidate_factor), visited); } } } -void dfs_with_info(const HyperbolicOctagonGroup& origin, - map& visited) +void dfs_with_info(const Octagon_group& origin, + map& visited) { assert(IsCanonical(origin)); - HyperbolicOctagonGroup id = HyperbolicOctagonGroup(Element(SqrtField(1, 0), SqrtField(0, 0)), - Element(SqrtField(0, 0), SqrtField(0, 0))); - pair new_pair(origin, id); + Octagon_group id = Octagon_group(Element(Sqrt_field(1, 0), Sqrt_field(0, 0)), + Element(Sqrt_field(0, 0), Sqrt_field(0, 0))); + pair new_pair(origin, id); dfs_with_info(new_pair, visited); } @@ -374,21 +667,21 @@ public: double x, y; }; - HyperbolicOctagonGroup m; + Octagon_group m; - IntersectionNumber(const HyperbolicOctagonGroup& m_) : m(m_) + IntersectionNumber(const Octagon_group& m_) : m(m_) {} long operator() () const { - set visited; - set::iterator it, it2; + set visited; + set::iterator it, it2; map nb_map; map::iterator mit; dfs(m, visited); - set > common; + set > common; for(it = visited.begin(); it != visited.end(); ++it) { for(it2 = it; it2 != visited.end(); ++it2) { if(*it == *it2) { @@ -417,12 +710,12 @@ public: } - void count_nb(const HyperbolicOctagonGroup& m1, const HyperbolicOctagonGroup& m2, set >& visited) const + void count_nb(const Octagon_group& m1, const Octagon_group& m2, set >& visited) const { - typedef pair matrix_pair; + typedef pair matrix_pair; visited.insert(matrix_pair(m1, m2)); - HyperbolicOctagonGroup c1 = m1, c2 = m2; + Octagon_group c1 = m1, c2 = m2; for(int i = 0; i < 8; i++) { c1 = gens[i]*m1*gens[(i + 4) % 8]; c2 = gens[i]*m2*gens[(i + 4) % 8]; @@ -435,7 +728,7 @@ public: //private: // check whether two axis have intersection - bool haveIntersection(const HyperbolicOctagonGroup& m1, const HyperbolicOctagonGroup& m2) const + bool haveIntersection(const Octagon_group& m1, const Octagon_group& m2) const { Point p1, p2; intersectWithInfinity(m1, p1, p2); @@ -451,12 +744,12 @@ public: return (sign1 * sign2 < 0); } - void intersectWithInfinity(const HyperbolicOctagonGroup& m, Point& p1, Point& p2) const + void intersectWithInfinity(const Octagon_group& m, Point& p1, Point& p2) const { Element a = m.A, b = m.B, factor = m.factor; - Element four = Element(SqrtField(4, 0), SqrtField(0, 0)); - Element two = Element(SqrtField(2, 0), SqrtField(0, 0)); + Element four = Element(Sqrt_field(4, 0), Sqrt_field(0, 0)); + Element two = Element(Sqrt_field(2, 0), Sqrt_field(0, 0)); Element D = (a - conj(a))*(a - conj(a)); D += four*b*conj(b)*factor; @@ -481,17 +774,17 @@ public: }; -void Delete(const set& canonical_set, vector& output) +void Delete(const set& canonical_set, vector& output) { - set redundant; + set redundant; - set::iterator it; + set::iterator it; for(it = canonical_set.begin(); it != canonical_set.end(); ++it) { if(redundant.find(*it) != redundant.end()) { continue; } - set visited; + set visited; dfs(*it, visited); visited.erase(*it); @@ -500,16 +793,16 @@ void Delete(const set& canonical_set, vector& output, double threshold = 10, int word_length = 13) +void generate_unique_words(vector& output, double threshold = 10, int word_length = 13) { get_generators(gens); - set unique_words; - vector temp; + set unique_words; + vector temp; generate_words(unique_words, temp, word_length, threshold); double l = 0; - set::iterator uit; + set::iterator uit; for(uit = unique_words.begin(); uit != unique_words.end(); ++uit) { l = uit->length(); if(0. < l && l < threshold) { @@ -521,14 +814,14 @@ void generate_unique_words(vector& output, double thresh } // words that correspond to union of 1-cycles -void generate_words_union_1_cycles(vector& out) +void generate_words_union_1_cycles(vector& out) { if(gens.size() == 0) { get_generators(gens); } - HyperbolicOctagonGroup f[4] = {gens[0], gens[5], gens[2], gens[7]}; + Octagon_group f[4] = {gens[0], gens[5], gens[2], gens[7]}; - HyperbolicOctagonGroup F[8] = { + Octagon_group F[8] = { f[0]*f[0].inverse(), f[0], f[0]*f[1], @@ -555,7 +848,7 @@ void generate_words_union_1_cycles(vector& out) } counter++; - HyperbolicOctagonGroup Tr = F[i]*F[k].inverse()*F[j]; + Octagon_group Tr = F[i]*F[k].inverse()*F[j]; // check that Tr != Id if(Tr.length() > 2.) { out.push_back(Tr); diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_Delaunay_hyperbolic_triangulation_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_Delaunay_hyperbolic_triangulation_2.h deleted file mode 100644 index 4b83790eecd..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_Delaunay_hyperbolic_triangulation_2.h +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2010 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. -// -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/candidate-packages/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h $ -// $Id: Delaunay_triangulation_2.h 57509 2010-07-15 09:14:09Z sloriot $ -// -// -// Author(s) : Mikhail Bogdanov - -#ifndef CGAL_PERIODIC_4_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H -#define CGAL_PERIODIC_4_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H - -#include - -// I needed to use a non-reserved word for this thing, there were problems when I (iiordano) (stupidly) used TYPE -#define CLEARLY_MY_TYPE 2 // 1 = Cross, 2 = Diametric -#define USE_TEST_THINGS 0 // 1 = True, 0 = False - -#if USE_TEST_THINGS == 1 -#include -#else -#include -#endif - -/* -#if CLEARLY_MY_TYPE == 1 -#include -#else -#include -#endif -*/ -//#include - -namespace CGAL { - - template < class Gt, - class Tds = Triangulation_data_structure_2 < - Triangulation_vertex_base_2 > > -#if USE_TEST_THINGS == 1 - class Periodic_4_Delaunay_hyperbolic_triangulation_2 : public Periodic_4_hyperbolic_triangulation_2 -#else - class Periodic_4_Delaunay_hyperbolic_triangulation_2 : public Delaunay_triangulation_2 -#endif - { - public: - typedef Periodic_4_Delaunay_hyperbolic_triangulation_2 Self; -#if USE_TEST_THINGS == 1 - typedef Periodic_4_hyperbolic_triangulation_2 Base; -#else - typedef Delaunay_triangulation_2 Base; -#endif - typedef typename Base::Vertex_handle Vertex_handle; - typedef typename Base::Face_handle Face_handle; - typedef typename Base::Edge Edge; - typedef typename Base::Locate_type Locate_type; - - typedef typename Base::Finite_edges_iterator Finite_edges_iterator; - typedef typename Base::Face_circulator Face_circulator; - - typedef Gt Geom_traits; - typedef typename Geom_traits::FT FT; - typedef typename Geom_traits::Point_2 Point_2; - typedef typename Geom_traits::Segment_2 Segment; - - //void insert_dummy_points(std::vector& ); - - void Set_recursion_depth(int new_depth) { - this->recursion_depth = new_depth; - } - -#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 - using Base::tds; -#endif - - /* - Periodic_4_Delaunay_hyperbolic_triangulation_2(const Gt& gt = Gt()) -#if USE_TEST_THINGS == 1 - : Periodic_4_hyperbolic_triangulation_2(gt) -#else - : Delaunay_triangulation_2(gt) -#endif - { - recursion_depth = 0; - } - - Periodic_4_Delaunay_hyperbolic_triangulation_2(const Periodic_4_Delaunay_hyperbolic_triangulation_2 &tr) -#if USE_TEST_THINGS == 1 - : Periodic_4_hyperbolic_triangulation_2(tr) -#else - : Delaunay_triangulation_2(tr) -#endif - { CGAL_triangulation_postcondition( this->is_valid() ); } - - - */ - - /************************ INSERT OVERLOADS **************************/ - - /* - - Vertex_handle insert(const Point_2 &p, - Face_handle start = Face_handle() ) - { - - std::vector copies; - - Vertex_handle vh = Base::insert(p, start); - - recursive_translate(g, copies, p, recursion_depth); - - for(int i = 0; i < copies.size(); i++) { - vh = Base::insert(copies[i], start); - } - - return vh; - } - - - Vertex_handle insert(const Point_2& p, - typename Base::Locate_type lt, - Face_handle loc, int li ) - { - return Base::insert(p, lt, loc, li); - } - - - template < class InputIterator > - std::ptrdiff_t - insert(InputIterator first, InputIterator last) - { - return Base::insert(first, last); - } - - - */ - - Object - dual(const Finite_edges_iterator& ei) const { - return this->dual(*ei); - } - - Object - dual(const Edge &e) const { - // default implementation - //assert(false); - return make_object(e); - } - - // Clears the triangulation and initializes it again. - void clear() { - tds().clear(); - init_tds(); - } - - private: - - /* - - void recursive_translate( -#if CLEARLY_MY_TYPE == 1 - Cross_translations g, -#else - Diametric_translations g, -#endif - std::vector& points, - Point_2 o, - int depth, - int start = -1, - int end = -1) - { - if (depth > 0) { - - if (start == -1 && end == -1) { - int start = points.size(); - int end = start + 8; - - Point_2 subject = o; - - // Add points in the order indicated by the group -- not necessary, but seems logical - points.push_back( g.a().DoAction(subject) ); - points.push_back( g.b().inverse().DoAction(subject) ); - points.push_back( g.c().DoAction(subject) ); - points.push_back( g.d().inverse().DoAction(subject) ); - points.push_back( g.a().inverse().DoAction(subject) ); - points.push_back( g.b().DoAction(subject) ); - points.push_back( g.c().inverse().DoAction(subject) ); - points.push_back( g.d().DoAction(subject) ); - - recursive_translate(g, points, o, depth - 1, start, end); - } - else - { - int my_start = points.size(); - int my_end = start; - - for (int i = start; i <= end; i++){ - Point_2 subject = points[i]; - points.push_back( g.a().DoAction(subject) ); - points.push_back( g.b().inverse().DoAction(subject) ); - points.push_back( g.c().DoAction(subject) ); - points.push_back( g.d().inverse().DoAction(subject) ); - points.push_back( g.a().inverse().DoAction(subject) ); - points.push_back( g.b().DoAction(subject) ); - points.push_back( g.c().inverse().DoAction(subject) ); - points.push_back( g.d().DoAction(subject) ); - my_end += 8; - } - - recursive_translate(g, points, o, depth - 1, my_start, my_end); - } - } - - } - - */ - - - - // Initializes the triangulation data structure - void init_tds() { - this->_infinite_vertex = tds().insert_first(); - } - - void paste_together_opposite_sides(const std::vector& on_vertex, const std::vector& on_boundary); - - // The following variable defines how many copies to insert on the PoincarĂ© disk (for visualisation purposes only!) - int recursion_depth; - -/* - -#if CLEARLY_MY_TYPE == 1 // This means that we must do Cross-translations (alternative identification) - Cross_translations g; -#else - Diametric_translations g; -#endif - -*/ - - - }; - -} // namespace CGAL - -//#include - -#endif // CGAL_PERIODIC_4_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_construct_hyperbolic_point_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_construct_hyperbolic_point_2.h index 18cf0c36200..314131ce4dd 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_construct_hyperbolic_point_2.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_construct_hyperbolic_point_2.h @@ -37,7 +37,7 @@ class Periodic_4_construct_hyperbolic_point_2 : public Construct_point_2_base public: typedef typename Kernel::Point_2 Point; - typedef HyperbolicOctagonGroup Offset; + typedef HyperbolicOctagonGroup Offset; typedef typename Kernel::Circle_2 Circle_2; typedef Point result_type; @@ -45,10 +45,6 @@ public: Periodic_4_construct_hyperbolic_point_2(const Circle_2 & dom) : _dom(dom) { } Point operator() ( const Point& p, const Offset& o ) const { - /* - return Point( p.x()+(_dom.xmax()-_dom.xmin())*o.x(), - p.y()+(_dom.ymax()-_dom.ymin())*o.y(), - p.z()+(_dom.zmax()-_dom.zmin())*o.z()); */ pair pt = o.apply(to_double(p.x()), to_double(p.y())); Point r = Point(pt.first, pt.second); diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h index 5cf187620c2..2ad08975f17 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h @@ -1,10 +1,9 @@ -// Copyright (c) 2006-2009 INRIA Sophia-Antipolis (France). +// Copyright (c) 2016 INRIA Nancy - Grand Est (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. +// 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. @@ -12,85 +11,197 @@ // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // -// $URL$ -// $Id$ -// +// $URL: $ +// $Id: $ // -// Author(s) : Nico Kruithof -// Manuel Caroli +// +// Author(s) : Iordan Iordanov + #ifndef CGAL_PERIODIC_4_HYPERBOLIC_DELAUNAY_TRIANGULATION_TRAITS_2_H #define CGAL_PERIODIC_4_HYPERBOLIC_DELAUNAY_TRIANGULATION_TRAITS_2_H -//#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -namespace CGAL { +#include +#include +#include "boost/tuple/tuple.hpp" +#include "boost/variant.hpp" + +namespace CGAL { + +template< class R > +class Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 { -template < class THT2 > -class Periodic_4_hyperbolic_Delaunay_triangulation_traits_base_2 - : public Periodic_3_triangulation_traits_base_3 -{ public: - typedef THT2 K; - typedef HyperbolicOctagonGroup Offset; - typedef Periodic_4_hyperbolic_triangulation_traits_base_2< K > Base; - typedef Periodic_4_hyperbolic_Delaunay_triangulation_traits_base_2< K > Self; - typedef typename Base::RT RT; - typedef typename Base::FT FT; - typedef typename Base::Point_2 Point_2; - typedef typename Base::Vector_2 Vector_2; - //typedef typename Base::Periodic_4_offset_2 Periodic_4_offset_2; + typedef R Kernel; - // The next typedef is there for backward compatibility - // Some users take their point type from the traits class. - // Before this type was Point - typedef Point_2 Point; + typedef Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 + Self; - typedef typename Base::Segment_2 Segment_2; - typedef typename Base::Triangle_2 Triangle_2; + typedef Triangulation_hyperbolic_traits_2 Base; - // Delaunay specific predicates - typedef Traits_with_offsets_adaptor - Side_of_oriented_circle_2; - typedef Traits_with_offsets_adaptor - Compare_distance_2; - typedef Traits_with_offsets_adaptor - Side_of_bounded_disc_2; + // Basic types + typedef typename Base::RT RT; + typedef typename Base::FT FT; + typedef typename Base::Point_2 Point_2; + typedef Point_2 Point; // Compatibility issues + typedef typename Base::Vector_2 Vector_2; + typedef typename Base::Triangle_2 Triangle_2; + typedef typename Base::Line_2 Line_2; + typedef typename Base::Ray_2 Ray_2; + typedef typename Base::Vector_3 Vector_3; + typedef typename Base::Point_3 Point_3; + typedef typename Base::Angle_2 Angle_2; + typedef typename Base::Iso_rectangle_2 Iso_rectangle_2; + typedef typename Base::Circle_2 Circle_2; + typedef typename Base::Arc_2 Arc_2; + typedef typename Base::Line_segment_2 Line_segment_2; + typedef typename Base::Segment_2 Segment_2; + typedef typename Base::Euclidean_line_2 Euclidean_line_2; - // Delaunay specific constructions - typedef Traits_with_hyperbolic_offsets_adaptor - Construct_circumcenter_2; + // Predicates and comparisons + typedef typename Base::Less_x_2 Less_x_2; + typedef typename Base::Less_y_2 Less_y_2; + typedef typename Base::Compare_x_2 Compare_x_2; + typedef typename Base::Compare_y_2 Compare_y_2; + typedef typename Base::Orientation_2 Orientation_2; + typedef typename Base::Side_of_oriented_circle_2 Side_of_oriented_circle_2; + typedef typename Base::Compare_distance_2 Compare_distance_2; + typedef typename Base::Compute_squared_distance_2 Compute_squared_distance_2; - // Operations - Side_of_oriented_circle_2 - side_of_oriented_circle_2_object() const { - return Side_of_oriented_circle_2(&this->_domain); - } - Compare_distance_2 - compare_distance_2_object() const { - return Compare_distance_2(&this->_domain); - } - Side_of_bounded_disc_2 - side_of_bounded_disc_2_object() const { - return Side_of_bounded_disc_2(&this->_domain); - } - Construct_circumcenter_2 - construct_circumcenter_2_object() const { - return Construct_circumcenter_2(&this->_domain); - } -}; + // Constructions + typedef typename Base::Construct_bisector_2 Construct_bisector_2; + typedef typename Base::Construct_hyperbolic_bisector_2 Construct_hyperbolic_bisector_2; + typedef typename Base::Construct_triangle_2 Construct_triangle_2; + typedef typename Base::Construct_direction_2 Construct_direction_2; + typedef typename Base::Construct_midpoint_2 Construct_midpoint_2; + typedef typename Base::Construct_circumcenter_2 Construct_circumcenter_2; + typedef typename Base::Construct_segment_2 Construct_segment_2; + typedef typename Base::Construct_ray_2 Construct_ray_2; + typedef typename Base::Is_hyperbolic Is_hyperbolic; -template < typename K > -class Periodic_4_hyperbolic_Delaunay_triangulation_traits_2; +private: + Circle_2 _domain; -} //namespace CGAL +public: + Periodic_4_hyperbolic_Delaunay_triangulation_traits_2() : + _domain(Point_2(0, 0), 1*1) + {} + + Periodic_4_hyperbolic_Delaunay_triangulation_traits_2(FT r) : + _domain(Point_2(0, 0), r*r) + {} + + Periodic_4_hyperbolic_Delaunay_triangulation_traits_2(const Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 & other) : + _domain(other._domain) + {} + + Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 &operator=(const Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 &) + { + return *this; + } + + + Construct_circumcenter_2 + construct_circumcenter_2_object() const { + return Construct_circumcenter_2(_domain); + } + + Construct_segment_2 + construct_segment_2_object() const { + return Construct_segment_2(_domain); + } + + Construct_midpoint_2 + construct_midpoint_2_object() const { + return Construct_midpoint_2(&_domain); + } + + Less_x_2 + less_x_2_object() const { + return Less_x_2(); + } + + Less_y_2 + less_y_2_object() const { + return Less_y_2(); + } + + Compare_x_2 + compare_x_2_object() const { + return Compare_x_2(); + } + + Compare_y_2 + compare_y_2_object() const { + return Compare_y_2(); + } + + Orientation_2 + orientation_2_object() const { + return Orientation_2(); + } + + Side_of_oriented_circle_2 + side_of_oriented_circle_2_object() const { + return Side_of_oriented_circle_2(); + } + + Construct_hyperbolic_bisector_2 + construct_hyperbolic_bisector_2_object() const { + return Construct_hyperbolic_bisector_2(_domain); + } + + Construct_bisector_2 + construct_bisector_2_object() const { + return Construct_bisector_2(); + } + + Compare_distance_2 + compare_distance_2_object() const { + return Compare_distance_2(); + } + + Construct_triangle_2 + construct_triangle_2_object() const { + return Construct_triangle_2(); + } + + Construct_direction_2 + construct_direction_2_object() const { + return Construct_direction_2(); + } + + Construct_ray_2 + construct_ray_2_object() const { + return Construct_ray_2(_domain); + } + + Is_hyperbolic + Is_hyperbolic_object() const { + return Is_hyperbolic(); + } + + +}; // class Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 + +} // namespace CGAL #endif // CGAL_PERIODIC_4_HYPERBOLIC_DELAUNAY_TRIANGULATION_TRAITS_2_H + + + + + + + + diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_2.h deleted file mode 100644 index 1cc35621cee..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_2.h +++ /dev/null @@ -1,4856 +0,0 @@ -// Copyright (c) 1997-2013 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// 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. -// -// $URL$ -// $Id$ -// -// Author(s) : Nico Kruithof - -#ifndef CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_2_H -#define CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_2_H - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace CGAL -{ - -/// Periodic triangulation class. -/// Its main functionality is: -/// - Insertion of points -/// - Deletion of points -/// - Point location -template < class Gt, - class Tds = Triangulation_data_structure_2 < - Periodic_2_triangulation_vertex_base_2, - Periodic_2_triangulation_face_base_2 > > -class Periodic_4_hyperbolic_triangulation_2: public Triangulation_cw_ccw_2 -{ - typedef Periodic_4_hyperbolic_triangulation_2 Self; - -public: - // Public types of Periodic_4_hyperbolic_triangulation_2 - /// The triangulation data structure type - typedef Tds Triangulation_data_structure; - /// The traits class - typedef Gt Geom_traits; - - /// The periodic offset type - typedef typename Gt::Periodic_2_offset_2 Offset; - /// The iso rectangle type - typedef typename Gt::Iso_rectangle_2 Iso_rectangle; - /// Integer tuple to store the number of sheets in each direction of space. - typedef array Covering_sheets; - - /// The point type - typedef typename Gt::Point_2 Point; - /// The segment type - typedef typename Gt::Segment_2 Segment; - /// The triangle type - typedef typename Gt::Triangle_2 Triangle; - - /// Represents a point-offset pair. The point in the pair lies in the original domain. - typedef std::pair Periodic_point; - /// A pair of periodic points representing a segment in the periodic domain. - typedef array, 2> Periodic_segment; - /// A triple of periodic points representing a triangle in the periodic domain. - typedef array, 3> Periodic_triangle; - - /// The vertex type - typedef typename Tds::Vertex Vertex; - /// The face type - typedef typename Tds::Face Face; - /// The edge type - typedef typename Tds::Edge Edge; - - /// Size type (an unsigned integral type) - typedef typename Tds::size_type size_type; - /// Difference type (a signed integral type) - typedef typename Tds::difference_type difference_type; - - /// Handle to a vertex - typedef typename Tds::Vertex_handle Vertex_handle; - /// Handle to a face - typedef typename Tds::Face_handle Face_handle; - - /// Iterator over the faces - typedef typename Tds::Face_iterator Face_iterator; - /// Iterator over the edges - typedef typename Tds::Edge_iterator Edge_iterator; - /// Iterator over the vertices - typedef typename Tds::Vertex_iterator Vertex_iterator; - /// Iterator over the vertices whose corresponding points lie in the - /// original domain, i.e. for each set of periodic copies the - /// Unique_vertex_iterator iterates over exactly one representative. - typedef Periodic_4_hyperbolic_triangulation_unique_vertex_iterator_2 - Unique_vertex_iterator; - - /// \name For compatibility with the Triangulation_2 class - // \{ - typedef Face_iterator Finite_faces_iterator; - typedef Edge_iterator Finite_edges_iterator; - typedef Vertex_iterator Finite_vertices_iterator; - typedef Face_iterator All_faces_iterator; - // \} - - /// Circulator over all faces incident to a vertex - typedef typename Tds::Face_circulator Face_circulator; - /// Circulator over all edges incident to a vertex - typedef typename Tds::Edge_circulator Edge_circulator; - /// Circulator over all vertices incident to a vertex - typedef typename Tds::Vertex_circulator Vertex_circulator; - - /// \name Periodic iterator types - //\{ - /// Iterator over all periodic triangles - typedef Periodic_4_hyperbolic_triangulation_triangle_iterator_2 - Periodic_triangle_iterator; - /// Iterator over all periodic segments - typedef Periodic_4_hyperbolic_triangulation_segment_iterator_2 - Periodic_segment_iterator; - /// Iterator over all periodic points - typedef Periodic_4_hyperbolic_triangulation_point_iterator_2 - Periodic_point_iterator; - //\} - - /// \name Enumeration types - //\{ - - /// Type determining how to iterate over the stored simplices in the triangulation - enum Iterator_type - { - STORED = 0, - UNIQUE, // 1 - STORED_COVER_DOMAIN, // 2 - UNIQUE_COVER_DOMAIN // 3 - };//3 - - /// Return type of a point location query - enum Locate_type - { - /// The query point lies on a vertex - VERTEX = 0, - /// The query point lies on an edge - EDGE, - /// The query point lies on a face - FACE, - /// The query point lies outside the affine hull of the triangulation, - /// which is the case when the triangulation is empty. - EMPTY - }; - //\} - - // Auxiliary iterators for convenience - // do not use default template argument to please VC++ - /// Functor that returns the point given a vertex - typedef Project_point Proj_point; - - /// \name STL types - // \{ - /// value_type similar to stl containers - typedef Point value_type; // to have a back_inserter - /// const_reference similar to stl containers - typedef const value_type& const_reference; - /// reference similar to stl containers - typedef value_type& reference; - // \} - - - /// Tag to distinguish Regular triangulations from others; - typedef Tag_false Weighted_tag; - -protected: - // Protected types of Periodic_4_hyperbolic_triangulation_2 - typedef typename Gt::Orientation_2 Orientation_2; - typedef typename Gt::Compare_x_2 Compare_x; - typedef typename Gt::Compare_y_2 Compare_y; - - - typedef typename Gt::FT FT; - typedef std::pair Virtual_vertex; - typedef std::map Virtual_vertex_map; - typedef typename Virtual_vertex_map::const_iterator Virtual_vertex_map_it; - - /// Vector is contains virtual copies with offset off: - /// virtual copy with offset off is stored at position: i=3*off[0]+off[1]-1 - typedef std::map > - Virtual_vertex_reverse_map; - typedef typename Virtual_vertex_reverse_map::const_iterator - Virtual_vertex_reverse_map_it; - typedef std::map > Too_long_edges_map; - typedef typename Too_long_edges_map::const_iterator Too_long_edges_map_it; - - /// \name Functors - // \{ - /// Functor for symbolically perturbing points - class Perturbation_order - { - const Self *t; - - public: - // Perturbation_order, public interface - Perturbation_order(const Self *tr) : - t(tr) - { - } - - bool operator()(const Point *p, const Point *q) const - { - return t->compare_xy(*p, *q) == SMALLER; - } - bool operator()(const Periodic_point *p, const Periodic_point *q) const - { - return t->compare_xy(p->first, q->first, p->second, q->second) == SMALLER; - } - }; - // \} - friend class Perturbation_order; - -private: - // Copy constructor helpers - class Finder; - void copy_multiple_covering(const Periodic_4_hyperbolic_triangulation_2 & tr); - -public: - // Public functions of Periodic_4_hyperbolic_triangulation_2 - /// \name Constructors - //\{ - /// Constructor - Periodic_4_hyperbolic_triangulation_2( - const Iso_rectangle &domain = Iso_rectangle(0, 0, 1, 1), - const Geom_traits &geom_traits = Geom_traits()); - - /// Copy constructor - Periodic_4_hyperbolic_triangulation_2(const Periodic_4_hyperbolic_triangulation_2 &tr); - /// Assignment - Periodic_4_hyperbolic_triangulation_2 &operator=(const Periodic_4_hyperbolic_triangulation_2 &tr); - - /// Copy the triangulation - void copy_triangulation(const Periodic_4_hyperbolic_triangulation_2 &tr); - /// Swap two triangulations - void swap(Periodic_4_hyperbolic_triangulation_2 &tr); - /// Clear the triangulation - void clear(); - - /// Serialize the triangulation to an output stream - std::ostream& save(std::ostream& os) const; - - /// Deserialize the triangulation from an input stream - std::istream& load(std::istream& is); - - //\} - - /// \name Access functions - //\{ - - /// Returns the geometric traits used for the predicates and constructions. - const Geom_traits& geom_traits() const - { - return _gt; - } - /// Returns the datastructure storing the triangulation. - const Triangulation_data_structure & tds() const - { - return _tds; - } - /// Returns the datastructure storing the triangulation. - Triangulation_data_structure & tds() - { - return _tds; - } - /// Returns the domain of the 1-sheeted cover. - const Iso_rectangle & domain() const - { - return _domain; - } - /// Returns the number of copies of the 1-sheeted cover stored in each of - /// the principal directions. - Covering_sheets number_of_sheets() const - { - return _cover; - } - /// Returns the dimension of the triangulation. - int dimension() const - { - return _tds.dimension() == 2 ? 2 : 0; - } - - //\} - - /// \name Number of simplices - //\{ - /// Returns whether the triangulation is empty. - bool empty() const - { - return _tds.dimension() < 2; - } - - /// Returns the number of vertices. Counts all vertices that are - /// representatives of the same point in the 1-cover as one vertex. - size_type number_of_vertices() const - { - if (is_1_cover()) - return _tds.number_of_vertices(); - else - return _tds.number_of_vertices() / 9; - } - - /// Returns the number of edges. Counts all edges that are - /// representatives of the same segment in the 1-cover as one edge. - size_type number_of_edges() const - { - if (is_1_cover()) - return _tds.number_of_edges(); - else - return _tds.number_of_edges() / 9; - } - /// Returns the number of faces. Counts all faces that are - /// representatives of the same triangle in the 1-cover as one face. - size_type number_of_faces() const - { - if (is_1_cover()) - return _tds.number_of_faces(); - else - return _tds.number_of_faces() / 9; - } - /// Returns the number of vertices stored in the datastructure. - size_type number_of_stored_vertices() const - { - return _tds.number_of_vertices(); - } - /// Returns the number of edges stored in the datastructure. - size_type number_of_stored_edges() const - { - return _tds.number_of_edges(); - } - /// Returns the number of faces stored in the datastructure. - size_type number_of_stored_faces() const - { - return _tds.number_of_faces(); - } - //\} - - - /// \name Methods regarding the covering - /// \{ - - /// Checks whether the triangulation is a valid simplicial complex in the one cover. - /// Uses an edge-length-criterion. - bool is_extensible_triangulation_in_1_sheet_h1() const; - - /// Checks whether the triangulation is a valid simplicial complex in the one cover. - /// Uses a criterion based on the maximal radius of the circumscribing circle. - bool is_extensible_triangulation_in_1_sheet_h2() const; - - /// Checks whether the triangulation is a valid simplicial complex in the one cover. - bool is_triangulation_in_1_sheet() const; - - /// Convert a 9 sheeted cover (used for sparse triangulations) to a single sheeted cover. - /// \pre !is_1_cover(); - void convert_to_1_sheeted_covering(); - /// Convert a single sheeted cover (used for dense triangulations) to a 9 sheeted cover. - /// \pre is_1_cover(); - void convert_to_9_sheeted_covering(); - // \} - - /// \name Geometric access functions - // \{ - - /// Returns the periodic point given by vertex v. If t is - /// represented in the 1-sheeted covering space, the offset is - /// always zero. Otherwise v can correspond to a periodic copy - /// outside domain of an input point. - Periodic_point periodic_point(const Vertex_handle &v) const - { - return Periodic_point(v->point(), get_offset(v)); - } - - /// If t is represented in the 1-sheeted covering space, this - /// function returns the periodic point given by the i-th vertex of - /// face f, that is the point in the original domain and the offset - /// of the vertex in f. If t is represented in the 9-sheeted - /// covering space, this offset is possibly added to another offset - /// determining the periodic copy. - /// \pre i == {0,1,2} - Periodic_point periodic_point(const Face_handle &f, int i) const - { - return Periodic_point(f->vertex(i)->point(), get_offset(f, i)); - } - - /// Returns the periodic segment formed by the two point-offset - /// pairs corresponding to the two vertices of edge (f,i). - /// \pre i == {0,1,2} - Periodic_segment periodic_segment(const Face_handle &f, int i) const - { - CGAL_triangulation_precondition( number_of_vertices() != 0 ); - CGAL_triangulation_precondition( i >= 0 && i <= 2); - return make_array(periodic_point(f, ccw(i)), - periodic_point(f, cw(i))); - } - - /// Same as the previous method for edge e. - Periodic_segment periodic_segment(const Edge &e) const - { - return periodic_segment(e.first, e.second); - } - - /// Returns the periodic triangle formed by the three point-offset - /// pairs corresponding to the three vertices of facet f. - Periodic_triangle periodic_triangle(const Face_handle &f) const - { - return make_array(periodic_point(f, 0), - periodic_point(f, 1), - periodic_point(f, 2)); - } - - /// Converts the Periodic_point pp (point-offset pair) to the corresponding - /// Point in \f$R^2\f$. - Point point(const Periodic_point & pp) const - { - return construct_point(pp.first, pp.second); - } - Point point(const Vertex_handle &v) const - { - return point(periodic_point(v)); - } - Point point(const Face_handle &fh, int i) const - { - return point(periodic_point(fh, i)); - } - /// Converts the Periodic_segment ps to a Segment in \f$R^2\f$. - Segment segment(const Periodic_segment &ps) const - { - return construct_segment(ps[0].first, ps[1].first, ps[0].second, ps[1].second); - } - /// Converts the Periodic_triangle pt to a Triagle in \f$R^2\f$. - Triangle triangle(const Periodic_triangle &pt) const - { - Triangle triang = construct_triangle(pt[0].first, pt[1].first, pt[2].first, - pt[0].second, pt[1].second, pt[2].second); - return triang; - } - - /// Constructs the segment associated with the edge (f,i), respects the offset - Segment segment(Face_handle f, int i) const - { - return segment(periodic_segment(f, i)); - } - /// Constructs the segment associated with the edge e, respects the offset - Segment segment(const Edge& e) const - { - return segment(periodic_segment(e)); - } - /// Constructs the segment associated with the edge ec, respects the offset - Segment segment(const Edge_circulator& ec) const - { - return segment(periodic_segment(ec->first, ec->second)); - } - /// Constructs the segment associated with the edge ei, respects the offset - Segment segment(const Edge_iterator& ei) const - { - return segment(periodic_segment(ei->first, ei->second)); - } - - /// Constructs the triangle associated with the face f, respects the offset - Triangle triangle(Face_handle f) const - { - return triangle(periodic_triangle(f)); - } - //\} - - Point move_in_domain(const Point &p) - { - typename Gt::FT x = p.x(); - typename Gt::FT y = p.y(); - - while (x < _domain.xmin()) x += _domain.xmax() - _domain.xmin(); - while (x >= _domain.xmax()) x -= _domain.xmax() - _domain.xmin(); - - while (y < _domain.ymin()) y += _domain.ymax() - _domain.ymin(); - while (y >= _domain.ymax()) y -= _domain.ymax() - _domain.ymin(); - - return Point(x, y); - } - - /// \name Queries on simplices - // \{ - bool is_edge(Vertex_handle va, Vertex_handle vb) const - { - return _tds.is_edge(va, vb); - } - bool is_edge(Vertex_handle va, Vertex_handle vb, Face_handle& fr, int & i) const - { - return _tds.is_edge(va, vb, fr, i); - } - bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) const - { - return _tds.is_face(v1, v2, v3); - } - bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, - Face_handle &fr) const - { - return _tds.is_face(v1, v2, v3, fr); - } - // \} - - /// \name Queries - // \{ - - /// Wrapper function for locate if only the requested point is given. - Face_handle locate(const Point &p, Face_handle start = Face_handle()) const - { - Locate_type lt; - int li; - return locate(p, Offset(), lt, li, start); - } - - /// Wrapper function for locate if the offset is omitted. - Face_handle locate(const Point& p, Locate_type& lt, int& li, - Face_handle start = Face_handle()) const - { - return locate(p, Offset(), lt, li, start); - } - - /// Returns the oriented side of the point p with respect to the - /// triangle defined by the face f - Oriented_side oriented_side(Face_handle f, const Point& p) const - { - return oriented_side(f, p, Offset()); - } - - // \} - - - /// \name Traversal of the Triangulation - // \{ - /// Iterator over all stored vertices. Starts at an arbitrary vertex. - /// Returns vertices_end() if t.number_of_vertices()=0. - Vertex_iterator vertices_begin() const - { - return _tds.vertices_begin(); - } - /// Past the end Vertex_iterator. - Vertex_iterator vertices_end() const - { - return _tds.vertices_end(); - } - /// Iterator over all stored edges. Starts at an arbitrary edge. - /// Returns edges_end() if t.number_of_vertices()=0. - Edge_iterator edges_begin() const - { - return _tds.edges_begin(); - } - /// Past the end Edge_iterator. - Edge_iterator edges_end() const - { - return _tds.edges_end(); - } - /// Iterator over all stored faces. Starts at an arbitrary face. - /// Returns faces_end() if t.number_of_vertices()=0. - Face_iterator faces_begin() const - { - return _tds.faces_begin(); - } - /// Past the end Face_iterator. - Face_iterator faces_end() const - { - return _tds.faces_end(); - } - - /// Iterator over all stored vertices. Starts at an arbitrary vertex. - /// Returns vertices_end() if t.number_of_vertices()=0. - Vertex_iterator finite_vertices_begin() const - { - return _tds.vertices_begin(); - } - /// Past the end Vertex_iterator. - Vertex_iterator finite_vertices_end() const - { - return _tds.vertices_end(); - } - /// Iterator over all stored edges. Starts at an arbitrary edge. - /// Returns edges_end() if t.number_of_vertices()=0. - Edge_iterator finite_edges_begin() const - { - return _tds.edges_begin(); - } - /// Past the end Edge_iterator. - Edge_iterator finite_edges_end() const - { - return _tds.edges_end(); - } - /// Iterator over all stored faces. Starts at an arbitrary face. - /// Returns faces_end() if t.number_of_vertices()=0. - Face_iterator finite_faces_begin() const - { - return _tds.faces_begin(); - } - /// Past the end Face_iterator. - Face_iterator finite_faces_end() const - { - return _tds.faces_end(); - } - - /// Iterator over all stored vertices. Starts at an arbitrary vertex. - /// Returns vertices_end() if t.number_of_vertices()=0. - Vertex_iterator all_vertices_begin() const - { - return _tds.vertices_begin(); - } - /// Past the end Vertex_iterator. - Vertex_iterator all_vertices_end() const - { - return _tds.vertices_end(); - } - /// Iterator over all stored edges. Starts at an arbitrary edge. - /// Returns edges_end() if t.number_of_vertices()=0. - Edge_iterator all_edges_begin() const - { - return _tds.edges_begin(); - } - /// Past the end Edge_iterator. - Edge_iterator all_edges_end() const - { - return _tds.edges_end(); - } - /// Iterator over all stored faces. Starts at an arbitrary face. - /// Returns faces_end() if t.number_of_vertices()=0. - Face_iterator all_faces_begin() const - { - return _tds.faces_begin(); - } - /// Past the end Face_iterator. - Face_iterator all_faces_end() const - { - return _tds.faces_end(); - } - - /// begin iterator over the non-virtual vertices - Unique_vertex_iterator unique_vertices_begin() const - { - return CGAL::filter_iterator(vertices_end(), - Periodic_4_hyperbolic_triangulation_2_internal::Domain_tester(this), - vertices_begin()); - } - /// past-the-end iterator over the non-virtual vertices - Unique_vertex_iterator unique_vertices_end() const - { - return CGAL::filter_iterator(vertices_end(), - Periodic_4_hyperbolic_triangulation_2_internal::Domain_tester(this)); - } - - // \} - /// \name Geometric iterators - //\{ - - /// Start iterator over the points - Periodic_point_iterator periodic_points_begin(Iterator_type it = STORED) const - { - return Periodic_point_iterator(this, it); - } - /// Past-the-end iterator over the points - Periodic_point_iterator periodic_points_end(Iterator_type it = STORED) const - { - return Periodic_point_iterator(this, 1, it); - } - - /// Start iterator over the segments - Periodic_segment_iterator periodic_segments_begin(Iterator_type it = STORED) const - { - return Periodic_segment_iterator(this, it); - } - /// Past-the-end iterator over the segments - Periodic_segment_iterator periodic_segments_end(Iterator_type it = STORED) const - { - return Periodic_segment_iterator(this, 1, it); - } - - /// Start iterator over the triangles - Periodic_triangle_iterator periodic_triangles_begin(Iterator_type it = STORED) const - { - return Periodic_triangle_iterator(this, it); - } - /// Past-the-end iterator over the triangles - Periodic_triangle_iterator periodic_triangles_end(Iterator_type it = STORED) const - { - return Periodic_triangle_iterator(this, 1, it); - } - //\} - - /// \name Incident simplices - // \{ - - Face_circulator incident_faces(Vertex_handle v, Face_handle f = Face_handle()) const - { - return _tds.incident_faces(v, f); - } - Edge_circulator incident_edges(Vertex_handle v, Face_handle f = Face_handle()) const - { - return _tds.incident_edges(v, f); - } -/* Vertex_circulator incident_vertices(Vertex_handle v, Face_handle f = */ -/* Face_handle()) const */ -/* { */ -/* bool DEPRECATED_USE_ADJACENT_VERTICES; */ -/* return adjacent_vertices(v, f); */ -/* } */ - Vertex_circulator adjacent_vertices(Vertex_handle v, Face_handle f = - Face_handle()) const - { - return _tds.incident_vertices(v, f); - } - // \} - - /// \name Traversal between adjacent faces - // \{ - - Vertex_handle mirror_vertex(Face_handle f, int i) const - { - return _tds.mirror_vertex(f, i); - } - int mirror_index(Face_handle f, int i) const - { - return _tds.mirror_index(f, i); - } - //\} - - - /// \name Modifiers - // \{ - - /// Flips the edge and all periodic copies - void flip(Face_handle f, int i); - - /// Inserts a point in the triangulation - /// \param p the point to be inserted - /// \param start the start face for point location - /// \return The new vertex handle or an existing Vertex_handle if p was inserted before - Vertex_handle insert(const Point &p, Face_handle start = Face_handle()); - - /// Inserts a point in the triangulation - /// \pre The point has been located in the triangulation - Vertex_handle insert(const Point& p, Locate_type lt, Face_handle loc, int li); - - /// Insert a point in the triangulation - Vertex_handle push_back(const Point& p) - { - return insert(p); - } - - // \} - - /// \name Advanced modifiers - //\{ - - /// Insert the first vertex in the triangulation and creates the 9-cover. - Vertex_handle insert_first(const Point& p); - /// Inserts p in the face f and sets the offsets of the newly created faces - /// Insert periodic copies in all periodic copies of the domain - Vertex_handle insert_in_face(const Point& p, Face_handle f); - /// Inserts (p,o) in the edge (f,i) and sets the offsets of the newly created faces - /// Insert periodic copies in all periodic copies of the domain - Vertex_handle insert_in_edge(const Point& p, Face_handle f, int i); - - /// Remove a degree 3 vertex from a 2D triangulation - void remove_degree_3(Vertex_handle v); - - bool remove_degree_init(Vertex_handle v, const Offset &v_o, - std::vector &f, - std::vector &w, std::vector &offset_w, - std::vector &i, int &d, int &maxd, bool &simplicity_criterion); - - /// Remove a vertex from a 2D triangulation with number_of_vertices() == 1 - void remove_first(Vertex_handle v); - - /// Changes the domain. Note that this function calls clear(), i.e., - /// it erases the existing triangulation. - void set_domain(const Iso_rectangle &domain) - { - clear(); - _domain = domain; - _gt.set_domain(_domain); - _edge_length_threshold = - FT(0.166) * (_domain.xmax() - _domain.xmin()) * (_domain.xmax() - _domain.xmin()); - } - //\} - - - /// \name Point location - - /// Do a remembering heuristic walk to locate point (p,o) - Face_handle - march_locate_2D(Face_handle f, const Point& p, const Offset& o, - Locate_type& lt, int& li) const; - - /// Checks whether the result of two point location queries are equivalent. - bool - compare_walks(const Point& p, Face_handle c1, Face_handle c2, - Locate_type& lt1, Locate_type& lt2, int li1, int li2) const; - - /// Testing where the point (p,off) lies w.r.t. the face f - Bounded_side side_of_face(const Point &p, const Offset &off, Face_handle f, - Locate_type <, int &li) const; - /// Testing where the point (p,off) lies w.r.t. the face f - Bounded_side side_of_face(const Point &p, Face_handle f, Locate_type <, - int &li) const - { - return side_of_face(p, Offset(), f, lt, li); - } - //\} - - /// \name Predicates and Constructions - //\{ - /// Determines whether the point p lies on the (un-)bounded side of - /// the triangle (p0,p1,p2) - Bounded_side - bounded_side(const Point &p0, const Point &p1, const Point &p2, const Point &p) const; - - /// Determines whether the point (p,o) lies on the (un-)bounded side of - /// the triangle ((p0,o0),(p1,o1),(p2,o2)) - Bounded_side - bounded_side(const Point &p0, const Point &p1, const Point &p2, const Point &p, - const Offset &o0, const Offset &o1, const Offset &o2, const Offset &o) const; - - /// Determines whether the point q lies strictly between the points p and r - /// p,q and r are supposed to be collinear points - bool - collinear_between(const Point& p, const Point& q, const Point& r) const; - - /// Determines whether the point (q,o_q) lies strictly between the points (p,o_p) and (r,o_r) - /// (q,o_q), (p,o_p) and (r,o_r) are supposed to be collinear points - bool - collinear_between(const Point& p, const Point& q, const Point& r, - const Offset& o_p, const Offset& o_q, const Offset& o_r) const; - - /// Compares the x-coordinates of p and q - Comparison_result compare_x(const Point& p, const Point& q) const; - /// Compares the x-coordinates of (p,o_p) and (q,o_q) - Comparison_result compare_x(const Point& p, const Point& q, - const Offset &o_p, const Offset &o_q) const; - - /// Compares p and q lexicographically - Comparison_result compare_xy(const Point& p, const Point& q, - const Offset &o_p, const Offset &o_q) const; - /// Compares (p,o_p) and (q,o_q) lexicographically - Comparison_result compare_xy(const Point& p, const Point& q) const; - /// Compares the x-coordinates of p and q - Comparison_result compare_y(const Point& p, const Point& q) const; - /// Compares the x-coordinates of (p,o_p) and (q,o_q) - Comparison_result compare_y(const Point& p, const Point& q, - const Offset &o_p, const Offset &o_q) const; - /// Checks for equality of p and q - bool xy_equal(const Point& p, const Point& q) const; - /// Returns the orientation of p1,p2,p3 - Orientation orientation(const Point& p1, const Point& p2, const Point& p3) const; - /// Returns the orientation of (p1,o1), (p2,o2), (p3,o3) - Orientation orientation(const Point& p1, const Point& p2, const Point& p3, - const Offset& o1, const Offset& o2, const Offset& o3) const; - - /// Determines whether the point p lies on the (un-)bounded side of - /// the circle through the vertices of f - Oriented_side - side_of_oriented_circle(Face_handle f, - const Point & p, bool perturb = false) const; - /// Determines whether the point p lies on the (un-)bounded side of - /// the circle through the points p0, p1 and p2 - Oriented_side - side_of_oriented_circle(const Point &p0, const Point &p1, const Point &p2, - const Point &p, bool perturb) const; - /// Determines whether the point (p,o) lies on the (un-)bounded side of - /// the circle through the points (p0,o0), (p1,o1) and (p2,o2) - Oriented_side - side_of_oriented_circle(const Point &p0, const Point &p1, const Point &p2, - const Point &p, const Offset &o0, const Offset &o1, const Offset &o2, - const Offset &o, bool perturb) const; - - - - /// Constructs the circumcenter of the face f, respects the offset - Point circumcenter(Face_handle f) const - { - return construct_circumcenter(f->vertex(0)->point(), - f->vertex(1)->point(), - f->vertex(2)->point(), - get_offset(f, 0), - get_offset(f, 1), - get_offset(f, 2)); - } - Point construct_circumcenter(const Point &p1, const Point &p2, const Point &p3, - const Offset &o1, const Offset &o2, const Offset &o3) const - { - return geom_traits().construct_circumcenter_2_object()(p1, p2, p3, o1, o2, o3); - } - //\} - - - /// \name Miscellaneous - //\{ - - /// Returns whether the union of the faces f and f->neighbor(i) form - /// a convex quadrilateral. - bool flippable(Face_handle f, int i); - - size_type degree(Vertex_handle v) const - { - return _tds.degree(v); - } - - /// Checks if the triangulation is valid. - bool is_valid(bool verbose = false, int level = 0) const; - /// Checks if the face is valid. - bool is_valid(Face_handle fh, bool verbose = false, int level = 0) const; - - //\} - - - /// \name Undocumented functions, needed by the geometric iterators - // \{ - /// [Undoc] Returns whether the stored triangulation covers a 1-cover. - bool is_1_cover() const - { - return (_cover[0] == 1) && (_cover[1] == 1); - } - - /// [Undoc] Combines two offsets, where the first offset is defined by the - /// virtual vertex and the second by the face. - Offset combine_offsets(const Offset& o_c, const Offset& o_t) const - { - Offset o_ct(_cover[0] * o_t.x(), _cover[1] * o_t.y()); - return o_c + o_ct; - } - /// [Undoc] Returns the offset of nb==ch->neighbor(i) with respect to ch. - /// Get the offset between the origins of the internal offset coordinate - /// systems of two neighboring faces with respect from ch to nb. - /// - /// - Find two corresponding vertices from each face - /// - Return the difference of their offsets. - /// - Offset get_neighbor_offset(Face_handle fh, int i) const - { - Face_handle nb = fh->neighbor(i); - return get_neighbor_offset(fh, i, nb, nb->index(fh)); - } - /// [Undoc] Returns the offset of nb==ch->neighbor(i) with respect to ch. - /// Get the offset between the origins of the internal offset coordinate - /// systems of two neighboring faces with respect from ch to nb. - /// - /// - Find two corresponding vertices from each face - /// - Return the difference of their offsets. - /// - Offset get_neighbor_offset(Face_handle fh, int i, Face_handle nb, int j) const - { - // Redundance in the signature - CGAL_triangulation_precondition(fh->neighbor(i) == nb); - CGAL_triangulation_precondition(nb->neighbor(j) == fh); - CGAL_triangulation_precondition(fh->vertex(cw(i)) == nb->vertex(ccw(j))); - - return int_to_off(nb->offset(ccw(j))) - int_to_off(fh->offset(cw(i))); - } - /// [Undoc] returns the combined offset of the vertex - /// (if we are not on the 1-cover) and the offset defined by the face. - Offset get_offset(Face_handle f, int i) const - { - if (is_1_cover()) - return int_to_off(f->offset(i)); - - Virtual_vertex_map_it it = _virtual_vertices.find(f->vertex(i)); - if (it != _virtual_vertices.end()) - return combine_offsets(it->second.second, int_to_off(f->offset(i))); - else - return combine_offsets(Offset(), int_to_off(f->offset(i))); - } - /// [Undoc] Returns the offset of the vertex if we are not on the 1-cover. - Offset get_offset(Vertex_handle vh) const - { - if (is_1_cover()) - return Offset(); - Virtual_vertex_map_it it = _virtual_vertices.find(vh); - if (it != _virtual_vertices.end()) - return it->second.second; - else - return Offset(); - } - - /// Converts an offset to a bit pattern where bit1==offx and bit0==offy. - int off_to_int(const Offset & off) const - { - CGAL_triangulation_assertion( off.x() == 0 || off.x() == 1 ); - CGAL_triangulation_assertion( off.y() == 0 || off.y() == 1 ); - int i = ((off.x() & 1) << 1) + (off.y() & 1); - return i; - } - /// Creates an offset from a bit pattern. - Offset int_to_off(int i) const - { - return Offset((i >> 1) & 1, i & 1); - } - - // \} - // Protected functions of Periodic_4_hyperbolic_triangulation_2 - /// Const accessor to the virtual vertices reverse map, - /// used to optimize point location for periodic copies. - const Virtual_vertex_reverse_map &virtual_vertices_reverse() const - { - return _virtual_vertices_reverse; - } - - /// [Undoc] Returns the non-virtual copy of the vertex. - Vertex_handle get_original_vertex(Vertex_handle vh) const - { - if (is_1_cover()) - return vh; - Virtual_vertex_map_it it = _virtual_vertices.find(vh); - if (it != _virtual_vertices.end()) - return it->second.first; - else - return vh; - } - - - /// Tests whether a vertex is a periodic copy of a vertex in the 3-cover. - bool is_virtual(Vertex_handle v) - { - if (is_1_cover()) - return false; - return (_virtual_vertices.find(v) != _virtual_vertices.end()); - } - - const std::vector& periodic_copies(const Vertex_handle v) const - { - CGAL_triangulation_precondition(number_of_sheets() != make_array(1, 1) ); - CGAL_triangulation_precondition(_virtual_vertices.find(v) == _virtual_vertices.end()); - CGAL_triangulation_assertion(_virtual_vertices_reverse.find(v) != _virtual_vertices_reverse.end()); - return _virtual_vertices_reverse.find(v)->second; - } - - template - Stream& draw_triangulation(Stream& os) const - { - Edge_iterator it = edges_begin(); - for (; it != edges_end(); ++it) - { - os << segment(it); - } - return os; - } -protected: - std::vector insert_dummy_points(); - - - inline void try_to_convert_to_one_cover() - { - // Fall back to 1-cover if the criterion that the longest edge is shorter - // than sqrt(0.166) is fulfilled. - if (_too_long_edge_counter == 0 && !is_1_cover()) - { - CGAL_triangulation_expensive_assertion( is_valid() ); - this->convert_to_1_sheeted_covering(); - CGAL_triangulation_expensive_assertion( is_valid() ); - } - } - -protected: - // Protected functions of Periodic_4_hyperbolic_triangulation_2 - - /// Inserts a point with an offset in the triangulation - /// \pre The point has been located in the triangulation - Vertex_handle insert(const Point& p, const Offset& o, Locate_type lt, - Face_handle loc, int li, Vertex_handle vh); - - /// \name Helper functions for queries - // \{ - - /// Locates the simplex containing the point represented by p and o. - /// - /// The type of the simplex is stored in lt. - /// The simplex containing the point is returned using lt and li. - /// The Face_handle start is the start point of the heuristic walk. - Face_handle - locate(const Point& p, const Offset &o, Locate_type& lt, int& li, - Face_handle start = Face_handle()) const; - /// Returns the oriented side of the point (p,o) with respect to the - /// triangle defined by the face f - Oriented_side - oriented_side(Face_handle f, const Point& p, const Offset &o) const; - // \} - - /// \name Insertion helpers - //\{ - /// Insert too long edges in the star of v - void insert_too_long_edges_in_star(Vertex_handle v); - - /// Insert too long edge - void insert_too_long_edge(Face_handle f, int i); - - /// Remove too long edges in the star of v - void remove_too_long_edges_in_star(Vertex_handle v); - - /// Removes an edge if it is too long - void remove_too_long_edge(Face_handle f, int i); - - /// Check whether an edge is too long - bool edge_is_too_long(const Point &p1, const Point &p2) const; - - /// Flips the edge, no periodic copies are flipped - void flip_single_edge(Face_handle f, int i); - - /// Remove a vertex from the virtual copies maps - /// Used when a Delaunay vertex is removed - void remove_from_virtual_copies(Vertex_handle v); - //\} - - /// \name Wrapping the traits - //\{ - Point construct_point(const Point& p, const Offset &o) const - { - return geom_traits().construct_point_2_object()(p, o); - } - Point construct_point(const Periodic_point& pp) const - { - return construct_point(pp.first, pp.second); - } - Triangle construct_triangle(const Point &p1, const Point &p2, - const Point &p3, const Offset &o1, const Offset &o2, const Offset &o3) const - { - return geom_traits().construct_triangle_2_object()(p1, p2, p3, o1, o2, o3); - } - Triangle construct_triangle(const Periodic_triangle& tri) const - { - return construct_triangle(tri[0].first, tri[1].first, tri[2].first, - tri[0].second, tri[1].second, tri[2].second); - } - Segment construct_segment(const Point &p1, const Point &p2, const Offset &o1, - const Offset &o2) const - { - return geom_traits().construct_segment_2_object()(p1, p2, o1, o2); - } - Segment construct_segment(const Periodic_segment& seg) const - { - return construct_segment(seg[0].first, seg[1].first, seg[0].second, - seg[1].second); - } - //\} - - /// Test whether removing vertex v decreases the dimension of the triangulation. - bool test_dim_down(Vertex_handle /*v*/) const - { - //test the dimensionality of the resulting triangulation - //upon removing of vertex v - return number_of_vertices() == 1; - } - void make_hole(Vertex_handle v, std::list & hole); - - - Face_handle create_face(Face_handle f1, int i1, Face_handle f2, int i2, Face_handle f3, int i3); - Face_handle create_face(Face_handle f1, int i1, Face_handle f2, int i2); - Face_handle create_face(Face_handle f, int i, Vertex_handle v); - Face_handle create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3); - Face_handle create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle f1, Face_handle f2, Face_handle f3); - Face_handle create_face(); - Face_handle create_face(Face_handle); //calls copy constructor of Face - void delete_face(Face_handle f); - void delete_vertex(Vertex_handle v); - - // template members - - bool well_oriented(Vertex_handle v) const - { - Face_circulator fc = incident_faces(v), done(fc); - do - { - Orientation o; - - Vertex_handle v0 = fc->vertex(0); - Vertex_handle v1 = fc->vertex(1); - Vertex_handle v2 = fc->vertex(2); - if (fc->has_zero_offsets()) - { - o = orientation(v0->point(), v1->point(), v2->point()); - } - else - { - Offset off0 = get_offset(fc, 0); - Offset off1 = get_offset(fc, 1); - Offset off2 = get_offset(fc, 2); - o = orientation(v0->point(), v1->point(), v2->point(), off0, off1, off2); - } - if (o != COUNTERCLOCKWISE) return false; - } - while (++fc != done); - return true; - } - - template - Vertex_handle star_hole(const Point& p, EdgeIt edge_begin, EdgeIt edge_end) - { - std::list empty_list; - return star_hole(p, edge_begin, edge_end, empty_list.begin(), - empty_list.end()); - } - - template - Vertex_handle star_hole(const Point& p, EdgeIt edge_begin, EdgeIt edge_end, - FaceIt face_begin, FaceIt face_end) - { - CGAL_assertion(is_1_cover()); - - Vertex_handle v = _tds.star_hole(edge_begin, edge_end, face_begin, face_end); - v->set_point(p); - return v; - } - - /// Periodic functions - //\{ - - /// These functions give the pair (vertex, offset) that corresponds - /// to the i-th vertex of face f. The vertex returned is not a virtual copy. - void get_vertex(Face_handle f, int i, Vertex_handle &vh, Offset &off) const; - /// These functions give the pair (vertex, offset) that corresponds - /// to the i-th vertex of vertex vh. The vertex returned is not a virtual copy. - void get_vertex(Vertex_handle vh_i, Vertex_handle &vh, Offset &off) const; - /// Returns the face containing the three vertices defined by vh[0], vh1[1] and vh[2]. - inline Face_handle get_face(const Vertex_handle* vh) const; - /// Constructs a list of too long edges in the triangulation. - int find_too_long_edges( - std::map >& edges) const; - - /// Returns the offset such that (p, o) lies on the bounded side of the face f. - Offset get_location_offset(Face_handle f, const Point &p, const Offset &o) const - { - CGAL_triangulation_precondition( number_of_vertices() != 0 ); - - if (is_1_cover() && f->has_zero_offsets()) - { - // default case: - return Offset(); - } - else - { - int cumm_off = f->offset(0) | f->offset(1) | f->offset(2); - // Special case for the periodic space. - // Fetch vertices and respective offsets of c from _virtual_vertices - const Point *pts[3]; - Offset off[3]; - for (int i = 0; i < 3; i++) - { - pts[i] = &(f->vertex(i)->point()); - off[i] = get_offset(f, i); - } - - // Main idea seems to just test all possibilities. - for (int i = 0; i < 4; i++) - { - if (((cumm_off | (~i)) & 3) == 3) - { - if (bounded_side(*pts[0], *pts[1], *pts[2], p, off[0], off[1], - off[2], combine_offsets(o, int_to_off(i))) != ON_UNBOUNDED_SIDE) - { - return int_to_off(i); - } - } - } - } - CGAL_assertion(false); - return Offset(); - } - - /// Assigns the offsets to the vertices of the face f, and makes the offset minimal in each direction. - void set_offsets(Face_handle f, int o0, int o1, int o2) - { - int off0[2] = { (o0 >> 1) & 1, (o0 & 1) }; - int off1[2] = { (o1 >> 1) & 1, (o1 & 1) }; - int off2[2] = { (o2 >> 1) & 1, (o2 & 1) }; - // Make sure that there is at least one zero offset in every direction - for (int i = 0; i < 2; i++) - { - int min_off = (std::min)((std::min)(off0[i], off1[i]), off2[i]); - if (min_off != 0) - { - off0[i] -= min_off; - off1[i] -= min_off; - off2[i] -= min_off; - } - } - o0 = ((off0[0] & 1) << 1) + (off0[1] & 1); - o1 = ((off1[0] & 1) << 1) + (off1[1] & 1); - o2 = ((off2[0] & 1) << 1) + (off2[1] & 1); - f->set_offsets(o0, o1, o2); - } - - /// Assigns the offsets to the vertices of the face f, and makes the offset minimal in each direction. - template - void set_offsets(Face_handle f, const Offset &o0, const Offset &o1, const Offset &o2) - { - int off0[2] = { o0.x(), o0.y() }; - int off1[2] = { o1.x(), o1.y() }; - int off2[2] = { o2.x(), o2.y() }; - for (int i = 0; i < 2; i++) - { - int min_off = (std::min)((std::min)(off0[i], off1[i]), off2[i]); - if (min_off != 0) - { - off0[i] -= min_off; - off1[i] -= min_off; - off2[i] -= min_off; - } - } - - CGAL_triangulation_assertion((std::min)((std::min)(off0[0], off1[0]), off2[0]) == 0); - CGAL_triangulation_assertion((std::min)((std::min)(off0[1], off1[1]), off2[1]) == 0); - CGAL_triangulation_assertion((0 <= off0[0]) && (off0[0] < 2)); - CGAL_triangulation_assertion((0 <= off1[0]) && (off1[0] < 2)); - CGAL_triangulation_assertion((0 <= off2[0]) && (off2[0] < 2)); - CGAL_triangulation_assertion((0 <= off0[1]) && (off0[1] < 2)); - CGAL_triangulation_assertion((0 <= off1[1]) && (off1[1] < 2)); - CGAL_triangulation_assertion((0 <= off2[1]) && (off2[1] < 2)); - - int o0i = ((off0[0] & 1) << 1) + (off0[1] & 1); - int o1i = ((off1[0] & 1) << 1) + (off1[1] & 1); - int o2i = ((off2[0] & 1) << 1) + (off2[1] & 1); - f->set_offsets(o0i, o1i, o2i); - } - //\} - - /// Checks the too_long_edges bookkeeping - bool is_valid_too_long_edges(bool verbose = false, int level = 0) const; - - /** @name Checking helpers */ //@{ - /// calls has_self_edges for every face of the triangulation - bool has_self_edges() const - { - Face_iterator it; - for ( it = all_faces_begin(); it != all_faces_end(); ++it ) - if (has_self_edges(it)) return true; - return false; - } - bool has_self_edges(Face_handle fh) const - { - CGAL_triangulation_assertion((fh->vertex(0) != fh->vertex(1)) || - (fh->offset(0) != fh->offset(1))); - CGAL_triangulation_assertion((fh->vertex(0) != fh->vertex(2)) || - (fh->offset(0) != fh->offset(2))); - CGAL_triangulation_assertion((fh->vertex(1) != fh->vertex(2)) || - (fh->offset(1) != fh->offset(2))); - return ((fh->vertex(0) == fh->vertex(1)) || - (fh->vertex(0) == fh->vertex(2)) || - (fh->vertex(1) == fh->vertex(2))); - } - - //@} - - -protected: - // Protected data of Periodic_4_hyperbolic_triangulation_2 - /// \name Triangulation data members - // \{ - - /// Geometric traits - Gt _gt; - /// Triangulation data structure - Tds _tds; - // \} - - /// Returns false, no infinite simplices in the periodic triangulation - template - inline bool is_infinite(T) const - { - return false; - } - -private: - /// Inserts (p,o) in the face f and sets the offsets of the newly created faces - /// Doesn't insert periodic copies - Vertex_handle insert_in_face(const Point& p, const Offset &o, - Face_handle f, - Vertex_handle vh); - /// Inserts (p,o) in the edge (f,i) and sets the offsets of the newly created faces - /// Doesn't insert periodic copies - Vertex_handle insert_in_edge(const Point& p, const Offset &o, - Face_handle f, int i, - Vertex_handle vh); - - /// Remove a vertex without removing it's possible periodic copies. - /// Helper functions - void remove_degree_3_single_copy(Vertex_handle vh); - - // Private data of Periodic_4_hyperbolic_triangulation_2 - /// \name Periodic members - //\{ - - /// Determines if we currently compute in 3-cover or 1-cover. - Covering_sheets _cover; - - /// The domain - Iso_rectangle _domain; - - /// This threshold should be chosen such that if all edges are shorter, - /// we can be sure that there are no self-edges anymore. - FT _edge_length_threshold; - - /// This adjacency list stores all edges that are longer than - /// edge_length_threshold. - Too_long_edges_map _too_long_edges; - /// Number of edges that are too long - size_t _too_long_edge_counter; - - /// map of offsets for periodic copies of vertices - Virtual_vertex_map _virtual_vertices; - /// map of a non-virtual vertex to its virtual copies - Virtual_vertex_reverse_map _virtual_vertices_reverse; - //\} -}; // class Periodic_4_hyperbolic_triangulation_2 - -// CONSTRUCTORS -template -Periodic_4_hyperbolic_triangulation_2::Periodic_4_hyperbolic_triangulation_2( - const Iso_rectangle & domain, const Geom_traits& geom_traits) - : _gt(geom_traits), _tds() - , _cover(make_array(1, 1)) - , _domain(domain) - , _too_long_edge_counter(0) -{ - CGAL_triangulation_precondition(_domain.xmax() - _domain.xmin() == - _domain.ymax() - _domain.ymin()); - set_domain(_domain); -} - -// copy constructor duplicates vertices and faces -template -Periodic_4_hyperbolic_triangulation_2::Periodic_4_hyperbolic_triangulation_2(const Periodic_4_hyperbolic_triangulation_2 &tr) -{ - copy_triangulation(tr); -} - -//Assignment -template -Periodic_4_hyperbolic_triangulation_2 & -Periodic_4_hyperbolic_triangulation_2::operator=( - const Periodic_4_hyperbolic_triangulation_2 &tr) -{ - copy_triangulation(tr); - return *this; -} - -// Helping functions -template < class GT, class Tds > -class Periodic_4_hyperbolic_triangulation_2::Finder -{ - const Self* _t; - const Point & _p; -public: - Finder(const Self* t, const Point &p) : _t(t), _p(p) {} - bool operator()(const Vertex_handle v) - { - return _t->xy_equal(v->point(), _p); - } -}; - -template < class GT, class Tds > -inline void -Periodic_4_hyperbolic_triangulation_2:: -copy_multiple_covering(const Periodic_4_hyperbolic_triangulation_2 & tr) -{ - // Write the respective offsets in the vertices to make them - // automatically copy with the tds. - for (Vertex_iterator vit = tr.vertices_begin() ; - vit != tr.vertices_end() ; ++vit) - { - vit->set_offset(tr.get_offset(vit)); - } - // copy the tds - _tds = tr.tds(); - // make a list of all vertices that belong to the original - // domain and initialize the basic structure of - // virtual_vertices_reverse - std::list vlist; - for (Vertex_iterator vit = vertices_begin() ; - vit != vertices_end() ; ++vit) - { - if (vit->offset() == Offset()) - { - vlist.push_back(vit); - _virtual_vertices_reverse.insert( - std::make_pair(vit, std::vector(8))); - CGAL_triangulation_assertion(_virtual_vertices_reverse.find(vit) - ->second.size() == 8); - } - } - // Iterate over all vertices that are not in the original domain - // and construct the respective entries to virtual_vertices and - // virtual_vertices_reverse - for (Vertex_iterator vit2 = vertices_begin() ; - vit2 != vertices_end() ; ++vit2) - { - if (vit2->offset() != Offset()) - { - //TODO: use some binding, maybe boost instead of the Finder. - typename std::list::iterator vlist_it - = std::find_if(vlist.begin(), vlist.end(), - Finder(this, vit2->point())); - Offset off = vit2->offset(); - _virtual_vertices.insert(std::make_pair(vit2, - std::make_pair(*vlist_it, off))); - _virtual_vertices_reverse.find(*vlist_it) - ->second[3 * off[0] + off[1] - 1] = vit2; - CGAL_triangulation_assertion(get_offset(vit2) == off); - } - } - // Cleanup vertex offsets - for (Vertex_iterator vit = vertices_begin() ; - vit != vertices_end() ; ++vit) - vit->clear_offset(); - for (Vertex_iterator vit = tr.vertices_begin() ; - vit != tr.vertices_end() ; ++vit) - vit->clear_offset(); - // Build up the too_long_edges container - _too_long_edge_counter = 0; - _too_long_edges.clear(); - for (Vertex_iterator vit = vertices_begin() ; - vit != vertices_end() ; ++vit) - _too_long_edges[vit] = std::list(); - std::pair edge_to_add; - Point p1, p2; - int i, j; - for (Edge_iterator eit = edges_begin() ; - eit != edges_end() ; ++eit) - { - if (&*(eit->first->vertex(cw(eit->second))) - < &*(eit->first->vertex(ccw(eit->second)))) - { - i = cw(eit->second); - j = ccw(eit->second); - } - else - { - i = ccw(eit->second); - j = cw(eit->second); - } - edge_to_add = std::make_pair(eit->first->vertex(i), - eit->first->vertex(j)); - p1 = construct_point(eit->first->vertex(i)->point(), - get_offset(eit->first, i)); - p2 = construct_point(eit->first->vertex(j)->point(), - get_offset(eit->first, j)); - Vertex_handle v_no = eit->first->vertex(i); - if (squared_distance(p1, p2) > _edge_length_threshold) - { - CGAL_triangulation_assertion( - find(_too_long_edges[v_no].begin(), - _too_long_edges[v_no].end(), - edge_to_add.second) == _too_long_edges[v_no].end()); - _too_long_edges[v_no].push_back(edge_to_add.second); - _too_long_edge_counter++; - } - } -} - -template -void Periodic_4_hyperbolic_triangulation_2::copy_triangulation( - const Periodic_4_hyperbolic_triangulation_2 &tr) -{ - _tds.clear(); - _gt = tr._gt; - _cover = tr._cover; - _domain = tr._domain; - _edge_length_threshold = tr._edge_length_threshold; - _too_long_edge_counter = tr._too_long_edge_counter; - if (tr.is_1_cover()) - { - _tds = tr.tds(); - } - else - { - copy_multiple_covering(tr); - } - CGAL_assertion(_too_long_edge_counter == tr._too_long_edge_counter); - CGAL_triangulation_expensive_postcondition(*this == tr); -} - -template -void Periodic_4_hyperbolic_triangulation_2::swap(Periodic_4_hyperbolic_triangulation_2 &tr) -{ - _tds.swap(tr._tds); - - Geom_traits t = geom_traits(); - _gt = tr.geom_traits(); - tr._gt = t; - - std::swap(tr._cover, _cover); - std::swap(tr._domain, _domain); - - std::swap(tr._edge_length_threshold, _edge_length_threshold); - std::swap(tr._too_long_edges, _too_long_edges); - std::swap(tr._too_long_edge_counter, _too_long_edge_counter); - - std::swap(tr._virtual_vertices, _virtual_vertices); - std::swap(tr._virtual_vertices_reverse, _virtual_vertices_reverse); -} - -template -void Periodic_4_hyperbolic_triangulation_2::clear() -{ - _tds.clear(); - _tds.set_dimension(-2); - - _too_long_edges.clear(); - _too_long_edge_counter = 0; - - _virtual_vertices.clear(); - _virtual_vertices_reverse.clear(); - - _cover = make_array(1, 1); -} - -template -bool Periodic_4_hyperbolic_triangulation_2::is_valid(Face_handle fh, bool /*verbose*/, int /*level*/) const -{ - bool result = true; - - int xmin, xmax, ymin, ymax; - xmin = ymin = 3; - xmax = ymax = 0; - for (int i = 0; i < 3; ++i) - { - Offset o = get_offset(fh, i); - xmin = (std::min)(xmin, o[0]); - xmax = (std::max)(xmax, o[0]); - ymin = (std::min)(ymin, o[1]); - ymax = (std::max)(ymax, o[1]); - } - // Should at most cross 1 border in each direction - result &= (xmax - xmin <= 1); - result &= (ymax - ymin <= 1); - if (!result) - { - std::cerr << "min/max: " << xmin << "," << xmax << " " << ymin << "," << ymax << std::endl; - for (int i = 0; i < 3; ++i) - { - Offset o = get_offset(fh, i); - std::cerr << "Offset: " << o << std::endl; - } - std::cerr << std::endl; - CGAL_triangulation_assertion(false); - } - - return result; -} - -template -bool Periodic_4_hyperbolic_triangulation_2::is_valid(bool verbose, int level) const -{ - bool result = _tds.is_valid(verbose, level); - CGAL_triangulation_assertion(result); - - if (dimension() == 2) - { - // Check positive orientation: - const Point *p[3]; - Offset off[3]; - for (Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) - { - for (int i = 0; i < 3; i++) - { - p[i] = &fit->vertex(i)->point(); - off[i] = get_offset(fit, i); - } - - if (orientation(*p[0], *p[1], *p[2], off[0], off[1], off[2]) != POSITIVE) - { - if (verbose) - { - std::cerr - << "Periodic_4_hyperbolic_triangulation_2: wrong orientation:" << "\n" - << *p[0] << " \t" << off[0] << "\n" - << *p[1] << " \t" << off[1] << "\n" - << *p[2] << " \t" << off[2] << std::endl; - } - result = false; - } - } - } - CGAL_triangulation_assertion(result); - - // Check for the right number of simplices - int copies = number_of_sheets()[0] * number_of_sheets()[1]; - result &= (number_of_stored_vertices() == copies * number_of_vertices()); - result &= (number_of_stored_edges() == copies * number_of_edges()); - result &= (number_of_stored_faces() == copies * number_of_faces()); - CGAL_triangulation_assertion(result); - - // check number of euler characteristic. This cannot be done by the Tds - // which does not know the genus - result &= (number_of_stored_vertices() - number_of_stored_edges() - + number_of_stored_faces() == 0); - CGAL_triangulation_assertion(result); - - result &= !has_self_edges(); - CGAL_triangulation_assertion(result); - - // Edges should not be longer than 1 periodicity - for (Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) - { - result &= is_valid(fit, verbose, level); - } - CGAL_triangulation_assertion(result); - - result &= is_1_cover() == _virtual_vertices.empty(); - result &= is_1_cover() == _virtual_vertices_reverse.empty(); - result &= (_virtual_vertices.size() == (number_of_sheets()[0] - * number_of_sheets()[1] - 1) * _virtual_vertices_reverse.size()); - CGAL_triangulation_assertion(result); - - for (Virtual_vertex_map_it it = _virtual_vertices.begin(); it - != _virtual_vertices.end(); ++it) - { - const Vertex_handle © = it->first; - const Vertex_handle &orig = it->second.first; - const Offset &off = it->second.second; - size_t index = number_of_sheets()[0] * off[0] + off[1] - 1; - Virtual_vertex_reverse_map_it rev_it = _virtual_vertices_reverse.find(orig); - if (rev_it != _virtual_vertices_reverse.end()) - { - if (index < rev_it->second.size()) - { - result &= (rev_it->second[index] == copy); - } - else - { - result &= false; - } - } - else - { - result &= false; - } - } - CGAL_triangulation_assertion(result); - - for (Virtual_vertex_reverse_map_it it = _virtual_vertices_reverse.begin(); it - != _virtual_vertices_reverse.end(); ++it) - { - const std::vector &copies = it->second; - result &= copies.size() == 8; - for (size_t i = 0; i < copies.size(); ++i) - { - Virtual_vertex_map_it copy_it = _virtual_vertices.find(copies[i]); - if (copy_it != _virtual_vertices.end()) - { - result &= copy_it->second.first == it->first; - } - else - { - result &= false; - } - } - } - - // Check the too_long_edges administration - result &= is_valid_too_long_edges(verbose, level); - - return result; -} - -template -bool Periodic_4_hyperbolic_triangulation_2::is_valid_too_long_edges(bool verbose, int /*level*/) const -{ - bool result = true; - - result &= is_1_cover() == _too_long_edges.empty(); - CGAL_triangulation_assertion(result); - size_t too_long_edges = 0; - for (Too_long_edges_map_it it = _too_long_edges.begin(); it - != _too_long_edges.end(); ++it) - { - too_long_edges += it->second.size(); - } - CGAL_triangulation_assertion(result); - if (_too_long_edge_counter != too_long_edges) - { - if (verbose) std::cout << "Too long edge counter is incorrect: " << _too_long_edge_counter << " != " << too_long_edges << std::endl; - result = false; - } - CGAL_triangulation_assertion(result); - - /// Expensive check whether the right too long edges are in the list - if (is_1_cover()) - { - for (Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit) - { - Vertex_handle vh1 = eit->first->vertex(ccw(eit->second)); - Vertex_handle vh2 = eit->first->vertex(cw(eit->second)); - Point p1 = construct_point(vh1->point(), get_offset(eit->first, ccw(eit->second))); - Point p2 = construct_point(vh2->point(), get_offset(eit->first, cw(eit->second))); - result &= (!edge_is_too_long(p1, p2)); - } - CGAL_triangulation_assertion(result); - } - else - { - too_long_edges = 0; - for (Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit) - { - Vertex_handle vh1 = eit->first->vertex(ccw(eit->second)); - Vertex_handle vh2 = eit->first->vertex(cw(eit->second)); - Point p1 = construct_point(vh1->point(), - get_offset(eit->first, ccw(eit->second))); - Point p2 = construct_point(vh2->point(), - get_offset(eit->first, cw(eit->second))); - - if (&*vh2 < &*vh1) - std::swap(vh1, vh2); - CGAL_triangulation_assertion(&*vh1 < &*vh2); - - bool too_long = edge_is_too_long(p1, p2); - if (too_long != edge_is_too_long(p2, p1)) - { - if (verbose) std::cout << "Long edge criterion not symmetric c(v1,v2) != c(v2,v1)" << std::endl; - result = false; - } - CGAL_triangulation_assertion(result); - - Too_long_edges_map_it it = _too_long_edges.find(vh1); - if (it == _too_long_edges.end()) - { - if (too_long) - { - if (verbose) std::cout << "1. Too long edge not in the datastructure" << std::endl; - result = false; - } - result &= !too_long; - CGAL_triangulation_assertion(result); - } - else - { - typename std::list::const_iterator it2 = find(it->second.begin(), it->second.end(), vh2); - if (too_long) - { - too_long_edges++; - if (it2 == it->second.end()) - { - if (verbose) std::cout << "2. Too long edge not in the datastructure" << std::endl; - result = false; - } - CGAL_triangulation_assertion(result); - } - else - { - if (it2 != it->second.end()) - { - if (verbose) std::cout << "Edge is not too long, but contained in the datastructure" << std::endl; - result = false; - } - CGAL_triangulation_assertion(result); - } - } - } - - if (_too_long_edge_counter != too_long_edges) - { - if (verbose) - std::cout << "Counts do not match: " << _too_long_edge_counter << " != " << too_long_edges << std::endl; - result = false; - } - CGAL_triangulation_assertion(result); - } - - return result; -} - -template -bool Periodic_4_hyperbolic_triangulation_2::flippable(Face_handle f, int i) -{ - Face_handle nb = f->neighbor(i); - int j = nb->index(f); - - const Point *p[4]; - - p[0] = &f->vertex(i)->point(); // i - p[1] = &nb->vertex(j)->point(); // opposite - p[2] = &f->vertex(ccw(i))->point(); // ccw - p[3] = &f->vertex(cw(i))->point(); // cw - - if (is_1_cover() && f->has_zero_offsets() && nb->has_zero_offsets()) - { - // if (orientation(*p[0], *p[1], *p[2]) != RIGHT_TURN) - // return false; - // if (orientation(*p[0], *p[1], *p[3]) != LEFT_TURN) - // return false; - if (orientation(*p[0], *p[1], *p[2]) == LEFT_TURN) - return false; - if (orientation(*p[0], *p[1], *p[3]) == RIGHT_TURN) - return false; - } - else - { - Offset off[4]; - off[0] = get_offset(f, i); - off[1] = combine_offsets(get_offset(nb, j), get_neighbor_offset(nb, j, f, i)); - off[2] = get_offset(f, ccw(i)); - off[3] = get_offset(f, cw(i)); - - // if (orientation(*p[0], *p[1], *p[2], off[0], off[1], off[2]) != RIGHT_TURN) - // return false; - // if (orientation(*p[0], *p[1], *p[3], off[0], off[1], off[3]) != LEFT_TURN) - // return false; - if (orientation(*p[0], *p[1], *p[2], off[0], off[1], off[2]) == LEFT_TURN) - return false; - if (orientation(*p[0], *p[1], *p[3], off[0], off[1], off[3]) == RIGHT_TURN) - return false; - } - - return true; -} - -template -void Periodic_4_hyperbolic_triangulation_2::flip(Face_handle f, int i) -{ - if (is_1_cover()) - { - flip_single_edge(f, i); - return; - } - - Vertex_handle vh1 = f->vertex( cw(i)); - Vertex_handle vh2 = f->vertex(ccw(i)); - Virtual_vertex_map_it it_vh1 = _virtual_vertices.find(vh1); - Virtual_vertex_map_it it_vh2 = _virtual_vertices.find(vh2); - - Offset vh1_offset, vh2_offset; - if (it_vh1 != _virtual_vertices.end()) - { - vh1 = it_vh1->second.first; - vh1_offset = it_vh1->second.second; - } - if (it_vh2 != _virtual_vertices.end()) - { - vh2 = it_vh2->second.first; - vh2_offset = it_vh2->second.second; - } - - CGAL_triangulation_assertion( - virtual_vertices_reverse().find(vh1) != virtual_vertices_reverse().end()); - CGAL_triangulation_assertion( - virtual_vertices_reverse().find(vh2) != virtual_vertices_reverse().end()); - const std::vector &v1s = - virtual_vertices_reverse().find(vh1)->second; - const std::vector &v2s = - virtual_vertices_reverse().find(vh2)->second; - - CGAL_assertion(v1s.size() == 8); - CGAL_assertion(v1s.size() == v2s.size()); - - Face_handle fh; - int index=0; - Vertex_handle vh1_copy, vh2_copy; - - // Virtual copies - for (int x = 0; x < 3; ++x) - { - for (int y = 0; y < 3; ++y) - { - int i1 = 3 * ((x + vh1_offset.x()) % 3) + ((y + vh1_offset.y()) % 3); - int i2 = 3 * ((x + vh2_offset.x()) % 3) + ((y + vh2_offset.y()) % 3); - - if (i1 == 0) - vh1_copy = vh1; - else - vh1_copy = v1s[i1 - 1]; - if (i2 == 0) - vh2_copy = vh2; - else - vh2_copy = v2s[i2 - 1]; - - bool found = is_edge(vh1_copy, vh2_copy, fh, index); - CGAL_USE(found); - CGAL_assertion(found); - if (found) - flip_single_edge(fh, index); - } - } - - try_to_convert_to_one_cover(); -} -template -void Periodic_4_hyperbolic_triangulation_2::flip_single_edge(Face_handle f, int i) -{ - CGAL_triangulation_precondition(f != Face_handle()); - CGAL_triangulation_precondition(i == 0 || i == 1 || i == 2); - CGAL_triangulation_precondition(dimension() == 2); - - CGAL_triangulation_precondition(flippable(f, i)); - - if (!is_1_cover()) - remove_too_long_edge(f, i); - - Face_handle nb = f->neighbor(i); - if (f->has_zero_offsets() && nb->has_zero_offsets()) - { - _tds.flip(f, i); - - if (!is_1_cover()) - insert_too_long_edge(f, ccw(i)); - - return; - } - - int nb_index = nb->index(f); - int offsets[4]; - offsets[0] = f->offset(i); - offsets[1] = f->offset(cw(i)); - offsets[2] = f->offset(ccw(i)); - offsets[3] = nb->offset(nb_index); - - // Move the offsets of f and nb in the same space by correcting for nb_offset - Offset nb_offset = get_neighbor_offset(f, i, nb, nb_index); - if (nb_offset.x() != 0) - { - if (nb_offset.x() == 1) - { - CGAL_assertion(((offsets[0] & 2) | (offsets[1] & 2) | (offsets[2] & 2)) == 0); - offsets[0] |= 2; - offsets[1] |= 2; - offsets[2] |= 2; - } - else - { - CGAL_triangulation_assertion(nb_offset.x() == -1); - CGAL_assertion((offsets[3] & 2) == 0); - offsets[3] |= 2; - } - } - if (nb_offset.y() != 0) - { - if (nb_offset.y() == 1) - { - CGAL_assertion(((offsets[0] & 1) | (offsets[1] & 1) | (offsets[2] & 1)) == 0); - offsets[0] |= 1; - offsets[1] |= 1; - offsets[2] |= 1; - } - else - { - CGAL_triangulation_assertion(nb_offset.y() == -1); - CGAL_assertion((offsets[3] & 1) == 0); - offsets[3] |= 1; - } - } - CGAL_assertion((offsets[0] & offsets[1] & offsets[2] & offsets[3]) == 0); - CGAL_triangulation_assertion_code(Vertex_handle vh = f->vertex(i)); - CGAL_triangulation_assertion_code(Vertex_handle vh_ccw = f->vertex(ccw(i))); - _tds.flip(f, i); - // Combinatorial checks - CGAL_triangulation_assertion(vh == f->vertex(i)); - CGAL_triangulation_assertion(vh_ccw == f->vertex(ccw(i))); - CGAL_triangulation_assertion(f->vertex(i) == nb->vertex(cw(nb_index))); - CGAL_triangulation_assertion(f->vertex(cw(i)) == nb->vertex(nb_index)); - - // Restore the offsets - int new_off[3]; - // For face f - new_off[i] = offsets[0]; - new_off[ccw(i)] = offsets[2]; - new_off[cw(i)] = offsets[3]; - set_offsets(f, new_off[0], new_off[1], new_off[2]); - // For face nb - new_off[nb_index] = offsets[3]; - new_off[ccw(nb_index)] = offsets[1]; - new_off[cw(nb_index)] = offsets[0]; - set_offsets(nb, new_off[0], new_off[1], new_off[2]); - - if (!is_1_cover()) - insert_too_long_edge(f, ccw(i)); -} - -template -void -Periodic_4_hyperbolic_triangulation_2::remove_from_virtual_copies(Vertex_handle v) -{ - typename Virtual_vertex_reverse_map::iterator rev_it = _virtual_vertices_reverse.find(v); - CGAL_triangulation_assertion(rev_it != _virtual_vertices_reverse.end()); - - const std::vector &virtual_copies = rev_it->second; - for (size_t i = 0; i < virtual_copies.size(); ++i) - { - _virtual_vertices.erase(virtual_copies[i]); - } - _virtual_vertices_reverse.erase(rev_it); -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::insert_first(const Point& p) -{ - CGAL_assertion(empty()); - // The empty triangulation has a single sheeted cover - _cover = make_array(3, 3); - - /// Virtual vertices, one per periodic domain - Vertex_handle vir_vertices[3][3]; - /// Virtual faces, two per periodic domain - Face_handle faces[3][3][2]; - - // Initialise vertices: - vir_vertices[0][0] = _tds.create_vertex(); - vir_vertices[0][0]->set_point(p); - _virtual_vertices_reverse[vir_vertices[0][0]] = std::vector(); - for (int i = 0; i < _cover[0]; i++) - { - for (int j = 0; j < _cover[1]; j++) - { - if ((i != 0) || (j != 0)) - { - // Initialise virtual vertices out of the domain for debugging - vir_vertices[i][j] = _tds.create_vertex(); - vir_vertices[i][j]->set_point(p); //+Offset(i,j)); - _virtual_vertices[vir_vertices[i][j]] = Virtual_vertex( - vir_vertices[0][0], Offset(i, j)); - _virtual_vertices_reverse[vir_vertices[0][0]].push_back( - vir_vertices[i][j]); - } - } - } - - // Create faces: - for (int i = 0; i < _cover[0]; i++) - { - for (int j = 0; j < _cover[1]; j++) - { - for (int f = 0; f < 2; f++) - { - // f faces per 'rectangle' - faces[i][j][f] = _tds.create_face(); - } - } - } - - // table containing the vertex information - // index to the right vertex: [number of faces][vertex][offset] - int vertex_ind[2][3][2] = { { { 0, 0 }, { 1, 1 }, { 0, 1 } }, { { 0, 0 }, { - 1, 0 - }, { 1, 1 } - } - }; - // Table containing the neighbor information - // [number of faces][neighbor][offset,face] - int neighb_ind[2][3][3] = { { { 0, 1, 1 }, { -1, 0, 1 }, { 0, 0, 1 } }, { { - 1, 0, 0 - }, { 0, 0, 0 }, { 0, -1, 0 } - } - }; - for (int i = 0; i < _cover[0]; i++) - { - for (int j = 0; j < _cover[1]; j++) - { - int offset = - ((i == _cover[0] - 1 ? 2 : 0) | (j == _cover[1] - 1 ? 1 : 0)); - for (int f = 0; f < 2; f++) - { - faces[i][j][f]->set_vertices(vir_vertices[(i + vertex_ind[f][0][0]) - % _cover[0]][(j + vertex_ind[f][0][1]) % _cover[1]], - vir_vertices[(i + vertex_ind[f][1][0]) % _cover[0]][(j - + vertex_ind[f][1][1]) % _cover[1]], vir_vertices[(i - + vertex_ind[f][2][0]) % _cover[0]][(j + vertex_ind[f][2][1]) - % _cover[1]]); - set_offsets(faces[i][j][f], offset & (vertex_ind[f][0][0] * 2 - + vertex_ind[f][0][1] * 1), offset & (vertex_ind[f][1][0] * 2 - + vertex_ind[f][1][1] * 1), offset & (vertex_ind[f][2][0] * 2 - + vertex_ind[f][2][1] * 1)); - faces[i][j][f]->set_neighbors(faces[(i + _cover[0] - + neighb_ind[f][0][0]) % _cover[0]][(j + _cover[1] - + neighb_ind[f][0][1]) % _cover[1]][neighb_ind[f][0][2]], faces[(i - + _cover[0] + neighb_ind[f][1][0]) % _cover[0]][(j + _cover[1] - + neighb_ind[f][1][1]) % _cover[1]][neighb_ind[f][1][2]], faces[(i - + _cover[0] + neighb_ind[f][2][0]) % _cover[0]][(j + _cover[1] - + neighb_ind[f][2][1]) % _cover[1]][neighb_ind[f][2][2]]); - } - } - } - // set pointers from the vertices to incident faces. - for (int i = 0; i < _cover[0]; i++) - { - for (int j = 0; j < _cover[1]; j++) - { - vir_vertices[i][j]->set_face(faces[i][j][0]); - } - } - - _tds.set_dimension(2); - - // create the base for too_long_edges; - CGAL_triangulation_assertion(_too_long_edges.empty() ); - CGAL_triangulation_assertion(_too_long_edge_counter == 0); - - // Insert all vertices as the first vertex in the _too_long_edges list - int k = 0; - std::list empty_list; - for (Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit) - { - _too_long_edges[vit] = empty_list; - k++; - } - - // Insert all edges as all edges are too long - _too_long_edge_counter = 0; - for (Edge_iterator eit = edges_begin(); eit != edges_end(); eit++) - { - Vertex_handle vh1 = eit->first->vertex(ccw(eit->second)); - Vertex_handle vh2 = eit->first->vertex(cw(eit->second)); - if (&*vh1 < &*vh2) - { - _too_long_edges[vh1].push_back(vh2); - } - else - { - _too_long_edges[vh2].push_back(vh1); - } - _too_long_edge_counter++; - } - - return vir_vertices[0][0]; -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert_in_edge(const Point& p, - Face_handle f, int i) -{ - return insert(p, EDGE, f, i); -} -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert_in_edge(const Point& p, const Offset &o, - Face_handle f, int i, - Vertex_handle vh) -{ - // Insert in edge calls an insert_in_face and a flip. - // Therefore there is no need to update the too_long_edges bookkeeping directly. - - CGAL_triangulation_assertion(number_of_vertices() != 0); - CGAL_triangulation_assertion((!is_1_cover()) || (o == Offset())); - - // Backup of the neighbor and its relative offset - Face_handle nb = f->neighbor(i); - int j = nb->index(f); - CGAL_triangulation_assertion_code(Offset current_offset = get_location_offset(f, p, o)); - CGAL_triangulation_assertion - (orientation(f->vertex(cw(i))->point(), p, f->vertex(ccw(i))->point(), - get_offset(f, cw(i)), combine_offsets(o, current_offset), get_offset(f, ccw(i))) == COLLINEAR && - collinear_between(f->vertex(cw(i))->point(), p, f->vertex(ccw(i))->point(), - get_offset(f, cw(i)), combine_offsets(o, current_offset), get_offset(f, ccw(i))) ); - - /// Insert in the face and flip an edge - Vertex_handle v = insert_in_face(p, o, f, vh); - flip_single_edge(nb, j); - - return v; -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert_in_face(const Point& p, Face_handle f) -{ - return insert(p, FACE, f, 0); -} -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert_in_face(const Point& p, const Offset &o, - Face_handle f, - Vertex_handle vh) -{ - CGAL_triangulation_assertion(f != Face_handle()); - CGAL_triangulation_assertion(number_of_vertices() != 0); - CGAL_triangulation_assertion((!is_1_cover()) || (o == Offset())); - - const bool simplicity_criterion = f->has_zero_offsets() && o.is_zero(); - - - Offset current_off; - - // Save the neighbors and the offsets - Face_handle nb[3]; - int nb_index[3]; - int offsets[3]; - CGAL_triangulation_assertion_code( Vertex_handle vertices[3]; ) - - if (!simplicity_criterion) - { - // Choose the periodic copy of tester.point() that is inside c. - current_off = get_location_offset(f, p, o); - - CGAL_triangulation_assertion(oriented_side(f, p, combine_offsets(o, current_off)) != ON_NEGATIVE_SIDE); - - for (int i = 0; i < 3; ++i) - { - nb[i] = f->neighbor(i); - nb_index[i] = nb[i]->index(f); - offsets[i] = f->offset(i); - CGAL_triangulation_assertion_code( vertices[i] = f->vertex(i); ); - } - } - - // Insert the new vertex - Vertex_handle v = _tds.insert_in_face(f); - v->set_point(p); - - if (!simplicity_criterion) - { - // Update the offsets - int v_offset = off_to_int(current_off); - int new_offsets[3]; - for (int i = 0; i < 3; ++i) - { - Face_handle new_face = nb[i]->neighbor(nb_index[i]); - int v_index = new_face->index(v); - - CGAL_triangulation_assertion(new_face->vertex(ccw(v_index)) == vertices[ccw(i)]); - CGAL_triangulation_assertion(new_face->vertex(cw(v_index)) == vertices[cw(i)]); - - new_offsets[v_index] = v_offset; - new_offsets[ccw(v_index)] = offsets[ccw(i)]; - new_offsets[cw(v_index)] = offsets[cw(i)]; - set_offsets(new_face, new_offsets[0], new_offsets[1], new_offsets[2]); - } - } - - if (!is_1_cover()) - { - // update the book-keeping in case of a periodic copy - if (vh != Vertex_handle()) - { - _virtual_vertices[v] = Virtual_vertex(vh, o); - _virtual_vertices_reverse[vh].push_back(v); - } - - insert_too_long_edges_in_star(v); - } - - return v; -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert(const Point &p, Face_handle start) -{ - CGAL_triangulation_assertion((_domain.xmin() <= p.x()) && - (p.x() < _domain.xmax())); - CGAL_triangulation_assertion((_domain.ymin() <= p.y()) && - (p.y() < _domain.ymax())); - - if (number_of_stored_vertices() == 0) - { - return insert_first(p); - } - - if (start == Face_handle()) - { - start = faces_begin(); - } - - Locate_type lt; - int li; - Face_handle loc = locate(p, lt, li, start); - - if (start != Face_handle()) - { - CGAL_assertion(start->vertex(0) != Vertex_handle()); - } - return insert(p, lt, loc, li); -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle -Periodic_4_hyperbolic_triangulation_2::insert(const Point& p, - Locate_type lt, Face_handle loc, int li) -{ - if (number_of_stored_vertices() == 0) - { - return insert_first(p); - } - - // vstart is a vertex incident to the Face_handle start that will be used as - // for creating a start point for the virtual vertices. - // We use the virtual copies of a vertex incident to loc. - Vertex_handle vstart; - if (!is_1_cover()) - { - Virtual_vertex_map_it vvmit = _virtual_vertices.find(loc->vertex(0)); - if (vvmit == _virtual_vertices.end()) - { - vstart = loc->vertex(0); - } - else - { - vstart = vvmit->second.first; - } - - // vstart should be non-virtual, but should have virtual copies - CGAL_triangulation_assertion(_virtual_vertices.find(vstart) - == _virtual_vertices.end()); - CGAL_triangulation_assertion(_virtual_vertices_reverse.find(vstart) - != _virtual_vertices_reverse.end()); - } - - Vertex_handle vh = insert(p, Offset(), lt, loc, li, Vertex_handle()); - - // Don't add periodic copies if we are on the 1-cover - if (is_1_cover()) - return vh; - - // Don't continue if the point lies on a vertex as this will break the - // start_vertices array below. - if (lt == VERTEX) - return vh; - - const std::vector &start_vertices = - _virtual_vertices_reverse.find(vstart)->second; - CGAL_assertion(start_vertices.size() == size_t(number_of_sheets()[0] * number_of_sheets()[1] - 1)); - - for (int i = 0; i < number_of_sheets()[0]; i++) - { - for (int j = 0; j < number_of_sheets()[1]; j++) - { - if ((i != 0) || (j != 0)) - { - loc = start_vertices[i * 3 + j - 1]->face(); - Offset offset(i, j); - - loc = locate(p, offset, lt, li, loc); - - insert(p, offset, lt, loc, li, vh); - } - } - } - - return vh; -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::insert(const Point& p, const Offset &o, Locate_type lt, - Face_handle loc, int li, Vertex_handle vh) -// insert a point p, whose localization is known (lt, f, i) -{ - Vertex_handle result; - switch (lt) - { - case FACE: - { - result = insert_in_face(p, o, loc, vh); - break; - } - case EDGE: - { - result = insert_in_edge(p, o, loc, li, vh); - break; - } - case VERTEX: - { - // The vertex is a special case, we can return immediately - CGAL_assertion(vh == Vertex_handle()); - return loc->vertex(li); - } - case EMPTY: - { - result = insert_first(p); - break; - } - default: - { - CGAL_triangulation_assertion(false); // locate step failed - return Vertex_handle(); - } - } - - if (!is_1_cover() && (vh == Vertex_handle())) - { - _virtual_vertices_reverse[result] = std::vector(); - } - - return result; -} - -template -inline void Periodic_4_hyperbolic_triangulation_2::remove_degree_3(Vertex_handle v) -{ - CGAL_assertion(number_of_vertices() > 1); - CGAL_assertion(degree(v) == 3); - - if (is_1_cover()) - { - remove_degree_3_single_copy(v); - return; - } - - { - Virtual_vertex_map_it it = _virtual_vertices.find(v); - if (it != _virtual_vertices.end()) - { - v = it->second.first; - } - } - - remove_too_long_edges_in_star(v); - - typename Virtual_vertex_reverse_map::iterator reverse_it = - _virtual_vertices_reverse.find(v); - CGAL_assertion(reverse_it != _virtual_vertices_reverse.end()); - - const std::vector &virtual_copies = reverse_it->second; - for (typename std::vector::const_iterator it = virtual_copies.begin(); - it != virtual_copies.end(); ++it) - { - _virtual_vertices.erase(*it); - remove_degree_3_single_copy(*it); - } - - _virtual_vertices_reverse.erase(reverse_it); - remove_degree_3_single_copy(v); - -} - -template -inline void Periodic_4_hyperbolic_triangulation_2::remove_degree_3_single_copy(Vertex_handle vh) -{ - Face_handle f = vh->face(); - int i = ccw(f->index(vh)); - Face_handle f2 = f->neighbor(i); - int j = f2->index(f); - // Get the offsets in ccw order - Offset off[3]; - off[i] = get_offset(f, i); - off[ccw(i)] = get_offset(f, ccw(i)); - off[cw(i)] = combine_offsets(get_offset(f2, j), get_neighbor_offset(f2, j, f, i)); - if (off[0].x() < 0 || off[1].x() < 0 || off[2].x() < 0) - { - Offset o(number_of_sheets()[0], 0); - off[0] += o; - off[1] += o; - off[2] += o; - } - if (off[0].y() < 0 || off[1].y() < 0 || off[2].y() < 0) - { - Offset o(0, number_of_sheets()[1]); - off[0] += o; - off[1] += o; - off[2] += o; - } - - // Remove the vertex, keep face f - _tds.remove_degree_3(vh, f); - - // Reset the offsets - set_offsets(f, - (off[0].x() >= number_of_sheets()[0] ? 2 : 0) + (off[0].y() >= number_of_sheets()[1] ? 1 : 0), - (off[1].x() >= number_of_sheets()[0] ? 2 : 0) + (off[1].y() >= number_of_sheets()[1] ? 1 : 0), - (off[2].x() >= number_of_sheets()[0] ? 2 : 0) + (off[2].y() >= number_of_sheets()[1] ? 1 : 0)); -} - -template -inline void Periodic_4_hyperbolic_triangulation_2::remove_first(Vertex_handle) -{ - CGAL_assertion(number_of_vertices() == 1); - clear(); - return; -} - - -template < class Gt, class Tds > -bool -Periodic_4_hyperbolic_triangulation_2:: -remove_degree_init(Vertex_handle v, const Offset &v_o, - std::vector &f, - std::vector &w, - std::vector &offset_w, - std::vector &i, - int &d, int &maxd, - bool &simplicity_criterion) -{ - Bbox_2 bbox = v->point().bbox(); - simplicity_criterion = is_1_cover(); - - f[0] = v->face(); - d = 0; - - do - { - i[d] = f[d]->index(v); - w[d] = f[d]->vertex( ccw(i[d]) ); - offset_w[d] = get_offset(f[d], ccw(i[d])) - get_offset(f[d], i[d]) + v_o; - w[d]->set_face( f[d]->neighbor(i[d])); // do no longer bother about set_face - simplicity_criterion &= (offset_w[d] == offset_w[0]); - - bbox = bbox + this->construct_point(w[d]->point(), offset_w[d]).bbox(); - - ++d; - if ( d == maxd) - { - maxd *= 2; - f.resize(maxd); - w.resize(maxd); - offset_w.resize(maxd); - i.resize(maxd); - } - - f[d] = f[d - 1]->neighbor( ccw(i[d - 1]) ); - - } - while(f[d] != f[0]); - - return is_1_cover() && - this->edge_is_too_long(Point(bbox.xmin(), bbox.ymin()), Point(bbox.xmax(), bbox.ymax())); -} - -template -void Periodic_4_hyperbolic_triangulation_2::make_hole(Vertex_handle v, std::list & hole) -{ - remove_too_long_edges_in_star(v); - - std::list to_delete; - - Face_handle f, fn; - int i, in; - Vertex_handle vv; - - Face_circulator fc = incident_faces(v); - Face_circulator done(fc); - do - { - f = fc; - fc++; - i = f->index(v); - fn = f->neighbor(i); - in = fn->index(f); - vv = f->vertex(cw(i)); - if (vv->face() == f) - vv->set_face(fn); - vv = f->vertex(ccw(i)); - if (vv->face() == f) - vv->set_face(fn); - fn->set_neighbor(in, Face_handle()); - hole.push_back(Edge(fn, in)); - to_delete.push_back(f); - } - while (fc != done); - - while (!to_delete.empty()) - { - delete_face(to_delete.front()); - to_delete.pop_front(); - } - return; -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Face_handle f1, int i1, Face_handle f2, int i2, - Face_handle f3, int i3) -{ - return _tds.create_face(f1, i1, f2, i2, f3, i3); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Face_handle f1, int i1, Face_handle f2, int i2) -{ - return _tds.create_face(f1, i1, f2, i2); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Face_handle f, int i, Vertex_handle v) -{ - return _tds.create_face(f, i, v); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) -{ - return _tds.create_face(v1, v2, v3); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, - Face_handle f1, Face_handle f2, Face_handle f3) -{ - return _tds.create_face(v1, v2, v3, f1, f2, f3); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face(Face_handle fh) -{ - return _tds.create_face(fh); -} - -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::create_face() -{ - return _tds.create_face(); -} - -template -inline -void Periodic_4_hyperbolic_triangulation_2::delete_face(Face_handle f) -{ - _tds.delete_face(f); -} - -template -inline -void Periodic_4_hyperbolic_triangulation_2::delete_vertex(Vertex_handle v) -{ - _tds.delete_vertex(v); -} - -template -bool Periodic_4_hyperbolic_triangulation_2::compare_walks(const Point& p, - Face_handle c1, Face_handle c2, Locate_type& lt1, Locate_type& lt2, - int li1, int li2) const -{ - bool b = true; - b &= (lt1 == lt2); - if ((lt1 == lt2) && (lt1 == VERTEX)) - { - b &= (c1->vertex(li1) == c2->vertex(li2)); - } - else if ((lt1 == lt2) && (lt1 == EDGE)) - { - b &= ((c1 == c2) - || ((c1->neighbor(li1) == c2) && (c2->neighbor(li2) == c1))); - } - else if ((lt1 == lt2) && (lt1 == EMPTY)) - { - // Skip - } - else - { - b &= (lt1 == lt2); - b &= (lt1 == FACE); - b &= (c1 == c2); - } - - if (!b) - { - std::cerr << "from compare_walks " << std::endl; - std::cerr << "point " << p << std::endl; - std::cerr << "locate 1 " << &*c1 << "\t" << lt1 << "\t" << li1 << std::endl; - std::cerr << "locate 2 " << &*c2 << "\t" << lt2 << "\t" << li2 << std::endl; - std::cerr << std::endl; - show_face(c1); - std::cerr << std::endl; - show_face(c2); - std::cerr << std::endl; - } - - CGAL_triangulation_assertion(b); - return b; -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Face_handle -Periodic_4_hyperbolic_triangulation_2:: -march_locate_2D(Face_handle f, const Point& query, - const Offset& o_p, Locate_type& lt, int& li) const -{ - CGAL_assertion(!empty()); - - Offset off_query = o_p; - - // Random generator - boost::rand48 rng; - boost::uniform_smallint<> two(0, 1); - boost::variate_generator > coin(rng, two); - - // Give the point the best start-offset possible - if (is_1_cover() && !f->has_zero_offsets()) - { - int cumm_off = f->offset(0) | f->offset(1) | f->offset(2); - if (((cumm_off & 2) == 2) && - (FT(2) * query.x() < (_domain.xmax() + _domain.xmin()))) - off_query += Offset(1, 0); - if (((cumm_off & 1) == 1) && - (FT(2) * query.y() < (_domain.ymax() + _domain.ymin()))) - off_query += Offset(0, 1); - } - - Face_handle prev = Face_handle(); - int prev_index = 0; - Offset off[3]; - Orientation o[3]; - while (1) - { - // Instead of testing its edges in a random order we do the following - // until we find a neighbor to go further: - // As we come from prev we do not have to check the edge leading to prev - // Now we flip a coin in order to decide if we start checking the - // edge before or the edge after the edge leading to prev - int left_first = coin() % 2; - - bool simplicity_criterion = - f->has_zero_offsets() && off_query.is_null() && is_1_cover(); - - const Point *p[3] = - { - &f->vertex(0)->point(), - &f->vertex(1)->point(), - &f->vertex(2)->point() - }; - - // Get the offsets - if (!simplicity_criterion) - { - if (!is_1_cover()) - { - // Just fetch the vertices of c as points with offsets - for (int i = 0; i < 3; i++) - { - off[i] = get_offset(f, i); - } - } - else - { - // We are on the one cover and on the boundary between domains - // Hence, we need to check predicates with offsets - for (int i = 0; i < 3; i++) - { - off[i] = int_to_off(f->offset(i)); - } - } - } - - if (prev == Face_handle()) - { - prev = f; - // First step, also check the prev_index - if (simplicity_criterion) - { - o[ccw(prev_index)] = - orientation(*p[ccw(prev_index)], *p[cw(prev_index)], query); - } - else - { - o[ccw(prev_index)] = - orientation(*p[ccw(prev_index)], *p[cw(prev_index)], query, - off[ccw(prev_index)], off[cw(prev_index)], off_query); - } - if (o[ccw(prev_index)] == NEGATIVE) - { - // This assignment is already done: prev = f - f = f->neighbor(prev_index); - int new_index = f->index(prev); - if (!(simplicity_criterion && f->has_zero_offsets())) - off_query = combine_offsets(off_query, - get_neighbor_offset(prev, prev_index, - f, new_index)); - prev_index = new_index; - continue; - } - } - else - { - o[ccw(prev_index)] = POSITIVE; - } - - if (left_first) - { - if (simplicity_criterion) - { - o[prev_index] = - orientation(*p[prev_index], *p[ccw(prev_index)], query); - } - else - { - o[prev_index] = - orientation(*p[prev_index], *p[ccw(prev_index)], query, - off[prev_index], off[ccw(prev_index)], off_query); - } - if (o[prev_index] == NEGATIVE) - { - prev = f; - f = f->neighbor(cw(prev_index)); - int new_index = f->index(prev); - if (!(simplicity_criterion && f->has_zero_offsets())) - off_query = combine_offsets(off_query, - get_neighbor_offset(prev, cw(prev_index), f, new_index)); - prev_index = new_index; - continue; - } - } - { - // Do right side - if (simplicity_criterion) - { - o[cw(prev_index)] = - orientation(*p[cw(prev_index)], *p[prev_index], query); - } - else - { - o[cw(prev_index)] = - orientation(*p[cw(prev_index)], *p[prev_index], query, - off[cw(prev_index)], off[prev_index], off_query); - } - if (o[cw(prev_index)] == NEGATIVE) - { - prev = f; - f = f->neighbor(ccw(prev_index)); - int new_index = f->index(prev); - if (!(simplicity_criterion && f->has_zero_offsets())) - off_query = combine_offsets(off_query, - get_neighbor_offset(prev, ccw(prev_index), f, new_index)); - prev_index = new_index; - continue; - } - } - if (!left_first) - { - if (simplicity_criterion) - { - o[prev_index] = orientation(*p[prev_index], *p[ccw(prev_index)], query); - } - else - { - o[prev_index] = orientation(*p[prev_index], *p[ccw(prev_index)], query, - off[prev_index], off[ccw(prev_index)], off_query); - } - if (o[prev_index] == NEGATIVE) - { - prev = f; - f = f->neighbor(cw(prev_index)); - int new_index = f->index(prev); - if (!(simplicity_criterion && f->has_zero_offsets())) - off_query = combine_offsets(off_query, - get_neighbor_offset(prev, cw(prev_index), f, new_index)); - prev_index = new_index; - continue; - } - } - - // now p is in c or on its boundary - int sum = (o[0] == COLLINEAR) + (o[1] == COLLINEAR) + (o[2] == COLLINEAR); - switch (sum) - { - case 0: - { - lt = FACE; - li = 4; - break; - } - case 1: - { - lt = EDGE; - li = (o[0] == COLLINEAR) ? 2 : (o[1] == COLLINEAR) ? 0 : 1; - break; - } - case 2: - { - lt = VERTEX; - li = (o[0] != COLLINEAR) ? 2 : (o[1] != COLLINEAR) ? 0 : 1; - break; - } - } - return f; - } -} - -template -typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -Gt, Tds >::locate(const Point& p, const Offset &o, Locate_type& lt, int& li, - Face_handle start) const -{ - CGAL_triangulation_assertion((_domain.xmin() <= p.x()) && - (p.x() < _domain.xmax())); - CGAL_triangulation_assertion((_domain.ymin() <= p.y()) && - (p.y() < _domain.ymax())); - - if (dimension() <= 0) - { - lt = EMPTY; - li = 4; - return Face_handle(); - } - - // Triangulation is not empty - if (start == Face_handle()) - { - start = faces_begin(); - } - - return march_locate_2D(start, p, o, lt, li); -} - -/** Delete each redundant face and the not anymore needed data - * structures. - * - * This function consists of four iterations over all faces and one - * iteration over all vertices: - * -# Face iteration: mark all faces that are to delete - * -# Face iteration: redirect neighbors of remaining faces - * -# Face iteration: redirect vertices of remaining faces - * -# Face iteration: delete all faces marked in the 1. iteration - * -# Vertex iteration: delete all vertices outside the original domain. - */ -template -void Periodic_4_hyperbolic_triangulation_2::convert_to_1_sheeted_covering() -{ - // ################################################################### - // ### First face iteration ########################################## - // ################################################################### - { - if (is_1_cover()) - return; - CGAL_triangulation_expensive_assertion(is_triangulation_in_1_sheet()); - - bool to_delete, has_simplifiable_offset; - Virtual_vertex_map_it vvmit; - // First iteration over all faces: Mark the faces that are to delete. - // Faces are to delete if they cannot be translated anymore in the - // direction of one of the axes without yielding negative offsets. - for (Face_iterator it = all_faces_begin(); it != all_faces_end(); ++it) - { - to_delete = false; - // for all directions in 2D Space - for (int j = 0; j < 2; j++) - { - has_simplifiable_offset = true; - // for all vertices of face it - for (int i = 0; i < 3; i++) - { - vvmit = _virtual_vertices.find(it->vertex(i)); - if (vvmit == _virtual_vertices.end()) - { - // if it->vertex(i) lies inside the original domain: - - // the face cannot be moved any more because if we did, then - // it->vertex(i) will get at least one negative offset. - has_simplifiable_offset = false; - } - else - { - // if it->vertex(i) lies outside the original domain: - - // The face can certainly be deleted if the offset contains a 2 - to_delete |= (vvmit->second.second[j] == 2); - // The face can be moved into one direction only if the offset of - // all for vertices is >=1 for this direction. Since we already - // tested for 2 it is sufficient to test here for 1. - has_simplifiable_offset &= (vvmit->second.second[j] == 1); - } - } - // if the offset can be simplified, i.e. the face can be moved, then - // it can be deleted. - if (has_simplifiable_offset) - to_delete = true; - } - // Mark all faces that are to delete. They cannot be deleted yet, - // because neighboring information still needs to be extracted. - it->set_additional_flag(to_delete ? 1 : 0); - } - } - - // ################################################################### - // ### Second face iteration ######################################### - // ################################################################### - { - Vertex_handle vert[3], nbv[3]; - Offset off[3]; - Face_handle nb, new_neighbor; - std::vector > new_neighbor_relations; - - // Second iteration over all faces: redirect neighbors where necessary - for (Face_iterator it = all_faces_begin(); it != all_faces_end(); ++it) - { - // Skip all faces that are to delete. - if (it->get_additional_flag() == 1) - continue; - - // Redirect neighbors: Only neighbors that are marked by the - // additional_flag have to be substituted by one of their periodic - // copies. The unmarked neighbors stay the same. - for (int i = 0; i < 3; i++) - { - if (it->neighbor(i)->get_additional_flag() != 1) - continue; - - nb = it->neighbor(i); - - for (int j = 0; j < 3; j++) - { - off[j] = Offset(); - get_vertex(nb, j, vert[j], off[j]); - } - int x, y; - x = (std::min)((std::min)(off[0][0], off[1][0]), off[2][0]); - y = (std::min)((std::min)(off[0][1], off[1][1]), off[2][1]); - - // The vector from nb to the "original" periodic copy of nb, that is - // the copy that will not be deleted. - Offset difference_offset(x, y); - CGAL_triangulation_assertion( !difference_offset.is_null() ); - - // We now have to find the "original" periodic copy of nb from - // its vertices. Therefore, we first have to find the vertices. - for (int j = 0; j < 3; j++) - { - CGAL_triangulation_assertion( (off[j] - difference_offset)[0] >= 0); - CGAL_triangulation_assertion( (off[j] - difference_offset)[1] >= 0); - CGAL_triangulation_assertion( (off[j] - difference_offset)[0] < 3); - CGAL_triangulation_assertion( (off[j] - difference_offset)[1] < 3); - - // find the Vertex_handles of the vertices of the "original" - // periodic copy of nb. If the vertex is inside the original - // domain, there is nothing to do - if ((off[j] - difference_offset).is_null()) - { - nbv[j] = vert[j]; - // If the vertex is outside the original domain, we have to search - // in _virtual_vertices in the "wrong" direction. That means, we - // cannot use _virtual_vertices.find but have to use - // _virtual_vertices_reverse. - } - else - { - Offset nbo = off[j] - difference_offset; - nbv[j] = _virtual_vertices_reverse.find(vert[j]) ->second[nbo[0] - * 3 + nbo[1] - 1]; - } - } - // Find the new neighbor by its 4 vertices - new_neighbor = get_face(nbv); - - // Store the new neighbor relation. This cannot be applied yet because - // it would disturb the functioning of get_face( ... ) - new_neighbor_relations.push_back(make_triple(it, i, new_neighbor)); - } - } - // Apply the new neighbor relations now. - for (unsigned int i = 0; i < new_neighbor_relations.size(); i++) - { - new_neighbor_relations[i].first->set_neighbor( - new_neighbor_relations[i].second, new_neighbor_relations[i].third); - } - } - - // ################################################################### - // ### Third face iteration ########################################## - // ################################################################### - { - Vertex_handle vert[3]; - Offset off[3]; - // Third iteration over all faces: redirect vertices where necessary - for (Face_iterator it = all_faces_begin(); it != all_faces_end(); ++it) - { - // Skip all faces that are marked to delete - if (it->get_additional_flag() == 1) - continue; - // Find the corresponding vertices of it in the original domain - // and set them as new vertices of it. - for (int i = 0; i < 3; i++) - { - off[i] = Offset(); - get_vertex(it, i, vert[i], off[i]); - it->set_vertex(i, vert[i]); - CGAL_triangulation_assertion(vert[i]->point()[0] < _domain.xmax()); - CGAL_triangulation_assertion(vert[i]->point()[1] < _domain.ymax()); - CGAL_triangulation_assertion(vert[i]->point()[0] >= _domain.xmin()); - CGAL_triangulation_assertion(vert[i]->point()[1] >= _domain.ymin()); - - // redirect also the face pointer of the vertex. - it->vertex(i)->set_face(it); - } - // Set the offsets. - set_offsets(it, off[0], off[1], off[2]); - CGAL_triangulation_assertion( int_to_off(it->offset(0)) == off[0] ); - CGAL_triangulation_assertion( int_to_off(it->offset(1)) == off[1] ); - CGAL_triangulation_assertion( int_to_off(it->offset(2)) == off[2] ); - } - } - - // ################################################################### - // ### Fourth face iteration ######################################### - // ################################################################### - { - // Delete the marked faces. - std::vector faces_to_delete; - for (Face_iterator fit = all_faces_begin(); fit != all_faces_end(); ++fit) - { - if (fit->get_additional_flag() == 1) - faces_to_delete.push_back(fit); - } - for (typename std::vector::iterator it = - faces_to_delete.begin(); it != faces_to_delete.end(); ++it) - { - _tds.delete_face(*it); - } - } - - // ################################################################### - // ### Vertex iteration ############################################## - // ################################################################### - { - // Delete all the vertices in _virtual_vertices, that is all vertices - // outside the original domain. - std::vector vertices_to_delete; - for (Vertex_iterator vit = all_vertices_begin(); vit != all_vertices_end(); ++vit) - { - if (_virtual_vertices.count(vit) != 0) - { - CGAL_triangulation_assertion( _virtual_vertices.count( vit ) == 1 ); - vertices_to_delete.push_back(vit); - } - } - for (typename std::vector::iterator it = - vertices_to_delete.begin(); it != vertices_to_delete.end(); ++it) - { - _tds.delete_vertex(*it); - } - } - - _cover = make_array(1, 1); - _virtual_vertices.clear(); - _virtual_vertices_reverse.clear(); - _too_long_edge_counter = 0; - _too_long_edges.clear(); - - CGAL_triangulation_assertion(is_1_cover()); -} - -template -void Periodic_4_hyperbolic_triangulation_2::convert_to_9_sheeted_covering() -{ - if (_cover == make_array(3, 3)) - return; - CGAL_triangulation_precondition(is_1_cover()); - - // Create 9 copies of each vertex and write virtual_vertices and - // virtual_vertices_reverse - std::list original_vertices; - // try to use std::copy instead of the following loop. - for (Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit) - original_vertices.push_back(vit); - for (typename std::list::iterator vit = - original_vertices.begin(); vit != original_vertices.end(); ++vit) - { - Vertex_handle v_cp; - std::vector copies; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - { - if (i == 0 && j == 0) - continue; - v_cp = _tds.create_vertex(*vit); - copies.push_back(v_cp); - _virtual_vertices.insert(std::make_pair(v_cp, std::make_pair(*vit, - Offset(i, j)))); - } - _virtual_vertices_reverse.insert(std::make_pair(*vit, copies)); - } - - // Create 9 copies of each face from the respective copies of the - // vertices and write virtual_faces and virtual_faces_reverse. - typedef std::map > - Virtual_face_map; - typedef std::map > - Virtual_face_reverse_map; - typedef typename Virtual_face_reverse_map::const_iterator VCRMIT; - - Virtual_face_map virtual_faces; - Virtual_face_reverse_map virtual_faces_reverse; - - std::list original_faces; - for (Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) - original_faces.push_back(fit); - - // Store vertex offsets in a separate data structure - std::list off_v; - for (typename std::list::iterator vit = - original_vertices.begin(); vit != original_vertices.end(); ++vit) - { - Face_handle ccc = (*vit)->face(); - int v_index = ccc->index(*vit); - off_v.push_back(int_to_off(ccc->offset(v_index))); - } - - // Store neighboring offsets in a separate data structure - std::list > off_nb; - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit) - { - array off_nb_f; - for (int i = 0; i < 3; i++) - { - Face_handle fff = *fit; - Face_handle nnn = fff->neighbor(i); - off_nb_f[i] = get_neighbor_offset(fff, i, nnn, nnn->index(fff)); - } - off_nb.push_back(off_nb_f); - } - - // Create copies of faces - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit) - { - Face_handle c_cp; - Vertex_handle v0, v1, v2; - std::vector copies; - Virtual_vertex_reverse_map_it vvrmit[3]; - Offset vvoff[3]; - for (int i = 0; i < 3; i++) - { - vvrmit[i] = _virtual_vertices_reverse.find((*fit)->vertex(i)); - CGAL_triangulation_assertion( - vvrmit[i] != _virtual_vertices_reverse.end()); - vvoff[i] = int_to_off((*fit)->offset(i)); - } - Vertex_handle vvh[3]; - for (int n = 0; n < 8; n++) // iterate over faces - { - for (int i = 0; i < 3; i++) // iterate over vertices of the face - { - // Decomposition of n into an offset (nx,ny): - // nx = ((n+1)/3)%3, ny = (n+1)%3 - int o_i = ((n + 1) / 3 + vvoff[i].x() + 3) % 3; - int o_j = ((n + 1) + vvoff[i].y() + 3) % 3; - int n_c = 3 * o_i + o_j - 1; - CGAL_triangulation_assertion(n_c >= -1); - if (n_c == -1) - vvh[i] = (*fit)->vertex(i); - else - vvh[i] = vvrmit[i]->second[n_c]; - } - c_cp = _tds.create_face(vvh[0], vvh[1], vvh[2]); - copies.push_back(c_cp); - } - virtual_faces_reverse.insert(std::make_pair(*fit, copies)); - } - - // Set new vertices of boundary faces of the original domain. - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit) - { - for (int i = 0; i < 3; i++) - { - Virtual_vertex_reverse_map_it vvrmit = _virtual_vertices_reverse.find( - (*fit)->vertex(i)); - CGAL_triangulation_assertion(vvrmit != _virtual_vertices_reverse.end()); - Offset vvoff = int_to_off((*fit)->offset(i)); - if (!vvoff.is_null()) - { - int n_f = 3 * vvoff.x() + vvoff.y() - 1; - CGAL_triangulation_assertion(n_f >= 0); - CGAL_triangulation_assertion(static_cast(n_f) < vvrmit->second.size()); - (*fit)->set_vertex(i, vvrmit->second[n_f]); - } - } - } - - // Set neighboring relations of face copies - typename std::list >::iterator oit = off_nb.begin(); - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit, ++oit) - { - CGAL_triangulation_assertion( oit != off_nb.end() ); - VCRMIT c_cp = virtual_faces_reverse.find(*fit); - CGAL_triangulation_assertion(c_cp != virtual_faces_reverse.end()); - for (int i = 0; i < 3; i++) - { - Face_handle fit_nb = (*fit)->neighbor(i); - VCRMIT c_cp_nb = virtual_faces_reverse.find(fit_nb); - CGAL_triangulation_assertion(c_cp_nb != virtual_faces_reverse.end()); - Offset nboff = (*oit)[i]; - for (int n = 0; n < 8; n++) - { - int n_nb; - if (nboff.is_null()) - n_nb = n; - else - { - int o_i = ((n + 1) / 3 - nboff.x() + 3) % 3; - int o_j = (n + 1 - nboff.y() + 3) % 3; - n_nb = 3 * o_i + o_j - 1; - } - if (n_nb == -1) - { - CGAL_triangulation_assertion(fit_nb->has_vertex(c_cp->second[n]->vertex(ccw(i))) ); - CGAL_triangulation_assertion(fit_nb->has_vertex(c_cp->second[n]->vertex( cw(i))) ); - c_cp->second[n]->set_neighbor(i, fit_nb); - } - else - { - CGAL_triangulation_assertion(n_nb >= 0); - CGAL_triangulation_assertion(static_cast(n_nb) <= c_cp_nb->second.size()); - CGAL_triangulation_assertion(c_cp_nb->second[n_nb]->has_vertex(c_cp->second[n]->vertex(ccw(i))) ); - CGAL_triangulation_assertion(c_cp_nb->second[n_nb]->has_vertex(c_cp->second[n]->vertex( cw(i))) ); - c_cp->second[n]->set_neighbor(i, c_cp_nb->second[n_nb]); - } - } - } - } - - // Set neighboring relations of original faces - oit = off_nb.begin(); - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit, ++oit) - { - CGAL_triangulation_assertion( oit != off_nb.end() ); - for (int i = 0; i < 3; i++) - { - Offset nboff = (*oit)[i]; - if (!nboff.is_null()) - { - Face_handle fit_nb = (*fit)->neighbor(i); - VCRMIT c_cp_nb = virtual_faces_reverse.find(fit_nb); - CGAL_triangulation_assertion(c_cp_nb != virtual_faces_reverse.end()); - int o_i = (3 - nboff.x()) % 3; - int o_j = (3 - nboff.y()) % 3; - int n_nb = 3 * o_i + o_j - 1; - CGAL_triangulation_assertion(n_nb >= 0); - CGAL_triangulation_assertion(static_cast(n_nb) <= c_cp_nb->second.size()); - CGAL_triangulation_assertion(c_cp_nb->second[n_nb]->has_vertex((*fit)->vertex(ccw(i))) ); - CGAL_triangulation_assertion(c_cp_nb->second[n_nb]->has_vertex((*fit)->vertex( cw(i))) ); - (*fit)->set_neighbor(i, c_cp_nb->second[n_nb]); - } - } - } - - // Set incident faces - for (Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) - { - for (int i = 0; i < 3; i++) - { - fit->vertex(i)->set_face(fit); - } - } - - // Set offsets where necessary - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit) - { - VCRMIT c_cp = virtual_faces_reverse.find(*fit); - CGAL_triangulation_assertion( c_cp != virtual_faces_reverse.end()); - Offset off[3]; - for (int i = 0; i < 3; i++) - off[i] = int_to_off((*fit)->offset(i)); - if (off[0].is_null() && off[1].is_null() && off[2].is_null()) - continue; - for (int n = 0; n < 8; n++) - { - Offset off_cp[4]; - int o_i = ((n + 1) / 3) % 3; - int o_j = (n + 1) % 3; - if (o_i != 2 && o_j != 2) - continue; - for (int i = 0; i < 3; i++) - { - off_cp[i] = Offset((o_i == 2) ? off[i].x() : 0, (o_j == 2) ? off[i].y() - : 0); - CGAL_triangulation_assertion(off_cp[i].x() == 0 || off_cp[i].x() == 1); - CGAL_triangulation_assertion(off_cp[i].y() == 0 || off_cp[i].y() == 1); - } - set_offsets(c_cp->second[n], off_cp[0], off_cp[1], off_cp[2]); - } - } - - // Iterate over all original faces and reset offsets. - for (typename std::list::iterator fit = original_faces.begin(); fit - != original_faces.end(); ++fit) - { - //This statement does not seem to have any effect - set_offsets(*fit, 0, 0, 0); - CGAL_triangulation_assertion((*fit)->offset(0) == 0); - CGAL_triangulation_assertion((*fit)->offset(1) == 0); - CGAL_triangulation_assertion((*fit)->offset(2) == 0); - } - - _cover = make_array(3, 3); - - // Set up too long edges data structure - int i = 0; - for (Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit) - { - _too_long_edges[vit] = std::list(); - ++i; - } - _too_long_edge_counter = find_too_long_edges(_too_long_edges); - - CGAL_triangulation_expensive_assertion(is_valid()); - - CGAL_triangulation_assertion(!is_1_cover()); -} - -// iterate over all edges and store the ones that are longer than -// edge_length_threshold in edges. Return the number of too long edges. -template -inline int Periodic_4_hyperbolic_triangulation_2::find_too_long_edges(std::map < - Vertex_handle, std::list > & edges) const -{ - Point p1, p2; - int counter = 0; - Vertex_handle v_no, vh; - for (Edge_iterator eit = edges_begin(); eit != edges_end(); eit++) - { - p1 = construct_point(eit->first->vertex(ccw(eit->second))->point(), - get_offset(eit->first, ccw(eit->second))); - p2 = construct_point(eit->first->vertex(cw(eit->second))->point(), - get_offset(eit->first, cw(eit->second))); - if (edge_is_too_long(p1, p2)) - { - if (&*(eit->first->vertex(ccw(eit->second))) < &*(eit->first->vertex(cw( - eit->second)))) - { - v_no = eit->first->vertex(ccw(eit->second)); - vh = eit->first->vertex(cw(eit->second)); - } - else - { - v_no = eit->first->vertex(cw(eit->second)); - vh = eit->first->vertex(ccw(eit->second)); - } - edges[v_no].push_back(vh); - counter++; - } - } - return counter; -} - -/** - * - fh->offset(i) is an bit tuple encapsulated in an integer. Each bit - * represents the offset in one direction --> 2-cover! - * - int_to_off(int) decodes this again. - * - Finally the offset vector is multiplied by cover. - * So if we are working in 3-cover we translate it to the neighboring - * 3-cover and not only to the neighboring domain. - */ -template -inline void Periodic_4_hyperbolic_triangulation_2::get_vertex(Face_handle fh, - int i, Vertex_handle &vh, Offset &off) const -{ - off = combine_offsets(Offset(), int_to_off(fh->offset(i))); - vh = fh->vertex(i); - - if (is_1_cover()) - return; - Vertex_handle vh_i = vh; - get_vertex(vh_i, vh, off); - return; -} - -template -inline void Periodic_4_hyperbolic_triangulation_2::get_vertex(Vertex_handle vh_i, - Vertex_handle &vh, Offset &off) const -{ - Virtual_vertex_map_it it = _virtual_vertices.find(vh_i); - - if (it == _virtual_vertices.end()) - { - // if vh_i is not contained in virtual_vertices, then it is in the - // original domain. - vh = vh_i; - CGAL_triangulation_assertion(vh != Vertex_handle()); - } - else - { - // otherwise it has to be looked up as well as its offset. - vh = it->second.first; - off += it->second.second; - CGAL_triangulation_assertion(vh->point().x() < _domain.xmax()); - CGAL_triangulation_assertion(vh->point().y() < _domain.ymax()); - CGAL_triangulation_assertion(vh->point().x() >= _domain.xmin()); - CGAL_triangulation_assertion(vh->point().y() >= _domain.ymin()); - } -} - -/** Find the Face that consists of the three given vertices - * - * Iterates over all faces and compare the three vertices of each face - * with the three vertices in vh. - */ -template -inline typename Periodic_4_hyperbolic_triangulation_2::Face_handle Periodic_4_hyperbolic_triangulation_2 < -GT, Tds >::get_face(const Vertex_handle* vh) const -{ - bool contains_v[2]; - Face_circulator fc = incident_faces(vh[2]); - Face_circulator done(fc); - do - { - CGAL_triangulation_assertion( - fc->vertex(0) == vh[2] || - fc->vertex(1) == vh[2] || - fc->vertex(2) == vh[2]); - for (int j = 0; j < 2; j++) - { - contains_v[j] = (fc->vertex(0) == vh[j]) || (fc->vertex(1) == vh[j]) - || (fc->vertex(2) == vh[j]); - } - if (contains_v[0] && contains_v[1]) - { - return fc; - } - } - while (++fc != done); - - CGAL_triangulation_assertion(false); - return Face_handle(); -} - -template -Bounded_side Periodic_4_hyperbolic_triangulation_2::side_of_face(const Point &q, - const Offset &off, Face_handle f, Locate_type <, int &li) const -{ - CGAL_triangulation_precondition(number_of_vertices() != 0); - - Orientation o0, o1, o2; - o0 = o1 = o2 = ZERO; - int cumm_off = f->offset(0) | f->offset(1) | f->offset(2); - - if ((cumm_off == 0) && is_1_cover()) - { - CGAL_triangulation_assertion(off == Offset()); - - const Point &p0 = f->vertex(0)->point(); - const Point &p1 = f->vertex(1)->point(); - const Point &p2 = f->vertex(2)->point(); - - if (((o0 = orientation(q, p1, p2)) == NEGATIVE) || ((o1 = orientation(p0, - q, p2)) == NEGATIVE) || ((o2 = orientation(p0, p1, q)) == NEGATIVE)) - { - return ON_UNBOUNDED_SIDE; - } - } - else // Special case for the periodic space. - { - Offset off_q; - Offset offs[3]; - const Point *p[3]; - for (int i = 0; i < 3; i++) - { - p[i] = &(f->vertex(i)->point()); - offs[i] = get_offset(f, i); - } - CGAL_triangulation_assertion(orientation(*p[0], *p[1], *p[2], - offs[0], offs[1], offs[2]) == POSITIVE); - bool found = false; - for (int i = 0; (i < 4) && (!found); i++) - { - if ((cumm_off | ((~i) & 3)) == 3) - { - o0 = o1 = o2 = NEGATIVE; - off_q = combine_offsets(off, int_to_off(i)); - - if (((o0 = orientation(q, *p[1], *p[2], off_q, offs[1], offs[2])) - != NEGATIVE) && ((o1 = orientation(*p[0], q, *p[2], offs[0], off_q, - offs[2])) != NEGATIVE) && ((o2 = orientation(*p[0], *p[1], q, - offs[0], offs[1], off_q)) != NEGATIVE)) - { - found = true; - } - } - } - if (!found) - return ON_UNBOUNDED_SIDE; - } - - // now all the oi's are >=0 - // sum gives the number of facets p lies on - int sum = ((o0 == ZERO) ? 1 : 0) + ((o1 == ZERO) ? 1 : 0) + ((o2 == ZERO) ? 1 - : 0); - - switch (sum) - { - case 0: - { - lt = FACE; - return ON_BOUNDED_SIDE; - } - case 1: - { - lt = EDGE; - // i = index such that q lies on edge (f,li) - li = (o0 == ZERO) ? 0 : (o1 == ZERO) ? 1 : 2; - return ON_BOUNDARY; - } - case 2: - { - lt = VERTEX; - // i = index such that q lies on vertex li - li = (o0 != ZERO) ? 0 : (o1 != ZERO) ? 1 : 2; - return ON_BOUNDARY; - } - default: - { - // impossible : cannot be on 3 edges for a real triangle - CGAL_triangulation_assertion(false); - return ON_BOUNDARY; - } - } -} - -template -Oriented_side Periodic_4_hyperbolic_triangulation_2::oriented_side(Face_handle f, - const Point& p, const Offset &o) const -{ - Point &p0 = f->vertex(0)->point(); - Point &p1 = f->vertex(1)->point(); - Point &p2 = f->vertex(2)->point(); - - int cumm_off = f->offset(0) | f->offset(1) | f->offset(2); - - if ((cumm_off == 0) && is_1_cover()) - { - CGAL_precondition(o == Offset()); - - // return position of point p with respect to the oriented triangle p0p1p2 - // the orientation of the vertices is assumed to be counter clockwise - CGAL_assertion(orientation(p0, p1, p2) == LEFT_TURN); - - Bounded_side bs = bounded_side(p0, p1, p2, p); - switch (bs) - { - case ON_BOUNDARY: - return ON_ORIENTED_BOUNDARY; - case ON_BOUNDED_SIDE: - return ON_POSITIVE_SIDE; - case ON_UNBOUNDED_SIDE: - return ON_NEGATIVE_SIDE; - } - } - else // Special case for the periodic space. - { - Offset off_q; - Offset off0 = get_offset(f, 0); - Offset off1 = get_offset(f, 1); - Offset off2 = get_offset(f, 2); - - // return position of point p with respect to the oriented triangle p0p1p2 - // the orientation of the vertices is assumed to be counter clockwise - CGAL_assertion(orientation(p0, p1, p2, off0, off1, off2) == LEFT_TURN); - - Bounded_side bs; - for (int i = 0; (i <= 7); i++) - { - if ((cumm_off | ((~i) & 3)) == 3) - { - off_q = combine_offsets(o, int_to_off(i)); - bs = bounded_side(p0, p1, p2, p, off0, off1, off2, off_q); - if (bs != ON_UNBOUNDED_SIDE) - { - return (bs == ON_BOUNDARY ? ON_ORIENTED_BOUNDARY : ON_POSITIVE_SIDE); - } - } - } - - return ON_NEGATIVE_SIDE; - } - - CGAL_assertion(false); - return ON_NEGATIVE_SIDE; -} - -template -Bounded_side Periodic_4_hyperbolic_triangulation_2::bounded_side(const Point &p0, const Point &p1, const Point &p2, const Point &p) const -{ - - // return position of point p with respect to triangle p0p1p2 - CGAL_triangulation_precondition( orientation(p0, p1, p2) != COLLINEAR); - - Orientation o1 = orientation(p0, p1, p); - Orientation o2 = orientation(p1, p2, p); - Orientation o3 = orientation(p2, p0, p); - - if (o1 == COLLINEAR) - { - if (o2 == COLLINEAR || o3 == COLLINEAR) - return ON_BOUNDARY; - if (collinear_between(p0, p, p1)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - if (o2 == COLLINEAR) - { - if (o3 == COLLINEAR) - return ON_BOUNDARY; - if (collinear_between(p1, p, p2)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - if (o3 == COLLINEAR) - { - if (collinear_between(p2, p, p0)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - // from here none ot, o1, o2 and o3 are known to be non null - if (o1 == o2 && o2 == o3) - return ON_BOUNDED_SIDE; - return ON_UNBOUNDED_SIDE; -} - -template -Bounded_side Periodic_4_hyperbolic_triangulation_2::bounded_side(const Point &p0, - const Point &p1, const Point &p2, const Point &p, const Offset &o0, - const Offset &o1, const Offset &o2, const Offset &o) const -{ - // return position of point p with respect to triangle p0p1p2 - CGAL_triangulation_precondition( orientation(p0, p1, p2, o0, o1, o2) != COLLINEAR); - Orientation orient1 = orientation(p0, p1, p, o0, o1, o); - Orientation orient2 = orientation(p1, p2, p, o1, o2, o); - Orientation orient3 = orientation(p2, p0, p, o2, o0, o); - - if (orient1 == COLLINEAR) - { - if (orient2 == COLLINEAR || orient3 == COLLINEAR) - return ON_BOUNDARY; - if (collinear_between(p0, p, p1, o0, o, o1)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - if (orient2 == COLLINEAR) - { - if (orient3 == COLLINEAR) - return ON_BOUNDARY; - if (collinear_between(p1, p, p2, o1, o, o2)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - if (orient3 == COLLINEAR) - { - if (collinear_between(p2, p, p0, o2, o, o0)) - return ON_BOUNDARY; - return ON_UNBOUNDED_SIDE; - } - - // from here none ot, o1, o2 and o3 are known to be non null - if (orient1 == orient2 && orient2 == orient3) - return ON_BOUNDED_SIDE; - return ON_UNBOUNDED_SIDE; -} - - -template -bool Periodic_4_hyperbolic_triangulation_2::collinear_between(const Point& p, - const Point& q, const Point& r) const -{ - // return true if point q is strictly between p and r - // p,q and r are supposed to be collinear points - Comparison_result c_pr = compare_x(p, r); - Comparison_result c_pq; - Comparison_result c_qr; - if(c_pr == EQUAL) - { - c_pq = compare_y(p, q); - c_qr = compare_y(q, r); - } - else - { - c_pq = compare_x(p, q); - c_qr = compare_x(q, r); - } - return ( (c_pq == SMALLER) && (c_qr == SMALLER) ) || - ( (c_pq == LARGER) && (c_qr == LARGER) ); - -} - -template -bool Periodic_4_hyperbolic_triangulation_2::collinear_between(const Point& p, - const Point& q, const Point& r, const Offset& o_p, const Offset& o_q, - const Offset& o_r) const -{ - // return true if point q is strictly between p and r - // p,q and r are supposed to be collinear points - Comparison_result c_pr = compare_x(p, r, o_p, o_r); - Comparison_result c_pq; - Comparison_result c_qr; - if (c_pr == EQUAL) - { - c_pq = compare_y(p, q, o_p, o_q); - c_qr = compare_y(q, r, o_q, o_r); - } - else - { - c_pq = compare_x(p, q, o_p, o_q); - c_qr = compare_x(q, r, o_q, o_r); - } - return (((c_pq == SMALLER) && (c_qr == SMALLER)) || - ((c_pq == LARGER) && (c_qr == LARGER))); -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_x( - const Point& p, const Point& q) const -{ - return geom_traits().compare_x_2_object()(p, q); -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_x( - const Point& p, const Point& q, const Offset &o_p, const Offset &o_q) const -{ - return geom_traits().compare_x_2_object()(p, q, o_p, o_q); -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_xy( - const Point& p, const Point& q) const -{ - Comparison_result res = geom_traits().compare_x_2_object()(p, q); - if (res == EQUAL) - { - return geom_traits().compare_y_2_object()(p, q); - } - return res; -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_xy( - const Point& p, const Point& q, const Offset &o_p, const Offset &o_q) const -{ - Comparison_result res = geom_traits().compare_x_2_object()(p, q, o_p, o_q); - if (res == EQUAL) - { - return geom_traits().compare_y_2_object()(p, q, o_p, o_q); - } - return res; -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_y( - const Point& p, const Point& q) const -{ - return geom_traits().compare_y_2_object()(p, q); -} - -template -inline Comparison_result Periodic_4_hyperbolic_triangulation_2::compare_y( - const Point& p, const Point& q, const Offset &o_p, const Offset &o_q) const -{ - return geom_traits().compare_y_2_object()(p, q, o_p, o_q); -} - -template -inline -bool Periodic_4_hyperbolic_triangulation_2::xy_equal(const Point& p, - const Point& q) const -{ - return compare_xy(p, q) == EQUAL; -} - -template -inline Orientation Periodic_4_hyperbolic_triangulation_2::orientation( - const Point& p0, const Point& p1, const Point& p2) const -{ - return geom_traits().orientation_2_object()(p0, p1, p2); -} -template -inline Orientation Periodic_4_hyperbolic_triangulation_2::orientation( - const Point& p0, const Point& p1, const Point& p2, const Offset& o0, - const Offset& o1, const Offset& o2) const -{ - return geom_traits().orientation_2_object()(p0, p1, p2, o0, o1, o2); -} - - -template -Oriented_side Periodic_4_hyperbolic_triangulation_2::side_of_oriented_circle( - const Point &p0, const Point &p1, const Point &p2, const Point &p, - bool perturb) const -{ - Oriented_side os = geom_traits().side_of_oriented_circle_2_object()(p0, p1, p2, p); - if ((os != ON_ORIENTED_BOUNDARY) || (!perturb)) - return os; - - // We are now in a degenerate case => we do a symbolic perturbation. - - // We sort the points lexicographically. - const Point * points[4] = { &p0, &p1, &p2, &p }; - std::sort(points, points + 4, Perturbation_order(this)); - - // We successively look whether the leading monomial, then 2nd monomial - // of the determinant has non null coefficient. - // 2 iterations are enough (cf paper) - for (int i = 3; i > 0; --i) - { - if (points[i] == &p) - return ON_NEGATIVE_SIDE; // since p0 p1 p2 are non collinear - // and positively oriented - Orientation o; - if (points[i] == &p2 && (o = orientation(p0, p1, p)) != COLLINEAR) - return Oriented_side(o); - if (points[i] == &p1 && (o = orientation(p0, p, p2)) != COLLINEAR) - return Oriented_side(o); - if (points[i] == &p0 && (o = orientation(p, p1, p2)) != COLLINEAR) - return Oriented_side(o); - } - CGAL_triangulation_assertion(false); - return ON_NEGATIVE_SIDE; -} - -template -Oriented_side Periodic_4_hyperbolic_triangulation_2::side_of_oriented_circle( - const Point &p0, const Point &p1, const Point &p2, const Point &p, - const Offset &o0, const Offset &o1, const Offset &o2, const Offset &o, - bool perturb) const -{ - Oriented_side os = geom_traits().side_of_oriented_circle_2_object()(p0, p1, p2, p, o0, o1, o2, o); - if ((os != ON_ORIENTED_BOUNDARY) || (!perturb)) - return os; - - // We are now in a degenerate case => we do a symbolic perturbation. - // We sort the points lexicographically. - Periodic_point pts[4] = { std::make_pair(p0, o0), std::make_pair(p1, o1), - std::make_pair(p2, o2), std::make_pair(p, o) - }; - const Periodic_point *points[4] = { &pts[0], &pts[1], &pts[2], &pts[3] }; - - std::sort(points, points + 4, Perturbation_order(this)); - - // We successively look whether the leading monomial, then 2nd monomial - // of the determinant has non null coefficient. - // 2 iterations are enough (cf paper) - for (int i = 3; i > 0; --i) - { - if (points[i] == &pts[3]) - return ON_NEGATIVE_SIDE; // since p0 p1 p2 are non collinear - // and positively oriented - Orientation orient; - if ((points[i] == &pts[2]) && ((orient = orientation(p0, p1, p, o0, o1, o)) - != COLLINEAR)) - return Oriented_side(orient); - if ((points[i] == &pts[1]) && ((orient = orientation(p0, p, p2, o0, o, o2)) - != COLLINEAR)) - return Oriented_side(orient); - if ((points[i] == &pts[0]) && ((orient = orientation(p, p1, p2, o, o1, o2)) - != COLLINEAR)) - return Oriented_side(orient); - } - CGAL_triangulation_assertion(false); - return ON_NEGATIVE_SIDE; -} - -template -Oriented_side Periodic_4_hyperbolic_triangulation_2::side_of_oriented_circle( - Face_handle f, const Point & p, bool perturb) const -{ - Oriented_side os = ON_NEGATIVE_SIDE; - - int i = 0; - // TODO: optimize which copies to check depending on the offsets in - // the face. - while (os == ON_NEGATIVE_SIDE && i < 4) - { - os = side_of_oriented_circle(f->vertex(0)->point(), f->vertex(1)->point(), f->vertex(2)->point(), p, - get_offset(f, 0), get_offset(f, 1), get_offset(f, 2), combine_offsets(Offset(), int_to_off(i)), - perturb); - i++; - } - - return os; -} - - -template -void Periodic_4_hyperbolic_triangulation_2::insert_too_long_edges_in_star(Vertex_handle vh) -{ - // Insert the too long edges in the star of vh - Face_handle f = vh->face(); - Face_handle f_start = f; - - do - { - int i = ccw(f->index(vh)); - - insert_too_long_edge(f, i); - - // Proceed to the next face - f = f->neighbor(i); - } - while (f != f_start); -} - -template -void Periodic_4_hyperbolic_triangulation_2::insert_too_long_edge(Face_handle f, int i) -{ - Vertex_handle vh1 = f->vertex(ccw(i)); - Vertex_handle vh2 = f->vertex(cw(i)); - CGAL_assertion(vh1 != Vertex_handle()); - CGAL_assertion(vh2 != Vertex_handle()); - Point p1 = construct_point(vh1->point(), get_offset(f, ccw(i))); - Point p2 = construct_point(vh2->point(), get_offset(f, cw(i))); - - if (&*vh1 < &*vh2) - { - if (edge_is_too_long(p1, p2) && - (find(_too_long_edges[vh1].begin(), _too_long_edges[vh1].end(), vh2) == _too_long_edges[vh1].end())) - { - _too_long_edges[vh1].push_back(vh2); - _too_long_edge_counter++; - } - } - else - { - CGAL_triangulation_precondition(&*vh2 < &*vh1); - if (edge_is_too_long(p2, p1) && - (find(_too_long_edges[vh2].begin(), _too_long_edges[vh2].end(), vh1) == _too_long_edges[vh2].end())) - { - _too_long_edges[vh2].push_back(vh1); - _too_long_edge_counter++; - } - } -} - -template -void Periodic_4_hyperbolic_triangulation_2::remove_too_long_edges_in_star( - Vertex_handle vh) -{ - if (is_1_cover()) - return; - - // Insert the too long edges in the star of vh - Face_handle f = vh->face(); - Face_handle f_start = f; - - do - { - int i = f->index(vh); - int i2 = ccw(i); - Vertex_handle vh2 = f->vertex(i2); - - // Point corresponding to v - Point p1 = construct_point(vh->point(), get_offset(f, f->index(vh))); - // Point corresponding to the other vertex - Point p2 = construct_point(vh2->point(), get_offset(f, i2)); - - if (&*vh < &*vh2) - { - if (edge_is_too_long(p1, p2) && - (find(_too_long_edges[vh].begin(), _too_long_edges[vh].end(), vh2) != - _too_long_edges[vh].end())) - { - _too_long_edges[vh].remove(vh2); - _too_long_edge_counter--; - } - } - else - { - CGAL_triangulation_precondition(&*vh2 < &*vh); - if (edge_is_too_long(p1, p2) && - (find(_too_long_edges[vh2].begin(), _too_long_edges[vh2].end(), vh) != - _too_long_edges[vh2].end())) - { - _too_long_edges[vh2].remove(vh); - _too_long_edge_counter--; - } - } - - // Proceed to the next face - f = f->neighbor(i2); - } - while (f != f_start); -} - -template -void Periodic_4_hyperbolic_triangulation_2::remove_too_long_edge(Face_handle f, - int i) -{ - Vertex_handle vh1 = f->vertex(cw(i)); - Vertex_handle vh2 = f->vertex(ccw(i)); - Point p1 = construct_point(vh1->point(), get_offset(f, cw(i))); - Point p2 = construct_point(vh2->point(), get_offset(f, ccw(i))); - if (edge_is_too_long(p1, p2)) - { - if (&*vh1 < &*vh2) - { - typename std::list::iterator it = find( - _too_long_edges[vh1].begin(), _too_long_edges[vh1].end(), vh2); - if (it != _too_long_edges[vh1].end()) - { - _too_long_edges[vh1].erase(it); - _too_long_edge_counter--; - } - } - else - { - typename std::list::iterator it = find( - _too_long_edges[vh2].begin(), _too_long_edges[vh2].end(), vh1); - if (it != _too_long_edges[vh2].end()) - { - _too_long_edges[vh2].erase(it); - _too_long_edge_counter--; - } - } - } -} - -template -bool Periodic_4_hyperbolic_triangulation_2::edge_is_too_long(const Point &p1, - const Point &p2) const -{ - return squared_distance(p1, p2) > _edge_length_threshold; -} - -template -inline bool Periodic_4_hyperbolic_triangulation_2::is_extensible_triangulation_in_1_sheet_h1() const -{ - if (!is_1_cover()) - { - if (_too_long_edge_counter == 0) - return true; - else - return false; - } - else - { - typename Geom_traits::FT longest_edge_squared_length(0); - Segment s; - for (Periodic_segment_iterator psit = periodic_segments_begin(UNIQUE); psit - != periodic_segments_end(UNIQUE); ++psit) - { - s = construct_segment(*psit); - longest_edge_squared_length = (std::max)(longest_edge_squared_length, - s.squared_length()); - } - return (longest_edge_squared_length < _edge_length_threshold); - } -} - -template -inline bool Periodic_4_hyperbolic_triangulation_2::is_extensible_triangulation_in_1_sheet_h2() const -{ - typedef typename Geom_traits::Construct_circumcenter_2 Construct_circumcenter; - typedef typename Geom_traits::FT FT; - Construct_circumcenter construct_circumcenter = - _gt.construct_circumcenter_2_object(); - for (Periodic_triangle_iterator tit = periodic_triangles_begin(UNIQUE); tit - != periodic_triangles_end(UNIQUE); ++tit) - { - Point cc = construct_circumcenter(tit->at(0).first, tit->at(1).first, - tit->at(2).first, tit->at(0).second, tit->at(1).second, - tit->at(2).second); - - if (!(FT(16) * squared_distance(cc, point(tit->at(0))) < (_domain.xmax() - - _domain.xmin()) * (_domain.xmax() - _domain.xmin()))) - return false; - } - return true; -} - -template -inline bool Periodic_4_hyperbolic_triangulation_2::is_triangulation_in_1_sheet() const -{ - if (is_1_cover()) - return true; - for (Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit) - { - if (_virtual_vertices.find(vit) == _virtual_vertices.end()) - continue; - std::set nb_v_odom; - Vertex_handle vh; - Offset off; - Vertex_circulator vcir = adjacent_vertices(vit); - Vertex_circulator vstart = vcir; - size_t degree = 0; - do - { - get_vertex(vcir, vh, off); - nb_v_odom.insert(vh); - degree++; - } - while (++vcir != vstart); - if (degree != nb_v_odom.size()) - return false; - } - return true; -} - -template -std::ostream& -Periodic_4_hyperbolic_triangulation_2::save(std::ostream& os) const -{ - // writes : - // the number of vertices - // the domain as four coordinates: xmin ymin ymax zmax - // the current covering that guarantees the triangulation to be a - // simplicial complex - // the non combinatorial information on vertices (points in case of 1-sheeted - // covering, point-offset pairs otherwise) - // ALL PERIODIC COPIES OF ONE VERTEX MUST BE STORED CONSECUTIVELY - // the number of faces - // the faces by the indices of their vertices in the preceding list - // of vertices, plus the non combinatorial information on each face - // the neighbors of each face by their index in the preceding list of faces - - // outputs dimension, domain and number of vertices - Covering_sheets cover = number_of_sheets(); - size_type n = number_of_vertices(); - - - if (is_ascii(os)) - os << domain() << std::endl - << cover[0] << " " << cover[1] << std::endl - << n*cover[0]*cover[1] << std::endl; - else - { - os << domain(); - write(os, cover[0]); - write(os, cover[1]); - write(os, n * cover[0]*cover[1]); - } - std::cout << "Line:" << __LINE__ << " cover[0]:" << cover[0] << " cover[1]:" << cover[1] << " n*c0*c1:" << (n * cover[0]*cover[1]) << std::endl; - - std::cout << "save, #Vertices: " << n << std::endl; - - if (n == 0) - return os; - - // write the vertices - Unique_hash_map V; - std::size_t i = 0; - if (is_1_cover()) - { - for (Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it) - { - V[it] = i++; - os << it->point(); - if (is_ascii(os)) - os << std::endl; - } - } - else - { - Virtual_vertex_map_it vit, vvit; - std::vector vv; - for (Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it) - { - vit = _virtual_vertices.find(it); - if (vit != _virtual_vertices.end()) continue; - V[it] = i++; - if (is_ascii(os)) - os << it->point() << std::endl - << Offset(0, 0) << std::endl; - else - os << it->point() << Offset(0, 0); - CGAL_triangulation_assertion(_virtual_vertices_reverse.find(it) - != _virtual_vertices_reverse.end()); - vv = _virtual_vertices_reverse.find(it)->second; - CGAL_triangulation_assertion(vv.size() == 8); - for (std::size_t j = 0; j < vv.size(); j++) - { - vvit = _virtual_vertices.find(vv[j]); - CGAL_triangulation_assertion(vvit != _virtual_vertices.end()); - V[vv[j]] = i++; - if (is_ascii(os)) - os << vv[j]->point() << std::endl - << vvit->second.second << std::endl; - else os << vv[j]->point() << vvit->second.second; - } - } - } - CGAL_triangulation_postcondition(i == _cover[0]*_cover[1]*n); - - Unique_hash_map F; - int inum = 0; - // asks the tds for the combinatorial information - // vertices of the faces - size_type m = _tds.number_of_faces(); - if (is_ascii(os)) os << std::endl << m << std::endl; - else write(os, m); - std::cout << "save, #Faces: " << m << std::endl; - - for( Face_iterator ib = faces_begin(); - ib != faces_end(); ++ib) - { - F[ib] = inum++; - for(int j = 0; j < 3 ; ++j) - { - if(is_ascii(os)) os << V[ib->vertex(j)] << " "; - else write(os, V[ib->vertex(j)]); - } - os << *ib ; - if(is_ascii(os)) os << "\n"; - } - if(is_ascii(os)) os << "\n"; - - std::cout << "save, face check: " << inum << " == " << m << std::endl; - CGAL_assertion(m == (size_type)inum); - - // neighbor pointers of the faces - for( Face_iterator it = faces_begin(); - it != faces_end(); ++it) - { - for(int j = 0; j < 3; ++j) - { - CGAL_assertion(F.is_defined(it->neighbor(j))); - if(is_ascii(os)) os << F[it->neighbor(j)] << " "; - else write(os, F[it->neighbor(j)]); - } - if(is_ascii(os)) os << "\n"; - } - - // write offsets - //for (unsigned int i=0 ; ioffset(j); - if ( j == 3 ) - os << std::endl; - else - os << ' '; - } - else write(os, ch->offset(j)); - } - } - - // write the non combinatorial information on the faces - // using the << operator of Face - // works because the iterator of the tds traverses the faces in the - // same order as the iterator of the triangulation - if(number_of_vertices() != 0) - { - for(Face_iterator it = faces_begin(); it != faces_end(); ++it) - { - os << *it; // other information - if(is_ascii(os)) - os << std::endl; - } - } - - return os; -} - -template -std::istream& -Periodic_4_hyperbolic_triangulation_2::load(std::istream& is) -{ - // reads - // the current covering that guarantees the triangulation to be a - // simplicial complex - // the number of vertices - // the non combinatorial information on vertices (points in case of 1-sheeted - // covering, point-offset pairs otherwise) - // ALL PERIODIC COPIES OF ONE VERTEX MUST BE STORED CONSECUTIVELY - // the number of faces - // the faces by the indices of their vertices in the preceding list - // of vertices, plus the non combinatorial information on each face - // the neighbors of each face by their index in the preceding list of face - CGAL_triangulation_precondition(is.good()); - - clear(); - - Iso_rectangle domain(0, 0, 1, 1); - int cx = 0, cy = 0; - size_type n = 0; - - if (is_ascii(is)) - { - is >> domain; - is >> cx >> cy >> n; - } - else - { - is >> domain; - read(is, cx); - read(is, cy); - read(is, n); - } - std::cout << "Line:" << __LINE__ << " cx:" << cx << " cy:" << cy << " n:" << n << std::endl; - - CGAL_triangulation_assertion((n / (cx * cy))*cx*cy == n); - - tds().set_dimension((n == 0 ? -2 : 2)); - _domain = domain; - _gt.set_domain(domain); - _cover = make_array(cx, cy); - - if ( n == 0 ) return is; - - std::map< std::size_t, Vertex_handle > V; - - if (cx == 1 && cy == 1) - { - Point p; - for (std::size_t i = 0; i < n; i++) - { - V[i] = tds().create_vertex(); - is >> p; - V[i]->set_point(p); - } - } - else - { - Vertex_handle v, w; - std::vector vv; - Offset off; - Point p; - for (std::size_t i = 0; i < n; i++) - { - v = tds().create_vertex(); - V[i] = v; - is >> p >> off; - V[i]->set_point(p); - vv.clear(); - for (int j = 1; j < cx * cy; j++) - { - i++; - w = tds().create_vertex(); - V[i] = w; - is >> p >> off; - V[i]->set_point(p); - vv.push_back(w); - _virtual_vertices[w] = std::make_pair(v, off); - } - _virtual_vertices_reverse[v] = vv; - } - } - - // Creation of the faces - std::size_t index; - size_type m; - if (is_ascii(is)) is >> m; - else read(is, m); - std::vector F(m); - std::cout << "load, #Faces: " << m << std::endl; - { - for(size_t i = 0; i < m; ++i) - { - F[i] = _tds.create_face() ; - for(int j = 0; j < 3 ; ++j) - { - if (is_ascii(is)) is >> index; - else read(is, index); - CGAL_assertion(index < V.size()); - F[i]->set_vertex(j, V[index]); - // The face pointer of vertices is set too often, - // but otherwise we had to use one more map - V[index]->set_face(F[i]); - } - // read in non combinatorial info of the face - is >> *(F[i]) ; - } - } - - // Setting the neighbor pointers - { - for(size_t i = 0; i < m; ++i) - { - for(int j = 0; j < 3; ++j) - { - if (is_ascii(is)) is >> index; - else read(is, index); - if (index >= F.size()) { - std::cout << __FILE__ << ", " << __FUNCTION__ << ", l:" << __LINE__ << " f=" - << i << "<" << m << ", index=" << j << " nb=" << index << " #F=" << F.size() - << std::endl; - } - CGAL_assertion(i < F.size()); - CGAL_assertion(index < F.size()); - F[i]->set_neighbor(j, F[index]); - } - } - } - - // read offsets - int off[3] = {0, 0, 0}; - for (std::size_t j = 0 ; j < m; j++) - { - if (is_ascii(is)) - is >> off[0] >> off[1] >> off[2]; - else - { - read(is, off[0]); - read(is, off[1]); - read(is, off[2]); - } - set_offsets(F[j], off[0], off[1], off[2]); - } - - // read potential other information - for (std::size_t j = 0 ; j < m; j++) - is >> *(F[j]); - - int i = 0; - for (Vertex_iterator vi = vertices_begin(); - vi != vertices_end(); ++vi) - { - _too_long_edges[vi] = std::list(); - ++i; - } - - _edge_length_threshold = FT(0.166) * (_domain.xmax() - _domain.xmin()) - * (_domain.xmax() - _domain.xmin()); - _too_long_edge_counter = find_too_long_edges(_too_long_edges); - - CGAL_triangulation_expensive_assertion( is_valid() ); - return is; -} - - -namespace internal -{ - -/// Internal function used by operator==. -//TODO: introduce offsets -template -bool -test_next(const Periodic_4_hyperbolic_triangulation_2 &t1, - const Periodic_4_hyperbolic_triangulation_2 &t2, - typename Periodic_4_hyperbolic_triangulation_2::Face_handle c1, - typename Periodic_4_hyperbolic_triangulation_2::Face_handle c2, - std::map < typename Periodic_4_hyperbolic_triangulation_2::Face_handle, - typename Periodic_4_hyperbolic_triangulation_2::Face_handle > &Cmap, - std::map < typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle, - typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle > &Vmap) -{ - // This function tests and registers the 4 neighbors of c1/c2, - // and recursively calls itself over them. - // Returns false if an inequality has been found. - - // Precondition: c1, c2 have been registered as well as their 4 vertices. - CGAL_triangulation_precondition(t1.number_of_vertices() != 0); - CGAL_triangulation_precondition(Cmap[c1] == c2); - CGAL_triangulation_precondition(Vmap.find(c1->vertex(0)) != Vmap.end()); - CGAL_triangulation_precondition(Vmap.find(c1->vertex(1)) != Vmap.end()); - CGAL_triangulation_precondition(Vmap.find(c1->vertex(2)) != Vmap.end()); - - typedef Periodic_4_hyperbolic_triangulation_2 Tr1; - typedef Periodic_4_hyperbolic_triangulation_2 Tr2; - typedef typename Tr1::Vertex_handle Vertex_handle1; - typedef typename Tr1::Face_handle Face_handle1; - typedef typename Tr2::Vertex_handle Vertex_handle2; - typedef typename Tr2::Face_handle Face_handle2; - typedef typename std::map::const_iterator Cit; - typedef typename std::map < Vertex_handle1, - Vertex_handle2 >::const_iterator Vit; - - for (int i = 0; i <= 2; ++i) - { - Face_handle1 n1 = c1->neighbor(i); - Cit cit = Cmap.find(n1); - Vertex_handle1 v1 = c1->vertex(i); - Vertex_handle2 v2 = Vmap[v1]; - Face_handle2 n2 = c2->neighbor(c2->index(v2)); - if (cit != Cmap.end()) - { - // n1 was already registered. - if (cit->second != n2) - return false; - continue; - } - // n1 has not yet been registered. - // We check that the new vertices match geometrically. - // And we register them. - Vertex_handle1 vn1 = n1->vertex(n1->index(c1)); - Vertex_handle2 vn2 = n2->vertex(n2->index(c2)); - Vit vit = Vmap.find(vn1); - if (vit != Vmap.end()) - { - // vn1 already registered - if (vit->second != vn2) - return false; - } - else - { - if (t1.geom_traits().compare_xy_2_object()(vn1->point(), - vn2->point()) != 0) - return false; - - // We register vn1/vn2. - Vmap.insert(std::make_pair(vn1, vn2)); - } - - // We register n1/n2. - Cmap.insert(std::make_pair(n1, n2)); - // We recurse on n1/n2. - if (!test_next(t1, t2, n1, n2, Cmap, Vmap)) - return false; - } - - return true; -} - -} // namespace internal - - -template -std::istream& -operator>>(std::istream& is, Periodic_4_hyperbolic_triangulation_2 &tr) -{ - return tr.load(is); -} -template -std::ostream& -operator<<(std::ostream& os, Periodic_4_hyperbolic_triangulation_2 &tr) -{ - return tr.save(os); -} - -template < class GT, class Tds1, class Tds2 > -bool -operator==(const Periodic_4_hyperbolic_triangulation_2 &t1, - const Periodic_4_hyperbolic_triangulation_2 &t2) -{ - typedef typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle - Vertex_handle1; - typedef typename Periodic_4_hyperbolic_triangulation_2::Face_handle - Face_handle1; - typedef typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle - Vertex_handle2; - typedef typename Periodic_4_hyperbolic_triangulation_2::Vertex_handle - Vertex_iterator2; - typedef typename Periodic_4_hyperbolic_triangulation_2::Face_handle - Face_handle2; - typedef typename Periodic_4_hyperbolic_triangulation_2::Face_circulator - Face_circulator2; - - typedef typename Periodic_4_hyperbolic_triangulation_2::Point Point; - typedef typename Periodic_4_hyperbolic_triangulation_2::Offset Offset; - - // Some quick checks. - if ( t1.domain() != t2.domain() - || t1.number_of_sheets() != t2.number_of_sheets()) - return false; - - if ( t1.number_of_vertices() != t2.number_of_vertices() - || t1.number_of_faces() != t2.number_of_faces()) - return false; - - // Special case for empty triangulations - if (t1.number_of_vertices() == 0) - return true; - - // We will store the mapping between the 2 triangulations vertices and - // faces in 2 maps. - std::map Vmap; - std::map Cmap; - - // find a common point - Vertex_handle1 v1 = static_cast(t1.vertices_begin()); - Vertex_handle2 iv2; - for (Vertex_iterator2 vit2 = t2.vertices_begin() ; - vit2 != t2.vertices_end(); ++vit2) - { - if (t1.compare_xy(vit2->point(), v1->point(), - t2.get_offset(vit2), t1.get_offset(v1)) != EQUAL) - continue; - iv2 = static_cast(vit2); - break; - } - if (iv2 == Vertex_handle2()) - return false; - Vmap.insert(std::make_pair(v1, iv2)); - - // We pick one face of t1, and try to match it against the - // faces of t2. - Face_handle1 c = v1->face(); - Vertex_handle1 v2 = c->vertex(t1.cw(c->index(v1))); - Vertex_handle1 v3 = c->vertex(t1.ccw(c->index(v1))); - Point p2 = v2->point(); - Point p3 = v3->point(); - Offset o2 = t1.get_offset(v2); - Offset o3 = t1.get_offset(v3); - - Face_circulator2 fc = t2.incident_faces(iv2), done(fc); - do - { - int inf = fc->index(iv2); - - if (t1.compare_xy(p2, fc->vertex((inf + 1) % 3)->point(), - o2, t2.get_offset(fc->vertex((inf + 1) % 3))) == EQUAL) - Vmap.insert(std::make_pair(v2, fc->vertex((inf + 1) % 3))); - else if (t1.compare_xy(p2, fc->vertex((inf + 2) % 3)->point(), - o2, t2.get_offset(fc->vertex((inf + 2) % 3))) == EQUAL) - Vmap.insert(std::make_pair(v2, fc->vertex((inf + 2) % 3))); - else - continue; // None matched v2. - - if (t1.compare_xy(p3, fc->vertex((inf + 1) % 3)->point(), - o3, t2.get_offset(fc->vertex((inf + 1) % 3))) == EQUAL) - Vmap.insert(std::make_pair(v3, fc->vertex((inf + 1) % 3))); - else if (t1.compare_xy(p3, fc->vertex((inf + 2) % 3)->point(), - o3, t2.get_offset(fc->vertex((inf + 2) % 3))) == EQUAL) - Vmap.insert(std::make_pair(v3, fc->vertex((inf + 2) % 3))); - else - continue; // None matched v3. - - // Found it ! - Cmap.insert(std::make_pair(c, fc)); - break; - } - while (++fc != done); - - if (Cmap.size() == 0) - return false; - - // We now have one face, we need to propagate recursively. - return internal::test_next(t1, t2, - Cmap.begin()->first, Cmap.begin()->second, Cmap, Vmap); -} - -template < class GT, class Tds1, class Tds2 > -inline -bool -operator!=(const Periodic_4_hyperbolic_triangulation_2 &t1, - const Periodic_4_hyperbolic_triangulation_2 &t2) -{ - return ! (t1 == t2); -} - - -void insert_dummy_points(); - -#include - -} //namespace CGAL - - -#endif //CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_2_H diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_dummy.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_dummy.h deleted file mode 100644 index d0192bd8fad..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_dummy.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2010 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. -// -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/candidate-packages/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h $ -// $Id: Delaunay_triangulation_2.h 57509 2010-07-15 09:14:09Z sloriot $ -// -// -// Author(s) : Mikhail Bogdanov - -#ifndef CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_DUMMY_H -#define CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_DUMMY_H - -#include -#include - -// Added by Iordanov -/* -#if CLEARLY_MY_TYPE == 1 -#include -#else -#include -#endif -*/ - -namespace CGAL { - - // this class might to be moved to hyperbolic traits - template - class Construct_reflection - { - typedef typename GT::Point_2 Point_2; - typedef typename GT::Circle_2 Circle_2; - typedef typename GT::Vector_2 Vector_2; - typedef typename GT::FT FT; - - typedef typename GT::Compute_squared_distance_2 Compute_squared_distance_2; - typedef typename GT::Construct_vector_2 Construct_vector_2; - typedef typename GT::Construct_scaled_vector_2 Construct_scaled_vector_2; - typedef typename GT::Construct_translated_point_2 Construct_translated_point_2; - - typedef CGAL::Regular_triangulation_filtered_traits_2 Rtr_2; - typedef typename Rtr_2::Construct_weighted_circumcenter_2 Construct_weighted_circumcenter_2; - typedef typename Rtr_2::Weighted_point_2 Weighted_point_2; - typedef typename Rtr_2::Bare_point Bare_point; - - public: - Construct_reflection(const Circle_2& c = Circle_2(Point_2(0.0, 0.0), 1.)): _unit_circle(c) - { - } - - // exact arithmetic! very nice! - Point_2 operator ()(const Point_2& p, const Point_2& q, const Point_2& r) const - { - typedef typename GT::Collinear_2 Collinear_2; - if(Collinear_2()(p, q, _unit_circle.center())){ - assert(false); - } - Weighted_point_2 wp(p); - Weighted_point_2 wq(q); - Weighted_point_2 wo(_unit_circle.center(), _unit_circle.squared_radius()); - - Bare_point center = Construct_weighted_circumcenter_2()(wp, wo, wq); - FT radius = Compute_squared_distance_2()(p, center); - FT dist = Compute_squared_distance_2()(r,center); - Vector_2 vect = Construct_vector_2()(center,r); - vect = Construct_scaled_vector_2()(vect,radius/dist); - Point_2 image = Construct_translated_point_2()(center,vect); - return image; - } - - private: - const Circle_2& _unit_circle; - }; - - template - typename GT::Point_2 apply_rotation(const typename GT::Point_2& p) - { - // Note Iordan: This is rotation by \pi/4 -- the second and third argument are the values of cos(\theta) and sin(\theta), respectively - CGAL::Aff_transformation_2 rotate(CGAL::ROTATION, std::sqrt(0.5), std::sqrt(0.5)); - - return rotate(p); - } - - - - - - - template - void compute_dummy_points( std::vector& inner_points, - std::vector& points_on_boundary, - std::vector& points_on_vertex) - { - assert(inner_points.size() == 0); - assert(points_on_boundary.size() == 0); - assert(points_on_vertex.size() == 0); - - typedef typename GT::Kernel K; - typedef typename GT::Point_2 Point_2; - - double phi = CGAL_PI / 8.; - double psi = CGAL_PI / 3.; - double rho = std::sqrt(cos(psi)*cos(psi) - sin(phi)*sin(phi)); - - const Point_2 o(0.0, 0.0); - const Point_2 a(cos(phi)*cos(phi + psi)/rho, sin(phi)*cos(phi + psi)/rho); - const Point_2 b(a.x(), -a.y()); - - inner_points.push_back(a); - Point_2 c = Construct_reflection()(a, b, o); - Point_2 d = Construct_reflection()(a, c, b); - //inner_points.push_back(d); - Point_2 e = Construct_reflection()(d, c, a); - Point_2 f = Construct_reflection()(d, e, c); - - int size = inner_points.size(); - for(int i = 0; i < 7; i++) { - for(int j = 0; j < size; j++) { - inner_points.push_back(apply_rotation(inner_points[i*size + j])); - } - } - inner_points.push_back(o); - - points_on_boundary.push_back(c); - for(int i = 1; i < 4; i++) { - points_on_boundary.push_back(apply_rotation(points_on_boundary[i-1])); - } - - points_on_vertex.push_back(apply_rotation(f)); - } - - /* - - template - void recursive_translate(Diametric_translations g, - std::vector& points, - int depth, - int start, - int end) { - - if (depth > 0) { - int my_start = points.size(); - int my_end = start; - - for (int i = start; i <= end; i++){ - typename GT::Point_2 subject = points[i]; - points.push_back( g.a().DoAction(subject) ); - points.push_back( g.b().inverse().DoAction(subject) ); - points.push_back( g.c().DoAction(subject) ); - points.push_back( g.d().inverse().DoAction(subject) ); - points.push_back( g.a().inverse().DoAction(subject) ); - points.push_back( g.b().DoAction(subject) ); - points.push_back( g.c().inverse().DoAction(subject) ); - points.push_back( g.d().DoAction(subject) ); - my_end += 8; - } - - recursive_translate(g, points, depth - 1, my_start, my_end); - } - - } - - - - template - void recursive_translate(Diametric_translations g, - std::vector& points, - typename GT::Point_2 subject, - int depth) { - - if (depth > 0) { - int start = points.size(); - int end = start + 8; - - // Add points in the order indicated by the group -- not necessary, but seems logical - points.push_back( g.a().DoAction(subject) ); - points.push_back( g.b().inverse().DoAction(subject) ); - points.push_back( g.c().DoAction(subject) ); - points.push_back( g.d().inverse().DoAction(subject) ); - points.push_back( g.a().inverse().DoAction(subject) ); - points.push_back( g.b().DoAction(subject) ); - points.push_back( g.c().inverse().DoAction(subject) ); - points.push_back( g.d().DoAction(subject) ); - - recursive_translate(g, points, depth - 1, start, end); - } - - } -*/ - - template < class GT, class TDS > - void Delaunay_hyperbolic_triangulation_2::insert_dummy_points(std::vector& all_points) { - //clear(); - - std::vector inner_points, points_on_boundary, points_on_vertex; - - compute_dummy_points(inner_points, points_on_boundary, points_on_vertex); - - /*std::vector*/ all_points = inner_points; - - for (int i = 0; i < points_on_boundary.size(); i++) { - all_points.push_back(points_on_boundary[i]); - } - - for (int i = 0; i < points_on_vertex.size(); i++) { - all_points.push_back(points_on_vertex[i]); - } - - std::cout << "All points length: " << all_points.size() << std::endl; - - //for (int i = 0; i < all_points.size(); i++) { - // processInput(all_points[i]); - //} - - //Base::insert(all_points.begin(), all_points.end()); - - /* - Diametric_translations g; - std::vector copies; - for (int i = 0; i < all_points.size(); i++) { - recursive_translate(g, copies, all_points[i], recursion_depth); - } - - std::cout << "Copies length: " << copies.size() << std::endl; - Base::insert(copies.begin(), copies.end()); - */ - - } - - } // namespace CGAL - -#endif // CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_DUMMY_H - diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h deleted file mode 100644 index ef3396dd86f..00000000000 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2006-2009 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// 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. -// -// $URL$ -// $Id$ -// -// -// Author(s) : Nico Kruithof -// Manuel Caroli - -#ifndef CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H -#define CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H - - -#include -#include -#include -#include -#include - - -namespace CGAL { - -template < class THT2 > -class Periodic_4_hyperbolic_triangulation_traits_base_2 - : public THT2 -{ -public: - typedef THT2 K; - typedef HyperbolicOctagonGroup Offset; - typedef Periodic_4_hyperbolic_triangulation_traits_base_2< K > Self; - - typedef typename K::RT RT; - typedef typename K::FT FT; - typedef typename K::Point_2 Point_2; - //typedef typename K::Vector_3 Vector_3; - typedef Offset Periodic_4_hyperbolic_offset_2; - typedef typename K::Circle_2 Circle_2; - - // The next typedef is there for backward compatibility - // Some users take their point type from the traits class. - // Before this type was Point - typedef Point_2 Point; - - - // Triangulation predicates - typedef Traits_with_hyperbolic_offsets_adaptor - Compare_xy_2; - typedef Traits_with_hyperbolic_offsets_adaptor - Orientation_2; - - // Triangulation constructions - typedef Periodic_4_construct_hyperbolic_point_2 - Construct_hyperbolic_point_2; - typedef Traits_with_hyperbolic_offsets_adaptor - Construct_segment_2; - typedef Traits_with_hyperbolic_offsets_adaptor - Construct_hyperbolic_triangle_2; - - // Access - void set_domain(const Circle_2& domain) { - _domain = domain; - } - - Circle_2 get_domain() const { - return _domain; - } - - // Operations - Compare_xy_2 - compare_xy_2_object() const { - return Compare_xy_2(&_domain); - } - Orientation_2 - orientation_2_object() const { - return Orientation_2(&_domain); - } - - Construct_hyperbolic_point_2 - construct_hyperbolic_point_2_object() const { - return Construct_point_2(_domain); - } - Construct_segment_2 - construct_segment_2_object() const { - return Construct_segment_2(&_domain); - } - - -protected: - Circle_2 _domain; -}; - -namespace future_release -{ -template < typename K > -class Periodic_4_hyperbolic_triangulation_traits_2; -} - -} //namespace CGAL - - -#include - - -namespace CGAL -{ -template < typename K > -class Periodic_4_hyperbolic_Delaunay_triangulation_traits_2; - -} - -#endif // CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Qt/HyperbolicPainterOstream.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Qt/HyperbolicPainterOstream.h index 9b4e3231b0f..b379a3cb8ed 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Qt/HyperbolicPainterOstream.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Qt/HyperbolicPainterOstream.h @@ -22,19 +22,19 @@ #include -#include +#include namespace CGAL{ namespace Qt { template - class PainterOstream > : public PainterOstream { + class PainterOstream > : public PainterOstream { public: typedef PainterOstream Base; - typedef PainterOstream > Self; + typedef PainterOstream > Self; - typedef Triangulation_hyperbolic_traits_2 Gt; + typedef Periodic_4_hyperbolic_Delaunay_triangulation_traits_2 Gt; private: typedef typename Gt::Segment_2 Segment_2; diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Traits_with_hyperbolic_offsets_adaptor.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Traits_with_hyperbolic_offsets_adaptor.h index 92e560c13fd..4c2211144d0 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Traits_with_hyperbolic_offsets_adaptor.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Traits_with_hyperbolic_offsets_adaptor.h @@ -36,7 +36,7 @@ template < class K, class Functor_ > typedef K Kernel; typedef Functor_ Functor; - typedef typename Kernel::Point_3 Point; + typedef typename Kernel::Point_2 Point; typedef HyperbolicOctagonGroup Offset; public: @@ -86,7 +86,7 @@ public: protected: Point pp(const Point &p, const Offset &o) const { - return Construct_point_3(*_domain)(p,o); + return Construct_point_2(*_domain)(p,o); } public: const Circle_2* _domain;