move our experimental package with its history to its new branch

This commit is contained in:
Mikhail Bogdanov 2012-07-02 16:35:03 +00:00 committed by Aymeric PELLE
parent 03939133ac
commit 35a23aa8e2
43 changed files with 9428 additions and 101 deletions

4671
.gitattributes vendored

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
========== code
--- sqrt
check whether and when an exact type is needed for sqrt.
- sqrt can be kept eg for demos
- when needed, replace the inexact CGAL::sqrt by the new type
replacing CGAL::Root_of_2, see
CGAL::https://cgal.geometryfactory.com/CGAL/Members/wiki/Features/Unique_sqrt_extension
Done. std::sqrt is replaced by CGAL::sqrt everywhere,
because it's used only for computation of the Voronoi diagram.
--- use the Circular_kernel?
because Do_intersect is in the Circular_kernel
Done. CGAL::do_intersect is a solution.
No need for the Circular_kernel.
--- iterators
- Finite_faces_iterator should return only faces marked HYPERBOLIC
- for edges, rename adjacent_face to incident_face
Done.
--- interface
provide a complete interface, like for the Euclidean package (adapted
to the hyperbolic case of course)
In progress.
--- make Constrained_delaunay_... work with Hyperbolic_triangulation_2
--- make Mesh_2 work with Hyperbolic_triangulation_2
O.Faugeras and his student are waiting for it.
========== documentation
to be written, so that the package can be submitted to the EB
========== test-suite
to be written
========== demo
--- fix bugs:
- conflict regions (when inserting or in mode 'show conflict zone)
show Euclidean triangles instead of hyperbolic triangles
- in mode 'draw circumcenter', some triangles that are not in the
hyperbolic DT appear, with their circle intersecting the infinite
line. They should not appear.
Done
- However, we could think to add a specific mode allowing to show
triangles that are not hyperbolic. Not sure whether this is interesting.
- cosmetic detail: the title of the demo should mention "hyperbolic"
--- PainterOstream
Is it clean for CGAL to have a local file?
I have to ask Laurent to make some members of PainterOstream protected.
It allows me to have a local file with partial specialization of
the class PainterOstream.
I have to discuss with Laurent.

View File

@ -0,0 +1,81 @@
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.
project (Hyperbolic_Triangulation_2_demo)
cmake_minimum_required(VERSION 2.4.5)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
if ( COMMAND cmake_policy )
cmake_policy( SET CMP0003 NEW )
endif()
find_package(CGAL COMPONENTS Qt4)
include(${CGAL_USE_FILE})
set( QT_USE_QTXML TRUE )
set( QT_USE_QTMAIN TRUE )
set( QT_USE_QTSCRIPT TRUE )
set( QT_USE_QTOPENGL TRUE )
find_package(Qt4)
include_directories (BEFORE ${CGAL_DIR}/demo/Triangulation_2)
include_directories (BEFORE ../../include)
# demos contain their own headers
include_directories (BEFORE include)
if ( CGAL_FOUND AND CGAL_Qt4_FOUND AND QT4_FOUND )
include(${QT_USE_FILE})
#--------------------------------
# The "Delaunay" demo: Delaunay_triangulation_2
#--------------------------------
# UI files (Qt Designer files)
qt4_wrap_ui( DT_UI_FILES ${CGAL_DIR}/demo/Triangulation_2/Delaunay_triangulation_2.ui )
# qrc files (resources files, that contain icons, at least)
qt4_add_resources ( DT_RESOURCE_FILES ${CGAL_DIR}/demo/Triangulation_2/Delaunay_triangulation_2.qrc )
# use the Qt MOC preprocessor on classes that derives from QObject
qt4_generate_moc( "Hyperbolic_Delaunay_triangulation_2_demo.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Hyperbolic_Delaunay_triangulation_2_demo.moc" )
# The executable itself.
add_executable ( Hyperbolic_Delaunay_triangulation_2_demo Hyperbolic_Delaunay_triangulation_2_demo.cpp Hyperbolic_Delaunay_triangulation_2_demo.moc ${DT_UI_FILES} ${DT_RESOURCE_FILES} )
add_to_cached_list( CGAL_EXECUTABLE_TARGETS Hyperbolic_Delaunay_triangulation_2_demo )
# Link with Qt libraries
target_link_libraries( Hyperbolic_Delaunay_triangulation_2_demo ${QT_LIBRARIES} )
# Link with CGAL
target_link_libraries( Hyperbolic_Delaunay_triangulation_2_demo ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES})
#--------------------------------
# The "hyperbolic" demo: Hyperbolic_translations_2
#--------------------------------
# UI files (Qt Designer files)
qt4_wrap_ui( DT_UI_FILES ui/Hyperbolic_translations_2.ui )
# qrc files (resources files, that contain icons, at least)
qt4_add_resources ( DT_RESOURCE_FILES resources/Hyperbolic_translations_2.qrc )
# use the Qt MOC preprocessor on classes that derives from QObject
qt4_generate_moc( "Hyperbolic_translations_2_demo.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Hyperbolic_translations_2_demo.moc" )
# The executable itself.
add_executable ( Hyperbolic_translations_2_demo Hyperbolic_translations_2_demo.cpp Hyperbolic_translations_2_demo.moc ${DT_UI_FILES} ${DT_RESOURCE_FILES} )
add_to_cached_list( CGAL_EXECUTABLE_TARGETS Hyperbolic_translations_2_demo )
# Link with Qt libraries
target_link_libraries( Hyperbolic_translations_2_demo ${QT_LIBRARIES} )
# Link with CGAL
target_link_libraries( Hyperbolic_translations_2_demo ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES})
else()
message(STATUS "NOTICE: This demo requires CGAL and Qt4, and will not be compiled.")
endif()

View File

@ -0,0 +1,424 @@
#include <fstream>
// CGAL headers
#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/Triangulation_hyperbolic_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>
// GraphicsView items and event filters (input classes)
#include "TriangulationCircumcircle.h"
#include "TriangulationMovingPoint.h"
#include "TriangulationConflictZone.h"
#include "TriangulationRemoveVertex.h"
#include "TriangulationPointInputAndConflictZone.h"
#include <CGAL/Qt/TriangulationGraphicsItem.h>
#include <CGAL/Qt/VoronoiGraphicsItem.h>
// for viewportsBbox
#include <CGAL/Qt/utility.h>
// the two base classes
#include "ui_Delaunay_triangulation_2.h"
#include <CGAL/Qt/DemosMainWindow.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel R;
typedef CGAL::Triangulation_hyperbolic_traits_2<R> K;
typedef K::Point_2 Point_2;
typedef K::Iso_rectangle_2 Iso_rectangle_2;
typedef CGAL::Delaunay_hyperbolic_triangulation_2<K> Delaunay;
class MainWindow :
public CGAL::Qt::DemosMainWindow,
public Ui::Delaunay_triangulation_2
{
Q_OBJECT
private:
Delaunay dt;
QGraphicsEllipseItem* disk;
QGraphicsScene scene;
CGAL::Qt::TriangulationGraphicsItem<Delaunay> * dgi;
CGAL::Qt::VoronoiGraphicsItem<Delaunay> * 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()
{
setupUi(this);
this->graphicsView->setAcceptDrops(false);
// Add Poincaré disk
qreal origin_x = 0, origin_y = 0, radius = 100, diameter = 2*radius;
qreal left_top_corner_x = origin_x - radius;
qreal left_top_corner_y = origin_y - radius;
qreal width = diameter, height = diameter;
disk = new QGraphicsEllipseItem(left_top_corner_x, left_top_corner_y, width, height);
scene.addItem(disk);
// Add a GraphicItem for the Delaunay triangulation
dgi = new CGAL::Qt::TriangulationGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
dgi, SLOT(modelChanged()));
dgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(dgi);
// Add a GraphicItem for the Voronoi diagram
vgi = new CGAL::Qt::VoronoiGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
vgi, SLOT(modelChanged()));
vgi->setEdgesPen(QPen(Qt::blue, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(vgi);
vgi->hide();
// Setup input handlers. They get events before the scene gets them
// and the input they generate is passed to the triangulation with
// the signal/slot mechanism
pi = new CGAL::Qt::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);
// Turn the vertical axis upside down
this->graphicsView->matrix().scale(1, -1);
// The navigation adds zooming and translation functionality to the
// QGraphicsView
this->addNavigation(this->graphicsView);
this->setupStatusBar();
this->setupOptionsMenu();
this->addAboutDemo(":/cgal/help/about_Delaunay_triangulation_2.html");
this->addAboutCGAL();
this->addRecentFiles(this->menuFile, this->actionQuit);
connect(this, SIGNAL(openRecentFile(QString)),
this, SLOT(open(QString)));
}
void
MainWindow::processInput(CGAL::Object o)
{
Point_2 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);
}
}
emit(changed());
}
/*
* Qt Automatic Connections
* http://doc.trolltech.com/4.4/designer-using-a-component.html#automatic-connections
*
* setupUi(this) generates connections to the slots named
* "on_<action_name>_<signal_name>"
*/
void
MainWindow::on_actionInsertPoint_toggled(bool checked)
{
if(checked){
scene.installEventFilter(pi);
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;
Iso_rectangle_2 isor = convert(rect);
CGAL::Random_points_in_iso_rectangle_2<Point_2> pg(isor.min(), isor.max());
bool ok = false;
const int number_of_points =
QInputDialog::getInteger(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_2> points;
points.reserve(number_of_points);
for(int i = 0; i < number_of_points; ++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_2 p;
std::vector<K::Point_2> 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()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Save points"),
".");
if(! fileName.isEmpty()){
std::ofstream ofs(qPrintable(fileName));
for(Delaunay::Finite_vertices_iterator
vit = dt.finite_vertices_begin(),
end = dt.finite_vertices_end();
vit!= end; ++vit)
{
ofs << vit->point() << std::endl;
}
}
}
void
MainWindow::on_actionRecenter_triggered()
{
this->graphicsView->setSceneRect(dgi->boundingRect());
this->graphicsView->fitInView(dgi->boundingRect(), Qt::KeepAspectRatio);
}
#include "Hyperbolic_Delaunay_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();
}

View File

@ -0,0 +1,713 @@
#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/Triangulation_hyperbolic_traits_2.h>
// to be deleted
#include <CGAL/Qt/HyperbolicPainterOstream.h>
//
#include <CGAL/point_generators_2.h>
// Maintain translations
#include <TranslationInfo.h>
#include <Translations.h>
// Qt headers
#include <QtGui>
#include <QString>
#include <QActionGroup>
#include <QFileDialog>
#include <QInputDialog>
#include <QGraphicsEllipseItem>
// experiment
#include "GroupOfIndex2.h"
#include "OriginalDomainNeighbors.h"
//
// GraphicsView items and event filters (input classes)
#include "PointTranslationWithInfo.h"
#include "TriangulationCircumcircle.h"
#include "TriangulationMovingPoint.h"
#include "TriangulationConflictZone.h"
#include "TriangulationRemoveVertex.h"
#include "TriangulationPointInputAndConflictZone.h"
#include <CGAL/Qt/TriangulationGraphicsItem.h>
#include <CGAL/Qt/VoronoiGraphicsItem.h>
// for viewportsBbox
#include <CGAL/Qt/utility.h>
// the two base classes
#include "ui_Hyperbolic_translations_2.h"
#include <CGAL/Qt/DemosMainWindow.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel R;
typedef CGAL::Triangulation_hyperbolic_traits_2<R> K;
typedef K::Point_2 Point_2;
typedef K::Iso_rectangle_2 Iso_rectangle_2;
typedef K Gt;
// keep the name of the translation for every vertex
typedef TranslationInfo<std::wstring> Vb_info;
typedef CGAL::Triangulation_vertex_base_with_info_2< Vb_info, Gt > Vb;
typedef CGAL::Triangulation_face_base_with_info_2 <CGAL::Hyperbolic_face_info_2, Gt > Fb;
typedef CGAL::Delaunay_hyperbolic_triangulation_2< Gt, CGAL::Triangulation_data_structure_2<Vb, Fb> > Delaunay;
class MainWindow :
public CGAL::Qt::DemosMainWindow,
public Ui::Delaunay_triangulation_2
{
Q_OBJECT
private:
Delaunay dt;
QGraphicsEllipseItem* disk;
QGraphicsScene scene;
CGAL::Qt::TriangulationGraphicsItem<Delaunay> * dgi;
CGAL::Qt::VoronoiGraphicsItem<Delaunay> * 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;
// hyperbolic translations
typedef CGAL::Hyperbolic_isometry_2<Gt> Hyperbolic_isometry;
typedef Hyperbolic_isometry::complex complex;
// storage of static data: translations a, b, c, d
typedef Translations<Gt> Translations;
typedef CGAL::Qt::PointTranslationWithInfo<Delaunay, Hyperbolic_isometry> PointTranslation;
PointTranslation *trs_a;
PointTranslation *trs_b;
PointTranslation *trs_c;
PointTranslation *trs_d;
// experiment
typedef CGAL::Qt::OriginalDomainNeighbors<Delaunay, Hyperbolic_isometry> OriginalDomainNeighbors;
typedef Group_of_index_2<Hyperbolic_isometry> Group_of_index_2;
// delete later, for some experiments
Group_of_index_2::List words;
//
Group_of_index_2 g2;
Group_of_index_2 g4;
Group_of_index_2 g8;
Group_of_index_2 g16;
// extra groups, we can delete them
Group_of_index_2 g32;
Group_of_index_2 g64;
Group_of_index_2 g128;
Group_of_index_2 g256;
Group_of_index_2 g512;
Group_of_index_2 g1024;
//
OriginalDomainNeighbors *odn;
OriginalDomainNeighbors *odn2;
//
public:
MainWindow();
public slots:
void processInput(CGAL::Object o);
void on_actionMovingPoint_toggled(bool checked);
void on_actionDo_translation_a_toggled(bool checked);
void on_actionDo_translation_b_toggled(bool checked);
void on_actionDo_translation_c_toggled(bool checked);
void on_actionDo_translation_d_toggled(bool checked);
void on_actionG_toggled(bool checked);
void on_actionG2_toggled(bool checked);
void on_actionG4_toggled(bool checked);
void on_actionG8_toggled(bool checked);
void on_actionG16_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();
};
// delete
bool inverses(int i, int j)
{
if((i == 0 && j == 2) || (i == 1 && j == 3) || (i == 4 && j == 6) || (i == 5 && j == 7)) {
return true;
}
if((i == 2 && j == 0) || (i == 3 && j == 1) || (i == 6 && j == 4) || (i == 7 && j == 5)) {
return true;
}
return false;
}
template<class TList>
void GenerateWordsOfLengthLessThan4(const TList& input, TList& output)
{
typename TList::value_type el;
std::copy(input.begin(), input.end(), std::insert_iterator<TList>(output, output.end()));
typename TList::const_iterator gi, gj, gk, gl;
gi = input.begin();
int i, j, k;
for(i = 0, gi = input.begin(); gi != input.end(); i++, gi++) {
for(j = 0, gj = input.begin(); gj != input.end(); j++, gj++) {
if(inverses(i, j)) {
continue;
}
el.g = gi->g * gj->g;
output.push_back(el);
}
}
for(i = 0, gi = input.begin(); gi != input.end(); i++, gi++) {
for(j = 0, gj = input.begin(); gj != input.end(); j++, gj++) {
for(k = 0, gk = input.begin(); gk != input.end(); k++, gk++) {
if(inverses(i, j) || inverses(j, k)) {
continue;
}
el.g = gi->g * gj->g * gk->g;
output.push_back(el);
}
}
}
}
MainWindow::MainWindow()
: DemosMainWindow(), dt(K(1))
{
setupUi(this);
this->graphicsView->setAcceptDrops(false);
// Add Poincaré disk
qreal squared_radius = to_double(dt.geom_traits().unit_circle().squared_radius());
qreal origin_x = 0, origin_y = 0, radius = CGAL::sqrt(squared_radius), diameter = 2*radius;
qreal left_top_corner_x = origin_x - radius;
qreal left_top_corner_y = origin_y - radius;
qreal width = diameter, height = diameter;
disk = new QGraphicsEllipseItem(left_top_corner_x, left_top_corner_y, width, height);
scene.addItem(disk);
// add the origin to the triangulation
dt.insert(Point_2(0, 0));
// Add a GraphicItem for the Delaunay triangulation
dgi = new CGAL::Qt::TriangulationGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
dgi, SLOT(modelChanged()));
dgi->setVerticesPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(dgi);
// Add a GraphicItem for the Voronoi diagram
vgi = new CGAL::Qt::VoronoiGraphicsItem<Delaunay>(&dt);
QObject::connect(this, SIGNAL(changed()),
vgi, SLOT(modelChanged()));
vgi->setEdgesPen(QPen(Qt::blue, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
scene.addItem(vgi);
vgi->hide();
// Setup input handlers. They get events before the scene gets them
// and the input they generate is passed to the triangulation with
// the signal/slot mechanism
pi = new CGAL::Qt::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);
// initialization of translations
trs_a = new PointTranslation(Translations::a(), scene, &dt, this);
trs_b = new PointTranslation(Translations::b(), scene, &dt, this);
trs_c = new PointTranslation(Translations::c(), scene, &dt, this);
trs_d = new PointTranslation(Translations::d(), scene, &dt, this);
trs_a->info().setString(L"a");
trs_b->info().setString(L"b");
trs_c->info().setString(L"c");
trs_d->info().setString(L"d");
QObject::connect(trs_a, SIGNAL(modelChanged()),
this, SIGNAL(changed()));
QObject::connect(trs_b, SIGNAL(modelChanged()),
this, SIGNAL(changed()));
QObject::connect(trs_c, SIGNAL(modelChanged()),
this, SIGNAL(changed()));
QObject::connect(trs_d, SIGNAL(modelChanged()),
this, SIGNAL(changed()));
// experiment
std::cout << "G: " << Translations::list().size() << std::endl;
g2.add_group(&Translations::list());
std::cout << "G_2: " << g2.number_of_elements() << std::endl;
g4.add_group(&g2.list());
std::cout << "G_4: " << g4.number_of_elements() << std::endl;
g8.add_group(&g4.list());
std::cout << "G_8: " << g8.number_of_elements() << std::endl;
g16.add_group(&g8.list());
std::cout << "G_16: " << g16.number_of_elements() << std::endl;
g32.add_group(&g16.list());
std::cout << "G_32: " << g32.number_of_elements() << std::endl;
g64.add_group(&g32.list());
std::cout << "G_64: " << g64.number_of_elements() << std::endl;
g128.add_group(&g64.list());
std::cout << "G_128: " << g128.number_of_elements() << std::endl;
g256.add_group(&g128.list());
std::cout << "G_256: " << g256.number_of_elements() << std::endl;
odn = new OriginalDomainNeighbors(scene, &dt, this);
QObject::connect(odn, SIGNAL(modelChanged()),
this, SIGNAL(changed()));
GenerateWordsOfLengthLessThan4(Translations::list(), words);
//
//
// 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);
ag->addAction(this->actionDo_translation_a);
ag->addAction(this->actionDo_translation_b);
ag->addAction(this->actionDo_translation_c);
ag->addAction(this->actionDo_translation_d);
ag->addAction(this->actionG);
ag->addAction(this->actionG2);
ag->addAction(this->actionG4);
ag->addAction(this->actionG8);
ag->addAction(this->actionG16);
// 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);
// Turn the vertical axis upside down
this->graphicsView->matrix().scale(1, -1);
// The navigation adds zooming and translation functionality to the
// QGraphicsView
this->addNavigation(this->graphicsView);
this->setupStatusBar();
this->setupOptionsMenu();
this->addAboutDemo(":/cgal/help/about_Delaunay_triangulation_2.html");
this->addAboutCGAL();
this->addRecentFiles(this->menuFile, this->actionQuit);
connect(this, SIGNAL(openRecentFile(QString)),
this, SLOT(open(QString)));
}
void
MainWindow::processInput(CGAL::Object o)
{
Point_2 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
//uncomment!
//if(disk->contains(qp)){
//dt.insert(p);
//}
//delete
if(disk->contains(qp)){
std::cout << "inserted point " << p << std::endl;
odn2 = new OriginalDomainNeighbors(scene, &dt, this, p, 1);
QObject::connect(odn2, SIGNAL(modelChanged()), this, SIGNAL(changed()));
odn2->assign(g4.begin(), g4.end());
odn2->assign(words.begin(), words.end());
}
}
emit(changed());
}
/*
* Qt Automatic Connections
* http://doc.trolltech.com/4.4/designer-using-a-component.html#automatic-connections
*
* setupUi(this) generates connections to the slots named
* "on_<action_name>_<signal_name>"
*/
void
MainWindow::on_actionInsertPoint_toggled(bool checked)
{
if(checked){
scene.installEventFilter(pi);
scene.installEventFilter(trv);
} else {
scene.removeEventFilter(pi);
scene.removeEventFilter(trv);
}
}
void
MainWindow::on_actionDo_translation_a_toggled(bool checked)
{
if(checked){
scene.installEventFilter(trs_a);
trs_a->show();
} else {
scene.removeEventFilter(trs_a);
trs_a->hide();
}
}
void
MainWindow::on_actionDo_translation_b_toggled(bool checked)
{
if(checked){
scene.installEventFilter(trs_b);
trs_b->show();
} else {
scene.removeEventFilter(trs_b);
trs_b->hide();
}
}
void
MainWindow::on_actionDo_translation_c_toggled(bool checked)
{
if(checked){
scene.installEventFilter(trs_c);
trs_c->show();
} else {
scene.removeEventFilter(trs_c);
trs_c->hide();
}
}
void
MainWindow::on_actionDo_translation_d_toggled(bool checked)
{
if(checked){
scene.installEventFilter(trs_d);
trs_d->show();
} else {
scene.removeEventFilter(trs_d);
trs_d->hide();
}
}
void
MainWindow::on_actionG_toggled(bool checked)
{
if(checked){
odn->assign(Translations::list_begin(), Translations::list_end());
}
}
void
MainWindow::on_actionG2_toggled(bool checked)
{
if(checked){
odn->assign(g2.begin(), g2.end());
}
}
void
MainWindow::on_actionG4_toggled(bool checked)
{
if(checked){
odn->assign(g4.begin(), g4.end());
}
}
void
MainWindow::on_actionG8_toggled(bool checked)
{
if(checked){
odn->assign(g8.begin(), g8.end());
}
}
void
MainWindow::on_actionG16_toggled(bool checked)
{
if(checked){
// odn->assign(g16.begin(), g16.end());
// Delete! Add all the words of length less than 4 + some words of length 4.
odn->assign(g4.begin(), g4.end());
odn->assign(words.begin(), words.end());
}
}
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;
Iso_rectangle_2 isor = convert(rect);
CGAL::Random_points_in_iso_rectangle_2<Point_2> pg(isor.min(), isor.max());
bool ok = false;
const int number_of_points =
QInputDialog::getInteger(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_2> points;
points.reserve(number_of_points);
for(int i = 0; i < number_of_points; ++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_2 p;
std::vector<K::Point_2> 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()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Save points"),
".");
if(! fileName.isEmpty()){
std::ofstream ofs(qPrintable(fileName));
for(Delaunay::Finite_vertices_iterator
vit = dt.finite_vertices_begin(),
end = dt.finite_vertices_end();
vit!= end; ++vit)
{
ofs << vit->point() << std::endl;
}
}
}
void
MainWindow::on_actionRecenter_triggered()
{
this->graphicsView->setSceneRect(dgi->boundingRect());
this->graphicsView->fitInView(dgi->boundingRect(), Qt::KeepAspectRatio);
}
#include "Hyperbolic_translations_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();
}

View File

@ -0,0 +1,208 @@
#ifndef CGAL_GROUP_OF_INDEX_2
#define CGAL_GROUP_OF_INDEX_2
#include <Translations.h>
template<class Translation>
class Group_of_index_2
{
public:
typedef Element<Translation> Element;
typedef typename Translation::FT FT;
typedef std::list<Element> List;
typedef CGAL::Circulator_from_container<List> Circulator;
typedef typename List::iterator List_iterator;
typedef typename List::size_type Size_type;
typedef std::pair<Translation, int> Node;
typedef std::vector<Node> Vector;
Group_of_index_2() : is_computed(false), l(&Translations<typename Translation::Geom_traits>::list())
{
}
void add_group(List* l_)
{
l = l_;
generate();
}
List& list()
{
return l2;
}
const List& list() const
{
return l2;
}
/*
template<class OutputIterator>
OutputIterator group_of_index_2(OutputIterator oit) const
{
return std::copy(g2.begin(), g2.end(), oit);
}*/
void generate()
{
if(!is_computed) {
compute();
refine();
is_computed = true;
}
}
List_iterator begin()
{
return l2.begin();
}
List_iterator end()
{
return l2.end();
}
Size_type number_of_elements() const
{
return l2.size();
}
private:
// the lists can not be copied.
Group_of_index_2(const Group_of_index_2&);
Group_of_index_2& operator= (const Group_of_index_2&) const;
bool is_computed;
void compute();
void compute_via_vector();
void refine(FT e = 0.000001);
List* l;
List l2;
Vector g;
Vector g2;
};
template<class Translation>
void Group_of_index_2<Translation>::refine(FT e)
{
typedef typename Translation::Geom_traits Gt;
typedef typename Translation::complex complex;
Circulator begin(&l2);
Circulator next = boost::next(begin);
if(begin == 0 || begin == next) {
return;
}
int steps_nb = l2.size();
for(int i = 0; i < steps_nb; i++, begin = next, next = boost::next(begin)) {
complex dif_m = begin->g.m() - next->g.m();
complex dif_n = begin->g.n() - next->g.n();
if(std::norm(dif_m) < e && std::norm(dif_n) < e) {
l2.erase(begin->inverse.current_iterator());
l2.erase(begin.current_iterator());
steps_nb--;
}
}
}
template<class Translation>
void Group_of_index_2<Translation>::compute_via_vector()
{
int nb = g.size();
g2.resize(2*nb);
for(int i = 0; i < nb; i++) {
int inv = g[i].second;
int next_inv = (inv + 1) & nb-1;
int prev_inv = (inv - 1) & nb-1;
g2[2*i].first = g[i].first*g[next_inv].first;
// compute position of the inverse element of g2[2*i]
int inv_pos = g[next_inv].second;
g2[2*i].second = 2*inv_pos + 1;
g2[2*i + 1].first = g[i].first*g[prev_inv].first;
// compute position of the inverse element of g2[2*i + 1]
inv_pos = g[prev_inv].second;
g2[2*i + 1].second = 2*inv_pos;
}
}
template<class Translation>
void Group_of_index_2<Translation>::compute()
{
typedef std::map<Element*, std::pair<Circulator, Circulator> > MapLtoL2;
MapLtoL2 l_to_l2;
typedef typename MapLtoL2::iterator Map_it;
l2.resize(2*l->size());
Circulator li(l);
Circulator Next, Prev;
Circulator l2i(&l2);
if(li == 0) {
return;
}
// add g
do {
Circulator item1 = l2i, item2 = boost::next(l2i);
Next = li->inverse;
Next = boost::next(Next);
item1->g = li->g * Next->g;
// aux value
item1->inverse = Next->inverse;
Prev = li->inverse;
Prev = boost::prior(Prev);
item2->g = li->g * Prev->g;
// aux value
item2->inverse = Prev->inverse;
l_to_l2.insert(std::make_pair(&*li, std::make_pair(item1, item2)));
li = boost::next(li);
l2i = boost::next(l2i, 2);
} while( li != Circulator( l ) );
// add inverse
int i = 0;
l2i = Circulator(&l2);
do {
Map_it mit = l_to_l2.find(&*l2i->inverse);
assert(mit != l_to_l2.end());
std::pair<Circulator, Circulator> val = mit->second;
if(i % 2 == 0) {
l2i->inverse = val.second;
} else {
l2i->inverse = val.first;
}
l2i++;
i++;
} while( l2i != Circulator( &l2 ) );
}
#endif // CGAL_GROUP_OF_INDEX_2

View File

@ -0,0 +1,99 @@
#ifndef CGAL_QT_ORIGINAL_DOMAIN_NEIGHBORS
#define CGAL_QT_ORIGINAL_DOMAIN_NEIGHBORS
#include <CGAL/circulator.h>
#include <CGAL/Qt/GraphicsViewInput.h>
#include <QGraphicsSceneMouseEvent>
#include <QEvent>
#include <PointGraphicsItem.h>
namespace CGAL {
namespace Qt {
template <typename DT, typename Translation>
class OriginalDomainNeighbors : public GraphicsViewInput
{
public:
typedef typename DT::Face_handle Face_handle;
typedef typename DT::Vertex_handle Vertex_handle;
typedef typename DT::Point Point;
OriginalDomainNeighbors(QGraphicsScene& scene_, DT * dt_, QObject* parent, Point p_, int color);
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end)
{
insert(begin, end);
}
protected:
template <typename InputIterator>
void insert(InputIterator begin, InputIterator end);
Point do_point_translation(const Translation& translation) const;
virtual Vertex_handle insert_point(const Point& p);
private:
DT * dt;
// center of original domain
Point p;
int color;
};
template <typename DT, typename Translation>
OriginalDomainNeighbors<DT, Translation>::OriginalDomainNeighbors(QGraphicsScene& ,
DT * dt_,
QObject* parent,
Point p_ = Point(0, 0),
int color_ = 0)
: GraphicsViewInput(parent), dt(dt_), p(p_), color(color_)
{
}
template <typename DT, typename Translation>
template <typename InputIterator>
void
OriginalDomainNeighbors<DT, Translation>::insert(InputIterator begin, InputIterator end)
{
insert_point(p);
for(InputIterator it = begin; it != end; ++it) {
Translation t = it->g;
Point neighbor = do_point_translation(it->g);
insert_point(neighbor);
}
}
template <typename DT, typename Translation>
typename OriginalDomainNeighbors<DT, Translation>::Point
OriginalDomainNeighbors<DT, Translation>::do_point_translation(const Translation& translation) const
{
return translation.DoAction(p);
}
template <typename DT, typename Translation>
typename OriginalDomainNeighbors<DT, Translation>::Vertex_handle
OriginalDomainNeighbors<DT, Translation>::insert_point(const Point& p)
{
Vertex_handle v = dt->insert(p);
v->info().setColor(color);
emit(modelChanged());
return v;
}
} // namespace Qt
} // namespace CGAL
#endif // CGAL_QT_ORIGINAL_DOMAIN_NEIGHBORS

View File

@ -0,0 +1,151 @@
#ifndef CGAL_QT_POINT_GRAPHICS_ITEM_H
#define CGAL_QT_POINT_GRAPHICS_ITEM_H
#include <CGAL/Bbox_2.h>
#include <CGAL/Qt/GraphicsItem.h>
#include <CGAL/Qt/Converter.h>
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
namespace CGAL {
namespace Qt {
template <typename T>
class PointGraphicsItem : public GraphicsItem
{
public:
typedef typename T::Point Point;
typedef typename T::Geom_traits Geom_traits;
PointGraphicsItem(Point p = Point());
void modelChanged();
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void setPoint(const Point& p)
{
m_p = p;
updateBoundingBox();
update();
}
Point getPoint() const
{
return m_p;
}
const QPen& vertexPen() const
{
return vertex_pen;
}
void setVertexPen(const QPen& pen)
{
vertex_pen = pen;
}
void paintOneVertex(const Point& point) const;
protected:
void updateBoundingBox();
void paintVertex(QPainter* painter, const Point& point) const;
QPainter* m_painter;
Point m_p;
CGAL::Bbox_2 bb;
bool bb_initialized;
QRectF bounding_rect;
QPen vertex_pen;
};
template <typename T>
PointGraphicsItem<T>::PointGraphicsItem(Point p)
: m_painter(0), m_p(p), bb(0,0,0,0), bb_initialized(false)
{
setVertexPen(QPen(::Qt::green, 3.));
updateBoundingBox();
setZValue(3);
}
template <typename T>
QRectF
PointGraphicsItem<T>::boundingRect() const
{
return bounding_rect;
}
template <typename T>
void
PointGraphicsItem<T>::modelChanged()
{
updateBoundingBox();
update();
}
template <typename T>
void
PointGraphicsItem<T>::paintOneVertex(const Point& p) const
{
pointVertex(m_painter, p);
}
template <typename T>
void
PointGraphicsItem<T>::paintVertex(QPainter *painter, const Point& p) const
{
Converter<Geom_traits> convert;
painter->setPen(this->vertexPen());
QMatrix matrix = painter->matrix();
painter->resetMatrix();
painter->drawPoint(matrix.map(convert(p)));
painter->setMatrix(matrix);
}
template <typename T>
void
PointGraphicsItem<T>::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget * /*widget*/)
{
painter->setPen(this->vertexPen());
paintVertex(painter, m_p);
}
template <typename T>
void
PointGraphicsItem<T>::updateBoundingBox()
{
bb = m_p.bbox();
bb_initialized = true;
bounding_rect = QRectF(bb.xmin(),
bb.ymin(),
bb.xmax()-bb.xmin(),
bb.ymax()-bb.ymin());
}
} // namespace Qt
} // namespace CGAL
#endif // CGAL_QT_POINT_GRAPHICS_ITEM_H

View File

@ -0,0 +1,172 @@
#ifndef CGAL_QT_POINT_TRANSLATION
#define CGAL_QT_POINT_TRANSLATION
#include <CGAL/Qt/GraphicsViewInput.h>
#include <QGraphicsSceneMouseEvent>
#include <QEvent>
#include <PointGraphicsItem.h>
namespace CGAL {
namespace Qt {
template <typename DT, typename Translation>
class PointTranslation : public GraphicsViewInput
{
public:
typedef typename DT::Face_handle Face_handle;
typedef typename DT::Vertex_handle Vertex_handle;
typedef typename DT::Point Point;
PointTranslation(const Translation& translation_, QGraphicsScene& scene_, DT * dt_, QObject* parent);
void show();
void hide();
protected:
Point do_point_translation() const;
virtual Vertex_handle insert_point(const Point& p);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
Translation translation;
Vertex_handle chosen_vertex;
private:
void highlight_chosen_vertex();
DT * dt;
QGraphicsScene& scene;
QGraphicsEllipseItem* circle;
// highlight the chosen vertex
PointGraphicsItem<DT>* highlight_point;
};
template <typename DT, typename Translation>
PointTranslation<DT, Translation>::PointTranslation(const Translation& translation_,
QGraphicsScene& scene_,
DT * dt_,
QObject* parent)
: GraphicsViewInput(parent), translation(translation_), dt(dt_), scene(scene_)
{
highlight_point = new PointGraphicsItem<DT>();
highlight_point->hide();
// scene is the holder of the added item
scene.addItem(highlight_point);
}
template <typename DT, typename Translation>
void
PointTranslation<DT, Translation>::show()
{
highlight_point->show();
}
template <typename DT, typename Translation>
void
PointTranslation<DT, Translation>::hide()
{
highlight_point->hide();
}
template <typename DT, typename Translation>
typename PointTranslation<DT, Translation>::Point
PointTranslation<DT, Translation>::do_point_translation() const
{
return translation.DoAction(chosen_vertex->point());
}
template <typename DT, typename Translation>
typename PointTranslation<DT, Translation>::Vertex_handle
PointTranslation<DT, Translation>::insert_point(const Point& p)
{
Vertex_handle v = dt->insert(p, chosen_vertex->face());
emit(modelChanged());
return v;
}
template <typename DT, typename Translation>
void
PointTranslation<DT, Translation>::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(chosen_vertex == Vertex_handle() ||
event->modifiers() != 0 ||
event->button() != ::Qt::LeftButton) {
return;
}
// translate chosen point
Point translated_point = do_point_translation();
// insert to the triangulation
insert_point(translated_point);
}
template <typename DT, typename Translation>
void
PointTranslation<DT, Translation>::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Point scene_pos = Point(event->scenePos().x(), event->scenePos().y());
Face_handle start_face = Face_handle();
if(chosen_vertex != Vertex_handle()) {
start_face = chosen_vertex->face();
}
Vertex_handle new_chosen_vertex = dt->nearest_vertex(scene_pos, start_face);
// highlight the vertex if only it's been changed
if(new_chosen_vertex != chosen_vertex) {
chosen_vertex = new_chosen_vertex;
highlight_chosen_vertex();
}
}
template <typename DT, typename Translation>
bool
PointTranslation<DT, Translation>::eventFilter(QObject *obj, QEvent *event)
{ if (event->type() == QEvent::GraphicsSceneMousePress) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
mousePressEvent(mouseEvent);
return true;
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
mouseMoveEvent(mouseEvent);
return false; // do not eat move event!
} else{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
template <typename DT, typename Translation>
void
PointTranslation<DT, Translation>::highlight_chosen_vertex()
{
assert(chosen_vertex != Vertex_handle());
highlight_point->setPoint(chosen_vertex->point());
highlight_point->show();
emit(modelChanged());
}
} // namespace Qt
} // namespace CGAL
#endif // CGAL_QT_POINT_TRANSLATION

View File

@ -0,0 +1,123 @@
#ifndef CGAL_QT_POINT_TRANSLATION_WITH_INFO
#define CGAL_QT_POINT_TRANSLATION_WITH_INFO
#include <PointTranslation.h>
namespace CGAL {
namespace Qt {
template <typename DT, typename Translation>
class PointTranslationWithInfo : public PointTranslation<DT, Translation>
{
typedef PointTranslation<DT, Translation> Base;
public:
typedef typename DT::Face_handle Face_handle;
typedef typename DT::Vertex_handle Vertex_handle;
typedef typename DT::Point Point;
typedef typename DT::Vertex::Info Info;
PointTranslationWithInfo(const Translation& translation_, QGraphicsScene& scene_, DT * dt_, QObject* parent);
const Info& info() const { return _info; }
Info& info() { return _info; }
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
virtual Vertex_handle insert_point(const Point& p);
Info compute_info() const;
void add_info(Vertex_handle v) const;
void show_info(const QPointF& pos, Vertex_handle v) const;
private:
Info _info;
};
template <typename DT, typename Translation>
PointTranslationWithInfo<DT, Translation>::PointTranslationWithInfo(const Translation& translation_,
QGraphicsScene& scene_,
DT * dt_,
QObject* parent)
: Base(translation_, scene_, dt_, parent)
{
}
template <typename DT, typename Translation>
typename PointTranslationWithInfo<DT, Translation>::Info
PointTranslationWithInfo<DT, Translation>::compute_info() const
{
return this->chosen_vertex->info() + info();
}
template <typename DT, typename Translation>
void
PointTranslationWithInfo<DT, Translation>::add_info(Vertex_handle v) const
{
Info new_info = compute_info();
v->info().setString(new_info.toString());
}
template <typename DT, typename Translation>
void
PointTranslationWithInfo<DT, Translation>::show_info(const QPointF& pos, Vertex_handle v) const
{
if(v == Vertex_handle()) {
return;
}
const Info& vertex_info = this->chosen_vertex->info();
QToolTip::showText(pos.toPoint(), QString::fromStdWString(vertex_info.toString()));
}
template <typename DT, typename Translation>
typename PointTranslationWithInfo<DT, Translation>::Vertex_handle
PointTranslationWithInfo<DT, Translation>::insert_point(const Point& p)
{
Vertex_handle v = Base::insert_point(p);
add_info(v);
return v;
}
template <typename DT, typename Translation>
void
PointTranslationWithInfo<DT, Translation>::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Base::mouseMoveEvent(event);
show_info(event->scenePos(), this->chosen_vertex);
}
template <typename DT, typename Translation>
bool
PointTranslationWithInfo<DT, Translation>::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::GraphicsSceneMouseMove) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
mouseMoveEvent(mouseEvent);
return false; // do not eat move event!
}
return Base::eventFilter(obj, event);
}
} // namespace Qt
} // namespace CGAL
#endif // CGAL_QT_POINT_TRANSLATION_WITH_INFO

View File

@ -0,0 +1,48 @@
template<typename String>
class TranslationInfo
{
public:
TranslationInfo() : color(0)
{
}
TranslationInfo(const String& name)
: name_of_translation(name), color(0)
{
}
void setString(const String& name)
{
name_of_translation = name;
}
const String& toString() const
{
return name_of_translation;
}
void setColor(int new_color)
{
color = new_color;
}
int getColor() const
{
return color;
}
private:
String name_of_translation;
int color;
};
template<typename String>
TranslationInfo<String> operator + (const TranslationInfo<String>& l, const TranslationInfo<String>& r)
{
TranslationInfo<String> result;
result.setString(l.toString() + r.toString());
return result;
}

View File

@ -0,0 +1,183 @@
#ifndef CGAL_HYPERBOLIC_TRANSLATIONS_2_H
#define CGAL_HYPERBOLIC_TRANSLATIONS_2_H
#include <CGAL/Hyperbolic_isometry_2.h>
template<typename Translation>
struct Element
{
typedef typename std::list<Element> List;
typedef CGAL::Circulator_from_container<List> Circulator;
Translation g;
// circulator iterator to an inverse translation in the list
Circulator inverse;
};
template<typename Gt>
class Translations
{
public:
typedef typename Gt::FT FT;
typedef typename std::complex<FT> complex;
typedef CGAL::Hyperbolic_isometry_2<Gt> Hyperbolic_isometry;
typedef Element<Hyperbolic_isometry> Element;
typedef std::list<Element> List;
typedef typename List::iterator List_iterator;
typedef CGAL::Circulator_from_container<List> Circulator;
typedef std::pair<Hyperbolic_isometry, int> Node;
typedef std::vector<Node> Vector;
typedef typename Vector::iterator Vector_iterator;
static Hyperbolic_isometry& a()
{
compute();
return g[0].first;
}
static Hyperbolic_isometry& b()
{
compute();
return g[1].first;
}
static Hyperbolic_isometry& c()
{
compute();
return g[2].first;
}
static Hyperbolic_isometry& d()
{
compute();
return g[3].first;
}
static const Vector& get_vector_of_translations()
{
compute();
return g;
}
static Vector_iterator vector_begin()
{
compute();
return g.begin();
}
static Vector_iterator vector_end()
{
compute();
return g.end();
}
static List_iterator list_begin()
{
compute();
return l.begin();
}
static List_iterator list_end()
{
compute();
return l.end();
}
static List& list()
{
compute();
return l;
}
private:
static void compute_g()
{
const FT k1 = (FT(2) + CGAL::sqrt(2.))/FT(2);
const FT k2 = CGAL::sqrt(CGAL::sqrt(2.));
const FT k3 = (CGAL::sqrt(2.)*k2)/FT(2);
std::complex<FT> m(k1, k1);
std::complex<FT> n(k2*k1, -k3);
g.resize(8);
// a
g[0].first = Hyperbolic_isometry(conj(m), conj(n));
g[0].second = 2;
// b
g[3].first = Hyperbolic_isometry(m, -n);
g[3].second = 1;
// c
g[4].first = Hyperbolic_isometry(conj(m), -conj(n));
g[4].second = 6;
// d
g[7].first = Hyperbolic_isometry(m, n);
g[7].second = 5;
int index = g[0].second;
g[index].first = g[0].first.inverse();
g[index].second = 0;
index = g[3].second;
g[index].first = g[3].first.inverse();
g[index].second = 3;
index = g[4].second;
g[index].first = g[4].first.inverse();
g[index].second = 4;
index = g[7].second;
g[index].first = g[7].first.inverse();
g[index].second = 7;
}
static void compute_l()
{
l.resize(g.size());
std::vector<Circulator> aux_list;
aux_list.reserve(8);
for(List_iterator li = l.begin(); li != l.end(); li++) {
aux_list.push_back( Circulator(&l, li) );
}
for(typename List::size_type i = 0; i < aux_list.size(); i++) {
aux_list[i]->g = g[i].first;
aux_list[i]->inverse = aux_list[g[i].second];
}
}
static void compute()
{
static bool computed = false;
if(!computed) {
compute_g();
compute_l();
computed = true;
}
}
static Vector g;
static List l;
};
// default initialization
template<typename Gt>
typename Translations<Gt>::Vector
Translations<Gt>::g;
template<typename Gt>
typename Translations<Gt>::List
Translations<Gt>::l;
#endif // CGAL_HYPERBOLIC_TRANSLATIONS_2_H

View File

@ -0,0 +1,13 @@
<RCC>
<qresource prefix="/cgal/Actions">
<file>icons/G2.png</file>
<file>icons/G4.png</file>
<file>icons/G8.png</file>
<file>icons/G16.png</file>
<file>icons/G.png</file>
<file>icons/a.png</file>
<file>icons/b.png</file>
<file>icons/c.png</file>
<file>icons/d.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

View File

@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>GeometryFactory</author>
<class>Delaunay_triangulation_2</class>
<widget class="QMainWindow" name="Delaunay_triangulation_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>CGAL Delaunay Triangulation</string>
</property>
<property name="windowIcon">
<iconset resource="../../../../CGAL-3.8/demo/resources/CGAL.qrc">
<normaloff>:/cgal/logos/cgal_icon</normaloff>:/cgal/logos/cgal_icon</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QGraphicsView" name="graphicsView">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="transformationAnchor">
<enum>QGraphicsView::NoAnchor</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="fileToolBar">
<property name="windowTitle">
<string>File Tools</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionClear"/>
<addaction name="actionLoadPoints"/>
<addaction name="actionSavePoints"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>Visualization Tools</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionInsertPoint"/>
<addaction name="actionDo_translation_a"/>
<addaction name="actionDo_translation_b"/>
<addaction name="actionDo_translation_c"/>
<addaction name="actionDo_translation_d"/>
<addaction name="actionMovingPoint"/>
<addaction name="actionCircumcenter"/>
<addaction name="actionShowConflictZone"/>
<addaction name="separator"/>
<addaction name="actionShowDelaunay"/>
<addaction name="actionShowVoronoi"/>
<addaction name="separator"/>
<addaction name="actionRecenter"/>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="separator"/>
<addaction name="actionClear"/>
<addaction name="actionLoadPoints"/>
<addaction name="actionSavePoints"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>&amp;Edit</string>
</property>
<addaction name="actionInsertRandomPoints"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>&amp;Tools</string>
</property>
<addaction name="actionInsertPoint"/>
<addaction name="actionDo_translation_a"/>
<addaction name="actionDo_translation_b"/>
<addaction name="actionDo_translation_c"/>
<addaction name="actionDo_translation_d"/>
<addaction name="actionG"/>
<addaction name="actionG2"/>
<addaction name="actionG4"/>
<addaction name="actionG8"/>
<addaction name="actionG16"/>
<addaction name="actionMovingPoint"/>
<addaction name="actionCircumcenter"/>
<addaction name="actionShowConflictZone"/>
<addaction name="separator"/>
<addaction name="actionShowDelaunay"/>
<addaction name="actionShowVoronoi"/>
<addaction name="separator"/>
<addaction name="actionRecenter"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTools"/>
</widget>
<action name="actionAbout">
<property name="text">
<string>&amp;About</string>
</property>
</action>
<action name="actionAboutCGAL">
<property name="text">
<string>About &amp;CGAL</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>&amp;Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionInsertRandomPoints">
<property name="text">
<string>&amp;Insert random points</string>
</property>
<property name="shortcut">
<string>Ctrl+I</string>
</property>
</action>
<action name="actionMovingPoint">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/Triangulation_2/Delaunay_triangulation_2.qrc">
<normaloff>:/cgal/Actions/icons/moving_point.png</normaloff>:/cgal/Actions/icons/moving_point.png</iconset>
</property>
<property name="text">
<string>&amp;Simulate insertion</string>
</property>
<property name="toolTip">
<string comment="The comment">Simulate Insertion</string>
</property>
<property name="statusTip">
<string comment="and its comment">Move mouse with left button pressed to see where point would be inserted</string>
</property>
<property name="whatsThis">
<string comment="what">whats this</string>
</property>
</action>
<action name="actionInsertPoint">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/Input.qrc">
<normaloff>:/cgal/Input/inputPoint.png</normaloff>:/cgal/Input/inputPoint.png</iconset>
</property>
<property name="text">
<string>&amp;Insert Point</string>
</property>
<property name="toolTip">
<string>Insert Point</string>
</property>
<property name="statusTip">
<string>Left: Insert vtx</string>
</property>
</action>
<action name="actionClear">
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/File.qrc">
<normaloff>:/cgal/fileToolbar/fileNew.png</normaloff>:/cgal/fileToolbar/fileNew.png</iconset>
</property>
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="actionShowVoronoi">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/Triangulation_2.qrc">
<normaloff>:/cgal/Triangulation_2/Voronoi_diagram_2.png</normaloff>:/cgal/Triangulation_2/Voronoi_diagram_2.png</iconset>
</property>
<property name="text">
<string>Show &amp;Voronoi Diagram</string>
</property>
<property name="shortcut">
<string>Ctrl+V</string>
</property>
</action>
<action name="actionShowDelaunay">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/Triangulation_2/Delaunay_triangulation_2.qrc">
<normaloff>:/cgal/Actions/icons/triangulation.png</normaloff>:/cgal/Actions/icons/triangulation.png</iconset>
</property>
<property name="text">
<string>Show &amp;Delaunay Triangulation</string>
</property>
<property name="shortcut">
<string>Ctrl+D</string>
</property>
</action>
<action name="actionLoadPoints">
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/File.qrc">
<normaloff>:/cgal/fileToolbar/fileOpen.png</normaloff>:/cgal/fileToolbar/fileOpen.png</iconset>
</property>
<property name="text">
<string>&amp;Load Points...</string>
</property>
<property name="shortcut">
<string>Ctrl+L</string>
</property>
</action>
<action name="actionSavePoints">
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/File.qrc">
<normaloff>:/cgal/fileToolbar/fileSave.png</normaloff>:/cgal/fileToolbar/fileSave.png</iconset>
</property>
<property name="text">
<string>&amp;Save Points...</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionCircumcenter">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/Triangulation_2/Delaunay_triangulation_2.qrc">
<normaloff>:/cgal/Actions/icons/circumcenter.png</normaloff>:/cgal/Actions/icons/circumcenter.png</iconset>
</property>
<property name="text">
<string>&amp;Circumcenter</string>
</property>
<property name="toolTip">
<string>Draw circumcenter</string>
</property>
</action>
<action name="actionRecenter">
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/icons/Input.qrc">
<normaloff>:/cgal/Input/zoom-best-fit</normaloff>:/cgal/Input/zoom-best-fit</iconset>
</property>
<property name="text">
<string>Re&amp;center the viewport</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</action>
<action name="actionShowConflictZone">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../../../CGAL-3.8/demo/Triangulation_2/Delaunay_triangulation_2.qrc">
<normaloff>:/cgal/Actions/icons/conflict_zone.png</normaloff>:/cgal/Actions/icons/conflict_zone.png</iconset>
</property>
<property name="text">
<string>Show Conflict Zone</string>
</property>
</action>
<action name="actionDo_translation_a">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/a.png</normaloff>:/cgal/Actions/icons/a.png</iconset>
</property>
<property name="text">
<string>Do translation &quot;a&quot;</string>
</property>
</action>
<action name="actionDo_translation_b">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/b.png</normaloff>:/cgal/Actions/icons/b.png</iconset>
</property>
<property name="text">
<string>Do translation &quot;b&quot;</string>
</property>
</action>
<action name="actionDo_translation_c">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/c.png</normaloff>:/cgal/Actions/icons/c.png</iconset>
</property>
<property name="text">
<string>Do translation &quot;c&quot;</string>
</property>
</action>
<action name="actionDo_translation_d">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/d.png</normaloff>:/cgal/Actions/icons/d.png</iconset>
</property>
<property name="text">
<string>Do translation &quot;d&quot;</string>
</property>
</action>
<action name="actionG">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/G.png</normaloff>:/cgal/Actions/icons/G.png</iconset>
</property>
<property name="text">
<string>G</string>
</property>
</action>
<action name="actionG2">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/G2.png</normaloff>:/cgal/Actions/icons/G2.png</iconset>
</property>
<property name="text">
<string>G2</string>
</property>
</action>
<action name="actionG4">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/G4.png</normaloff>:/cgal/Actions/icons/G4.png</iconset>
</property>
<property name="text">
<string>G4</string>
</property>
</action>
<action name="actionG8">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/G8.png</normaloff>:/cgal/Actions/icons/G8.png</iconset>
</property>
<property name="text">
<string>G8</string>
</property>
</action>
<action name="actionG16">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources/Hyperbolic_translations_2.qrc">
<normaloff>:/cgal/Actions/icons/G16.png</normaloff>:/cgal/Actions/icons/G16.png</iconset>
</property>
<property name="text">
<string>G16</string>
</property>
</action>
</widget>
<resources>
<include location="../../../../CGAL-3.8/demo/Triangulation_2/Delaunay_triangulation_2.qrc"/>
<include location="../../../../CGAL-3.8/demo/icons/File.qrc"/>
<include location="../resources/Hyperbolic_translations_2.qrc"/>
<include location="../../../../CGAL-3.8/demo/resources/CGAL.qrc"/>
<include location="../../../../CGAL-3.8/demo/icons/Triangulation_2.qrc"/>
<include location="../../../../CGAL-3.8/demo/icons/Input.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,71 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <cassert>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef CGAL::Triangulation_vertex_base_2<Gt> Vb;
typedef CGAL::Constrained_triangulation_face_base_2<Gt> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
// typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, TDS> CDT;
typedef CDT::Point Point;
int main()
{
CDT cdt;
std::cout << "Inserting 8 constraints " << std::endl;
// cdt.insert_constraint( Point(-0.25, 0), Point(0, 0.25) );
// cdt.insert_constraint( Point( 0, 0.25), Point(0.25, 0) );
// cdt.insert_constraint( Point( 0.25, 0), Point(0, -0.25) );
// cdt.insert_constraint( Point( 0, -0.25), Point(-0.25, 0) );
cdt.insert_constraint( Point(-0.85, 0), Point(-0.6, 0.6) );
cdt.insert_constraint( Point( -0.6, 0.6), Point(0, 0.85) );
cdt.insert_constraint( Point( 0, 0.85), Point(0.6, 0.6) );
cdt.insert_constraint( Point( 0.6, 0.6), Point(0.85, 0) );
cdt.insert_constraint( Point( 0.85, 0), Point(0.6, -0.6) );
cdt.insert_constraint( Point( 0.6, -0.6), Point(0, -0.85) );
cdt.insert_constraint( Point( 0, -0.85), Point(-0.6, -0.6) );
cdt.insert_constraint( Point( -0.6, -0.6), Point(-0.85, 0) );
//cdt.insert( Point( 0, 0 ) );
// for (int i = 1; i < 6; ++i)
// cdt.insert_constraint( Point(0,i), Point(6,i));
// for (int j = 1; j < 6; ++j)
// cdt.insert_constraint( Point(j,0), Point(j,6));
assert(cdt.is_valid());
int count = 0;
int edgesCount = 0;
for (CDT::Finite_edges_iterator eit = cdt.finite_edges_begin();
eit != cdt.finite_edges_end();
++eit) {
edgesCount++;
if (cdt.is_constrained(*eit)) ++count;
}
std::cout << "The number of resulting constrained edges is ";
std::cout << count << std::endl;
std::cout << "Edges count: ";
std::cout << edgesCount << std::endl;
int verticesCount = 0;
for(CDT::Finite_vertices_iterator vit = cdt.finite_vertices_begin();
vit != cdt.finite_vertices_end();
++vit) {
std::cout << (*vit).point().x() << " " << (*vit).point().y() << std::endl;
verticesCount++;
}
std::cout << verticesCount << std::endl;
return 0;
}

View File

@ -0,0 +1,57 @@
#include <fstream>
// CGAL headers
#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/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Random.h>
#include <CGAL/point_generators_2.h>
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef Gt::Point_2 Point_2;
typedef Gt::Circle_2 Circle_2;
typedef Gt::FT FT;
typedef CGAL::Delaunay_hyperbolic_triangulation_2<Gt> Dt;
int main()
{
CGAL::Timer timer;
typedef CGAL::Creator_uniform_2<FT, Point_2> Creator;
FT r = 100;
CGAL::Random_points_in_disc_2<Point_2, Creator> in_disc(r);
int n = 10000;
std::vector<Point_2> pts;
std::vector<Point_2>::iterator ip;
// Generating n random points
for (int i=0 ; i < n ; i++) {
pts.at(i) = *in_disc;
in_disc++;
}
timer.start();
Dt dt = Dt(Gt(r));
for(ip = pts.begin(); ip != pts.end(); ++ip) {
dt.insert(*ip);
}
timer.stop();
std::cout << "Number of points: " << n << std::endl;
std::cout << "Time: " << timer.time() << std::endl;
timer.reset();
return 0;
}

View File

@ -0,0 +1,59 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef CGAL::Triangulation_vertex_base_2<Gt> Vb;
typedef CGAL::Delaunay_mesh_face_base_2<Gt> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, Tds> CDT;
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
typedef CGAL::Delaunay_mesher_2<CDT, Criteria> Mesher;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point Point;
int main()
{
CDT cdt;
Vertex_handle va = cdt.insert(Point(-4,0));
Vertex_handle vb = cdt.insert(Point(0,-1));
Vertex_handle vc = cdt.insert(Point(4,0));
Vertex_handle vd = cdt.insert(Point(0,1));
cdt.insert(Point(2, 0.6));
cdt.insert_constraint(va, vb);
cdt.insert_constraint(vb, vc);
cdt.insert_constraint(vc, vd);
cdt.insert_constraint(vd, va);
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
std::cout << "Meshing the triangulation with default criterias..."
<< std::endl;
Mesher mesher(cdt);
mesher.refine_mesh();
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
std::cout << "Meshing with new criterias..." << std::endl;
// 0.125 is the default shape bound. It corresponds to abound 20.6 degree.
// 0.5 is the upper bound on the length of the longuest edge.
// See reference manual for Delaunay_mesh_size_traits_2<K>.
mesher.set_criteria(Criteria(0.125, 0.5));
mesher.refine_mesh();
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
}

View File

@ -0,0 +1,58 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef CGAL::Triangulation_vertex_base_2<Gt> Vb;
typedef CGAL::Delaunay_mesh_face_base_2<Gt> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, Tds> CDT;
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point Point;
int main()
{
CDT cdt;
/*
Vertex_handle va = cdt.insert(Point(-4,0));
Vertex_handle vb = cdt.insert(Point(0,-1));
Vertex_handle vc = cdt.insert(Point(4,0));
Vertex_handle vd = cdt.insert(Point(0,1));
cdt.insert(Point(2, 0.6));
cdt.insert_constraint(va, vb);
cdt.insert_constraint(vb, vc);
cdt.insert_constraint(vc, vd);
cdt.insert_constraint(vd, va);
*/
cdt.insert_constraint( Point(-0.85, 0), Point(-0.6, 0.6) );
cdt.insert_constraint( Point( -0.6, 0.6), Point(0, 0.85) );
cdt.insert_constraint( Point( 0, 0.85), Point(0.6, 0.6) );
cdt.insert_constraint( Point( 0.6, 0.6), Point(0.85, 0) );
cdt.insert_constraint( Point( 0.85, 0), Point(0.6, -0.6) );
cdt.insert_constraint( Point( 0.6, -0.6), Point(0, -0.85) );
cdt.insert_constraint( Point( 0, -0.85), Point(-0.6, -0.6) );
cdt.insert_constraint( Point( -0.6, -0.6), Point(-0.85, 0) );
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
std::cout << "Meshing the triangulation..." << std::endl;
CGAL::refine_Delaunay_mesh_2(cdt, Criteria(0.125, 0.5));
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
}

View File

@ -0,0 +1,67 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef CGAL::Triangulation_vertex_base_2<Gt> Vb;
typedef CGAL::Delaunay_mesh_face_base_2<Gt> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, Tds> CDT;
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point Point;
int main()
{
CDT cdt;
Vertex_handle va = cdt.insert(Point(2,0));
Vertex_handle vb = cdt.insert(Point(0,2));
Vertex_handle vc = cdt.insert(Point(-2,0));
Vertex_handle vd = cdt.insert(Point(0,-2));
cdt.insert_constraint(va, vb);
cdt.insert_constraint(vb, vc);
cdt.insert_constraint(vc, vd);
cdt.insert_constraint(vd, va);
va = cdt.insert(Point(3,3));
vb = cdt.insert(Point(-3,3));
vc = cdt.insert(Point(-3,-3));
vd = cdt.insert(Point(3,0-3));
cdt.insert_constraint(va, vb);
cdt.insert_constraint(vb, vc);
cdt.insert_constraint(vc, vd);
cdt.insert_constraint(vd, va);
std::list<Point> list_of_seeds;
list_of_seeds.push_back(Point(0, 0));
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
std::cout << "Meshing the domain..." << std::endl;
CGAL::refine_Delaunay_mesh_2(cdt, list_of_seeds.begin(), list_of_seeds.end(),
Criteria());
std::cout << "Number of vertices: " << cdt.number_of_vertices() << std::endl;
std::cout << "Number of finite faces: " << cdt.number_of_faces() << std::endl;
int mesh_faces_counter = 0;
for(CDT::Finite_faces_iterator fit = cdt.finite_faces_begin();
fit != cdt.finite_faces_end(); ++fit)
{
if(fit->is_in_domain()) ++mesh_faces_counter;
}
std::cout << "Number of faces in the mesh domain: " << mesh_faces_counter << std::endl;
}

View File

@ -0,0 +1,56 @@
#include <fstream>
#include <string>
// CGAL headers
#include <CGAL/Random.h>
#include <CGAL/point_generators_2.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef K::FT FT;
using namespace std;
int main()
{
typedef CGAL::Creator_uniform_2<FT, Point_2> Creator;
FT r = 0;
cout << "Please, enter radius of the disk:" << std::endl;
cin >> r;
assert(r > 0);
int nb = 0;
cout << "Please, enter number of points:" << std::endl;
cin >> nb;
assert(nb >= 0);
CGAL::Random_points_in_disc_2<Point_2, Creator> in_disk(r);
vector<Point_2> pts(nb);
// file name
string file_name("points.cin");
// output file
ofstream output;
output.open(file_name.c_str());
// write random points to the file
for (int i=0 ; i < nb ; i++) {
output << *in_disk << std::endl;
in_disk++;
}
output.close();
std::cout << "file name: " << file_name << std::endl;
std::cout << "Done." << std::endl;
return 0;
}

View File

@ -0,0 +1,45 @@
#include <fstream>
// CGAL headers
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef CGAL::Delaunay_triangulation_2<K> Dt;
int main()
{
CGAL::Timer timer;
std::vector<Point_2> pts;
std::ifstream f("points.cin");
Point_2 p;
while(f >> p) {
pts.push_back(p);
}
f.close();
timer.start();
Dt dt = Dt();
dt.insert(pts.begin(), pts.end());
timer.stop();
std::cout << "R^2" << std::endl;
std::cout << "Number of points: " << dt.number_of_vertices() << std::endl;
std::cout << "Time: " << timer.time() << std::endl;
timer.reset();
return 0;
}

View File

@ -0,0 +1,51 @@
#include <fstream>
// CGAL headers
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_hyperbolic_triangulation_2.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef K::Point_2 Point_2;
typedef K::FT FT;
typedef CGAL::Delaunay_hyperbolic_triangulation_2<Gt> HDt;
int main()
{
CGAL::Timer timer;
std::vector<Point_2> pts;
std::ifstream f("points.cin");
Point_2 p;
while(f >> p) {
pts.push_back(p);
}
f.close();
// Radius of the Poincare Disk
FT r = 100;
timer.start();
HDt hdt = HDt(Gt(r));
hdt.insert(pts.begin(), pts.end());
timer.stop();
std::cout << "H^2" << std::endl;
std::cout << "Number of points: " << hdt.number_of_vertices() << std::endl;
std::cout << "Time: " << timer.time() << std::endl;
return 0;
}

View File

@ -0,0 +1,51 @@
#include <fstream>
// CGAL headers
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_hyperbolic_triangulation_2.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Timer.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef K::Point_2 Point_2;
typedef K::FT FT;
typedef CGAL::Delaunay_hyperbolic_triangulation_2<Gt> HDt;
int main()
{
CGAL::Timer timer;
std::vector<Point_2> pts;
std::ifstream f("points.cin");
Point_2 p;
while(f >> p) {
pts.push_back(p);
}
f.close();
// Radius of the Poincare Disk
FT r = 100;
timer.start();
HDt hdt = HDt(Gt(r));
hdt.insert2(pts.begin(), pts.end());
timer.stop();
std::cout << "H^2" << std::endl;
std::cout << "Number of points: " << hdt.number_of_vertices() << std::endl;
std::cout << "Time: " << timer.time() << std::endl;
return 0;
}

View File

@ -0,0 +1,30 @@
#include <fstream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
#include <CGAL/Triangulation_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_hyperbolic_traits_2<K> Gt;
typedef CGAL::Triangulation_2<Gt> Triangulation;
typedef Triangulation::Vertex_circulator Vertex_circulator;
typedef Triangulation::Point Point;
int main() {
std::ifstream in("/Users/mbogdano/Projects/Hyperbolic_triangulation_2/examples/Hyperbolic_triangulation_2/data/triangulation.cin");
std::istream_iterator<Point> begin(in);
std::istream_iterator<Point> end;
Triangulation t;
t.insert(begin, end);
Vertex_circulator vc = t.incident_vertices(t.infinite_vertex()),
done(vc);
if (vc != 0) {
do { std::cout << vc->point() << std::endl;
}while(++vc != done);
}
return 0;
}

View File

@ -0,0 +1,674 @@
// 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 a 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;
typedef typename Geom_traits::Triangulation_euclidean_traits_2 Euclidean_geom_traits;
/*
#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();
std::vector<Point> points (first, last);
spatial_sort (points.begin(), points.end(), geom_traits());
Face_handle f;
for (typename std::vector<Point>::const_iterator p = points.begin(), end = points.end();
p != end; ++p)
f = insert (*p, 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 of 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 start = Base::infinite_face();
// mark it as visited
visited_faces.insert(start);
// put the element whom neighbors we are going to explore.
backtrack.push(start);
// test whether a face is finite invisible or not
Mark_face test(*this);
Face_handle current, 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;
Face_handle f = v->face();
Face_handle next;
int i;
Face_handle start(f);
do {
i = f->index(v);
next = f->neighbor(ccw(i)); // turn ccw around v
mark_face(f);
f = next;
} while(next != start);
return;
}
template<class Mark_face_test>
void mark_face(const Face_handle& f, const Mark_face_test& test) const
{
if(has_infinite_vertex(f)) {
return;
}
f->info() = test(f);
}
void mark_face(const Face_handle& f) const
{
Mark_face test(*this);
mark_face(f, test);
}
class Mark_face
{
public:
typedef typename Gt::Circle_2 Circle_2;
Mark_face(const Self& tr) :
_tr(tr)
{}
Face_info operator ()(const Face_handle& f) const
{
Face_info info;
if(_tr.has_infinite_vertex(f)) {
return info;
}
construct_circumscribing_circle(f);
if (intersection_with_circle_at_infinity()) {
info.set_finite_invisible(true);
info.set_invisible_edge(find_invisible_edge(f));
return info;
}
return info;
}
private:
void construct_circumscribing_circle(const Face_handle& f) const
{
//assert(_tr.has_infinite_vertex(f));
Point p1 = f->vertex(0)->point();
Point p2 = f->vertex(1)->point();
Point p3 = f->vertex(2)->point();
_circle = Circle_2(p1, p2, p3);
}
bool intersection_with_circle_at_infinity() const
{
const Circle_2& unit_circle = _tr.geom_traits().unit_circle();
return CGAL::do_intersect(unit_circle, _circle);
}
// assume that the circumscribing circle of a given face intersects
// the circle at infinity
unsigned char find_invisible_edge(const Face_handle& f) const
{
typedef Euclidean_geom_traits Egt;
typedef typename Egt::Construct_circumcenter_2 Construct_circumcenter_2;
typedef typename Egt::Direction_2 Direction_2;
assert(!_tr.has_infinite_vertex(f));
Point p0 = f->vertex(0)->point();
Point p1 = f->vertex(1)->point();
Point p2 = f->vertex(2)->point();
Point c = _circle.center();
Direction_2 d0(p0.x()-c.x(), p0.y()-c.y());
Direction_2 d1(p1.x()-c.x(), p1.y()-c.y());
Direction_2 d2(p2.x()-c.x(), p2.y()-c.y());
Direction_2 d(c.x(), c.y());
if(d.counterclockwise_in_between(d0, d1)) {
return 2;
}
if(d.counterclockwise_in_between(d1, d2)) {
return 0;
}
return 1;
}
Mark_face(const Mark_face&);
Mark_face& operator= (const Mark_face&);
mutable Circle_2 _circle;
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);
}
};
} //namespace CGAL
#endif // CGAL_DELAUNAY_HYPERBOLIC_TRIANGULATION_2_H

View File

@ -0,0 +1,103 @@
// Copyright (c) 2011 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://mbogdanov@scm.gforge.inria.fr/svn/cgal/trunk/Triangulation_2/include/CGAL/Triangulation_hyperbolic_traits_2.h $
// $Id: Hyperboloic_isometry_2.h 57323 2010-07-05 10:07:39Z sloriot $
//
//
// Author(s) : Mikhail Bogdanov
#ifndef CGAL_HYPERBOLIC_ISOMETRY_2_H
#define CGAL_HYPERBOLIC_ISOMETRY_2_H
#include <complex>
#include <CGAL/number_utils.h>
namespace CGAL {
/*
z -> (m*z + n)/(conj(n)*z + conj(m))
*/
template<class Gt>
class Hyperbolic_isometry_2
{
public:
typedef Gt Geom_traits;
typedef typename Gt::FT FT;
typedef typename Gt::Point Point;
typedef std::complex<FT> complex;
Hyperbolic_isometry_2(const complex& m = complex(1, 0), const complex& n = complex(0, 0))
: m_(m), n_(n)
{
}
~Hyperbolic_isometry_2()
{
}
complex DoAction(const complex& z) const
{
return (m_*z + n_)/(std::conj(n_)*z + std::conj(m_));
}
Point DoAction(const Point& p) const
{
complex z = complex(p.x(), p.y());
complex result = DoAction(z);
return Point(result.real(), result.imag());
}
Hyperbolic_isometry_2 inverse() const
{
return Hyperbolic_isometry_2(-std::conj(m_), n_);
}
Hyperbolic_isometry_2 operator * (const Hyperbolic_isometry_2& other) const
{
return Hyperbolic_isometry_2(m_*other.m_ + n_*std::conj(other.n_), m_*other.n_ + n_*std::conj(other.m_));
}
void file_output(std::ostream& os) const
{
os << m_ << " " << n_ << std::endl;
}
complex m() const
{
return m_;
}
complex n() const
{
return n_;
}
private:
complex m_;
complex n_;
};
template <class Gt>
std::ostream&
operator<<(std::ostream& os, const Hyperbolic_isometry_2<Gt> &isometry)
{
isometry.file_output(os);
return os;
}
} // namespace CGAL
#endif // CGAL_HYPERBOLIC_ISOMETRY_2_H

View File

@ -0,0 +1,99 @@
// Copyright (c) 2011 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://mbogdanov@scm.gforge.inria.fr/svn/cgal/trunk/Triangulation_2/include/CGAL/Triangulation_hyperbolic_traits_2.h $
// $Id: Triangulation_hyperbolic_traits_2.h 57323 2010-07-05 10:07:39Z sloriot $
//
//
// Author(s) : Mikhail Bogdanov
#ifndef CGAL_HYPERBOLIC_PAINTER_OSTREAM_H
#define CGAL_HYPERBOLIC_PAINTER_OSTREAM_H
#include <CGAL/Qt/PainterOstream.h>
#include <CGAL/Triangulation_hyperbolic_traits_2.h>
namespace CGAL{
namespace Qt {
template <typename K>
class PainterOstream<Triangulation_hyperbolic_traits_2<K> > : public PainterOstream<K> {
public:
typedef PainterOstream<K> Base;
typedef PainterOstream<Triangulation_hyperbolic_traits_2<K> > Self;
typedef Triangulation_hyperbolic_traits_2<K> Gt;
private:
typedef typename Gt::Segment_2 Segment_2;
typedef typename Gt::Line_segment_2 Line_segment_2;
typedef typename Gt::Arc_2 Arc_2;
//typedef typename Gt::Line_2 Line_2;
typedef typename K::Point_2 Point_2;
typedef typename K::Circle_2 Circle_2;
public:
PainterOstream(QPainter* p, QRectF rect = QRectF())
: Base(p, rect), qp(p), convert(rect) {}
using Base::operator <<;
PainterOstream& operator << (const Segment_2& s)
{
if(const Line_segment_2* line_segment = boost::get<Line_segment_2>(&s)){
operator << (*line_segment);
return *this;
}
if(const Arc_2* arc = boost::get<Arc_2>(&s)){
const Circle_2& circle = arc->get<0>();
const Point_2& center = circle.center();
const Point_2& source = arc->get<1>();
const Point_2& target = arc->get<2>();
double asource = std::atan2( -to_double(source.y() - center.y()),
to_double(source.x() - center.x()));
double atarget = std::atan2( -to_double(target.y() - center.y()),
to_double(target.x() - center.x()));
std::swap(asource, atarget);
double aspan = atarget - asource;
if(aspan < 0.)
aspan += 2 * CGAL_PI;
const double coeff = 180*16/CGAL_PI;
this->qp->drawArc(this->convert(circle.bbox()),
(int)(asource * coeff),
(int)(aspan * coeff));
}
return *this;
}
private:
// ToDo: These objects must be deleted
// Copies of these objects are in the base class.
// We need access to the copies in the base class.
QPainter* qp;
Converter<K> convert;
};
} //namespace Qt
} //namespace CGAL
#endif // CGAL_HYPERBOLIC_PAINTER_OSTREAM_H

View File

@ -0,0 +1,309 @@
// Copyright (c) 2008 GeometryFactory Sarl (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/trunk/GraphicsView/include/CGAL/Qt/TriangulationGraphicsItem.h $
// $Id: TriangulationGraphicsItem.h 61414 2011-02-24 16:36:04Z sloriot $
//
//
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
#ifndef CGAL_QT_TRIANGULATION_GRAPHICS_ITEM_H
#define CGAL_QT_TRIANGULATION_GRAPHICS_ITEM_H
#include <CGAL/Bbox_2.h>
#include <CGAL/apply_to_range.h>
#include <CGAL/Qt/PainterOstream.h>
#include <CGAL/Qt/GraphicsItem.h>
#include <CGAL/Qt/Converter.h>
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
namespace CGAL {
namespace Qt {
template <typename T>
class TriangulationGraphicsItem : public GraphicsItem
{
typedef typename T::Geom_traits Geom_traits;
public:
TriangulationGraphicsItem(T* t_);
void modelChanged();
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void operator()(typename T::Face_handle fh);
const QPen& verticesPen() const
{
return vertices_pen;
}
const QPen& edgesPen() const
{
return edges_pen;
}
void setVerticesPen(const QPen& pen)
{
vertices_pen = pen;
}
void setEdgesPen(const QPen& pen)
{
edges_pen = pen;
}
bool visibleVertices() const
{
return visible_vertices;
}
void setVisibleVertices(const bool b)
{
visible_vertices = b;
update();
}
bool visibleEdges() const
{
return visible_edges;
}
void setVisibleEdges(const bool b)
{
visible_edges = b;
update();
}
protected:
virtual void drawAll(QPainter *painter);
void paintVertices(QPainter *painter);
void paintOneVertex(const typename T::Point& point);
virtual void paintVertex(typename T::Vertex_handle vh);
void updateBoundingBox();
T * t;
QPainter* m_painter;
PainterOstream<Geom_traits> painterostream;
typename T::Vertex_handle vh;
typename T::Point p;
CGAL::Bbox_2 bb;
bool bb_initialized;
QRectF bounding_rect;
QPen vertices_pen;
QPen edges_pen;
bool visible_edges;
bool visible_vertices;
};
template <typename T>
TriangulationGraphicsItem<T>::TriangulationGraphicsItem(T * t_)
: t(t_), painterostream(0),
bb(0,0,0,0), bb_initialized(false),
visible_edges(true), visible_vertices(true)
{
setVerticesPen(QPen(::Qt::red, 3.));
if(t->number_of_vertices() == 0){
this->hide();
}
updateBoundingBox();
setZValue(3);
}
template <typename T>
QRectF
TriangulationGraphicsItem<T>::boundingRect() const
{
return bounding_rect;
}
template <typename T>
void
TriangulationGraphicsItem<T>::operator()(typename T::Face_handle fh)
{
if(visible_edges) {
for (int i=0; i<3; i++) {
if (fh < fh->neighbor(i) || t->is_infinite(fh->neighbor(i))){
m_painter->setPen(this->edgesPen());
painterostream << t->segment(fh,i);
}
}
}
if(visible_vertices) {
for (int i=0; i<3; i++) {
paintVertex(fh->vertex(i));
}
}
}
template <typename T>
void
TriangulationGraphicsItem<T>::drawAll(QPainter *painter)
{
painterostream = PainterOstream<Geom_traits>(painter);
if(visibleEdges()) {
for(typename T::Finite_edges_iterator eit = t->finite_edges_begin();
eit != t->finite_edges_end();
++eit){
painterostream << t->segment(*eit);
}
}
paintVertices(painter);
}
template <typename T>
void
TriangulationGraphicsItem<T>::paintVertices(QPainter *painter)
{
if(visibleVertices()) {
Converter<Geom_traits> convert;
painter->setPen(verticesPen());
QMatrix matrix = painter->matrix();
painter->resetMatrix();
for(typename T::Finite_vertices_iterator it = t->finite_vertices_begin();
it != t->finite_vertices_end();
it++){
// draw vertices with color storing in their info
if(it->info().getColor() == 0) {
painter->setPen(QPen(::Qt::red, 3.));
}
if(it->info().getColor() == 1) {
painter->setPen(QPen(::Qt::green, 3.));
}
//
QPointF point = matrix.map(convert(it->point()));
painter->drawPoint(point);
}
}
}
template <typename T>
void
TriangulationGraphicsItem<T>::paintOneVertex(const typename T::Point& point)
{
Converter<Geom_traits> convert;
m_painter->setPen(this->verticesPen());
QMatrix matrix = m_painter->matrix();
m_painter->resetMatrix();
m_painter->drawPoint(matrix.map(convert(point)));
m_painter->setMatrix(matrix);
}
template <typename T>
void
TriangulationGraphicsItem<T>::paintVertex(typename T::Vertex_handle vh)
{
Converter<Geom_traits> convert;
m_painter->setPen(this->verticesPen());
QMatrix matrix = m_painter->matrix();
m_painter->resetMatrix();
m_painter->drawPoint(matrix.map(convert(vh->point())));
m_painter->setMatrix(matrix);
}
template <typename T>
void
TriangulationGraphicsItem<T>::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget * /*widget*/)
{
painter->setPen(this->edgesPen());
// painter->drawRect(boundingRect());
if ( t->dimension()<2 || option->exposedRect.contains(boundingRect()) ) {
drawAll(painter);
} else {
m_painter = painter;
painterostream = PainterOstream<Geom_traits>(painter);
CGAL::apply_to_range (*t,
typename T::Point(option->exposedRect.left(),
option->exposedRect.bottom()),
typename T::Point(option->exposedRect.right(),
option->exposedRect.top()),
*this);
}
}
// We let the bounding box only grow, so that when vertices get removed
// the maximal bbox gets refreshed in the GraphicsView
template <typename T>
void
TriangulationGraphicsItem<T>::updateBoundingBox()
{
prepareGeometryChange();
if(t->number_of_vertices() == 0){
bb = Bbox_2(0,0,0,0);
bb_initialized = false;
return;
} else if(! bb_initialized){
bb = t->finite_vertices_begin()->point().bbox();
bb_initialized = true;
}
if(t->dimension() <2){
for(typename T::Finite_vertices_iterator it = t->finite_vertices_begin();
it != t->finite_vertices_end();
++it){
bb = bb + it->point().bbox();
}
} else {
typename T::Vertex_handle inf = t->infinite_vertex();
typename T::Vertex_circulator vc = t->incident_vertices(inf), done(vc);
do {
bb = bb + vc->point().bbox();
++vc;
} while(vc != done);
}
bounding_rect = QRectF(bb.xmin(),
bb.ymin(),
bb.xmax()-bb.xmin(),
bb.ymax()-bb.ymin());
}
template <typename T>
void
TriangulationGraphicsItem<T>::modelChanged()
{
if((t->number_of_vertices() == 0) ){
this->hide();
} else if((t->number_of_vertices() > 0) && (! this->isVisible())){
this->show();
}
updateBoundingBox();
update();
}
} // namespace Qt
} // namespace CGAL
#endif // CGAL_QT_TRIANGULATION_GRAPHICS_ITEM_H

View File

@ -0,0 +1,424 @@
// 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://mbogdanov@scm.gforge.inria.fr/svn/cgal/trunk/Triangulation_2/include/CGAL/Triangulation_hyperbolic_traits_2.h $
// $Id: Triangulation_hyperbolic_traits_2.h 57323 2010-07-05 10:07:39Z sloriot $
//
//
// Author(s) : Mikhail Bogdanov
#ifndef CGAL_TRIANGULATION_HYPERBOLIC_TRAITS_2_H
#define CGAL_TRIANGULATION_HYPERBOLIC_TRAITS_2_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>
#include <CGAL/Regular_triangulation_filtered_traits_2.h>
#include "boost/tuple/tuple.hpp"
#include "boost/variant.hpp"
namespace CGAL {
template < class R >
class Triangulation_hyperbolic_traits_2 {
public:
typedef Triangulation_hyperbolic_traits_2<R> Self;
typedef R Triangulation_euclidean_traits_2;
typedef R Rep;
typedef typename R::RT RT;
typedef typename R::Point_2 Point_2;
typedef typename R::Vector_2 Vector_2;
typedef typename R::Triangle_2 Triangle_2;
typedef typename R::Line_2 Line_2;
typedef typename R::Ray_2 Ray_2;
typedef typename R::Less_x_2 Less_x_2;
typedef typename R::Less_y_2 Less_y_2;
typedef typename R::Compare_x_2 Compare_x_2;
typedef typename R::Compare_y_2 Compare_y_2;
typedef typename R::Orientation_2 Orientation_2;
typedef typename R::Side_of_oriented_circle_2 Side_of_oriented_circle_2;
typedef typename R::Construct_bisector_2 Construct_bisector_2;
typedef typename R::Compare_distance_2 Compare_distance_2;
typedef typename R::Construct_triangle_2 Construct_triangle_2;
typedef typename R::Construct_direction_2 Construct_direction_2;
typedef typename R::Angle_2 Angle_2;
typedef typename R::Construct_midpoint_2 Construct_midpoint_2;
typedef typename R::Compute_squared_distance_2 Compute_squared_distance_2;
typedef typename R::Iso_rectangle_2 Iso_rectangle_2;
typedef typename R::Circle_2 Circle_2;
typedef boost::tuple<Circle_2, Point_2, Point_2> Arc_2;
typedef typename R::Segment_2 Line_segment_2;
typedef boost::variant<Arc_2, Line_segment_2> Segment_2;
typedef typename R::Line_2 Euclidean_line_2;
private:
// Poincaré disk
const Circle_2 _unit_circle;
public:
const Circle_2& unit_circle() const
{
return _unit_circle;
}
Angle_2
angle_2_object() const
{ return Angle_2(); }
Compute_squared_distance_2
compute_squared_distance_2_object() const
{ return Compute_squared_distance_2(); }
class Construct_segment_2
{
typedef typename CGAL::Regular_triangulation_filtered_traits_2<R> Regular_geometric_traits_2;
typedef typename Regular_geometric_traits_2::Construct_weighted_circumcenter_2 Construct_weighted_circumcenter_2;
typedef typename Regular_geometric_traits_2::Weighted_point_2 Weighted_point_2;
typedef typename Regular_geometric_traits_2::Bare_point Bare_point;
public:
Construct_segment_2(const Circle_2& c) : _unit_circle(c)
{
}
Segment_2 operator()(const Point_2& p, const Point_2& q) const
{
typedef typename R::Collinear_2 Collinear_2;
if(Collinear_2()(p, q, _unit_circle.center())){
return Line_segment_2(p, q);
}
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);
Circle_2 circle( center, radius);
assert(circle.has_on_boundary(p) && circle.has_on_boundary(q));
if(Orientation_2()(p, q, center) == LEFT_TURN) {
return Arc_2(circle, p, q);
}
return Arc_2(circle, q, p);
}
private:
const Circle_2& _unit_circle;
};
Construct_segment_2
construct_segment_2_object() const
{
return Construct_segment_2(_unit_circle);
}
class Construct_circumcenter_2
{
public:
Construct_circumcenter_2(const Circle_2& c) : _unit_circle(c)
{}
// TODO: improve this function
Point_2 operator()(Point_2 p, Point_2 q, Point_2 r)
{
assert(_unit_circle.bounded_side(p) == ON_BOUNDED_SIDE);
assert(_unit_circle.bounded_side(q) == ON_BOUNDED_SIDE);
assert(_unit_circle.bounded_side(r) == ON_BOUNDED_SIDE);
Circle_2 circle(p, q, r);
// circle must be inside the unit one
assert(CGAL::do_intersect(_unit_circle, circle) == false);
if(circle.center() <= _unit_circle.center() && circle.center() >= _unit_circle.center()){
return _unit_circle.center();
}
FT x0 = circle.center().x(), y0 = circle.center().y();
// a*alphaˆ2 + b*alpha + c = 0;
FT a = x0*x0 + y0*y0;
FT b = a - circle.squared_radius() + _unit_circle.squared_radius();
FT c = _unit_circle.squared_radius();
FT D = b*b - 4*a*c;
FT alpha = (b - CGAL::sqrt(to_double(D)))/(2*a);
Point_2 center(x0*alpha, y0*alpha);
if(!circle.has_on_bounded_side(center))
{ std::cout << "Center does not belong to the pencil of spheres!!!" << std::endl;} ;
return center;
}
private:
const Circle_2 _unit_circle;
};
Construct_circumcenter_2
construct_circumcenter_2_object()
{
Construct_circumcenter_2(_unit_circle);
}
Construct_midpoint_2
construct_midpoint_2_object() const
{ return Construct_midpoint_2(); }
//for natural_neighbor_coordinates_2
typedef typename R::FT FT;
typedef typename R::Equal_x_2 Equal_x_2;
typedef typename R::Compute_area_2 Compute_area_2;
Compute_area_2 compute_area_2_object () const
{
return Compute_area_2();
}
// for compatibility with previous versions
typedef Point_2 Point;
typedef Segment_2 Segment;
typedef Triangle_2 Triangle;
typedef Ray_2 Ray;
//typedef Line_2 Line;
Triangulation_hyperbolic_traits_2() :
_unit_circle(Point_2(0, 0), 100*100)
{}
Triangulation_hyperbolic_traits_2(FT r) :
_unit_circle(Point_2(0, 0), r*r)
{}
Triangulation_hyperbolic_traits_2(const Triangulation_hyperbolic_traits_2 & other) :
_unit_circle(other._unit_circle)
{}
Triangulation_hyperbolic_traits_2 &operator=
(const Triangulation_hyperbolic_traits_2 &)
{ return *this;}
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_circumcenter_2
construct_circumcenter_2_object() const
{return Construct_circumcenter_2(_unit_circle);}
class Construct_hyperbolic_bisector_2
{
public:
Construct_hyperbolic_bisector_2(const Circle_2& unit_circle) :
_unit_circle(unit_circle) {}
Segment_2 operator()(Point_2 p, Point_2 q) const
{
// If two points are almost of the same distance to the origin, then
// the bisector is supported by the circle of huge radius etc.
// This circle is computed inexactly.
// At present time, in this case the bisector is supported by the line.
Compute_squared_distance_2 dist = Compute_squared_distance_2();
Point origin = _unit_circle.center();
FT dif = dist(origin, p) - dist(origin, q);
FT eps = 0.0000000001;
// Bisector is straight in euclidean sense
if(dif > -eps && dif < eps){
// ideally
//if(Compare_distance_2()(_unit_circle.center(), p, q) == EQUAL){
// TODO: calling R::Construct_bisector
Euclidean_line_2 l = Construct_bisector_2()(p, q);
// compute the ending points
std::pair<Point_2, Point_2> points = find_intersection(l);
// TODO: improve
Vector_2 v(points.first, points.second);
if(v*l.to_vector() > 0){
return Line_segment_2(points.first, points.second);
}
return Line_segment_2(points.second, points.first);
}
Circle_2 c = construct_supporting_circle(p, q);
// compute the ending points
std::pair<Point_2, Point_2> points = find_intersection(c);
if(Orientation_2()(points.first, points.second, c.center()) == LEFT_TURN) {
return Arc_2(c, points.first, points.second);
}
return Arc_2(c, points.second, points.first);
}
private:
// The cirle belongs to the pencil with limit points p and q
Circle_2 construct_supporting_circle(Point_2 p, Point_2 q) const
{
// p, q are zero-circles
// (x, y, xˆ2 + yˆ2 - rˆ2) = alpha*(xp, yp, xpˆ2 + ypˆ2) + (1-alpha)*(xq, yq, xqˆ2 + yqˆ2)
// xˆ2 + yˆ2 - rˆ2 = Rˆ2, where R - is a radius of the given unit circle
FT op = p.x()*p.x() + p.y()*p.y();
FT oq = q.x()*q.x() + q.y()*q.y();
FT alpha = (_unit_circle.squared_radius() - oq) / (op - oq);
FT x = alpha*p.x() + (1-alpha)*q.x();
FT y = alpha*p.y() + (1-alpha)*q.y();
FT radius = x*x + y*y - _unit_circle.squared_radius();
//improve
typename R::Line_2 l = typename R::Construct_bisector_2()(p, q);
Point_2 middle = Construct_midpoint_2()(p, q);
Point_2 temp = middle + l.to_vector();
if(Orientation_2()(middle, temp, Point_2(x, y)) == ON_POSITIVE_SIDE){
return Circle_2(Point_2(x, y), radius, CLOCKWISE);
}
return Circle_2(Point_2(x, y), radius, COUNTERCLOCKWISE);
}
// Find intersection of an input circle orthogonal to the Poincaré disk
// and the circle representing this disk
// TODO: sqrt(to_double()?)
std::pair<Point_2, Point_2> find_intersection(Circle_2& circle) const
{
FT x = circle.center().x(), y = circle.center().y();
// axˆ2 + 2bˆx + c = 0;
FT a = x*x + y*y;
FT b = -_unit_circle.squared_radius() * x;
FT c = _unit_circle.squared_radius()*_unit_circle.squared_radius() - _unit_circle.squared_radius()*y*y;
assert(b*b - a*c > 0);
FT D = CGAL::sqrt(to_double(b*b - a*c));
FT x1 = (-b - D)/a;
FT x2 = (-b + D)/a;
FT y1 = (_unit_circle.squared_radius() - x1*x)/y;
FT y2 = (_unit_circle.squared_radius() - x2*x)/y;
return std::make_pair(Point_2(x1, y1), Point_2(x2, y2));
}
// Find intersection of an input line orthogonal to the Poincaré disk
// and the circle representing this disk
// TODO: sqrt(to_double()?)
std::pair<Point_2, Point_2> find_intersection(Euclidean_line_2& l) const
{
typedef typename R::Vector_2 Vector_2;
Vector_2 v = l.to_vector();
// normalize the vector
FT squared_coeff = _unit_circle.squared_radius()/v.squared_length();
FT coeff = CGAL::sqrt(to_double(squared_coeff));
Point_2 p1(coeff*v.x(), coeff*v.y());
Point_2 p2(-p1.x(), -p1.y());
return std::make_pair(p1, p2);
}
private:
const Circle_2 _unit_circle;
};
Construct_hyperbolic_bisector_2
construct_hyperbolic_bisector_2_object() const
{ return Construct_hyperbolic_bisector_2(_unit_circle);}
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();}
class Construct_ray_2
{
public:
Construct_ray_2(Circle_2 c) :
_unit_circle(c) {}
Segment_2 operator()(Point_2 p, Segment_2 l) const
{
if(typename R::Segment_2* s = boost::get<typename R::Segment_2>(&l)){
return operator()(p, *s);
}
if(Arc_2* arc = boost::get<Arc_2>(&l)){
if(arc->get<0>().orientation() == CLOCKWISE){
arc->get<1>() = p;
return *arc;
}
arc->get<2>() = p;
return *arc;
}
assert(false);
return Segment_2();
}
Segment_2 operator()(Point_2 p, typename R::Segment_2 s) const
{
return typename R::Segment_2(p, s.target());
}
private:
const Circle_2 _unit_circle;
};
Construct_ray_2 construct_ray_2_object() const
{return Construct_ray_2(_unit_circle);}
};
} //namespace CGAL
#endif // CGAL_TRIANGULATION_HYPERBOLIC_TRAITS_2_H