mirror of https://github.com/CGAL/cgal
Modifications to Dehn's algorithm and reorganization of classes hierarchy (inheriting from Misha's classes)
This commit is contained in:
parent
1b9351f8fb
commit
2a3e9bac34
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -4,15 +4,17 @@
|
|||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_hyperbolic_triangulation_2.h>
|
||||
|
||||
#include <CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h>
|
||||
|
||||
// to be deleted
|
||||
#include <CGAL/Qt/HyperbolicPainterOstream.h>
|
||||
//
|
||||
|
||||
#include <CGAL/point_generators_2.h>
|
||||
// unique words
|
||||
#include <CGAL/Square_root_2_field.h>
|
||||
#include <CGAL/Hyperbolic_octagon_group.h>
|
||||
#include <CGAL/Hyperbolic_random_points_in_disc_2.h>
|
||||
// to be deleted (iiordano: why?)
|
||||
#include <CGAL/Qt/HyperbolicPainterOstream.h>
|
||||
// for viewportsBbox
|
||||
#include <CGAL/Qt/utility.h>
|
||||
|
||||
// Qt headers
|
||||
#include <QtGui>
|
||||
|
|
@ -22,50 +24,42 @@
|
|||
#include <QInputDialog>
|
||||
#include <QGraphicsEllipseItem>
|
||||
|
||||
// for filtering
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
// 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 <CGAL/Qt/TriangulationGraphicsItem.h>
|
||||
#include <CGAL/Qt/VoronoiGraphicsItem.h>
|
||||
|
||||
// store color
|
||||
#include <CGAL/TranslationInfo.h>
|
||||
// visualise color
|
||||
#include <CGAL/Qt/TriangulationGraphicsItemWithColorInfo.h>
|
||||
|
||||
// unique words
|
||||
//#include <temp.h>
|
||||
#include <CGAL/Square_root_2_field.h>
|
||||
#include <CGAL/Hyperbolic_octagon_group.h>
|
||||
|
||||
#include <CGAL/Hyperbolic_random_points_in_disc_2.h>
|
||||
|
||||
// dummy points
|
||||
//#include <CGAL/Periodic_2_hyperbolic_triangulation_dummy.h>
|
||||
|
||||
// for filtering
|
||||
#include <set>
|
||||
|
||||
// for viewportsBbox
|
||||
#include <CGAL/Qt/utility.h>
|
||||
|
||||
// the two base classes
|
||||
#include "ui_Delaunay_triangulation_2.h"
|
||||
#include <CGAL/Qt/TriangulationGraphicsItemWithColorInfo.h> // Visualise color
|
||||
#include <CGAL/TranslationInfo.h> // Store color
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
|
||||
#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 <CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_dummy.h>
|
||||
#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<R> K;
|
||||
|
||||
typedef CGAL::Triangulation_hyperbolic_traits_2<R> THT2;
|
||||
typedef CGAL::Periodic_4_hyperbolic_Delaunay_triangulation_traits_2<R>
|
||||
K;
|
||||
typedef K::Point_2 Point;
|
||||
// keep color
|
||||
typedef TranslationInfo<std::string> 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 <CGAL::Hyperbolic_face_info_2, K >
|
||||
Fb;
|
||||
typedef CGAL::Delaunay_hyperbolic_triangulation_2< K, CGAL::Triangulation_data_structure_2<Vb, Fb> >
|
||||
typedef CGAL::Periodic_4_hyperbolic_Delaunay_triangulation_2< K, CGAL::Triangulation_data_structure_2<Vb, Fb> >
|
||||
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<HyperbolicOctagonGroup>& v, vector<HyperbolicOctagonGroup> g, int depth = 1) {
|
||||
void recurr(vector<Octagon_group>& v, vector<Octagon_group> g, int depth = 1) {
|
||||
if (depth > 1) {
|
||||
|
||||
recurr(v, g, depth-1);
|
||||
|
||||
vector<HyperbolicOctagonGroup> tmp;
|
||||
vector<Octagon_group> tmp;
|
||||
vector<string> tmpw;
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
tmp.push_back(v[i]);
|
||||
|
|
@ -127,24 +118,24 @@ void recurr(vector<HyperbolicOctagonGroup>& v, vector<HyperbolicOctagonGroup> g,
|
|||
}
|
||||
|
||||
|
||||
void my_unique_words(std::vector<Point>& p, Point input, int length) {
|
||||
std::vector<HyperbolicOctagonGroup> g;
|
||||
void my_unique_words(std::vector<Point>& p, Point input, int depth) {
|
||||
std::vector<Octagon_group> g;
|
||||
get_generators(g);
|
||||
std::vector<HyperbolicOctagonGroup> v;
|
||||
recurr(v, g, length);
|
||||
std::set<HyperbolicOctagonGroup> s;
|
||||
std::vector<Octagon_group> v;
|
||||
recurr(v, g, depth);
|
||||
std::set<Octagon_group> 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<HyperbolicOctagonGroup>::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<Octagon_group>::iterator it = s.begin(); it != s.end(); it++) {
|
||||
Octagon_group m = *it;
|
||||
pair<double, double> 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<Point>& points, Point input = Point(0, 0), d
|
|||
|
||||
cout << "apply_unique_words called with threshold = " << threshold << ", word_length = " << word_length << ", d = " << d << endl;
|
||||
|
||||
static vector<HyperbolicOctagonGroup> unique_words;
|
||||
static vector<Octagon_group> 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<Point>& points, Point input = Point(0, 0), d
|
|||
|
||||
void apply_unique_words_G(std::vector<Point>& points, Point input = Point(0, 0), double threshold = 6/*13.5*/, int word_length = 6/*20*/)
|
||||
{
|
||||
static vector<HyperbolicOctagonGroup> unique_words;
|
||||
static vector<Octagon_group> 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<Point>& 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<int> 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<Point> 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<K> convert;
|
||||
//Circle_2 isor = convert(rect);
|
||||
//CGAL::Random_points_in_disc_2<Point> 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<Point> 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<GT>(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
|
||||
|
|
|
|||
|
|
@ -1,767 +0,0 @@
|
|||
#include <fstream>
|
||||
|
||||
// CGAL headers
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_hyperbolic_triangulation_2.h>
|
||||
|
||||
#include <CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h>
|
||||
|
||||
// to be deleted
|
||||
#include <CGAL/Qt/HyperbolicPainterOstream.h>
|
||||
//
|
||||
|
||||
#include <CGAL/point_generators_2.h>
|
||||
|
||||
// Qt headers
|
||||
#include <QtGui>
|
||||
#include <QString>
|
||||
#include <QActionGroup>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QGraphicsEllipseItem>
|
||||
|
||||
#include <string>
|
||||
|
||||
// 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 <CGAL/Qt/TriangulationGraphicsItem.h>
|
||||
#include <CGAL/Qt/VoronoiGraphicsItem.h>
|
||||
|
||||
// store color
|
||||
#include <CGAL/TranslationInfo.h>
|
||||
// visualise color
|
||||
#include <CGAL/Qt/TriangulationGraphicsItemWithColorInfo.h>
|
||||
|
||||
// unique words
|
||||
//#include <temp.h>
|
||||
#include <CGAL/Square_root_2_field.h>
|
||||
#include <CGAL/Hyperbolic_octagon_group.h>
|
||||
|
||||
#include <CGAL/Hyperbolic_random_points_in_disc_2.h>
|
||||
|
||||
// dummy points
|
||||
//#include <CGAL/Periodic_2_hyperbolic_triangulation_dummy.h>
|
||||
|
||||
// for filtering
|
||||
#include <set>
|
||||
|
||||
// for viewportsBbox
|
||||
#include <CGAL/Qt/utility.h>
|
||||
|
||||
// the two base classes
|
||||
#include "ui_Delaunay_triangulation_2.h"
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
|
||||
#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<R> K;
|
||||
typedef K::Point_2 Point;
|
||||
// keep color
|
||||
typedef TranslationInfo<std::string> Vb_info;
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_2< Vb_info, K >
|
||||
Vb;
|
||||
typedef CGAL::Triangulation_face_base_with_info_2 <CGAL::Hyperbolic_face_info_2, K >
|
||||
Fb;
|
||||
typedef CGAL::Delaunay_hyperbolic_triangulation_2< K, CGAL::Triangulation_data_structure_2<Vb, Fb> >
|
||||
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<HyperbolicOctagonGroup>& v, vector<HyperbolicOctagonGroup> g, int depth = 1) {
|
||||
if (depth > 1) {
|
||||
|
||||
recurr(v, g, depth-1);
|
||||
|
||||
vector<HyperbolicOctagonGroup> tmp;
|
||||
vector<string> 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<Point>& p, Point input, int length) {
|
||||
std::vector<HyperbolicOctagonGroup> g;
|
||||
get_generators(g);
|
||||
std::vector<HyperbolicOctagonGroup> v;
|
||||
recurr(v, g, length);
|
||||
std::set<HyperbolicOctagonGroup> 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<HyperbolicOctagonGroup>::iterator it = s.begin(); it != s.end(); it++) {
|
||||
HyperbolicOctagonGroup m = *it;
|
||||
pair<double, double> 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<Point>& 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<HyperbolicOctagonGroup> 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<double, double> res;
|
||||
for(size_t i = 0; i < unique_words.size(); i++) {
|
||||
pair<double, double> 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<Point>& points, Point input = Point(0, 0), double threshold = 6/*13.5*/, int word_length = 6/*20*/)
|
||||
{
|
||||
static vector<HyperbolicOctagonGroup> 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 << "," <<endl;
|
||||
}
|
||||
fwords << unique_words[unique_words.size() - 1].label << endl;
|
||||
fwords << "];\nreturn words;";
|
||||
fwords.close();
|
||||
*/
|
||||
//
|
||||
}
|
||||
|
||||
ifstream findices("indicesG8_1");
|
||||
long index;
|
||||
vector<long> indices;
|
||||
while(findices >> index) {
|
||||
indices.push_back(index);
|
||||
}
|
||||
cout << "indices size " << indices.size() << endl;
|
||||
|
||||
pair<double, double> res;
|
||||
for(size_t i = 0; i < indices.size(); i++) {
|
||||
pair<double, double> 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<int> ccol;
|
||||
|
||||
Delaunay dt;
|
||||
QGraphicsEllipseItem * disk;
|
||||
QGraphicsScene scene;
|
||||
|
||||
CGAL::Qt::TriangulationGraphicsItem<Delaunay> * dgi;
|
||||
CGAL::Qt::VoronoiGraphicsItem<Delaunay> * vgi;
|
||||
|
||||
// for drawing Voronoi diagram of the orbit of the origin
|
||||
CGAL::Qt::VoronoiGraphicsItem<Delaunay> * origin_vgi;
|
||||
|
||||
CGAL::Qt::TriangulationMovingPoint<Delaunay> * mp;
|
||||
CGAL::Qt::TriangulationConflictZone<Delaunay> * cz;
|
||||
CGAL::Qt::TriangulationRemoveVertex<Delaunay> * trv;
|
||||
CGAL::Qt::TriangulationPointInputAndConflictZone<Delaunay> * pi;
|
||||
CGAL::Qt::TriangulationCircumcircle<Delaunay> * 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<Point> 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<Delaunay>(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<Delaunay>(&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<Delaunay>(&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<Delaunay>(&scene, &dt, this );
|
||||
|
||||
QObject::connect(pi, SIGNAL(generate(CGAL::Object)),
|
||||
this, SLOT(processInput(CGAL::Object)));
|
||||
|
||||
mp = new CGAL::Qt::TriangulationMovingPoint<Delaunay>(&dt, this);
|
||||
// TriangulationMovingPoint<Delaunay> 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<Delaunay>(&dt, this);
|
||||
QObject::connect(trv, SIGNAL(modelChanged()),
|
||||
this, SIGNAL(changed()));
|
||||
|
||||
tcc = new CGAL::Qt::TriangulationCircumcircle<Delaunay>(&scene, &dt, this);
|
||||
tcc->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
|
||||
cz = new CGAL::Qt::TriangulationConflictZone<Delaunay>(&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<Point> 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<Point> 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<Point> 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_<action_name>_<signal_name>"
|
||||
*/
|
||||
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<K> convert;
|
||||
//Circle_2 isor = convert(rect);
|
||||
//CGAL::Random_points_in_disc_2<Point> 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<int>::max(),
|
||||
1,
|
||||
&ok);
|
||||
|
||||
if(!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
//std::vector<Point> 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<Point_2> pts;
|
||||
Hyperbolic_random_points_in_disc_2<GT>(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<K::Point> 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();
|
||||
}
|
||||
|
|
@ -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 <CGAL/Triangulation_face_base_with_info_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_2.h>
|
||||
|
||||
#include <stack>
|
||||
#include <set>
|
||||
|
||||
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<Gt>,
|
||||
Triangulation_face_base_with_info_2<Hyperbolic_face_info_2, Gt> > >
|
||||
class Delaunay_hyperbolic_triangulation_2 : public Delaunay_triangulation_2<Gt,Tds>
|
||||
{
|
||||
public:
|
||||
typedef Delaunay_hyperbolic_triangulation_2<Gt, Tds> Self;
|
||||
typedef Delaunay_triangulation_2<Gt,Tds> Base;
|
||||
|
||||
typedef Triangulation_face_base_with_info_2<Hyperbolic_face_info_2, Gt> 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,Tds>(gt) {}
|
||||
|
||||
Delaunay_hyperbolic_triangulation_2(
|
||||
const Delaunay_hyperbolic_triangulation_2<Gt,Tds> &tr)
|
||||
: Delaunay_triangulation_2<Gt,Tds>(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<InputIterator>::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<InputIterator>::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<Face_handle> visited_faces;
|
||||
|
||||
// maintain a stack to be able to backtrack
|
||||
// to the most recent faces which neighbors are not visited
|
||||
std::stack<Face_handle> 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<class Mark_face_test>
|
||||
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<All_faces_iterator, Infinite_hyperbolic_tester>
|
||||
{
|
||||
typedef Filter_iterator<All_faces_iterator, Infinite_hyperbolic_tester> 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<All_edges_iterator,
|
||||
Infinite_hyperbolic_tester>
|
||||
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<typename Gt::Point_2>& );
|
||||
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#include <CGAL/Periodic_4_hyperbolic_triangulation_dummy.h>
|
||||
|
||||
#endif // CGAL_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H
|
||||
|
|
@ -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 <CGAL/Triangulation_face_base_with_info_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_2.h>
|
||||
|
||||
#include <stack>
|
||||
#include <set>
|
||||
|
||||
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
|
||||
|
|
@ -154,8 +154,9 @@ public:
|
|||
};
|
||||
|
||||
|
||||
|
||||
template<class Square_root_2_field>
|
||||
Square_root_2_field Hyperbolic_octagon_group<Square_root_2_field>::factor = Square_root_2_field(-1, 1);
|
||||
Square_root_2_field Hyperbolic_octagon_group<Square_root_2_field>::factor = Square_root_2_field(-1, 1); /*Square_root_2_field(-1, 1);*/
|
||||
|
||||
// just to give an order(ing)
|
||||
template<class Int>
|
||||
|
|
@ -207,57 +208,349 @@ ostream& operator<<(ostream& os, const Hyperbolic_octagon_group<Square_root_2_fi
|
|||
return os;
|
||||
}
|
||||
|
||||
typedef long long ll;
|
||||
typedef Square_root_2_field<ll> SqrtField;
|
||||
typedef Hyperbolic_octagon_group<SqrtField> HyperbolicOctagonGroup;
|
||||
typedef HyperbolicOctagonGroup::Matrix_element Element;
|
||||
typedef long long ll;
|
||||
typedef Square_root_2_field<ll> Sqrt_field;
|
||||
typedef Hyperbolic_octagon_group<Sqrt_field> Octagon_group;
|
||||
typedef pair<Octagon_group, int> 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<HyperbolicOctagonGroup>& gens)
|
||||
|
||||
|
||||
void get_generators(vector<Octagon_group>& 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<Element> B(8, Element(SqrtField(0, 0), SqrtField(0, 0)));
|
||||
vector<Element> 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<Octagon_group_with_index>& w) {
|
||||
vector<Octagon_group_with_index> 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<Octagon_group_with_index>& seq, vector<Octagon_group_with_index> const w) {
|
||||
int start = 0;
|
||||
int mstart = 0;
|
||||
int end = 1;
|
||||
int max = 1;
|
||||
int len = 1;
|
||||
vector<Octagon_group_with_index> 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<Octagon_group_with_index>& w, vector<Octagon_group_with_index> 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<int>& v, int begin, int end) {
|
||||
vector<int> 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<Octagon_group_with_index>& c, int start, int end) {
|
||||
vector<int> idx;
|
||||
vector<Octagon_group> 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<Octagon_group_with_index>& c, vector<Octagon_group_with_index> 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<Octagon_group_with_index>& w, vector<Octagon_group_with_index> original) {
|
||||
|
||||
bool replaced = false;
|
||||
|
||||
// Handle empty string case
|
||||
if (original.size() == 0) {
|
||||
return replaced; // false
|
||||
}
|
||||
|
||||
// Look for longest subword forward
|
||||
vector<Octagon_group_with_index> lfwd;
|
||||
int idxf = Longest_sequence(lfwd, original);
|
||||
int Nf = lfwd.size();
|
||||
|
||||
// Get inverse of the original word
|
||||
vector<Octagon_group_with_index> inv;
|
||||
Invert(inv, original);
|
||||
|
||||
// Look for longest subword backwards
|
||||
vector<Octagon_group_with_index> lbwd;
|
||||
int idxb = Longest_sequence(lbwd, inv);
|
||||
int Nb = lbwd.size();
|
||||
|
||||
// Assign parameters based on results to homogenise the logic
|
||||
vector<Octagon_group_with_index> 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<Octagon_group_with_index> 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<Octagon_group_with_index> cmpl;
|
||||
Get_complement_word(cmpl, sub);
|
||||
|
||||
vector<Octagon_group_with_index> 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<Octagon_group_with_index> 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<Octagon_group_with_index>& w, vector<Octagon_group_with_index> const original) {
|
||||
bool is_identity = false;
|
||||
vector<Octagon_group_with_index> tmp;
|
||||
tmp = original;
|
||||
|
||||
while (tmp.size() > 0) {
|
||||
Simplify_word(tmp);
|
||||
vector<Octagon_group_with_index> 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<HyperbolicOctagonGroup> gens;
|
||||
vector<Octagon_group> gens;
|
||||
|
||||
bool IsCanonical(const HyperbolicOctagonGroup& m);
|
||||
bool IsCanonical(const Octagon_group& m);
|
||||
|
||||
void generate_words( set<HyperbolicOctagonGroup>& words, vector<HyperbolicOctagonGroup>& prev, int depth, double threshold )
|
||||
void generate_words( set<Octagon_group>& words, vector<Octagon_group>& prev, int depth, double threshold )
|
||||
{
|
||||
if (depth == 1) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
|
|
@ -267,10 +560,10 @@ void generate_words( set<HyperbolicOctagonGroup>& words, vector<HyperbolicOctago
|
|||
return;
|
||||
}
|
||||
|
||||
vector<HyperbolicOctagonGroup> els;
|
||||
vector<Octagon_group> 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<HyperbolicOctagonGroup>& words, vector<HyperbolicOctago
|
|||
}
|
||||
|
||||
// does the axis of a given matrix go through the fundamental octagon
|
||||
bool IsCanonical(const HyperbolicOctagonGroup& m)
|
||||
bool IsCanonical(const Octagon_group& m)
|
||||
{
|
||||
HyperbolicOctagonGroup temp = m;
|
||||
Octagon_group temp = m;
|
||||
|
||||
// rotate while |B1| < |B2|
|
||||
SqrtField B1, B2;
|
||||
SqrtField C = SqrtField(-1, -1);
|
||||
Sqrt_field B1, B2;
|
||||
Sqrt_field C = Sqrt_field(-1, -1);
|
||||
for(int i = 0; i < 8 && C != C.abs(); i++) {
|
||||
B1 = real(temp.B).abs();
|
||||
B2 = imag(temp.B).abs();
|
||||
|
|
@ -307,22 +600,22 @@ bool IsCanonical(const HyperbolicOctagonGroup& m)
|
|||
assert(C == C.abs());
|
||||
|
||||
// (2 - sqrt(2))(|B1| + (sqrt(2) - 1)|B2|)
|
||||
SqrtField right = SqrtField(2, -1)*(B1 + SqrtField(-1, 1)*B2);
|
||||
Sqrt_field right = Sqrt_field(2, -1)*(B1 + Sqrt_field(-1, 1)*B2);
|
||||
|
||||
// |A2|
|
||||
SqrtField left = imag(temp.A).abs();
|
||||
Sqrt_field left = imag(temp.A).abs();
|
||||
|
||||
// left <= right -> true
|
||||
C = right - left;
|
||||
return C == C.abs();
|
||||
}
|
||||
|
||||
void dfs(const HyperbolicOctagonGroup& m, set<HyperbolicOctagonGroup>& visited)
|
||||
void dfs(const Octagon_group& m, set<Octagon_group>& 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<HyperbolicOctagonGroup>& visited)
|
|||
}
|
||||
}
|
||||
|
||||
// map<HyperbolicOctagonGroup m, HyperbolicOctagonGroup Aux>, m = Aux * origin * Aux^{-1}
|
||||
void dfs_with_info(const pair<HyperbolicOctagonGroup, HyperbolicOctagonGroup>& new_pair,
|
||||
map <HyperbolicOctagonGroup, HyperbolicOctagonGroup>& visited)
|
||||
// map<Octagon_group m, Octagon_group Aux>, m = Aux * origin * Aux^{-1}
|
||||
void dfs_with_info(const pair<Octagon_group, Octagon_group>& new_pair,
|
||||
map <Octagon_group, Octagon_group>& 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<HyperbolicOctagonGroup, HyperbolicOctagonGroup>(candidate, candidate_factor), visited);
|
||||
dfs_with_info(pair<Octagon_group, Octagon_group>(candidate, candidate_factor), visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dfs_with_info(const HyperbolicOctagonGroup& origin,
|
||||
map<HyperbolicOctagonGroup, HyperbolicOctagonGroup>& visited)
|
||||
void dfs_with_info(const Octagon_group& origin,
|
||||
map<Octagon_group, Octagon_group>& visited)
|
||||
{
|
||||
assert(IsCanonical(origin));
|
||||
HyperbolicOctagonGroup id = HyperbolicOctagonGroup(Element(SqrtField(1, 0), SqrtField(0, 0)),
|
||||
Element(SqrtField(0, 0), SqrtField(0, 0)));
|
||||
pair<HyperbolicOctagonGroup, HyperbolicOctagonGroup> 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<Octagon_group, Octagon_group> 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<HyperbolicOctagonGroup> visited;
|
||||
set<HyperbolicOctagonGroup>::iterator it, it2;
|
||||
set<Octagon_group> visited;
|
||||
set<Octagon_group>::iterator it, it2;
|
||||
map<long, long> nb_map;
|
||||
map<long, long>::iterator mit;
|
||||
|
||||
dfs(m, visited);
|
||||
|
||||
set<pair< HyperbolicOctagonGroup, HyperbolicOctagonGroup> > common;
|
||||
set<pair< Octagon_group, Octagon_group> > 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<pair< HyperbolicOctagonGroup, HyperbolicOctagonGroup> >& visited) const
|
||||
void count_nb(const Octagon_group& m1, const Octagon_group& m2, set<pair< Octagon_group, Octagon_group> >& visited) const
|
||||
{
|
||||
typedef pair<HyperbolicOctagonGroup, HyperbolicOctagonGroup> matrix_pair;
|
||||
typedef pair<Octagon_group, Octagon_group> 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<HyperbolicOctagonGroup>& canonical_set, vector<HyperbolicOctagonGroup>& output)
|
||||
void Delete(const set<Octagon_group>& canonical_set, vector<Octagon_group>& output)
|
||||
{
|
||||
set<HyperbolicOctagonGroup> redundant;
|
||||
set<Octagon_group> redundant;
|
||||
|
||||
set<HyperbolicOctagonGroup>::iterator it;
|
||||
set<Octagon_group>::iterator it;
|
||||
for(it = canonical_set.begin(); it != canonical_set.end(); ++it) {
|
||||
if(redundant.find(*it) != redundant.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
set<HyperbolicOctagonGroup> visited;
|
||||
set<Octagon_group> visited;
|
||||
dfs(*it, visited);
|
||||
visited.erase(*it);
|
||||
|
||||
|
|
@ -500,16 +793,16 @@ void Delete(const set<HyperbolicOctagonGroup>& canonical_set, vector<HyperbolicO
|
|||
}
|
||||
}
|
||||
|
||||
void generate_unique_words(vector<HyperbolicOctagonGroup>& output, double threshold = 10, int word_length = 13)
|
||||
void generate_unique_words(vector<Octagon_group>& output, double threshold = 10, int word_length = 13)
|
||||
{
|
||||
get_generators(gens);
|
||||
|
||||
set<HyperbolicOctagonGroup> unique_words;
|
||||
vector<HyperbolicOctagonGroup> temp;
|
||||
set<Octagon_group> unique_words;
|
||||
vector<Octagon_group> temp;
|
||||
generate_words(unique_words, temp, word_length, threshold);
|
||||
|
||||
double l = 0;
|
||||
set<HyperbolicOctagonGroup>::iterator uit;
|
||||
set<Octagon_group>::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<HyperbolicOctagonGroup>& output, double thresh
|
|||
}
|
||||
|
||||
// words that correspond to union of 1-cycles
|
||||
void generate_words_union_1_cycles(vector<HyperbolicOctagonGroup>& out)
|
||||
void generate_words_union_1_cycles(vector<Octagon_group>& 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<HyperbolicOctagonGroup>& 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);
|
||||
|
|
|
|||
|
|
@ -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 <vector>
|
||||
|
||||
// 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 <CGAL/Periodic_4_hyperbolic_triangulation_2.h>
|
||||
#else
|
||||
#include <CGAL/Delaunay_triangulation_2.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if CLEARLY_MY_TYPE == 1
|
||||
#include <CGAL/Cross_translations.h>
|
||||
#else
|
||||
#include <CGAL/Diametric_translations.h>
|
||||
#endif
|
||||
*/
|
||||
//#include <CGAL/Periodic_2_hyperbolic_triangulation_dummy.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < class Gt,
|
||||
class Tds = Triangulation_data_structure_2 <
|
||||
Triangulation_vertex_base_2<Gt> > >
|
||||
#if USE_TEST_THINGS == 1
|
||||
class Periodic_4_Delaunay_hyperbolic_triangulation_2 : public Periodic_4_hyperbolic_triangulation_2<Gt,Tds>
|
||||
#else
|
||||
class Periodic_4_Delaunay_hyperbolic_triangulation_2 : public Delaunay_triangulation_2<Gt,Tds>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
typedef Periodic_4_Delaunay_hyperbolic_triangulation_2<Gt, Tds> Self;
|
||||
#if USE_TEST_THINGS == 1
|
||||
typedef Periodic_4_hyperbolic_triangulation_2<Gt,Tds> Base;
|
||||
#else
|
||||
typedef Delaunay_triangulation_2<Gt,Tds> 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<typename GT::Point_2>& );
|
||||
|
||||
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,Tds>(gt)
|
||||
#else
|
||||
: Delaunay_triangulation_2<Gt,Tds>(gt)
|
||||
#endif
|
||||
{
|
||||
recursion_depth = 0;
|
||||
}
|
||||
|
||||
Periodic_4_Delaunay_hyperbolic_triangulation_2(const Periodic_4_Delaunay_hyperbolic_triangulation_2<Gt,Tds> &tr)
|
||||
#if USE_TEST_THINGS == 1
|
||||
: Periodic_4_hyperbolic_triangulation_2<Gt,Tds>(tr)
|
||||
#else
|
||||
: Delaunay_triangulation_2<Gt,Tds>(tr)
|
||||
#endif
|
||||
{ CGAL_triangulation_postcondition( this->is_valid() ); }
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/************************ INSERT OVERLOADS **************************/
|
||||
|
||||
/*
|
||||
|
||||
Vertex_handle insert(const Point_2 &p,
|
||||
Face_handle start = Face_handle() )
|
||||
{
|
||||
|
||||
std::vector<Point_2> 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<Gt> g,
|
||||
#else
|
||||
Diametric_translations<Gt> g,
|
||||
#endif
|
||||
std::vector<Point_2>& 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<Vertex_handle>& on_vertex, const std::vector<Vertex_handle>& 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<Gt> g;
|
||||
#else
|
||||
Diametric_translations<Gt> g;
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
//#include <Periodic_2_hyperbolic_triangulation_dummy.h>
|
||||
|
||||
#endif // CGAL_PERIODIC_4_DELAUNAY_HYPERBOLIC_TRIANGULATION_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<double, double> pt = o.apply(to_double(p.x()), to_double(p.y()));
|
||||
Point r = Point(pt.first, pt.second);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <Nico.Kruithof@sophia.inria.fr>
|
||||
// Manuel Caroli <Manuel.Caroli@sophia.inria.fr>
|
||||
//
|
||||
// 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 <CGAL/basic.h>
|
||||
#include <CGAL/Traits_with_hyperbolic_offsets_adaptor.h>
|
||||
#include <CGAL/Periodic_4_construct_hyperbolic_point_2.h>
|
||||
#include <CGAL/Periodic_4_hyperbolic_triangulation_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_octagon_group.h>
|
||||
#include <CGAL/Point_2.h>
|
||||
#include <CGAL/Segment_2.h>
|
||||
#include <CGAL/Triangle_2.h>
|
||||
#include <CGAL/Line_2.h>
|
||||
#include <CGAL/Ray_2.h>
|
||||
#include <CGAL/predicates_on_points_2.h>
|
||||
#include <CGAL/basic_constructions_2.h>
|
||||
#include <CGAL/distance_predicates_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
#include <CGAL/Regular_triangulation_filtered_traits_2.h>
|
||||
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
|
||||
#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<THT2>
|
||||
{
|
||||
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<R>
|
||||
Self;
|
||||
|
||||
typedef typename Base::Segment_2 Segment_2;
|
||||
typedef typename Base::Triangle_2 Triangle_2;
|
||||
typedef Triangulation_hyperbolic_traits_2<R> Base;
|
||||
|
||||
// Delaunay specific predicates
|
||||
typedef Traits_with_offsets_adaptor<Self,
|
||||
typename K::Side_of_oriented_circle_2>
|
||||
Side_of_oriented_circle_2;
|
||||
typedef Traits_with_offsets_adaptor<Self, typename K::Compare_distance_2>
|
||||
Compare_distance_2;
|
||||
typedef Traits_with_offsets_adaptor<Self,
|
||||
typename K::Side_of_bounded_disc_2>
|
||||
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<Self,
|
||||
typename K::Construct_circumcenter_2>
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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 <CGAL/Regular_triangulation_filtered_traits_2.h>
|
||||
#include <CGAL/Aff_transformation_2.h>
|
||||
|
||||
// Added by Iordanov
|
||||
/*
|
||||
#if CLEARLY_MY_TYPE == 1
|
||||
#include <CGAL/Cross_translations.h>
|
||||
#else
|
||||
#include <CGAL/Diametric_translations.h>
|
||||
#endif
|
||||
*/
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
// this class might to be moved to hyperbolic traits
|
||||
template<class GT>
|
||||
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<GT> 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<class GT>
|
||||
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<GT> rotate(CGAL::ROTATION, std::sqrt(0.5), std::sqrt(0.5));
|
||||
|
||||
return rotate(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class GT>
|
||||
void compute_dummy_points( std::vector<typename GT::Point_2>& inner_points,
|
||||
std::vector<typename GT::Point_2>& points_on_boundary,
|
||||
std::vector<typename GT::Point_2>& 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<K>()(a, b, o);
|
||||
Point_2 d = Construct_reflection<K>()(a, c, b);
|
||||
//inner_points.push_back(d);
|
||||
Point_2 e = Construct_reflection<K>()(d, c, a);
|
||||
Point_2 f = Construct_reflection<K>()(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<K>(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<K>(points_on_boundary[i-1]));
|
||||
}
|
||||
|
||||
points_on_vertex.push_back(apply_rotation<K>(f));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
template<class GT>
|
||||
void recursive_translate(Diametric_translations<GT> g,
|
||||
std::vector<typename GT::Point_2>& 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<class GT>
|
||||
void recursive_translate(Diametric_translations<GT> g,
|
||||
std::vector<typename GT::Point_2>& 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<GT, TDS>::insert_dummy_points(std::vector<typename GT::Point_2>& all_points) {
|
||||
//clear();
|
||||
|
||||
std::vector<typename GT::Point_2> inner_points, points_on_boundary, points_on_vertex;
|
||||
|
||||
compute_dummy_points<GT>(inner_points, points_on_boundary, points_on_vertex);
|
||||
|
||||
/*std::vector<typename GT::Point_2>*/ 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<GT> g;
|
||||
std::vector<Point_2> 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
|
||||
|
||||
|
|
@ -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 <Nico.Kruithof@sophia.inria.fr>
|
||||
// Manuel Caroli <Manuel.Caroli@sophia.inria.fr>
|
||||
|
||||
#ifndef CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H
|
||||
#define CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H
|
||||
|
||||
|
||||
#include <CGAL/Traits_with_hyperbolic_offsets_adaptor.h>
|
||||
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
|
||||
#include <CGAL/Square_root_2_field.h>
|
||||
#include <CGAL/Hyperbolic_octagon_group.h>
|
||||
#include <CGAL/Periodic_4_construct_hyperbolic_point_2.h>
|
||||
|
||||
|
||||
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<Self, typename K::Compare_xy_2>
|
||||
Compare_xy_2;
|
||||
typedef Traits_with_hyperbolic_offsets_adaptor<Self, typename K::Orientation_2>
|
||||
Orientation_2;
|
||||
|
||||
// Triangulation constructions
|
||||
typedef Periodic_4_construct_hyperbolic_point_2<Self, typename K::Construct_point_2>
|
||||
Construct_hyperbolic_point_2;
|
||||
typedef Traits_with_hyperbolic_offsets_adaptor<Self, typename K::Construct_segment_2>
|
||||
Construct_segment_2;
|
||||
typedef Traits_with_hyperbolic_offsets_adaptor<Self, typename K::Construct_triangle_2>
|
||||
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 <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
|
||||
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
template < typename K >
|
||||
class Periodic_4_hyperbolic_Delaunay_triangulation_traits_2;
|
||||
|
||||
}
|
||||
|
||||
#endif // CGAL_PERIODIC_4_HYPERBOLIC_TRIANGULATION_TRAITS_2_H
|
||||
|
|
@ -22,19 +22,19 @@
|
|||
|
||||
#include <CGAL/Qt/PainterOstream.h>
|
||||
|
||||
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
|
||||
#include <CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h>
|
||||
|
||||
namespace CGAL{
|
||||
|
||||
namespace Qt {
|
||||
|
||||
template <typename K>
|
||||
class PainterOstream<Triangulation_hyperbolic_traits_2<K> > : public PainterOstream<K> {
|
||||
class PainterOstream<Periodic_4_hyperbolic_Delaunay_triangulation_traits_2<K> > : public PainterOstream<K> {
|
||||
public:
|
||||
typedef PainterOstream<K> Base;
|
||||
typedef PainterOstream<Triangulation_hyperbolic_traits_2<K> > Self;
|
||||
typedef PainterOstream<Periodic_4_hyperbolic_Delaunay_triangulation_traits_2<K> > Self;
|
||||
|
||||
typedef Triangulation_hyperbolic_traits_2<K> Gt;
|
||||
typedef Periodic_4_hyperbolic_Delaunay_triangulation_traits_2<K> Gt;
|
||||
|
||||
private:
|
||||
typedef typename Gt::Segment_2 Segment_2;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue