Misc code cleaning

This commit is contained in:
Mael Rouxel-Labbé 2025-03-15 00:01:43 +01:00
parent c672ed6fc1
commit 33ed6b6482
31 changed files with 1090 additions and 866 deletions

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.12...3.29) cmake_minimum_required(VERSION 3.12...3.31)
project( Triangulation_on_hyperbolic_surface_2_Demo ) project( Triangulation_on_hyperbolic_surface_2_Demo )
@ -9,35 +9,25 @@ include_directories(${CMAKE_BINARY_DIR})
# Instruct CMake to run moc automatically when needed. # Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
# CGAL and its components # CGAL and its components
find_package(CGAL REQUIRED COMPONENTS Core Qt6) find_package(CGAL REQUIRED COMPONENTS Core Qt6)
find_package(Qt6 QUIET COMPONENTS Widgets) find_package(Qt6 QUIET COMPONENTS Widgets)
if ( NOT CGAL_FOUND ) if ( NOT CGAL_FOUND )
message(STATUS "This project requires the CGAL library, and will not be compiled.") message(STATUS "This project requires the CGAL library, and will not be compiled.")
return() return()
endif() endif()
if ( NOT CGAL_Qt6_FOUND OR NOT Qt6_FOUND) if ( NOT CGAL_Qt6_FOUND OR NOT Qt6_FOUND)
message(STATUS "This project requires the Qt6 library, and will not be compiled.") message(STATUS "This project requires the Qt6 library, and will not be compiled.")
return() return()
endif() endif()
# Boost and its components # Boost and its components
find_package( Boost REQUIRED ) find_package( Boost REQUIRED )
if ( NOT Boost_FOUND ) if ( NOT Boost_FOUND )
message(STATUS "This project requires the Boost library, and will not be compiled.") message(STATUS "This project requires the Boost library, and will not be compiled.")
return() return()
endif() endif()
# ui files, created with Qt Designer # ui files, created with Qt Designer

View File

@ -2,6 +2,7 @@
#include <CGAL/Exact_rational.h> #include <CGAL/Exact_rational.h>
#include <CGAL/Simple_cartesian.h> #include <CGAL/Simple_cartesian.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h> #include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <CGAL/Hyperbolic_surface_traits_2.h> #include <CGAL/Hyperbolic_surface_traits_2.h>
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h> #include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
@ -20,7 +21,8 @@ typedef Triangulation_on_hyperbolic_surface_2<Traits> Triangul
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv){ int main(int argc, char** argv)
{
// 1. Generate the triangulation // 1. Generate the triangulation
Factory factory; Factory factory;
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(time(NULL)); Domain domain = factory.make_hyperbolic_fundamental_domain_g2(time(NULL));

View File

@ -12,7 +12,9 @@
#include "window.h" #include "window.h"
DemoWindowItem::DemoWindowItem() : CGAL::Qt::GraphicsItem(){ DemoWindowItem::DemoWindowItem()
: CGAL::Qt::GraphicsItem()
{
// Clear // Clear
_edges.clear(); _edges.clear();
@ -28,9 +30,15 @@ DemoWindowItem::DemoWindowItem() : CGAL::Qt::GraphicsItem(){
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DemoWindowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ void DemoWindowItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
// 1. Draw the poincaré disk // 1. Draw the poincaré disk
QRectF circle_rect = QRectF(-_poincare_disk_radius_in_pixels-3, -_poincare_disk_radius_in_pixels-3, 2*_poincare_disk_radius_in_pixels+6, 2*_poincare_disk_radius_in_pixels+6); QRectF circle_rect = QRectF(-_poincare_disk_radius_in_pixels-3,
-_poincare_disk_radius_in_pixels-3,
2*_poincare_disk_radius_in_pixels+6,
2*_poincare_disk_radius_in_pixels+6);
painter->setPen(_poincare_disk_pen); painter->setPen(_poincare_disk_pen);
painter->setBrush(QBrush()); painter->setBrush(QBrush());
painter->drawEllipse(circle_rect); painter->drawEllipse(circle_rect);
@ -38,26 +46,32 @@ void DemoWindowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *op
// 2. Draw the edges // 2. Draw the edges
painter->setBrush(QBrush()); painter->setBrush(QBrush());
painter->setPen(_edges_pen); painter->setPen(_edges_pen);
for (int i=0; i<_edges.size(); i++){ for (int i=0; i<_edges.size(); i++) {
draw_edge(painter, _edges[i].first, _edges[i].second); draw_edge(painter, _edges[i].first, _edges[i].second);
} }
} }
QRectF DemoWindowItem::boundingRect() const{ QRectF DemoWindowItem::boundingRect() const {
return QRectF(-_poincare_disk_radius_in_pixels-3, -_poincare_disk_radius_in_pixels-3, _poincare_disk_radius_in_pixels+6, _poincare_disk_radius_in_pixels+6); return QRectF(-_poincare_disk_radius_in_pixels-3,
-_poincare_disk_radius_in_pixels-3,
_poincare_disk_radius_in_pixels+6,
_poincare_disk_radius_in_pixels+6);
} }
void DemoWindowItem::modelChanged(){} // Only used by Qt : we don't need to fill it void DemoWindowItem::modelChanged() {} // Only used by Qt : we don't need to fill it
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DemoWindowItem::draw_triangulation(Triangulation& triangulation){ void DemoWindowItem::draw_triangulation(Triangulation& triangulation)
typedef std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> RealizationVector; {
typedef std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,
Point, Point, Point> > RealizationVector;
RealizationVector realized_triangles; RealizationVector realized_triangles;
realized_triangles = triangulation.lift(); realized_triangles = triangulation.lift();
Point point_1, point_2, point_3; Point point_1, point_2, point_3;
for (typename RealizationVector::iterator it = realized_triangles.begin(); it != realized_triangles.end(); ++it){ for (typename RealizationVector::iterator it = realized_triangles.begin(); it != realized_triangles.end(); ++it) {
point_1 = std::get<1>(*it); point_1 = std::get<1>(*it);
point_2 = std::get<2>(*it); point_2 = std::get<2>(*it);
point_3 = std::get<3>(*it); point_3 = std::get<3>(*it);
@ -70,7 +84,8 @@ void DemoWindowItem::draw_triangulation(Triangulation& triangulation){
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DemoWindowItem::draw_point(QPainter* painter, Point position){ void DemoWindowItem::draw_point(QPainter* painter, Point position)
{
// First convert the point in doubles, well-scaled // First convert the point in doubles, well-scaled
double point_x = _poincare_disk_radius_in_pixels * CGAL::to_double(position.x()); double point_x = _poincare_disk_radius_in_pixels * CGAL::to_double(position.x());
double point_y = _poincare_disk_radius_in_pixels * CGAL::to_double(position.y()); double point_y = _poincare_disk_radius_in_pixels * CGAL::to_double(position.y());
@ -78,10 +93,10 @@ void DemoWindowItem::draw_point(QPainter* painter, Point position){
// Then draw a small circle // Then draw a small circle
QRectF circle_rect = QRectF(point_x-1, point_y-1, 3, 3); QRectF circle_rect = QRectF(point_x-1, point_y-1, 3, 3);
painter->drawEllipse(circle_rect); painter->drawEllipse(circle_rect);
} }
void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target){ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target)
{
// First convert the points coordinates to doubles // First convert the points coordinates to doubles
double src_x = CGAL::to_double(source.x()); double src_x = CGAL::to_double(source.x());
@ -91,9 +106,10 @@ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target){
double tar_y = CGAL::to_double(target.y()); double tar_y = CGAL::to_double(target.y());
// 0. If src and tar are too colinear or too close from each other then draw a line // 0. If src and tar are too colinear or too close from each other then draw a line
double determinant = src_x*tar_y - src_y*tar_x; // determinant of the matrix whose columns are the vectors src and tar : indicates colinearity double determinant = src_x*tar_y - src_y*tar_x; // determinant of the matrix whose columns are the vectors src and tar : indicates colinearity
double distance_squared = (src_x-tar_x)*(src_x-tar_x) + (src_y-tar_y)*(src_y-tar_y); double distance_squared = (src_x-tar_x)*(src_x-tar_x) + (src_y-tar_y)*(src_y-tar_y);
if ((std::abs(determinant) < computation_treshold_squared) || (distance_squared < computation_treshold_squared)){ if ((std::abs(determinant) < computation_treshold_squared) || (distance_squared < computation_treshold_squared)) {
// src and tar are too colinear or too close from each other // src and tar are too colinear or too close from each other
draw_line(painter, src_x, src_y, tar_x, tar_y); draw_line(painter, src_x, src_y, tar_x, tar_y);
return; return;
@ -102,7 +118,7 @@ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target){
// 1. Compute the center of the circle supporting the geodesic between src and tar // 1. Compute the center of the circle supporting the geodesic between src and tar
// 1.a Inverse src and tar with respect to the unit circle and find the euclidean midpoints of the segments between respectively // 1.a Inverse src and tar with respect to the unit circle and find the euclidean midpoints of the segments between respectively
// src and it's inversion, and tar and it's inversion // src and its inversion, and tar and its inversion
double src_norm_2 = src_x*src_x + src_y*src_y; // Can't be too close to zero because determinant was not double src_norm_2 = src_x*src_x + src_y*src_y; // Can't be too close to zero because determinant was not
double tar_norm_2 = tar_x*tar_x + tar_y*tar_y; // Can't be too close to zero because determinant was not double tar_norm_2 = tar_x*tar_x + tar_y*tar_y; // Can't be too close to zero because determinant was not
@ -118,10 +134,9 @@ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target){
double tar_mid_x = (tar_x + tar_inv_x) / 2; double tar_mid_x = (tar_x + tar_inv_x) / 2;
double tar_mid_y = (tar_y + tar_inv_y) / 2; double tar_mid_y = (tar_y + tar_inv_y) / 2;
// 1.b Solve a system to find the intersection (center_x, center_y) of the bisectors of the two segments [src, src_inv] and [tar, tar_inv] : // 1.b Solve a system to find the intersection (center_x, center_y) of the bisectors of the two segments [src, src_inv] and [tar, tar_inv]:
// (center_x \\ center y) = (a & b \\ c & d)^{-1} \times (u_x \\ u_y) // (center_x \\ center y) = (a & b \\ c & d)^{-1} \times (u_x \\ u_y)
// 1.b.i define the system // 1.b.i define the system
double a = src_x; double a = src_x;
@ -141,9 +156,10 @@ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target){
draw_arc(painter, src_x, src_y, tar_x, tar_y, center_x, center_y); draw_arc(painter, src_x, src_y, tar_x, tar_y, center_x, center_y);
} }
void DemoWindowItem::draw_line(QPainter* painter,
void DemoWindowItem::draw_line(QPainter* painter, double point_1_x, double point_1_y, double point_2_x, double point_2_y){ double point_1_x, double point_1_y,
double point_2_x, double point_2_y)
{
// Convert to doubles and scale by the radius of the poincaré disk // Convert to doubles and scale by the radius of the poincaré disk
double src_x = _poincare_disk_radius_in_pixels * point_1_x; double src_x = _poincare_disk_radius_in_pixels * point_1_x;
double src_y = _poincare_disk_radius_in_pixels * point_1_y; double src_y = _poincare_disk_radius_in_pixels * point_1_y;
@ -155,9 +171,11 @@ void DemoWindowItem::draw_line(QPainter* painter, double point_1_x, double point
painter->drawLine(line); painter->drawLine(line);
} }
void DemoWindowItem::draw_arc(QPainter* painter,
void DemoWindowItem::draw_arc(QPainter* painter, double point_1_x, double point_1_y, double point_1_x, double point_1_y,
double point_2_x, double point_2_y, double center_x, double center_y){ double point_2_x, double point_2_y,
double center_x, double center_y)
{
// Draws the arc supported by the circle whose center is (center_x, center_y) and whose extremities are src and tar // Draws the arc supported by the circle whose center is (center_x, center_y) and whose extremities are src and tar
// 1. Scale by the radius of the poincaré disk // 1. Scale by the radius of the poincaré disk
@ -183,7 +201,7 @@ void DemoWindowItem::draw_arc(QPainter* painter, double point_1_x, double point_
// If the source and the target are too close from each other (less than 10 pixels) or if the circle is very big then just draw a line // If the source and the target are too close from each other (less than 10 pixels) or if the circle is very big then just draw a line
double dist_sq = (src_x-tar_x)*(src_x-tar_x) + (src_y - tar_y)*(src_y-tar_y); double dist_sq = (src_x-tar_x)*(src_x-tar_x) + (src_y - tar_y)*(src_y-tar_y);
double rad_sq = (xM-xc)*(xM-xc) + (yM-yc)*(yM-yc); double rad_sq = (xM-xc)*(xM-xc) + (yM-yc)*(yM-yc);
if ( (dist_sq < 100) || (rad_sq > 1000 * dist_sq) ){ if ((dist_sq < 100) || (rad_sq > 1000 * dist_sq)) {
QLineF line (src_x, src_y, tar_x, tar_y); QLineF line (src_x, src_y, tar_x, tar_y);
painter->drawLine(line); painter->drawLine(line);
return; return;
@ -211,15 +229,16 @@ void DemoWindowItem::draw_arc(QPainter* painter, double point_1_x, double point_
painter->drawArc(bbox_rect, src_angle*16, sweep_angle*16); painter->drawArc(bbox_rect, src_angle*16, sweep_angle*16);
} }
double DemoWindowItem::deg_angle(double x, double y){ double DemoWindowItem::deg_angle(double x, double y)
{
// To avoid problems when further division by x (ok since x^2 + y^2 not too small) : // To avoid problems when further division by x (ok since x^2 + y^2 not too small) :
if (x*x < computation_treshold_squared){ if (x*x < computation_treshold_squared) {
if (y>0) return 90; if (y>0) return 90;
return -90; return -90;
} }
double angle = 180. * std::atan(y / x) / M_PI; double angle = 180. * std::atan(y / x) / M_PI;
if (x < 0){ if (x < 0) {
return angle + 180.; return angle + 180.;
} }
return angle; return angle;
@ -229,7 +248,8 @@ double DemoWindowItem::deg_angle(double x, double y){
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DemoWindow::DemoWindow() : DemosMainWindow(){ DemoWindow::DemoWindow() : DemosMainWindow()
{
setupUi(this); // Method automatically generated by the ui file and here inherited from Ui::MainWindow. Builds the window and the contents for us... setupUi(this); // Method automatically generated by the ui file and here inherited from Ui::MainWindow. Builds the window and the contents for us...
this->graphicsView->setScene(&_scene); // ... in particular graphicsView is already constructed : we just put our scene in it and then do things within the scene this->graphicsView->setScene(&_scene); // ... in particular graphicsView is already constructed : we just put our scene in it and then do things within the scene
_scene.setItemIndexMethod(QGraphicsScene::NoIndex); _scene.setItemIndexMethod(QGraphicsScene::NoIndex);
@ -241,7 +261,8 @@ DemoWindow::DemoWindow() : DemosMainWindow(){
setWindowTitle("Hyperbolic surfaces triangulation 2 Demo"); setWindowTitle("Hyperbolic surfaces triangulation 2 Demo");
} }
DemoWindowItem& DemoWindow::item(){ DemoWindowItem& DemoWindow::item()
{
return *_item; return *_item;
} }

View File

@ -23,6 +23,7 @@
#include <CGAL/Exact_rational.h> #include <CGAL/Exact_rational.h>
#include <CGAL/Simple_cartesian.h> #include <CGAL/Simple_cartesian.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h> #include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <CGAL/Hyperbolic_surface_traits_2.h> #include <CGAL/Hyperbolic_surface_traits_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
@ -33,13 +34,14 @@ typedef CGAL::Hyperbolic_surface_traits_2<ParentTraits>
typedef Traits::Hyperbolic_point_2 Point; typedef Traits::Hyperbolic_point_2 Point;
typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation; typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation;
class DemoWindowItem : class DemoWindowItem
public CGAL::Qt::GraphicsItem : public CGAL::Qt::GraphicsItem
{ {
Q_OBJECT // Qt macro for Qt objects Q_OBJECT // Qt macro for Qt objects
// (Q_OBJECT does not support templates) // (Q_OBJECT does not support templates)
private: private:
typedef CGAL::Bbox_2 Bbox_2; // "Bounding box" : just a box type used for drawing typedef CGAL::Bbox_2 Bbox_2; // "Bounding box": just a box type used for drawing
// Edges to draw // Edges to draw
std::vector<std::pair<Point,Point>> _edges; std::vector<std::pair<Point,Point>> _edges;
@ -50,7 +52,9 @@ private:
// radius of the poincaré disk // radius of the poincaré disk
const int _poincare_disk_radius_in_pixels = 600; const int _poincare_disk_radius_in_pixels = 600;
// Approximation treshold : used to decide when to simplify a computation (ex : draw a line instead of an arc if an hyperbolic segment is very small)
// Approximation treshold: used to decide when to simplify a computation (ex: draw a line
// instead of an arc if an hyperbolic segment is very small)
const double computation_treshold = 0.001; const double computation_treshold = 0.001;
const double computation_treshold_squared = computation_treshold*computation_treshold; const double computation_treshold_squared = computation_treshold*computation_treshold;
@ -81,11 +85,13 @@ private:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DemoWindow : class DemoWindow
public CGAL::Qt::DemosMainWindow, public Ui::MainWindow : public CGAL::Qt::DemosMainWindow,
public Ui::MainWindow
{ {
Q_OBJECT // Qt macro for Qt objects Q_OBJECT // Qt macro for Qt objects
// (Q_OBJECT does not support templates) // (Q_OBJECT does not support templates)
private: private:
QGraphicsScene _scene; QGraphicsScene _scene;
DemoWindowItem* _item; DemoWindowItem* _item;

View File

@ -1,14 +1,14 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
\cgalModels{ComplexNumber} \cgalModels{ComplexNumber}
\tparam FT is the field type and must be a model of `FieldNumberType`. \tparam FT is the field type and must be a model of `FieldNumberType`.
*/ */
template <class FT> template <class FT>
class Complex_number { class Complex_number {
}; };
}; // namespace CGAL } // namespace CGAL

View File

@ -1,30 +1,34 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
represents a fundamental domain of a closed orientable hyperbolic surface. represents a fundamental domain of a closed orientable hyperbolic surface.
The domain is given as a polygon \f$ P \f$ represented by the list of its vertices in the Poincaré disk model, The domain is given as a polygon \f$ P \f$ represented by the list of its vertices in the Poincaré disk model,
together with a pairing of the sides of \f$ P \f$. together with a pairing of the sides of \f$ P \f$.
The \f$ n \f$-th side of \f$ P \f$ is the side between the \f$ n \f$-th and the \f$ (n+1) \f$-th vertex, where indices are modulo the number of vertices of \f$ P \f$. The \f$ n \f$-th side of \f$ P \f$ is the side between the \f$ n \f$-th and the \f$ (n+1) \f$-th vertex, where indices are modulo the number of vertices of \f$ P \f$.
The side pairings are represented by a list of integers, such that if the \f$ n \f$-th integer of the list is \f$ m \f$, then the \f$ n \f$-th side is paired to the \f$ m \f$-th side. The side pairings are represented by a list of integers, such that if the \f$ n \f$-th integer of the list is \f$ m \f$, then the \f$ n \f$-th side is paired to the \f$ m \f$-th side.
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`. \tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
\sa `Hyperbolic_fundamental_domain_factory_2` \sa `Hyperbolic_fundamental_domain_factory_2`
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_fundamental_domain_2 { class Hyperbolic_fundamental_domain_2
{
public: public:
/// \name Types /// \name Types
/// @{ /// @{
/*! /*!
Point type. Point type.
*/ */
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
/// @} /// @}
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
Default constructor Default constructor
*/ */
@ -32,8 +36,9 @@ public:
/*! /*!
Constructor from vertices and pairings ranges. Constructor from vertices and pairings ranges.
@tparam PointRange a model of the concepts `RandomAccessContainer` whose `value_type` is `Point`.
@tparam PairingRange a model of the concepts `RandomAccessContainer` whose `value_type` is `std::size_t`. \tparam PointRange a model of the concepts `RandomAccessContainer` whose `value_type` is `Point`.
\tparam PairingRange a model of the concepts `RandomAccessContainer` whose `value_type` is `std::size_t`.
*/ */
template<class PointRange, class PairingRange> template<class PointRange, class PairingRange>
Hyperbolic_fundamental_domain_2(PointRange & vertices, PairingRange & pairings); Hyperbolic_fundamental_domain_2(PointRange & vertices, PairingRange & pairings);
@ -41,6 +46,7 @@ public:
/// \name Access Functions /// \name Access Functions
/// @{ /// @{
/*! /*!
returns the number of vertices (equivalently, the number of sides) of the domain. returns the number of vertices (equivalently, the number of sides) of the domain.
@ -68,24 +74,28 @@ public:
\pre <code> is_valid() </code> \pre <code> is_valid() </code>
*/ */
Hyperbolic_isometry_2<Traits> side_pairing(std::size_t i) const; Hyperbolic_isometry_2<Traits> side_pairing(std::size_t i) const;
/// @} /// @}
/// @{
/// \name Validity /// \name Validity
/// @{
/*! /*!
checks that the number of vertices is even, that there are as many side pairings as vertices, and that the vertices all lie within the open unit disk. checks that the number of vertices is even, that there are as many side pairings as vertices,
and that the vertices all lie within the open unit disk.
*/ */
bool is_valid() const; bool is_valid() const;
/// @}
/// @}
}; };
}; // namespace CGAL } // namespace CGAL
/// \name Input/Output /// \name Input/Output
/// @{ /// @{
/*!
inserts the domain in a stream. /*!
\brief inserts the domain in a stream.
The format of the output is the following. The format of the output is the following.
The first line prints the number \f$n\f$ of vertices of the domain. The first line prints the number \f$n\f$ of vertices of the domain.
@ -93,13 +103,14 @@ public:
For \f$ i=0 \f$ to \f$ n-1 \f$ the i-th vertex is printed on a separate line. For \f$ i=0 \f$ to \f$ n-1 \f$ the i-th vertex is printed on a separate line.
\pre <code> is_valid() </code> \pre <code> is_valid() </code>
*/ */
std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain); std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain);
/*! /*!
extracts the domain from a stream. \brief extracts the domain from a stream.
The format of the input must be the same as the format of the output of 'operator<<()'. The format of the input must be the same as the format of the output of 'operator<<()'.
*/ */
std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain); std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain);
/// @}
/// @}

View File

@ -1,21 +1,23 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
Factory class, whose only purpose is to construct random fundamental domains of Factory class, whose only purpose is to construct random fundamental domains of
closed orientable hyperbolic surfaces. closed orientable hyperbolic surfaces.
The function `make_hyperbolic_fundamental_domain_g2()` constructs such a domain for The function `make_hyperbolic_fundamental_domain_g2()` constructs such a domain for
a surface of genus two. a surface of genus two.
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`. \tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_fundamental_domain_factory_2{ class Hyperbolic_fundamental_domain_factory_2
{
public: public:
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
Constructor. Constructor.
*/ */
@ -24,13 +26,13 @@ public:
/// \name Generation of a domain in genus two. /// \name Generation of a domain in genus two.
/// @{ /// @{
/*! /*!
randomly generates a convex domain of a closed orientable hyperbolic surface randomly generates a convex domain of a closed orientable hyperbolic surface of genus two from a seed.
of genus two from a seed.
*/ */
Hyperbolic_fundamental_domain_2<Traits> make_hyperbolic_fundamental_domain_g2(unsigned int seed); Hyperbolic_fundamental_domain_2<Traits> make_hyperbolic_fundamental_domain_g2(unsigned int seed);
/// @}
/// @}
}; };
}; // namespace CGAL } // namespace CGAL

View File

@ -1,40 +1,50 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
represents an isometry in the Poincaré disk model. represents an isometry in the Poincaré disk model.
The isometry \f$ f \f$ is represented by a list \f$ (c_0, c_1, c_2, c_3) \f$ of complex numbers, The isometry \f$ f \f$ is represented by a list \f$ (c_0, c_1, c_2, c_3) \f$ of complex numbers,
so that \f$ f(z) = (c_0 z + c_1) / (c_2 z + c_3) \f$ holds on every complex \f$ z \f$ in the open unit disk. so that \f$ f(z) = (c_0 z + c_1) / (c_2 z + c_3) \f$ holds on every complex \f$ z \f$ in the open unit disk.
Functionalities are offered to compose isometries, and apply an isometry to a point. Functionalities are offered to compose isometries, and apply an isometry to a point.
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`. \tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_isometry_2{ class Hyperbolic_isometry_2
public: {
public:
/// \name Types /// \name Types
/// @{ /// @{
/*! /*!
Complex number type. Complex number type.
*/ */
typedef typename Traits::Complex Complex_number; typedef typename Traits::Complex Complex_number;
/*! /*!
Point type. Point type.
*/ */
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
/// @} /// @}
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
Default constructor to the identity. Default constructor to the identity.
*/ */
Hyperbolic_isometry_2(); Hyperbolic_isometry_2();
/*! /*!
Constructor from coefficients. Constructor from coefficients.
*/ */
Hyperbolic_isometry_2(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3); Hyperbolic_isometry_2(const Complex_number& c0,
const Complex_number& c1,
const Complex_number& c2,
const Complex_number& c3);
/// @} /// @}
/*! /*!
@ -44,47 +54,52 @@ class Hyperbolic_isometry_2{
/*! /*!
sets the coefficients of the isometry. sets the coefficients of the isometry.
\warning The implementation does not check that the
resulting transformation is an isometry.
\warning The implementation does not check that the resulting transformation is an isometry.
*/ */
void set_coefficients(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3); void set_coefficients(const Complex_number& c0,
const Complex_number& c1,
const Complex_number& c2,
const Complex_number& c3);
/*! /*!
sets a particular coefficient of the isometry. sets a particular coefficient of the isometry.
\warning The implementation does not check that the
resulting transformation is an isometry.
\warning The implementation does not check that the resulting transformation is an isometry.
*/ */
void set_coefficient(int index, const Complex_number& coefficient); void set_coefficient(int index, const Complex_number& coefficient);
/// \name Access Functions /// \name Access Functions
/// @{ /// @{
/*! /*!
returns the index-th coefficient. returns the index-th coefficient.
*/ */
const Complex_number& get_coefficient(int index) const; const Complex_number& get_coefficient(int index) const;
/// @} /// @}
/// \name Operations /// \name Operations
/// @{ /// @{
/*! /*!
evaluates the isometry at point \f$ p \f$. evaluates the isometry at point \f$ p \f$.
*/ */
Point evaluate(const Point& p) const; Point evaluate(const Point& p) const;
/*! /*!
evaluates the isometry at point \f$ p \f$. evaluates the isometry at point \f$ p \f$.
*/ */
Point operator()(const Point& p) const; Point operator()(const Point& p) const;
/// @{
/*! /*!
returns the composition of two isometries. returns the composition of two isometries.
*/ */
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> operator*(const Hyperbolic_isometry_2<Traits>& iso1, const Hyperbolic_isometry_2<Traits>& iso2); Hyperbolic_isometry_2<Traits> operator*(const Hyperbolic_isometry_2<Traits>& iso1,
/// @} const Hyperbolic_isometry_2<Traits>& iso2);
/// @}
}; };
}; // namespace CGAL } // namespace CGAL

View File

@ -1,13 +1,13 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2TraitsClasses \ingroup PkgHyperbolicSurfaceTriangulation2TraitsClasses
\tparam HyperbolicTraits must be a model of `HyperbolicDelaunayTriangulationTraits_2`. \tparam HyperbolicTraits must be a model of `HyperbolicDelaunayTriangulationTraits_2`.
\cgalModels{HyperbolicSurfaceTraits_2} \cgalModels{HyperbolicSurfaceTraits_2}
*/ */
template<class HyperbolicTraits> template<class HyperbolicTraits>
class Hyperbolic_surface_traits_2 : public HyperbolicTraits {}; class Hyperbolic_surface_traits_2 : public HyperbolicTraits {};
}; // namespace CGAL } // namespace CGAL

View File

@ -1,97 +1,110 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
This item defines attributes of edges that are of type `Complex_number` reprensenting cross-ratios.
This item defines attributes of edges that are of type \tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
`Complex_number` reprensenting cross-ratios.
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`. \cgalModels{GenericMapItems}
\cgalModels{GenericMapItems}
*/ */
template<class Traits> template<class Traits>
struct Combinatorial_map_with_cross_ratios_item{ struct Combinatorial_map_with_cross_ratios_item
{
template <class CMap> template <class CMap>
struct Dart_wrapper{ struct Dart_wrapper
typedef Cell_attribute<CMap, Complex_number<typename Traits::FT>> Edge_attrib; {
typedef std::tuple<void,Edge_attrib,void> Attributes; typedef Cell_attribute<CMap, Complex_number<typename Traits::FT> > Edge_attrib;
typedef std::tuple<void, Edge_attrib, void> Attributes;
}; };
}; };
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses \ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
represents a triangulation of a closed orientable hyperbolic surface. represents a triangulation of a closed orientable hyperbolic surface.
The class provides functions such as the generation of the triangulation from a convex fundamental domain, The class provides functions such as the generation of the triangulation from a convex fundamental domain,
the Delaunay flip algorithm, and the construction of a portion of the lift of the triangulation in the hyperbolic plane. the Delaunay flip algorithm, and the construction of a portion of the lift of the triangulation in the hyperbolic plane.
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`. \tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
\tparam Attributes must be a model of `GenericMapItems` whose edges are
\tparam Attributes must be a model of `GenericMapItems` whose edges are decorated with complex numbers to represent cross ratios.
decorated with complex numbers to represent cross ratios.
*/ */
template<class Traits, class Attributes = Combinatorial_map_with_cross_ratios_item<Traits>> template<class Traits, class Attributes = Combinatorial_map_with_cross_ratios_item<Traits> >
class Triangulation_on_hyperbolic_surface_2 class Triangulation_on_hyperbolic_surface_2
{ {
public: public:
/// \name Types /// \name Types
/// @{ /// @{
/*! /*!
Type of combinatorial map whose edges are decorated with complex numbers. Type of combinatorial map whose edges are decorated with complex numbers.
*/ */
typedef Combinatorial_map<2, Attributes> Combinatorial_map_with_cross_ratios; typedef Combinatorial_map<2, Attributes> Combinatorial_map_with_cross_ratios;
/*! /*!
Combinatorial map dart descriptor type. Combinatorial map dart descriptor type.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::Dart_descriptor Dart_descriptor; typedef typename Combinatorial_map_with_cross_ratios::Dart_descriptor Dart_descriptor;
/*! /*!
Combinatorial map dart const descriptor type. Combinatorial map dart const descriptor type.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::Dart_const_descriptor Dart_const_descriptor; typedef typename Combinatorial_map_with_cross_ratios::Dart_const_descriptor Dart_const_descriptor;
/*! /*!
Range of one dart for each vertex (that is 0-cell) of the combinatorial map. Range of one dart for each vertex (that is 0-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<0> Vertex_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<0> Vertex_range;
/*! /*!
Range of one dart for each edge (that is 1-cell) of the combinatorial map. Range of one dart for each edge (that is 1-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<1> Edge_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<1> Edge_range;
/*! /*!
Range of one dart for each face (that is 2-cell) of the combinatorial map. Range of one dart for each face (that is 2-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<2> Face_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<2> Face_range;
/*! /*!
Range of one dart for each vertex (that is 0-cell) of the combinatorial map. Range of one dart for each vertex (that is 0-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<0> Vertex_const_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<0> Vertex_const_range;
/*! /*!
Range of one dart for each edge (that is 1-cell) of the combinatorial map. Range of one dart for each edge (that is 1-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<1> Edge_const_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<1> Edge_const_range;
/*! /*!
Range of one dart for each face (that is 2-cell) of the combinatorial map. Range of one dart for each face (that is 2-cell) of the combinatorial map.
*/ */
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<2> Face_const_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_const_range<2> Face_const_range;
/*! /*!
Point type. Point type.
*/ */
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
/*! /*!
stores a dart \f$ d \f$ of the combinatorial map, belonging to a triangle \f$ t \f$, and stores the three vertices of a lift of \f$ t \f$ in the hyperbolic plane. stores a dart \f$ d \f$ of the combinatorial map, belonging to a triangle \f$ t \f$,
and stores the three vertices of a lift of \f$ t \f$ in the hyperbolic plane.
*/ */
struct Anchor{ struct Anchor
{
typename Combinatorial_map_with_cross_ratios::Dart_descriptor dart; typename Combinatorial_map_with_cross_ratios::Dart_descriptor dart;
typename Traits::Hyperbolic_point_2 vertices[3]; typename Traits::Hyperbolic_point_2 vertices[3];
}; };
/// @} /// @}
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
Default constructor. Default constructor.
*/ */
@ -110,18 +123,22 @@ public:
Constructor from a decorated combinatorial map and an anchor. Constructor from a decorated combinatorial map and an anchor.
*/ */
Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap, Anchor& an_anchor); Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap, Anchor& an_anchor);
/// @} /// @}
/// \name Assignment /// \name Assignment
/// @{ /// @{
/*! /*!
\pre <code> other.is_valid() </code> \pre <code> other.is_valid() </code>
*/ */
Triangulation_on_hyperbolic_surface_2& operator=(Triangulation_on_hyperbolic_surface_2 other); Triangulation_on_hyperbolic_surface_2& operator=(Triangulation_on_hyperbolic_surface_2 other);
/// @} /// @}
/// \name Access Functions /// \name Access Functions
/// @{ /// @{
/*! /*!
returns the decorated combinatorial map. returns the decorated combinatorial map.
*/ */
@ -129,54 +146,60 @@ public:
/*! /*!
returns whether the triangulation has an anchor or not. returns whether the triangulation has an anchor or not.
\pre <code> is_valid() </code> \pre <code> is_valid() </code>
*/ */
bool has_anchor() const; bool has_anchor() const;
/*! /*!
returns the anchor. returns the anchor.
\pre <code> is_valid() && has_anchor() </code> \pre <code> is_valid() && has_anchor() </code>
*/ */
Anchor& anchor(); Anchor& anchor();
/*! /*!
returns the anchor. returns the anchor.
\pre <code> is_valid() && has_anchor() </code> \pre <code> is_valid() && has_anchor() </code>
*/ */
const Anchor& anchor() const; const Anchor& anchor() const;
/*! /*!
returns the range of vertices. returns the range of vertices.
*/ */
Vertex_range vertices_range(); Vertex_range vertices_range();
/*! /*!
returns the range of edges. returns the range of edges.
*/ */
Edge_range edges_range(); Edge_range edges_range();
/*! /*!
returns the range of faces. returns the range of faces.
*/ */
Face_range faces_range(); Face_range faces_range();
/*! /*!
returns the range of vertices. returns the range of vertices.
*/ */
Vertex_const_range vertices_const_range() const; Vertex_const_range vertices_const_range() const;
/*! /*!
returns the range of edges. returns the range of edges.
*/ */
Edge_const_range edges_const_range() const; Edge_const_range edges_const_range() const;
/*! /*!
returns the range of faces. returns the range of faces.
*/ */
Face_const_range faces_const_range() const; Face_const_range faces_const_range() const;
/// @}
/// @}
/// \name Delaunay Flip Algorithm /// \name Delaunay Flip Algorithm
/// @{ /// @{
/*! /*!
returns whether the edge supported by the dart is Delaunay flippable or not. An edge \f$ e \f$ is Delaunay flippable if the imaginary part of its cross ratio is positive. returns whether the edge supported by the dart is Delaunay flippable or not. An edge \f$ e \f$
is Delaunay flippable if the imaginary part of its cross ratio is positive.
\pre <code> is_valid() </code> \pre <code> is_valid() </code>
*/ */
@ -196,16 +219,18 @@ Face_const_range faces_const_range() const;
/*! /*!
applies the Delaunay flip algorithm: flips Delaunay-flippable edges until there is no such edge anymore. applies the Delaunay flip algorithm: flips Delaunay-flippable edges until there is no such edge anymore.
\pre <code> is_valid() </code> \pre <code> is_valid() </code>
*/ */
int make_Delaunay(); int make_Delaunay();
/// @} /// @}
/// \name Lifting /// \name Lifting
/// @{ /// @{
/*! /*!
lifts the triangulation in the hyperbolic plane. lifts the triangulation in the hyperbolic plane.
Returns, for every triangle \f$ t \f$ of the triangulation, one of the darts of \f$ t \f$ in the combinatorial map of the triangulation, together with a triple \f$ p,q,r \f$ of points in the hyperbolic plane. Returns, for every triangle \f$ t \f$ of the triangulation, one of the darts of \f$ t \f$ in the combinatorial map of the triangulation, together with a triple \f$ p,q,r \f$ of points in the hyperbolic plane.
The points \f$ p,q,r \f$ are the vertices of a lift of \f$ t \f$ in the hyperbolic plane. The points \f$ p,q,r \f$ are the vertices of a lift of \f$ t \f$ in the hyperbolic plane.
If the center parameter is set to true, then one of the vertices of the anchor is translated to the origin \f$ 0 \f$. If the center parameter is set to true, then one of the vertices of the anchor is translated to the origin \f$ 0 \f$.
@ -213,17 +238,21 @@ Face_const_range faces_const_range() const;
\pre <code> is_valid() && has_anchor() </code> \pre <code> is_valid() && has_anchor() </code>
*/ */
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point>> lift(bool center=true) const; std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point>> lift(bool center=true) const;
/// @} /// @}
/// \name Validity /// \name Validity
/// @{ /// @{
/*! /*!
checks that the underlying combinatorial map \f$ M \f$ has no boundary and calls the is_valid method of \f$ M \f$. checks that the underlying combinatorial map \f$ M \f$ has no boundary and calls the is_valid method of \f$ M \f$.
If there is an anchor, then checks that the dart descriptor of the anchor does indeed point to a dart of \f$ M \f$, and checks that the three vertices of the anchor lie within the open unit disk.
If there is an anchor, then checks that the dart descriptor of the anchor does indeed point to a dart of \f$ M \f$,
and checks that the three vertices of the anchor lie within the open unit disk.
*/ */
bool is_valid() const; bool is_valid() const;
/// @}
/// @}
}; };
}; // namespace CGAL } // namespace CGAL

View File

@ -1,30 +1,37 @@
namespace CGAL{ namespace CGAL {
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput \ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
inserts the triangulation in a stream. inserts the triangulation in a stream.
The format of the output is the following. The format of the output is the following.
Each dart of the triangulation is given an index between \f$ 0 \f$ and \f$ n-1 \f$, where \f$ n \f$ is the number of darts of the triangulation. Each dart of the triangulation is given an index between \f$ 0 \f$ and \f$ n-1 \f$, where \f$ n \f$
is the number of darts of the triangulation.
The first line contains the number \f$ n \f$ of darts. The first line contains the number \f$ n \f$ of darts.
The next line contains either 'yes' or 'no' and tells whether the triangulation has an anchor. The next line contains either 'yes' or 'no' and tells whether the triangulation has an anchor.
If the triangulation has an anchor, then the four next lines print the index of the dart of the anchor, and the three vertices of the anchor. If the triangulation has an anchor, then the four next lines print the index of the dart of the anchor,
and the three vertices of the anchor.
Then, for every triangle \f$ t \f$, the indices of the three darts of \f$ t \f$ are printed on three distinct lines. Then, for every triangle \f$ t \f$, the indices of the three darts of \f$ t \f$ are printed on three distinct lines.
Finally, for every edge \f$ e \f$, the indices of the two darts of \f$ e \f$ are printed on two distinct lines, followed by a third line on which the cross ratio of \f$ e \f$ is printed. Finally, for every edge \f$ e \f$, the indices of the two darts of \f$ e \f$ are printed on two distinct lines, followed by a third line on which the cross ratio of \f$ e \f$ is printed.
\pre <code> Triangulation_on_hyperbolic_surface_2<Traits>::is_valid() </code> \pre <code> Triangulation_on_hyperbolic_surface_2<Traits>::is_valid() </code>
*/ */
std::ostream& operator<<(std::ostream& s, const Triangulation_on_hyperbolic_surface_2<Traits>& triangulation); std::ostream& operator<<(std::ostream& s, const Triangulation_on_hyperbolic_surface_2<Traits>& triangulation);
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput \ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
extracts the triangulation from a stream. extracts the triangulation from a stream.
The format of the input should be the same as the format of the output of The format of the input should be the same as the format of the output of
the '<<' operator for Triangulation_on_hyperbolic_surface_2. the '<<' operator for Triangulation_on_hyperbolic_surface_2.
*/ */
std::istream& operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits>& triangulation); std::istream& operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits>& triangulation);
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput \ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
inserts the domain in a stream. inserts the domain in a stream.
The format of the output is the following. The format of the output is the following.
@ -33,22 +40,24 @@ namespace CGAL{
For \f$ i=0 \f$ to \f$ n-1 \f$ the i-th vertex is printed on a separate line. For \f$ i=0 \f$ to \f$ n-1 \f$ the i-th vertex is printed on a separate line.
\pre <code> Hyperbolic_fundamental_domain_2< Traits >::is_valid() </code> \pre <code> Hyperbolic_fundamental_domain_2< Traits >::is_valid() </code>
*/ */
std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain); std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain);
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput \ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
extracts the domain from a stream. extracts the domain from a stream.
The format of the input must be the same as the format of the output of The format of the input must be the same as the format of the output of
the '<<' operator for Hyperbolic_fundamental_domain_2. the '<<' operator for Hyperbolic_fundamental_domain_2.
*/ */
std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain); std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain);
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput \ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
inserts the isometry in a stream.
*/
std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry);
}; // namespace CGAL inserts the isometry in a stream.
*/
std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry);
} // namespace CGAL

View File

@ -1,29 +1,31 @@
// Copyright (c) 2024 INRIA Nancy - Grand Est (France). LIGM Marne-la-Vallée (France)
// All rights reserved.
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2Concepts \ingroup PkgHyperbolicSurfaceTriangulation2Concepts
\cgalConcept \cgalConcept
Describes a complex number type over a `FieldNumberType` for its real and Describes a complex number type over a `FieldNumberType` for its real and imaginary parts.
imaginary parts.
\cgalRefines{Field} \cgalRefines{Field}
\cgalHasModelsBegin \cgalHasModelsBegin
\cgalHasModels{CGAL::Complex_number} \cgalHasModels{CGAL::Complex_number}
\cgalHasModelsEnd \cgalHasModelsEnd
*/ */
class ComplexNumber { class ComplexNumber
{
public: public:
/// \name Types /// \name Types
/// @{ /// @{
/*! /*!
Number type for real and imaginary parts: must be a model of `FieldNumberType`. Number type for real and imaginary parts: must be a model of `FieldNumberType`.
*/ */
typedef unspecified_type FT; typedef unspecified_type FT;
/// @}
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
Default constructor, sets the both the real part and the imaginary part to \f$ 0 \f$. Default constructor, sets the both the real part and the imaginary part to \f$ 0 \f$.
*/ */
@ -46,10 +48,12 @@ public:
*/ */
template<class U,class V> template<class U,class V>
ComplexNumber(U&& real_part, V&& imaginary_part); ComplexNumber(U&& real_part, V&& imaginary_part);
/// @} /// @}
/// \name Get and Set /// \name Getter and Setter
/// @{ /// @{
/*! /*!
sets the real part to <code> real_part </code>. sets the real part to <code> real_part </code>.
*/ */
@ -69,86 +73,32 @@ public:
returns the imaginary part. returns the imaginary part.
*/ */
FT imag() const; FT imag() const;
/// @} /// @}
/// \name Operations /// \name Operations
/// @{ /// @{
/* /\*! */
/* returns +z. */
/* *\/ */
/* //ComplexNumber operator+(const ComplexNumber& z) const; */
/* /\*! */
/* returns -z. */
/* *\/ */
/* //ComplexNumber operator-(const ComplexNumber& z) const; */
/* /\*! */
/* Unary complex addition. */
/* *\/ */
/* //ComplexNumber operator+=(const ComplexNumber& other) const; */
/* /\*! */
/* Unary complex substraction. */
/* *\/ */
/* //ComplexNumber operator-=(const ComplexNumber& other) const; */
/* /\*! */
/* Unary complex multiplication. */
/* *\/ */
/* //ComplexNumber operator*=(const ComplexNumber& other) const; */
/* /\*! */
/* Unary complex division. */
/* *\/ */
/* //ComplexNumber operator/=(const ComplexNumber& other) const; */
/*! /*!
Copy operator. Copy operator.
*/ */
ComplexNumber operator=(const ComplexNumber& other) const; ComplexNumber operator=(const ComplexNumber& other) const;
/* /\*! */
/* Equality test. */
/* *\/ */
/* //bool operator==(const ComplexNumber& z1, const ComplexNumber& z2); */
/* /\*! */
/* Inequality test. */
/* *\/ */
/* // bool operator!=(const ComplexNumber& z1, const ComplexNumber& z2); */
/* /\*! */
/* Binary complex addition. */
/* *\/ */
/* //ComplexNumber operator+(const ComplexNumber& z1, const ComplexNumber& z2); */
/* /\*! */
/* Binary complex substraction. */
/* *\/ */
/* //ComplexNumber operator-(const ComplexNumber& z1, const ComplexNumber& z2); */
/* /\*! */
/* Binary complex multiplication. */
/* *\/ */
/* //ComplexNumber operator*(const ComplexNumber& z1, const ComplexNumber& z2); */
/* /\*! */
/* Binary complex division. */
/* *\/ */
/* //ComplexNumber operator/(const ComplexNumber& z1, const ComplexNumber& z2); */
/*! /*!
writes the complex in a stream. writes the complex in a stream.
*/ */
std::ostream& operator<<(std::ostream& s, const ComplexNumber& z); std::ostream& operator<<(std::ostream& s, const ComplexNumber& z);
/*! /*!
reads the complex from a stream. reads the complex from a stream.
*/ */
void operator>>(std::istream& s, ComplexNumber& z); void operator>>(std::istream& s, ComplexNumber& z);
/// @} /// @}
/// \relates ComplexNumber /// \relates ComplexNumber
/// @{ /// @{
/*! /*!
returns the square of the modulus. returns the square of the modulus.
*/ */
@ -158,5 +108,6 @@ public:
returns the conjugate. returns the conjugate.
*/ */
ComplexNumber conj(ComplexNumber z) const; ComplexNumber conj(ComplexNumber z) const;
/// @} /// @}
}; };

View File

@ -1,24 +1,26 @@
/*! /*!
\ingroup PkgHyperbolicSurfaceTriangulation2Concepts \ingroup PkgHyperbolicSurfaceTriangulation2Concepts
\cgalConcept \cgalConcept
This traits class must have a type for complex numbers. This traits class must have a type for complex numbers.
\cgalRefines{HyperbolicDelaunayTriangulationTraits_2} \cgalRefines{HyperbolicDelaunayTriangulationTraits_2}
\cgalHasModelsBegin \cgalHasModelsBegin
\cgalHasModels{CGAL::Hyperbolic_surface_traits_2} \cgalHasModels{CGAL::Hyperbolic_surface_traits_2}
\cgalHasModelsEnd \cgalHasModelsEnd
*/ */
class HyperbolicSurfaceTraits_2 { class HyperbolicSurfaceTraits_2
{
public: public:
/// \name Types /// \name Types
/// @{ /// @{
/*! /*!
represents a complex number, model of represents a complex number, model of `ComplexNumber`,
`ComplexNumber`, over the field `HyperbolicSurfaceTraits_2::FT` for its real and over the field `HyperbolicSurfaceTraits_2::FT` for its real and imaginary parts.
imaginary parts.
*/ */
typedef unspecified_type Complex; typedef unspecified_type Complex;
/// @} /// @}
}; };

View File

@ -12,7 +12,6 @@
/// \defgroup PkgHyperbolicSurfaceTriangulation2InputOutput Input/Output Functions /// \defgroup PkgHyperbolicSurfaceTriangulation2InputOutput Input/Output Functions
/// \ingroup PkgHyperbolicSurfaceTriangulation2Ref /// \ingroup PkgHyperbolicSurfaceTriangulation2Ref
/*! /*!
\addtogroup PkgHyperbolicSurfaceTriangulation2Ref \addtogroup PkgHyperbolicSurfaceTriangulation2Ref
@ -26,7 +25,7 @@
\cgalPkgSummaryEnd \cgalPkgSummaryEnd
\cgalPkgShortInfoBegin \cgalPkgShortInfoBegin
\cgalPkgSince{6} \cgalPkgSince{6.1}
\cgalPkgDependsOn{\ref PkgCombinatorialMaps} \cgalPkgDependsOn{\ref PkgCombinatorialMaps}
\cgalPkgBib{cgal:y-t2} \cgalPkgBib{cgal:y-t2}
\cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgLicense{\ref licensesGPL "GPL"}
@ -35,7 +34,6 @@
\cgalPkgDescriptionEnd \cgalPkgDescriptionEnd
\cgalClassifedRefPages \cgalClassifedRefPages
\cgalCRPSection{Concepts} \cgalCRPSection{Concepts}

View File

@ -1,12 +1,10 @@
cmake_minimum_required(VERSION 3.12...3.29) cmake_minimum_required(VERSION 3.12...3.31)
project( Triangulation_on_hyperbolic_surface_2_Examples ) project( Triangulation_on_hyperbolic_surface_2_Examples )
# CGAL and its components # CGAL and its components
find_package( CGAL REQUIRED ) find_package( CGAL REQUIRED )
include_directories(../../include/)
# create a target per cppfile # create a target per cppfile
file( file(
GLOB cppfiles GLOB cppfiles

View File

@ -15,7 +15,7 @@ typedef CGAL::Hyperbolic_fundamental_domain_2<Traits> Domain;
typedef CGAL::Hyperbolic_fundamental_domain_factory_2<Traits> Factory; typedef CGAL::Hyperbolic_fundamental_domain_factory_2<Traits> Factory;
typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation; typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation;
int main(){ int main() {
// Generates the domain: // Generates the domain:
Factory factory = Factory(); Factory factory = Factory();
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(time(NULL)); // get a random seed with time(NULL) Domain domain = factory.make_hyperbolic_fundamental_domain_g2(time(NULL)); // get a random seed with time(NULL)

View File

@ -10,21 +10,23 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Complex_number
#ifndef CGAL_COMPLEX_NUMBER_H #ifndef CGAL_COMPLEX_NUMBER_H
#define CGAL_COMPLEX_NUMBER_H #define CGAL_COMPLEX_NUMBER_H
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <utility>
namespace CGAL { namespace CGAL {
/* /*
Templated by a field FT. Represents a complex number over FT. Templated by a field FT. Represents a complex number over FT.
*/ */
template <class FT> template <class FT>
class Complex_number { class Complex_number
{
typedef Complex_number<FT> _Self; typedef Complex_number<FT> _Self;
FT _real, _imag; FT _real, _imag;
public: public:
@ -33,8 +35,8 @@ public:
{} {}
Complex_number(const FT& real_part, const FT& imaginary_part) Complex_number(const FT& real_part, const FT& imaginary_part)
: _real(real_part) : _real(real_part),
, _imag(imaginary_part) _imag(imaginary_part)
{} {}
Complex_number() Complex_number()
@ -43,15 +45,15 @@ public:
template<class U,class V> template<class U,class V>
Complex_number(U&& real_part, V&& imaginary_part) Complex_number(U&& real_part, V&& imaginary_part)
: _real(std::forward<U>(real_part)) : _real(std::forward<U>(real_part)),
, _imag(std::forward<V>(imaginary_part)) _imag(std::forward<V>(imaginary_part))
{} {}
void real(const FT& real_part){ void real(const FT& real_part) {
_real = real_part; _real = real_part;
} }
void imag(const FT& imaginary_part){ void imag(const FT& imaginary_part) {
_imag = imaginary_part; _imag = imaginary_part;
} }
@ -89,7 +91,7 @@ public:
return !operator==(z1, z2); return !operator==(z1, z2);
} }
friend _Self operator+(const _Self& z1, const _Self& z2){ friend _Self operator+(const _Self& z1, const _Self& z2) {
return _Self(z1._real+z2._real, z1._imag+z2._imag); return _Self(z1._real+z2._real, z1._imag+z2._imag);
} }
@ -101,50 +103,53 @@ public:
return _Self(z1._real*z2._real-z1._imag*z2._imag, z1._real*z2._imag+z1._imag*z2._real); return _Self(z1._real*z2._real-z1._imag*z2._imag, z1._real*z2._imag+z1._imag*z2._real);
} }
friend _Self operator/(const _Self& z1, const _Self& z2){ friend _Self operator/(const _Self& z1, const _Self& z2) {
FT m2 = norm(z2); FT m2 = norm(z2);
return _Self(z1._real/m2, z1._imag/m2)*conj(z2); return _Self(z1._real/m2, z1._imag/m2)*conj(z2);
} }
friend std::ostream& operator<<(std::ostream& s, const _Self& z){ friend std::ostream& operator<<(std::ostream& s, const _Self& z) {
s << z._real << std::endl << z._imag << std::endl; s << z._real << std::endl << z._imag << std::endl;
return s; return s;
} }
friend void operator>>(std::istream& s, _Self& z){ friend void operator>>(std::istream& s, _Self& z) {
FT ft; FT ft;
s >> ft; s >> ft;
z.real(ft); z.real(ft);
s >> ft; s >> ft;
z.imag(ft); z.imag(ft);
} }
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class FT> template<class FT>
Complex_number<FT>& Complex_number<FT>::operator+=(const Complex_number<FT>& other) { Complex_number<FT>& Complex_number<FT>::operator+=(const Complex_number<FT>& other)
{
_real += other.real(); _real += other.real();
_imag += other.imag(); _imag += other.imag();
return *this; return *this;
} }
template<class FT> template<class FT>
Complex_number<FT>& Complex_number<FT>::operator-=(const Complex_number<FT>& other) { Complex_number<FT>& Complex_number<FT>::operator-=(const Complex_number<FT>& other)
{
_real -= other.real(); _real -= other.real();
_imag -= other.imag(); _imag -= other.imag();
return *this; return *this;
} }
template<class FT> template<class FT>
Complex_number<FT>& Complex_number<FT>::operator*=(const Complex_number<FT>& other) { Complex_number<FT>& Complex_number<FT>::operator*=(const Complex_number<FT>& other)
{
_real = _real*other.real() - _imag*other.imag(); _real = _real*other.real() - _imag*other.imag();
_imag = _real*other.imag() + _imag*other.real(); _imag = _real*other.imag() + _imag*other.real();
return *this; return *this;
} }
template<class FT> template<class FT>
Complex_number<FT>& Complex_number<FT>::operator/=(const Complex_number<FT>& other) { Complex_number<FT>& Complex_number<FT>::operator/=(const Complex_number<FT>& other)
{
FT m2 = norm(other); FT m2 = norm(other);
_real /= m2; _real /= m2;
_imag /= m2; _imag /= m2;
@ -153,12 +158,14 @@ Complex_number<FT>& Complex_number<FT>::operator/=(const Complex_number<FT>& oth
} }
template<class FT> template<class FT>
FT norm(const Complex_number<FT>& z) { FT norm(const Complex_number<FT>& z)
{
return z.real()*z.real() + z.imag()*z.imag(); return z.real()*z.real() + z.imag()*z.imag();
} }
template<class FT> template<class FT>
Complex_number<FT> conj(const Complex_number<FT>& z) { Complex_number<FT> conj(const Complex_number<FT>& z)
{
return Complex_number<FT>(z.real(), -z.imag()); return Complex_number<FT>(z.real(), -z.imag());
} }

View File

@ -10,18 +10,17 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Hyperbolic_fundamental_domain_2
#ifndef CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_2_H #ifndef CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_2_H
#define CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_2_H #define CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_2_H
#include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/Hyperbolic_isometry_2.h> #include <CGAL/Hyperbolic_isometry_2.h>
#include <CGAL/basic.h>
#include <vector> #include <CGAL/assertions.h>
#include <iostream> #include <iostream>
#include <vector>
namespace CGAL { namespace CGAL {
@ -33,22 +32,31 @@ identifying every two paired sides in a way that respects the orientation of P w
orientable hyperbolic surface. orientable hyperbolic surface.
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_fundamental_domain_2 { class Hyperbolic_fundamental_domain_2
{
public: public:
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
Hyperbolic_fundamental_domain_2(){}; Hyperbolic_fundamental_domain_2() {};
template<class PointRange, class PairingRange> template<class PointRange, class PairingRange>
Hyperbolic_fundamental_domain_2(PointRange & vertices, PairingRange & pairings){ Hyperbolic_fundamental_domain_2(PointRange & vertices, PairingRange & pairings)
{
_vertices = std::vector<Point>(vertices.begin(), vertices.end()); _vertices = std::vector<Point>(vertices.begin(), vertices.end());
_pairings = std::vector<int>(pairings.begin(), pairings.end()); _pairings = std::vector<int>(pairings.begin(), pairings.end());
} }
std::size_t size() const; // Returns the number of vertices (equivalently, the number of sides) // returns the number of vertices (equivalently, the number of sides)
const Point& vertex(std::size_t index) const; // Returns the index-th vertex std::size_t size() const;
std::size_t paired_side(std::size_t index) const; // Returns the index of the side paired to side A, where A is the index-th side
Hyperbolic_isometry_2<Traits> side_pairing(std::size_t index) const;// Returns the isometry that maps side A to side B, where B is the index-th side, and A is the side paired to B // returns the index-th vertex
const Point& vertex(std::size_t index) const;
// returns the index of the side paired to side A, where A is the index-th side
std::size_t paired_side(std::size_t index) const;
// returns the isometry that maps side A to side B, where B is the index-th side, and A is the side paired to B
Hyperbolic_isometry_2<Traits> side_pairing(std::size_t index) const;
std::istream& from_stream(std::istream& s); std::istream& from_stream(std::istream& s);
std::ostream& to_stream(std::ostream& s) const; std::ostream& to_stream(std::ostream& s) const;
@ -63,32 +71,43 @@ private:
//template<class Traits> std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain); //template<class Traits> std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain);
//template<class Traits> std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain); //template<class Traits> std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
std::size_t Hyperbolic_fundamental_domain_2<Traits>::size() const{ std::size_t
Hyperbolic_fundamental_domain_2<Traits>::
size() const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
return _vertices.size(); return _vertices.size();
} }
template<class Traits> template<class Traits>
const typename Hyperbolic_fundamental_domain_2<Traits>::Point& Hyperbolic_fundamental_domain_2<Traits>::vertex(std::size_t index) const{ const typename Hyperbolic_fundamental_domain_2<Traits>::Point&
Hyperbolic_fundamental_domain_2<Traits>::
vertex(std::size_t index) const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
return _vertices[index]; return _vertices[index];
} }
template<class Traits> template<class Traits>
std::size_t Hyperbolic_fundamental_domain_2<Traits>::paired_side(std::size_t index) const{ std::size_t
Hyperbolic_fundamental_domain_2<Traits>::
paired_side(std::size_t index) const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
return _pairings[index]; return _pairings[index];
} }
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> Hyperbolic_fundamental_domain_2<Traits>::side_pairing(std::size_t index) const{ Hyperbolic_isometry_2<Traits>
Hyperbolic_fundamental_domain_2<Traits>::
side_pairing(std::size_t index) const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
std::size_t n = size(); std::size_t n = size();
std::size_t paired_index = paired_side(index); std::size_t paired_index = paired_side(index);
@ -106,23 +125,29 @@ Hyperbolic_isometry_2<Traits> Hyperbolic_fundamental_domain_2<Traits>::side_pair
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
std::ostream& Hyperbolic_fundamental_domain_2<Traits>::to_stream(std::ostream& s) const{ std::ostream&
Hyperbolic_fundamental_domain_2<Traits>::
to_stream(std::ostream& s) const
{
std::size_t n = size(); std::size_t n = size();
s << std::to_string(n) << std::endl; s << std::to_string(n) << std::endl;
for (std::size_t k=0; k<n; ++k){ for (std::size_t k=0; k<n; ++k) {
s << paired_side(k) << std::endl; s << paired_side(k) << std::endl;
} }
for (std::size_t k=0; k<n; ++k){ for (std::size_t k=0; k<n; ++k) {
s << vertex(k) << std::endl; s << vertex(k) << std::endl;
} }
return s; return s;
} }
template<class Traits> template<class Traits>
std::istream& Hyperbolic_fundamental_domain_2<Traits>::from_stream(std::istream& s){ std::istream&
Hyperbolic_fundamental_domain_2<Traits>::
from_stream(std::istream& s)
{
_vertices.clear(); _vertices.clear();
_pairings.clear(); _pairings.clear();
@ -132,12 +157,12 @@ std::istream& Hyperbolic_fundamental_domain_2<Traits>::from_stream(std::istream&
_vertices.reserve(size); _vertices.reserve(size);
_pairings.reserve(size); _pairings.reserve(size);
for (std::size_t k=0; k<size; ++k){ for (std::size_t k=0; k<size; ++k) {
s >> line; s >> line;
_pairings.push_back(std::stoi(line)); _pairings.push_back(std::stoi(line));
} }
for (std::size_t k=0; k<size; ++k){ for (std::size_t k=0; k<size; ++k) {
Point p; Point p;
s >> p; s >> p;
_vertices.push_back(p); _vertices.push_back(p);
@ -145,43 +170,45 @@ std::istream& Hyperbolic_fundamental_domain_2<Traits>::from_stream(std::istream&
return s; return s;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
bool Hyperbolic_fundamental_domain_2<Traits>::is_valid()const{ bool
Hyperbolic_fundamental_domain_2<Traits>::
is_valid()const
{
// Get the number of vertices // Get the number of vertices
std::size_t n = _vertices.size(); std::size_t n = _vertices.size();
// Check that the number of vertices is even // Check that the number of vertices is even
if (n%2){ if (n%2) {
return false; return false;
} }
// Check that there are as many side pairings as vertices // Check that there are as many side pairings as vertices
if (_pairings.size() != n){ if (_pairings.size() != n) {
return false; return false;
} }
// Check that the _pairings vector encodes a perfect matching of the set {0,1,\dots,n-1} // Check that the _pairings vector encodes a perfect matching of the set {0,1,\dots,n-1}
std::vector<bool> already_paired(n); std::vector<bool> already_paired(n);
for (std::size_t k=0; k<n; ++k){ for (std::size_t k=0; k<n; ++k) {
already_paired[k] = false; already_paired[k] = false;
} }
for (std::size_t k=0; k<n; ++k){ for (std::size_t k=0; k<n; ++k) {
std::size_t paired_side = _pairings[k]; std::size_t paired_side = _pairings[k];
if ((paired_side<0) || (paired_side>=n)){ if ((paired_side<0) || (paired_side>=n)) {
return false; return false;
} }
if (already_paired[paired_side]){ if (already_paired[paired_side]) {
return false; return false;
} }
already_paired[paired_side] = true; already_paired[paired_side] = true;
} }
// Check that the vertices all lie within the open unit disk // Check that the vertices all lie within the open unit disk
for (std::size_t k=0; k<n; ++k){ for (std::size_t k=0; k<n; ++k) {
if (norm(Complex_number(_vertices[k].x(),_vertices[k].y())) >= typename Traits::FT(1)){ if (norm(Complex_number(_vertices[k].x(), _vertices[k].y())) >= typename Traits::FT(1)) {
return false; return false;
} }
} }

View File

@ -10,8 +10,6 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Hyperbolic_fundamental_domain_factory_2
#ifndef CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_FACTORY_2_H #ifndef CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_FACTORY_2_H
#define CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_FACTORY_2_H #define CGAL_HYPERBOLIC_FUNDAMENTAL_DOMAIN_FACTORY_2_H
@ -21,6 +19,7 @@
#include <CGAL/Random.h> #include <CGAL/Random.h>
#include <cmath> #include <cmath>
#include <vector>
namespace CGAL { namespace CGAL {
@ -31,7 +30,8 @@ closed orientable hyperbolic surfaces. The function
genus 2. genus 2.
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_fundamental_domain_factory_2{ class Hyperbolic_fundamental_domain_factory_2
{
private: private:
typedef typename Traits::FT _FT; typedef typename Traits::FT _FT;
typedef typename Traits::Complex _Cmplx; typedef typename Traits::Complex _Cmplx;
@ -64,24 +64,26 @@ private:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
Hyperbolic_fundamental_domain_factory_2<Traits>::Hyperbolic_fundamental_domain_factory_2(){} Hyperbolic_fundamental_domain_factory_2<Traits>::Hyperbolic_fundamental_domain_factory_2() {}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
Hyperbolic_fundamental_domain_2<Traits> Hyperbolic_fundamental_domain_factory_2<Traits>::make_hyperbolic_fundamental_domain_g2(unsigned int seed){ Hyperbolic_fundamental_domain_2<Traits>
Hyperbolic_fundamental_domain_factory_2<Traits>::
make_hyperbolic_fundamental_domain_g2(unsigned int seed)
{
_random = Random(seed); _random = Random(seed);
bool is_domain_generated = false; bool is_domain_generated = false;
_Cmplx exact_z0, exact_z1, exact_z2, exact_z3; _Cmplx exact_z0, exact_z1, exact_z2, exact_z3;
while (!is_domain_generated){ while (!is_domain_generated) {
// 1. Generate inexact z0,z1,z2,z3 // 1. Generate inexact z0,z1,z2,z3
Complex_number<float> z0, z1, z2, z3; Complex_number<float> z0, z1, z2, z3;
z1 = random_complex_float(); z1 = random_complex_float();
z2 = random_complex_float(); z2 = random_complex_float();
z3 = random_complex_float(); z3 = random_complex_float();
while (! try_to_compute_inexact_z0_from_z1_z2_z3(z0,z1,z2,z3)){ while (! try_to_compute_inexact_z0_from_z1_z2_z3(z0,z1,z2,z3)) {
z1 = random_complex_float(); z1 = random_complex_float();
z2 = random_complex_float(); z2 = random_complex_float();
z3 = random_complex_float(); z3 = random_complex_float();
@ -95,7 +97,7 @@ Hyperbolic_fundamental_domain_2<Traits> Hyperbolic_fundamental_domain_factory_2<
// 3. Modify z3 to fix the area... // 3. Modify z3 to fix the area...
is_domain_generated = try_to_compute_exact_z3_from_z0_z1_z2(exact_z0, exact_z1, exact_z2, exact_z3); is_domain_generated = try_to_compute_exact_z3_from_z0_z1_z2(exact_z0, exact_z1, exact_z2, exact_z3);
if (is_domain_generated){ if (is_domain_generated) {
// ... and perform a sanity check // ... and perform a sanity check
is_domain_generated = sanity_check(exact_z0, exact_z1, exact_z2, exact_z3); is_domain_generated = sanity_check(exact_z0, exact_z1, exact_z2, exact_z3);
} }
@ -113,7 +115,7 @@ Hyperbolic_fundamental_domain_2<Traits> Hyperbolic_fundamental_domain_factory_2<
vertices.push_back(_Point(-exact_z3.real(), -exact_z3.imag())); vertices.push_back(_Point(-exact_z3.real(), -exact_z3.imag()));
std::vector<int> pairings; std::vector<int> pairings;
for (int k=0; k<8; ++k){ for (int k=0; k<8; ++k) {
pairings.push_back((k+4)%8); pairings.push_back((k+4)%8);
} }
@ -124,19 +126,22 @@ Hyperbolic_fundamental_domain_2<Traits> Hyperbolic_fundamental_domain_factory_2<
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
float Hyperbolic_fundamental_domain_factory_2<Traits>::random_positive_float(){ float Hyperbolic_fundamental_domain_factory_2<Traits>::random_positive_float() {
return _random.uniform_01<float>(); return _random.uniform_01<float>();
} }
template<class Traits> template<class Traits>
float Hyperbolic_fundamental_domain_factory_2<Traits>::random_float(){ float Hyperbolic_fundamental_domain_factory_2<Traits>::random_float() {
return _random.uniform_01<float>() * 2 - 1; return _random.uniform_01<float>() * 2 - 1;
} }
template<class Traits> template<class Traits>
Complex_number<float> Hyperbolic_fundamental_domain_factory_2<Traits>::random_complex_float(){ Complex_number<float>
Hyperbolic_fundamental_domain_factory_2<Traits>::
random_complex_float()
{
Complex_number<float> result (random_float(), random_positive_float()); Complex_number<float> result (random_float(), random_positive_float());
while (norm(result) >= 1){ while (norm(result) >= 1) {
result.real(random_float()); result.real(random_float());
result.imag(random_positive_float()); result.imag(random_positive_float());
} }
@ -147,23 +152,34 @@ Complex_number<float> Hyperbolic_fundamental_domain_factory_2<Traits>::random_co
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
typename Traits::FT Hyperbolic_fundamental_domain_factory_2<Traits>::exact_number_from_float(float x){ typename Traits::FT
if (x< 0){ Hyperbolic_fundamental_domain_factory_2<Traits>::
exact_number_from_float(float x)
{
if (x < 0) {
return _FT(0)-exact_number_from_float(-x); return _FT(0)-exact_number_from_float(-x);
} }
return _FT(int(x*CGAL_DENOMINATOR_FOR_GENERATION)%CGAL_DENOMINATOR_FOR_GENERATION)/_FT(CGAL_DENOMINATOR_FOR_GENERATION); return _FT(int(x*CGAL_DENOMINATOR_FOR_GENERATION)%CGAL_DENOMINATOR_FOR_GENERATION)/_FT(CGAL_DENOMINATOR_FOR_GENERATION);
} }
template<class Traits> template<class Traits>
typename Traits::Complex Hyperbolic_fundamental_domain_factory_2<Traits>::exact_complex_from_float_complex(const Complex_number<float>& z){ typename Traits::Complex
Hyperbolic_fundamental_domain_factory_2<Traits>::
exact_complex_from_float_complex(const Complex_number<float>& z)
{
return _Cmplx(exact_number_from_float(z.real()), exact_number_from_float(z.imag())); return _Cmplx(exact_number_from_float(z.real()), exact_number_from_float(z.imag()));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
bool Hyperbolic_fundamental_domain_factory_2<Traits>::try_to_compute_inexact_z0_from_z1_z2_z3(Complex_number<float>& z0, Complex_number<float>& z1, Complex_number<float>& z2, Complex_number<float>& z3){ bool Hyperbolic_fundamental_domain_factory_2<Traits>::
if ( ((z2/z1).imag()<=0) || ((z3/z2).imag()<=0) ){ try_to_compute_inexact_z0_from_z1_z2_z3(Complex_number<float>& z0,
Complex_number<float>& z1,
Complex_number<float>& z2,
Complex_number<float>& z3)
{
if (((z2/z1).imag()<=0) || ((z3/z2).imag()<=0)) {
return false; return false;
} }
@ -174,28 +190,31 @@ bool Hyperbolic_fundamental_domain_factory_2<Traits>::try_to_compute_inexact_z0_
float c = u.imag(); float c = u.imag();
const float COMPUTATION_TRESHOLD = 0.00001f; const float COMPUTATION_TRESHOLD = 0.00001f;
if (a+b+c> 0 - COMPUTATION_TRESHOLD){ if (a+b+c> 0 - COMPUTATION_TRESHOLD) {
return false; return false;
} }
z0.real( 2*c/(std::sqrt(b*b-4*a*c)-b) ); z0.real(2*c/(std::sqrt(b*b-4*a*c)-b));
z0.imag(0); z0.imag(0);
return true; return true;
} }
template<class Traits> template<class Traits>
bool Hyperbolic_fundamental_domain_factory_2<Traits>::try_to_compute_exact_z3_from_z0_z1_z2(_Cmplx& z0, _Cmplx& z1, _Cmplx& z2, _Cmplx& z3){ bool
Hyperbolic_fundamental_domain_factory_2<Traits>::
try_to_compute_exact_z3_from_z0_z1_z2(_Cmplx& z0, _Cmplx& z1, _Cmplx& z2, _Cmplx& z3)
{
_FT zero_number (0); _FT zero_number (0);
_FT one_number (1); _FT one_number (1);
if ( (z0.real()<=zero_number) || (z1.imag()<=zero_number) || (z2.imag()<=zero_number) || (z3.imag()<=zero_number) ){ if ((z0.real()<=zero_number) || (z1.imag()<=zero_number) || (z2.imag()<=zero_number) || (z3.imag()<=zero_number)) {
return false; return false;
} }
if ( (norm(z0)>=one_number) || (norm(z1)>=one_number) || (norm(z2)>=one_number) || (norm(z3)>=one_number) ){ if ((norm(z0)>=one_number) || (norm(z1)>=one_number) || (norm(z2)>=one_number) || (norm(z3)>=one_number)) {
return false; return false;
} }
if ( ((z1/z0).imag()<=zero_number) || ((z2/z1).imag()<=zero_number) || ((z3/z2).imag()<=zero_number) ){ if (((z1/z0).imag()<=zero_number) || ((z2/z1).imag()<=zero_number) || ((z3/z2).imag()<=zero_number)) {
return false; return false;
} }
@ -211,14 +230,14 @@ bool Hyperbolic_fundamental_domain_factory_2<Traits>::try_to_compute_exact_z3_fr
_FT P_of_zero = intermediate.imag(); _FT P_of_zero = intermediate.imag();
_FT P_of_one = (intermediate * (one_cmplx-f_of_z2*conj(f_of_z3))).imag(); _FT P_of_one = (intermediate * (one_cmplx-f_of_z2*conj(f_of_z3))).imag();
if (P_of_one == P_of_zero){ if (P_of_one == P_of_zero) {
return false; return false;
} }
_FT lbda = P_of_zero / (P_of_zero - P_of_one); _FT lbda = P_of_zero / (P_of_zero - P_of_one);
_Cmplx V (lbda*(f_of_z3.real()), lbda*(f_of_z3.imag())); _Cmplx V (lbda*(f_of_z3.real()), lbda*(f_of_z3.imag()));
if ( (V.imag()<=zero_number) || (norm(V)>=one_number) || ((V/f_of_z2).imag()<=zero_number) ){ if ((V.imag()<=zero_number) || (norm(V)>=one_number) || ((V/f_of_z2).imag()<=zero_number)) {
return false; return false;
} }
@ -230,27 +249,30 @@ bool Hyperbolic_fundamental_domain_factory_2<Traits>::try_to_compute_exact_z3_fr
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
bool Hyperbolic_fundamental_domain_factory_2<Traits>::sanity_check(_Cmplx& z0, _Cmplx& z1, _Cmplx& z2, _Cmplx& z3){ bool
Hyperbolic_fundamental_domain_factory_2<Traits>::
sanity_check(_Cmplx& z0, _Cmplx& z1, _Cmplx& z2, _Cmplx& z3)
{
_FT zero_number(0); _FT zero_number(0);
_FT one_number(1); _FT one_number(1);
// 1. Check the positions // 1. Check the positions
if ( (z0.imag()!=zero_number) || (z0.real()<=zero_number) || (z1.imag()<=zero_number) || (z2.imag()<=zero_number) || (z3.imag()<=zero_number) ){ if ((z0.imag()!=zero_number) || (z0.real()<=zero_number) || (z1.imag()<=zero_number) || (z2.imag()<=zero_number) || (z3.imag()<=zero_number)) {
return false; return false;
} }
if ( (norm(z0)>=one_number) || (norm(z1)>=one_number) || (norm(z2)>=one_number) || (norm(z3)>=one_number) ){ if ((norm(z0)>=one_number) || (norm(z1)>=one_number) || (norm(z2)>=one_number) || (norm(z3)>=one_number)) {
return false; return false;
} }
if ( ((z2/z1).imag()<=zero_number) || ((z3/z2).imag()<=zero_number) ){ if (((z2/z1).imag()<=zero_number) || ((z3/z2).imag()<=zero_number)) {
return false; return false;
} }
// 2. Check the area // 2. Check the area
_Cmplx one_cmplx (one_number, zero_number); _Cmplx one_cmplx (one_number, zero_number);
_Cmplx Z = (one_cmplx-z0*conj(z1)) * (one_cmplx-z1*conj(z2)) *(one_cmplx-z2*conj(z3)) *(one_cmplx+z3*conj(z0)); _Cmplx Z = (one_cmplx-z0*conj(z1)) * (one_cmplx-z1*conj(z2)) *(one_cmplx-z2*conj(z3)) *(one_cmplx+z3*conj(z0));
if (Z.imag()!=zero_number){ if (Z.imag()!=zero_number) {
return false; return false;
} }

View File

@ -10,8 +10,6 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Hyperbolic_isometry_2
#ifndef CGAL_HYPERBOLIC_ISOMETRY_2_H #ifndef CGAL_HYPERBOLIC_ISOMETRY_2_H
#define CGAL_HYPERBOLIC_ISOMETRY_2_H #define CGAL_HYPERBOLIC_ISOMETRY_2_H
@ -22,11 +20,13 @@
namespace CGAL { namespace CGAL {
/* /*
Represents a hyperbolic isometry in the Poincare disk model the hyperbolic plane. The isometry f is stored as list (c0, c1, c2, c3) of 4 complex numbers, Represents a hyperbolic isometry in the Poincare disk model the hyperbolic plane.
The isometry f is stored as list (c0, c1, c2, c3) of 4 complex numbers,
so that f(z) = (c0 z + c1) / (c2 z + c3) holds on every complex z in the open unit disk. so that f(z) = (c0 z + c1) / (c2 z + c3) holds on every complex z in the open unit disk.
*/ */
template<class Traits> template<class Traits>
class Hyperbolic_isometry_2{ class Hyperbolic_isometry_2
{
public: public:
typedef Hyperbolic_isometry_2<Traits> Self; typedef Hyperbolic_isometry_2<Traits> Self;
typedef typename Traits::FT FT; typedef typename Traits::FT FT;
@ -38,14 +38,14 @@ public:
void set_to_identity(); void set_to_identity();
// Can be used to set the coefficients manually. Warning : the implementation does not check that the resulting moebius transform fixes the unit circle. // Can be used to set the coefficients manually. Warning: the implementation does not check that the resulting moebius transform fixes the unit circle.
void set_coefficients(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3); void set_coefficients(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3);
void set_coefficient(int index, const Complex_number& coefficient); void set_coefficient(int index, const Complex_number& coefficient);
// Returns the index-th coefficient // returns the index-th coefficient
const Complex_number& get_coefficient(int index) const; const Complex_number& get_coefficient(int index) const;
// Evaluates the isometry at point // evaluates the isometry at point
Point evaluate(const Point& point) const; Point evaluate(const Point& point) const;
Point operator()(const Point& point) const; Point operator()(const Point& point) const;
@ -59,35 +59,53 @@ template<class Traits>
// template<class Traits> std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry); // template<class Traits> std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry);
// When inverse=false, returns the hyperbolic translation that maps -p to zero, and zero to p. Otherwise, returns the hyperbolic translation that maps p to zero, and zero to -p. // When inverse is 'false', returns the hyperbolic translation that maps -p to zero, and zero to p.
// Otherwise, returns the hyperbolic translation that maps p to zero, and zero to -p.
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> hyperbolic_translation(const typename Traits::Hyperbolic_point_2& p, bool inverse=false); Hyperbolic_isometry_2<Traits> hyperbolic_translation(const typename Traits::Hyperbolic_point_2& p,
bool inverse = false);
// When inverse=false, returns the hyperbolic rotation around zero that maps p to q. Otherwise, returns the hyperbolic rotation around zero that maps q to p. // When inverse is 'false', returns the hyperbolic rotation around zero that maps p to q.
// Otherwise, returns the hyperbolic rotation around zero that maps q to p.
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> hyperbolic_rotation(const typename Traits::Hyperbolic_point_2& p, const typename Traits::Hyperbolic_point_2& q, bool inverse=false); Hyperbolic_isometry_2<Traits> hyperbolic_rotation(const typename Traits::Hyperbolic_point_2& p,
const typename Traits::Hyperbolic_point_2& q,
bool inverse = false);
// Returns the hyperbolic isometry that maps p1 to q1 and p2 to q2 // returns the hyperbolic isometry that maps p1 to q1 and p2 to q2
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> isometry_pairing_the_sides(const typename Traits::Hyperbolic_point_2& p1, const typename Traits::Hyperbolic_point_2& p2, const typename Traits::Hyperbolic_point_2& q1, const typename Traits::Hyperbolic_point_2& q2); Hyperbolic_isometry_2<Traits> isometry_pairing_the_sides(const typename Traits::Hyperbolic_point_2& p1,
const typename Traits::Hyperbolic_point_2& p2,
const typename Traits::Hyperbolic_point_2& q1,
const typename Traits::Hyperbolic_point_2& q2);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits>::Hyperbolic_isometry_2(){ Hyperbolic_isometry_2<Traits>::
Hyperbolic_isometry_2()
{
set_to_identity(); set_to_identity();
} }
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits>::Hyperbolic_isometry_2(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3){ Hyperbolic_isometry_2<Traits>::
Hyperbolic_isometry_2(const Complex_number& c0,
const Complex_number& c1,
const Complex_number& c2,
const Complex_number& c3)
{
set_coefficients(c0,c1,c2,c3); set_coefficients(c0,c1,c2,c3);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
void Hyperbolic_isometry_2<Traits>::set_to_identity(){ void
Hyperbolic_isometry_2<Traits>::
set_to_identity()
{
set_coefficients(Complex_number(FT(1)), set_coefficients(Complex_number(FT(1)),
Complex_number(FT(0)), Complex_number(FT(0)),
Complex_number(FT(0)), Complex_number(FT(0)),
@ -95,7 +113,13 @@ void Hyperbolic_isometry_2<Traits>::set_to_identity(){
} }
template<class Traits> template<class Traits>
void Hyperbolic_isometry_2<Traits>::set_coefficients(const Complex_number& c0, const Complex_number& c1, const Complex_number& c2, const Complex_number& c3){ void
Hyperbolic_isometry_2<Traits>::
set_coefficients(const Complex_number& c0,
const Complex_number& c1,
const Complex_number& c2,
const Complex_number& c3)
{
set_coefficient(0, c0); set_coefficient(0, c0);
set_coefficient(1, c1); set_coefficient(1, c1);
set_coefficient(2, c2); set_coefficient(2, c2);
@ -103,39 +127,54 @@ void Hyperbolic_isometry_2<Traits>::set_coefficients(const Complex_number& c0, c
} }
template<class Traits> template<class Traits>
void Hyperbolic_isometry_2<Traits>::set_coefficient(int index, const Complex_number& coefficient){ void
Hyperbolic_isometry_2<Traits>::
set_coefficient(int index, const Complex_number& coefficient)
{
_coefficients[index] = coefficient; _coefficients[index] = coefficient;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
const typename Traits::Complex& Hyperbolic_isometry_2<Traits>::get_coefficient(int index) const{ const typename Traits::Complex&
Hyperbolic_isometry_2<Traits>::
get_coefficient(int index) const
{
return _coefficients[index]; return _coefficients[index];
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
typename Traits::Hyperbolic_point_2 Hyperbolic_isometry_2<Traits>::evaluate(const Point& point) const{ typename Traits::Hyperbolic_point_2
Complex_number z (point.x(), point.y()); Hyperbolic_isometry_2<Traits>::
evaluate(const Point& point) const
{
Complex_number z(point.x(), point.y());
Complex_number numerator_of_the_result = _coefficients[0] * z + _coefficients[1]; Complex_number numerator_of_the_result = _coefficients[0] * z + _coefficients[1];
Complex_number denominator_of_the_result = _coefficients[2] * z + _coefficients[3]; Complex_number denominator_of_the_result = _coefficients[2] * z + _coefficients[3];
Complex_number result = numerator_of_the_result / denominator_of_the_result; Complex_number result = numerator_of_the_result / denominator_of_the_result;
return Point(result.real(), result.imag()); return Point(result.real(), result.imag());
} }
template<class Traits> template<class Traits>
typename Traits::Hyperbolic_point_2 Hyperbolic_isometry_2<Traits>::operator()(const Point& point) const{ typename Traits::Hyperbolic_point_2
Hyperbolic_isometry_2<Traits>::
operator()(const Point& point) const
{
return evaluate(point); return evaluate(point);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> operator*(const Hyperbolic_isometry_2<Traits>& iso1, const Hyperbolic_isometry_2<Traits>& iso2) { Hyperbolic_isometry_2<Traits> operator*(const Hyperbolic_isometry_2<Traits>& iso1,
const Hyperbolic_isometry_2<Traits>& iso2)
{
Hyperbolic_isometry_2<Traits> result; Hyperbolic_isometry_2<Traits> result;
for (int i=0; i<2; i++){ for (int i=0; i<2; i++) {
for (int j=0; j<2; j++){ for (int j=0; j<2; j++) {
result.set_coefficient(2*i+j, result.set_coefficient(2*i+j,
iso1.get_coefficient(2*i) * iso2.get_coefficient(j) + iso1.get_coefficient(2*i+1) * iso2.get_coefficient(2+j)); iso1.get_coefficient(2*i) * iso2.get_coefficient(j) + iso1.get_coefficient(2*i+1) * iso2.get_coefficient(2+j));
} }
@ -146,10 +185,12 @@ template<class Traits>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> hyperbolic_translation(const typename Traits::Hyperbolic_point_2& p, bool inverse){ Hyperbolic_isometry_2<Traits> hyperbolic_translation(const typename Traits::Hyperbolic_point_2& p,
bool inverse)
{
typename Traits::Complex one (typename Traits::FT(1)); typename Traits::Complex one (typename Traits::FT(1));
typename Traits::Complex z; typename Traits::Complex z;
if (inverse){ if (inverse) {
z = typename Traits::Complex(p.x(), p.y()); z = typename Traits::Complex(p.x(), p.y());
} else { } else {
z = - typename Traits::Complex(p.x(), p.y()); z = - typename Traits::Complex(p.x(), p.y());
@ -160,10 +201,14 @@ Hyperbolic_isometry_2<Traits> hyperbolic_translation(const typename Traits::Hype
} }
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> hyperbolic_rotation(const typename Traits::Hyperbolic_point_2& p, const typename Traits::Hyperbolic_point_2& q, bool inverse){ Hyperbolic_isometry_2<Traits> hyperbolic_rotation(const typename Traits::Hyperbolic_point_2& p,
const typename Traits::Hyperbolic_point_2& q,
bool inverse)
{
typename Traits::Complex zero (typename Traits::FT(0)); typename Traits::Complex zero (typename Traits::FT(0));
Hyperbolic_isometry_2<Traits> result; Hyperbolic_isometry_2<Traits> result;
if (inverse){ if (inverse) {
result.set_coefficients(typename Traits::Complex(p.x(), p.y()), zero, zero, typename Traits::Complex(q.x(), q.y())); result.set_coefficients(typename Traits::Complex(p.x(), p.y()), zero, zero, typename Traits::Complex(q.x(), q.y()));
} else { } else {
result.set_coefficients(typename Traits::Complex(q.x(), q.y()), zero, zero, typename Traits::Complex(p.x(), p.y())); result.set_coefficients(typename Traits::Complex(q.x(), q.y()), zero, zero, typename Traits::Complex(p.x(), p.y()));
@ -172,11 +217,15 @@ Hyperbolic_isometry_2<Traits> hyperbolic_rotation(const typename Traits::Hyperbo
} }
template<class Traits> template<class Traits>
Hyperbolic_isometry_2<Traits> isometry_pairing_the_sides(const typename Traits::Hyperbolic_point_2& p1, const typename Traits::Hyperbolic_point_2& p2, const typename Traits::Hyperbolic_point_2& q1, const typename Traits::Hyperbolic_point_2& q2){ Hyperbolic_isometry_2<Traits> isometry_pairing_the_sides(const typename Traits::Hyperbolic_point_2& p1,
const typename Traits::Hyperbolic_point_2& p2,
const typename Traits::Hyperbolic_point_2& q1,
const typename Traits::Hyperbolic_point_2& q2)
{
Hyperbolic_isometry_2<Traits> A,B,Binv,C; Hyperbolic_isometry_2<Traits> A,B,Binv,C;
A = hyperbolic_translation<Traits>(p1); A = hyperbolic_translation<Traits>(p1);
B = hyperbolic_translation<Traits>(q1); B = hyperbolic_translation<Traits>(q1);
Binv = hyperbolic_translation<Traits>(q1,true); Binv = hyperbolic_translation<Traits>(q1, true);
C = hyperbolic_rotation<Traits>(A.evaluate(p2), B.evaluate(q2)); C = hyperbolic_rotation<Traits>(A.evaluate(p2), B.evaluate(q2));
return (Binv*C)*A; return (Binv*C)*A;
} }

View File

@ -10,8 +10,6 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Hyperbolic_surface_traits_2
#ifndef CGAL_HYPERBOLIC_SURFACE_TRAITS_2 #ifndef CGAL_HYPERBOLIC_SURFACE_TRAITS_2
#define CGAL_HYPERBOLIC_SURFACE_TRAITS_2 #define CGAL_HYPERBOLIC_SURFACE_TRAITS_2
@ -19,12 +17,12 @@
#include <CGAL/Complex_number.h> #include <CGAL/Complex_number.h>
#include <iostream>
namespace CGAL { namespace CGAL {
template<class HyperbolicTraitsClass> template<class HyperbolicTraitsClass>
class Hyperbolic_surface_traits_2 : public HyperbolicTraitsClass { class Hyperbolic_surface_traits_2
: public HyperbolicTraitsClass
{
public: public:
typedef typename HyperbolicTraitsClass::FT FT; typedef typename HyperbolicTraitsClass::FT FT;
typedef typename HyperbolicTraitsClass::Hyperbolic_point_2 Hyperbolic_point_2; typedef typename HyperbolicTraitsClass::Hyperbolic_point_2 Hyperbolic_point_2;

View File

@ -10,20 +10,24 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the class Triangulation_on_hyperbolic_surface_2
#ifndef CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H #ifndef CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H
#define CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H #define CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H
#include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/Hyperbolic_fundamental_domain_2.h>
#include <CGAL/basic.h>
#include <CGAL/Combinatorial_map.h> #include <CGAL/Combinatorial_map.h>
#include <CGAL/Hyperbolic_fundamental_domain_2.h>
#include <CGAL/assertions.h>
#include <fstream>
#include <iostream>
#include <map> #include <map>
#include <vector>
#include <queue> #include <queue>
#include <vector>
#include <tuple>
#include <unordered_map>
#include <utility>
namespace CGAL { namespace CGAL {
@ -34,31 +38,32 @@ It is also possible to specify an anchor for the triangulation. An anchor consis
2) three points A,B,C in the hyperbolic plane. The points A,B,C are the three vertices in counter-clockwise order of a triangle. This triangle is a lift 2) three points A,B,C in the hyperbolic plane. The points A,B,C are the three vertices in counter-clockwise order of a triangle. This triangle is a lift
of T, and A is a lift of V. of T, and A is a lift of V.
*/ */
template<class Traits> template<class Traits>
struct Combinatorial_map_with_cross_ratios_item{ struct Combinatorial_map_with_cross_ratios_item
{
template <class CMap> template <class CMap>
struct Dart_wrapper{ struct Dart_wrapper
typedef Cell_attribute<CMap, Complex_number<typename Traits::FT>> Edge_attrib; {
typedef std::tuple<void,Edge_attrib,void> Attributes; typedef Cell_attribute<CMap, Complex_number<typename Traits::FT> > Edge_attrib;
}; typedef std::tuple<void, Edge_attrib, void> Attributes;
}; };
};
template<class Traits, class Attributes = Combinatorial_map_with_cross_ratios_item<Traits>> template<class Traits, class Attributes = Combinatorial_map_with_cross_ratios_item<Traits> >
class Triangulation_on_hyperbolic_surface_2 class Triangulation_on_hyperbolic_surface_2
{ {
public: public:
typedef Combinatorial_map<2, Attributes> Combinatorial_map_with_cross_ratios;
typedef Combinatorial_map<2,Attributes> Combinatorial_map_with_cross_ratios; struct Anchor
{
struct Anchor{
typename Combinatorial_map_with_cross_ratios::Dart_descriptor dart; typename Combinatorial_map_with_cross_ratios::Dart_descriptor dart;
typename Traits::Hyperbolic_point_2 vertices[3]; typename Traits::Hyperbolic_point_2 vertices[3];
}; };
typedef typename Combinatorial_map_with_cross_ratios::Dart_descriptor Dart_descriptor; typedef typename Combinatorial_map_with_cross_ratios::Dart_descriptor Dart_descriptor;
//typedef typename Combinatorial_map_with_cross_ratios::Dart_range Dart_range; // typedef typename Combinatorial_map_with_cross_ratios::Dart_range Dart_range;
// typedef typename Combinatorial_map_with_cross_ratios::Dart_range::iterator Dart_iterator; // typedef typename Combinatorial_map_with_cross_ratios::Dart_range::iterator Dart_iterator;
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<0> Vertex_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<0> Vertex_range;
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<1> Edge_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<1> Edge_range;
typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<2> Face_range; typedef typename Combinatorial_map_with_cross_ratios::template One_dart_per_cell_range<2> Face_range;
@ -80,7 +85,6 @@ public:
// Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap); // Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap);
Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap, Anchor& anchor); Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap, Anchor& anchor);
Combinatorial_map_with_cross_ratios& combinatorial_map(); Combinatorial_map_with_cross_ratios& combinatorial_map();
bool has_anchor() const; bool has_anchor() const;
Anchor& anchor(); Anchor& anchor();
@ -93,12 +97,11 @@ public:
void flip(Dart_descriptor dart); void flip(Dart_descriptor dart);
bool is_Delaunay() const; bool is_Delaunay() const;
int make_Delaunay(); int make_Delaunay();
std::vector<std::tuple<Dart_const_descriptor,Point,Point,Point>> lift(bool center=true) const; std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > lift(bool center=true) const;
bool is_valid() const; bool is_valid() const;
//The following methods are not documented but they are non private for internal future use. // The following methods are not documented but they are non private for internal future use.
Dart_descriptor ccw(Dart_descriptor dart); Dart_descriptor ccw(Dart_descriptor dart);
Dart_descriptor cw(Dart_descriptor dart); Dart_descriptor cw(Dart_descriptor dart);
Dart_descriptor opposite(Dart_descriptor dart); Dart_descriptor opposite(Dart_descriptor dart);
@ -108,19 +111,19 @@ public:
Complex_number get_cross_ratio(Dart_const_descriptor dart) const; Complex_number get_cross_ratio(Dart_const_descriptor dart) const;
// Returns the cross ratio of the points a,b,c,d // returns the cross ratio of the points a,b,c,d
Complex_number cross_ratio(const Point& a, const Point& b, const Point& c, const Point& d) const; Complex_number cross_ratio(const Point& a, const Point& b, const Point& c, const Point& d) const;
// Returns the point d such that the cross ratio of a,b,c,d is cratio // returns the point d such that the cross ratio of a,b,c,d is cratio
Point fourth_point_from_cross_ratio(const Point& a, const Point& b, const Point& c, const Complex_number& cratio) const; Point fourth_point_from_cross_ratio(const Point& a, const Point& b, const Point& c, const Complex_number& cratio) const;
// Wrapper around the Cmap for iterating over vertices, edges or faces. // Wrapper around the Cmap for iterating over vertices, edges or faces.
Vertex_range vertices_range(){ Vertex_range vertices_range() {
return _combinatorial_map.template one_dart_per_cell<0>(); return _combinatorial_map.template one_dart_per_cell<0>();
} }
Edge_range edges_range(){ Edge_range edges_range() {
return _combinatorial_map.template one_dart_per_cell<1>(); return _combinatorial_map.template one_dart_per_cell<1>();
} }
Face_range faces_range(){ Face_range faces_range() {
return _combinatorial_map.template one_dart_per_cell<2>(); return _combinatorial_map.template one_dart_per_cell<2>();
} }
Vertex_const_range vertices_const_range() const { Vertex_const_range vertices_const_range() const {
@ -153,22 +156,24 @@ protected:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::Triangulation_on_hyperbolic_surface_2(const Domain& domain){ Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::
Triangulation_on_hyperbolic_surface_2(const Domain& domain)
{
// (Triangulates by adding an internal edge between domain.vertex(size-1) and the other vertices) // (Triangulates by adding an internal edge between domain.vertex(size-1) and the other vertices)
_combinatorial_map.clear(); _combinatorial_map.clear();
int size = domain.size(); int size = domain.size();
// Make the triangles // Make the triangles
std::vector<Dart_descriptor> dart_of_triangle(size-2); std::vector<Dart_descriptor> dart_of_triangle(size-2);
for (int k=0; k<size-2; ++k){ for (int k=0; k<size-2; ++k) {
dart_of_triangle[k] = _combinatorial_map.make_combinatorial_polygon(3); dart_of_triangle[k] = _combinatorial_map.make_combinatorial_polygon(3);
} }
// Sew the internal edges and set their cross ratios // Sew the internal edges and set their cross ratios
Dart_descriptor dart_1, dart_2; Dart_descriptor dart_1, dart_2;
Point p0,p1,p2,p3; Point p0, p1, p2, p3;
for (int k=1; k<size-2; ++k){ for (int k=1; k<size-2; ++k) {
dart_1 = dart_of_triangle[k]; dart_1 = dart_of_triangle[k];
dart_2 = cw(dart_of_triangle[k-1]); dart_2 = cw(dart_of_triangle[k-1]);
@ -182,13 +187,13 @@ Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::Triangulation_on_hyper
} }
// Sew the boundary edges and set their cross ratios // Sew the boundary edges and set their cross ratios
for (int k1=0; k1<size; k1++){ for (int k1=0; k1<size; k1++) {
int k2 = domain.paired_side(k1); int k2 = domain.paired_side(k1);
p0 = domain.vertex((k1+1)%size); p0 = domain.vertex((k1+1)%size);
p2 = domain.vertex(k1); p2 = domain.vertex(k1);
if (k1 == size-1){ if (k1 == size-1) {
dart_1 = dart_of_triangle[0]; dart_1 = dart_of_triangle[0];
p1 = domain.vertex(1); p1 = domain.vertex(1);
} else if (k1 == size-2) { } else if (k1 == size-2) {
@ -199,7 +204,7 @@ Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::Triangulation_on_hyper
p1 = domain.vertex(size-1); p1 = domain.vertex(size-1);
} }
if (k2 == size-1){ if (k2 == size-1) {
dart_2 = dart_of_triangle[0]; dart_2 = dart_of_triangle[0];
p3 = domain.vertex(1); p3 = domain.vertex(1);
} else if (k2 == size-2) { } else if (k2 == size-2) {
@ -212,7 +217,7 @@ Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::Triangulation_on_hyper
p3 = domain.side_pairing(k1).evaluate(p3); p3 = domain.side_pairing(k1).evaluate(p3);
if (_combinatorial_map.template is_sewable<2>(dart_1, dart_2)){ if (_combinatorial_map.template is_sewable<2>(dart_1, dart_2)) {
_combinatorial_map.template sew<2>(dart_1, dart_2); _combinatorial_map.template sew<2>(dart_1, dart_2);
_combinatorial_map.template set_attribute<1>(dart_1, _combinatorial_map.template create_attribute<1>(cross_ratio(p0,p1,p2,p3))); _combinatorial_map.template set_attribute<1>(dart_1, _combinatorial_map.template create_attribute<1>(cross_ratio(p0,p1,p2,p3)));
} }
@ -227,38 +232,51 @@ Triangulation_on_hyperbolic_surface_2<Traits,Attributes>::Triangulation_on_hyper
} }
/* template<class Traits, class Attributes> */ /* template<class Traits, class Attributes> */
/* Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap){ */ /* Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap) { */
/* copy_from(cmap); */ /* copy_from(cmap); */
/* } */ /* } */
template<class Traits, class Attributes> template<class Traits, class Attributes>
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap, Anchor& anchor){ Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
Triangulation_on_hyperbolic_surface_2(Combinatorial_map_with_cross_ratios& cmap,
Anchor& anchor)
{
copy_from(cmap, anchor); copy_from(cmap, anchor);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Combinatorial_map_with_cross_ratios& Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::combinatorial_map(){ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Combinatorial_map_with_cross_ratios&
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
combinatorial_map()
{
return _combinatorial_map; return _combinatorial_map;
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
bool Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::has_anchor() const { bool
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
has_anchor() const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
return _has_anchor; return _has_anchor;
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Anchor& typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Anchor&
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::anchor() { Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
anchor()
{
CGAL_precondition(is_valid() && has_anchor()); CGAL_precondition(is_valid() && has_anchor());
return _anchor; return _anchor;
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
const typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Anchor& const typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Anchor&
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::anchor() const { Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
anchor() const
{
CGAL_precondition(is_valid() && has_anchor()); CGAL_precondition(is_valid() && has_anchor());
return _anchor; return _anchor;
} }
@ -266,14 +284,21 @@ Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::anchor() const {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
bool Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::is_Delaunay_flippable(Dart_const_descriptor dart) const{ bool
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
is_Delaunay_flippable(Dart_const_descriptor dart) const
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
return ( get_cross_ratio(dart).imag()>Number(0) ); return (get_cross_ratio(dart).imag() > Number(0));
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::flip(Dart_descriptor dart){ void
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
flip(Dart_descriptor dart)
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
// First gather all the information needed // First gather all the information needed
Dart_descriptor a = opposite(dart); // Get a fresh descriptor Dart_descriptor a = opposite(dart); // Get a fresh descriptor
@ -292,30 +317,30 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::flip(Dart_descri
// Modify the anchor // Modify the anchor
if (_anchor.dart == a){ if (_anchor.dart == a) {
_anchor.dart = e; _anchor.dart = e;
_anchor.vertices[1] = Point(fourth_point_from_cross_ratio(_anchor.vertices[1], _anchor.vertices[2], _anchor.vertices[0], cross_ratio_AC)); _anchor.vertices[1] = Point(fourth_point_from_cross_ratio(_anchor.vertices[1], _anchor.vertices[2], _anchor.vertices[0], cross_ratio_AC));
} else if (_anchor.dart == b){ } else if (_anchor.dart == b) {
_anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[0], _anchor.vertices[1], _anchor.vertices[2], cross_ratio_AC)); _anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[0], _anchor.vertices[1], _anchor.vertices[2], cross_ratio_AC));
} else if (_anchor.dart == c){ } else if (_anchor.dart == c) {
_anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[2], _anchor.vertices[0], _anchor.vertices[1], cross_ratio_AC)); _anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[2], _anchor.vertices[0], _anchor.vertices[1], cross_ratio_AC));
} else if (_anchor.dart == d){ } else if (_anchor.dart == d) {
_anchor.dart = b; _anchor.dart = b;
_anchor.vertices[1] = Point(fourth_point_from_cross_ratio(_anchor.vertices[1], _anchor.vertices[2], _anchor.vertices[0], cross_ratio_AC)); _anchor.vertices[1] = Point(fourth_point_from_cross_ratio(_anchor.vertices[1], _anchor.vertices[2], _anchor.vertices[0], cross_ratio_AC));
} else if (_anchor.dart == e){ } else if (_anchor.dart == e) {
_anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[0], _anchor.vertices[1], _anchor.vertices[2], cross_ratio_AC)); _anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[0], _anchor.vertices[1], _anchor.vertices[2], cross_ratio_AC));
} else if (_anchor.dart == f){ } else if (_anchor.dart == f) {
_anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[2], _anchor.vertices[0], _anchor.vertices[1], cross_ratio_AC)); _anchor.vertices[2] = Point(fourth_point_from_cross_ratio(_anchor.vertices[2], _anchor.vertices[0], _anchor.vertices[1], cross_ratio_AC));
} }
// Compute the new cross ratios // Compute the new cross ratios
Complex_number one (Number(1), Number(0)); Complex_number one (Number(1), Number(0));
Complex_number cross_ratio_BD = (cross_ratio_AC) / ((cross_ratio_AC) - one) ; Complex_number cross_ratio_BD = (cross_ratio_AC) / ((cross_ratio_AC) - one);
Complex_number cross_ratio_AB_2 = one - (one - (cross_ratio_AB)) * (cross_ratio_AC) ; Complex_number cross_ratio_AB_2 = one - (one - (cross_ratio_AB)) * (cross_ratio_AC);
Complex_number cross_ratio_BC_2 = one - (one - (cross_ratio_BC)) / (cross_ratio_BD) ; Complex_number cross_ratio_BC_2 = one - (one - (cross_ratio_BC)) / (cross_ratio_BD);
Complex_number cross_ratio_CD_2 = one - (one - (cross_ratio_CD)) * (cross_ratio_AC) ; Complex_number cross_ratio_CD_2 = one - (one - (cross_ratio_CD)) * (cross_ratio_AC);
Complex_number cross_ratio_DA_2 = one - (one - (cross_ratio_DA)) / (cross_ratio_BD) ; Complex_number cross_ratio_DA_2 = one - (one - (cross_ratio_DA)) / (cross_ratio_BD);
// Make the topological flip // Make the topological flip
@ -346,30 +371,36 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::flip(Dart_descri
// Take care of the particular cases where we need to "flip again" // Take care of the particular cases where we need to "flip again"
if (opposite(e) == b){ if (opposite(e) == b) {
_combinatorial_map.template info<1>(e) = one - (one - cross_ratio_AB_2) * (cross_ratio_AC) ; _combinatorial_map.template info<1>(e) = one - (one - cross_ratio_AB_2) * (cross_ratio_AC);
} }
if (opposite(f) == c){ if (opposite(f) == c) {
_combinatorial_map.template info<1>(f) = one - (one - cross_ratio_BC_2) / (cross_ratio_BD) ; _combinatorial_map.template info<1>(f) = one - (one - cross_ratio_BC_2) / (cross_ratio_BD);
} }
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
bool Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::is_Delaunay() const{ bool
if (! is_valid()){ Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
is_Delaunay() const
{
if (! is_valid()) {
return false; return false;
} }
return (pick_edge_to_flip() == nullptr); return (pick_edge_to_flip() == nullptr);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
int Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::make_Delaunay(){ int
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
make_Delaunay()
{
CGAL_precondition(is_valid()); CGAL_precondition(is_valid());
int number_of_flips_done = 0; int number_of_flips_done = 0;
Dart_descriptor edge_to_flip = pick_edge_to_flip(); Dart_descriptor edge_to_flip = pick_edge_to_flip();
while (edge_to_flip != nullptr){ while (edge_to_flip != nullptr) {
flip(edge_to_flip); flip(edge_to_flip);
edge_to_flip = pick_edge_to_flip(); edge_to_flip = pick_edge_to_flip();
number_of_flips_done++; number_of_flips_done++;
@ -380,19 +411,31 @@ int Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::make_Delaunay(){
template<class Traits, class Attributes> template<class Traits, class Attributes>
std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor, typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point, typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point, typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point>> Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::lift(bool center) const{ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor,
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point,
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point,
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point> >
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
lift(bool center) const
{
CGAL_precondition(is_valid() && has_anchor()); CGAL_precondition(is_valid() && has_anchor());
std::vector<std::tuple<Dart_const_descriptor,Point,Point,Point>> realizations;
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > realizations;
size_t visited_darts_mark = _combinatorial_map.get_new_mark(); size_t visited_darts_mark = _combinatorial_map.get_new_mark();
_combinatorial_map.unmark_all(visited_darts_mark); _combinatorial_map.unmark_all(visited_darts_mark);
struct Compare { struct Compare
bool operator()(std::pair<Dart_const_descriptor,double> const & x, std::pair<Dart_const_descriptor,double> const & y) { {
bool operator()(const std::pair<Dart_const_descriptor,double>& x,
const std::pair<Dart_const_descriptor,double>& y)
{
return x.second > y.second; return x.second > y.second;
} }
}; };
std::priority_queue<std::pair<Dart_const_descriptor,double>, std::vector<std::pair<Dart_const_descriptor,double>>, Compare> queue;
std::priority_queue<std::pair<Dart_const_descriptor, double>,
std::vector<std::pair<Dart_const_descriptor, double> >, Compare> queue;
std::unordered_map<Dart_const_descriptor, Point> positions; std::unordered_map<Dart_const_descriptor, Point> positions;
@ -402,7 +445,7 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
_combinatorial_map.mark(const_ccw(_anchor.dart), visited_darts_mark); _combinatorial_map.mark(const_ccw(_anchor.dart), visited_darts_mark);
_combinatorial_map.mark(const_cw(_anchor.dart), visited_darts_mark); _combinatorial_map.mark(const_cw(_anchor.dart), visited_darts_mark);
if (center){ if (center) {
Isometry center_the_drawing = hyperbolic_translation<Traits>(_anchor.vertices[0]); Isometry center_the_drawing = hyperbolic_translation<Traits>(_anchor.vertices[0]);
positions[_anchor.dart] = center_the_drawing.evaluate(_anchor.vertices[0]); positions[_anchor.dart] = center_the_drawing.evaluate(_anchor.vertices[0]);
positions[const_ccw(_anchor.dart)] = center_the_drawing.evaluate(_anchor.vertices[1]); positions[const_ccw(_anchor.dart)] = center_the_drawing.evaluate(_anchor.vertices[1]);
@ -413,12 +456,16 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
positions[const_cw(_anchor.dart)] = _anchor.vertices[2]; positions[const_cw(_anchor.dart)] = _anchor.vertices[2];
} }
std::tuple<Dart_const_descriptor,Point,Point,Point> value = std::make_tuple(_anchor.dart, positions[_anchor.dart], positions[const_ccw(_anchor.dart)], positions[const_cw(_anchor.dart)]); std::tuple<Dart_const_descriptor, Point, Point, Point> value =
std::make_tuple(_anchor.dart,
positions[_anchor.dart],
positions[const_ccw(_anchor.dart)],
positions[const_cw(_anchor.dart)]);
realizations.push_back(value); realizations.push_back(value);
Complex_number anchor_z0 (_anchor.vertices[0].x(), _anchor.vertices[0].y()); Complex_number anchor_z0(_anchor.vertices[0].x(), _anchor.vertices[0].y());
Complex_number anchor_z1 (_anchor.vertices[1].x(), _anchor.vertices[1].y()); Complex_number anchor_z1(_anchor.vertices[1].x(), _anchor.vertices[1].y());
Complex_number anchor_z2 (_anchor.vertices[2].x(), _anchor.vertices[2].y()); Complex_number anchor_z2(_anchor.vertices[2].x(), _anchor.vertices[2].y());
double weight_of_anchor_dart = CGAL::to_double(norm(anchor_z0) + norm(anchor_z1)); double weight_of_anchor_dart = CGAL::to_double(norm(anchor_z0) + norm(anchor_z1));
double weight_of_ccw_anchor_dart = CGAL::to_double(norm(anchor_z1) + norm(anchor_z2)); double weight_of_ccw_anchor_dart = CGAL::to_double(norm(anchor_z1) + norm(anchor_z2));
@ -428,22 +475,20 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
queue.push(std::make_pair(const_ccw(_anchor.dart), weight_of_ccw_anchor_dart)); queue.push(std::make_pair(const_ccw(_anchor.dart), weight_of_ccw_anchor_dart));
queue.push(std::make_pair(const_cw(_anchor.dart), weight_of_cw_anchor_dart)); queue.push(std::make_pair(const_cw(_anchor.dart), weight_of_cw_anchor_dart));
while (! queue.empty()) {
while( ! queue.empty() ){
Dart_const_descriptor invader = queue.top().first; Dart_const_descriptor invader = queue.top().first;
queue.pop(); queue.pop();
Dart_const_descriptor invaded = const_opposite(invader); Dart_const_descriptor invaded = const_opposite(invader);
if (!_combinatorial_map.is_marked(invaded, visited_darts_mark)){ if (!_combinatorial_map.is_marked(invaded, visited_darts_mark)) {
_combinatorial_map.mark(invaded, visited_darts_mark); _combinatorial_map.mark(invaded, visited_darts_mark);
_combinatorial_map.mark(const_ccw(invaded), visited_darts_mark); _combinatorial_map.mark(const_ccw(invaded), visited_darts_mark);
_combinatorial_map.mark(const_cw(invaded), visited_darts_mark); _combinatorial_map.mark(const_cw(invaded), visited_darts_mark);
const Point &a = positions[const_ccw(invader)]; const Point& a = positions[const_ccw(invader)];
const Point &b = positions[const_cw(invader)]; const Point& b = positions[const_cw(invader)];
const Point &c = positions[invader]; const Point& c = positions[invader];
Complex_number cross_ratio = get_cross_ratio(invader); Complex_number cross_ratio = get_cross_ratio(invader);
positions[invaded] = a; positions[invaded] = a;
@ -451,18 +496,18 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
Point d = fourth_point_from_cross_ratio(a, b, c, cross_ratio); Point d = fourth_point_from_cross_ratio(a, b, c, cross_ratio);
positions[const_cw(invaded)] = d; positions[const_cw(invaded)] = d;
Complex_number za (a.x(), a.y()); Complex_number za(a.x(), a.y());
Complex_number zc (c.x(), c.y()); Complex_number zc(c.x(), c.y());
double invaded_distance_to_zero = CGAL::to_double(norm(za)); double invaded_distance_to_zero = CGAL::to_double(norm(za));
double invaded_ccw_distance_to_zero = CGAL::to_double(norm(zc)); double invaded_ccw_distance_to_zero = CGAL::to_double(norm(zc));
Complex_number znew (positions[const_cw(invaded)].x(), positions[const_cw(invaded)].y()); Complex_number znew(positions[const_cw(invaded)].x(), positions[const_cw(invaded)].y());
double invaded_cw_distance_to_zero = CGAL::to_double(norm(znew)); double invaded_cw_distance_to_zero = CGAL::to_double(norm(znew));
double invaded_ccw_weight = invaded_ccw_distance_to_zero + invaded_cw_distance_to_zero; double invaded_ccw_weight = invaded_ccw_distance_to_zero + invaded_cw_distance_to_zero;
double invaded_cw_weight = invaded_cw_distance_to_zero + invaded_distance_to_zero; double invaded_cw_weight = invaded_cw_distance_to_zero + invaded_distance_to_zero;
queue.push( std::make_pair(const_ccw(invaded), invaded_ccw_weight) ); queue.push(std::make_pair(const_ccw(invaded), invaded_ccw_weight));
queue.push( std::make_pair(const_cw(invaded), invaded_cw_weight) ); queue.push(std::make_pair(const_cw(invaded), invaded_cw_weight));
value = std::make_tuple(invaded, Point(a), Point(c), Point(d)); value = std::make_tuple(invaded, Point(a), Point(c), Point(d));
realizations.push_back(value); realizations.push_back(value);
@ -477,33 +522,36 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
bool Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::is_valid() const{ bool
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
is_valid() const
{
// 1. Check the combinatorial map // 1. Check the combinatorial map
// Check that the combinatorial map is valid // Check that the combinatorial map is valid
if ( !_combinatorial_map.is_valid() ){ if (!_combinatorial_map.is_valid()) {
return false; return false;
} }
// Check that the combinatorial map has no 1,2-boundary // Check that the combinatorial map has no 1,2-boundary
for (int k=1; k<3; ++k){ for (int k=1; k<3; ++k) {
if ( !_combinatorial_map.is_without_boundary(k) ){ if (!_combinatorial_map.is_without_boundary(k)) {
return false; return false;
} }
} }
// 2. Check the anchor, if any // 2. Check the anchor, if any
if (_has_anchor){ if (_has_anchor) {
// Check that the dart descriptor of the anchor points to a dart of the combinatorial map // Check that the dart descriptor of the anchor points to a dart of the combinatorial map
if ( !_combinatorial_map.is_dart_used(_anchor.dart) ){ if (!_combinatorial_map.is_dart_used(_anchor.dart)) {
return false; return false;
} }
// Check that the three vertices of the anchor lie within the open unit disk // Check that the three vertices of the anchor lie within the open unit disk
for (int k=0; k<3; ++k){ for (int k=0; k<3; ++k) {
// if (_anchor.vertices[k].get_z() >= Number(1)){ // if (_anchor.vertices[k].get_z() >= Number(1)) {
if ( norm(Complex_number(_anchor.vertices[k].x(),_anchor.vertices[k].y())) >= Number(1)){ if (norm(Complex_number(_anchor.vertices[k].x(),_anchor.vertices[k].y())) >= Number(1)) {
return false; return false;
} }
} }
@ -515,12 +563,16 @@ bool Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::is_valid() const
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::to_stream(std::ostream& s) const{ void
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
to_stream(std::ostream& s) const
{
CGAL_precondition(is_valid() && has_anchor()); CGAL_precondition(is_valid() && has_anchor());
// Give indices to the darts // Give indices to the darts
std::map<Dart_const_descriptor, int> darts_indices; std::map<Dart_const_descriptor, int> darts_indices;
int current_dart_index = 0; int current_dart_index = 0;
for (typename Dart_const_range::const_iterator it=_combinatorial_map.darts().begin(); it!=_combinatorial_map.darts().end(); ++it){ for (typename Dart_const_range::const_iterator it=_combinatorial_map.darts().begin(); it!=_combinatorial_map.darts().end(); ++it) {
darts_indices[it] = current_dart_index; darts_indices[it] = current_dart_index;
current_dart_index++; current_dart_index++;
} }
@ -529,7 +581,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::to_stream(std::o
s << current_dart_index << std::endl; s << current_dart_index << std::endl;
// Store the anchor, if any // Store the anchor, if any
if (_has_anchor){ if (_has_anchor) {
s << "yes" << std::endl; s << "yes" << std::endl;
s << darts_indices[_anchor.dart] << std::endl; s << darts_indices[_anchor.dart] << std::endl;
s << _anchor.vertices[0] << std::endl; s << _anchor.vertices[0] << std::endl;
@ -540,14 +592,14 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::to_stream(std::o
} }
// Store the triangles // Store the triangles
for (typename Face_const_range::const_iterator it = faces_const_range().begin(); it != faces_const_range().end(); ++it){ for (typename Face_const_range::const_iterator it = faces_const_range().begin(); it != faces_const_range().end(); ++it) {
s << darts_indices[it] << std::endl; s << darts_indices[it] << std::endl;
s << darts_indices[const_cw(it)] << std::endl; s << darts_indices[const_cw(it)] << std::endl;
s << darts_indices[const_ccw(it)] << std::endl; s << darts_indices[const_ccw(it)] << std::endl;
} }
// Store the edges // Store the edges
for (typename Edge_const_range::const_iterator it = edges_const_range().begin(); it != edges_const_range().end(); ++it){ for (typename Edge_const_range::const_iterator it = edges_const_range().begin(); it != edges_const_range().end(); ++it) {
s << darts_indices[it] << std::endl; s << darts_indices[it] << std::endl;
s << darts_indices[const_opposite(it)] << std::endl; s << darts_indices[const_opposite(it)] << std::endl;
s << get_cross_ratio(it); s << get_cross_ratio(it);
@ -555,7 +607,10 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::to_stream(std::o
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std::istream& s){ void
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
from_stream(std::istream& s)
{
_combinatorial_map.clear(); _combinatorial_map.clear();
// Load the number of darts // Load the number of darts
@ -566,7 +621,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std:
// Load the anchor // Load the anchor
int anchor_dart_id; int anchor_dart_id;
s >> line; s >> line;
if (!line.compare("yes")){ if (!line.compare("yes")) {
_has_anchor = true; _has_anchor = true;
s >> line; s >> line;
@ -582,7 +637,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std:
// Load the triangles // Load the triangles
std::vector<Dart_descriptor> darts_by_id (nb_darts); std::vector<Dart_descriptor> darts_by_id (nb_darts);
int index1, index2, index3; int index1, index2, index3;
for (int k=0; k<nb_darts/3; ++k){ for (int k=0; k<nb_darts/3; ++k) {
Dart_descriptor triangle_dart = _combinatorial_map.make_combinatorial_polygon(3); Dart_descriptor triangle_dart = _combinatorial_map.make_combinatorial_polygon(3);
s >> line; s >> line;
@ -600,7 +655,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std:
// Load the edges // Load the edges
Dart_descriptor dart_1, dart_2; Dart_descriptor dart_1, dart_2;
Complex_number cross_ratio; Complex_number cross_ratio;
for (int k=0; k<nb_darts/2; ++k){ for (int k=0; k<nb_darts/2; ++k) {
s >> line; s >> line;
index1 = std::stoi(line); index1 = std::stoi(line);
s >> line; s >> line;
@ -613,7 +668,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std:
} }
// (*) here // (*) here
if (_has_anchor){ if (_has_anchor) {
_anchor.dart = darts_by_id[anchor_dart_id]; _anchor.dart = darts_by_id[anchor_dart_id];
} }
} }
@ -621,48 +676,50 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::from_stream(std:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::ccw(Dart_descriptor dart){ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::ccw(Dart_descriptor dart) {
return _combinatorial_map.beta(dart, 1); return _combinatorial_map.beta(dart, 1);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::cw(Dart_descriptor dart){ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::cw(Dart_descriptor dart) {
return _combinatorial_map.beta(dart, 0); return _combinatorial_map.beta(dart, 0);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::opposite(Dart_descriptor dart){ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::opposite(Dart_descriptor dart) {
return _combinatorial_map.opposite(dart); return _combinatorial_map.opposite(dart);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_ccw(Dart_const_descriptor dart) const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_ccw(Dart_const_descriptor dart) const {
return _combinatorial_map.beta(dart, 1); return _combinatorial_map.beta(dart, 1);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_cw(Dart_const_descriptor dart) const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_cw(Dart_const_descriptor dart) const {
return _combinatorial_map.beta(dart, 0); return _combinatorial_map.beta(dart, 0);
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_opposite(Dart_const_descriptor dart) const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::const_opposite(Dart_const_descriptor dart) const {
return _combinatorial_map.opposite(dart); return _combinatorial_map.opposite(dart);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Complex_number Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::get_cross_ratio(Dart_const_descriptor dart) const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Complex_number Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::get_cross_ratio(Dart_const_descriptor dart) const {
return _combinatorial_map.template info_of_attribute<1>(_combinatorial_map.template attribute<1>(dart)); return _combinatorial_map.template info_of_attribute<1>(_combinatorial_map.template attribute<1>(dart));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::pick_edge_to_flip(){ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
auto &cm=_combinatorial_map.darts(); pick_edge_to_flip()
for (auto it = cm.begin(); it != cm.end(); ++it){ {
if ( is_Delaunay_flippable(it) ){ auto& cm = _combinatorial_map.darts();
for (auto it=cm.begin(); it!=cm.end(); ++it) {
if (is_Delaunay_flippable(it)) {
return it; return it;
} }
} }
@ -672,10 +729,13 @@ template<class Traits, class Attributes>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::pick_edge_to_flip() const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Dart_const_descriptor
const auto &cm=_combinatorial_map.darts(); Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
for (auto it = cm.begin(); it != cm.end(); ++it){ pick_edge_to_flip() const
if ( is_Delaunay_flippable(it) ){ {
const auto& cm = _combinatorial_map.darts();
for (auto it=cm.begin(); it!=cm.end(); ++it) {
if (is_Delaunay_flippable(it) ) {
return it; return it;
} }
} }
@ -685,20 +745,27 @@ template<class Traits, class Attributes>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::copy_from(Combinatorial_map_with_cross_ratios& cmap){ void
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
copy_from(Combinatorial_map_with_cross_ratios& cmap)
{
//_combinatorial_map.copy_from_const(cmap); //_combinatorial_map.copy_from_const(cmap);
_combinatorial_map.copy(cmap); _combinatorial_map.copy(cmap);
_has_anchor = false; _has_anchor = false;
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::copy_from(Combinatorial_map_with_cross_ratios& cmap, const Anchor& anchor){ void
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
copy_from(Combinatorial_map_with_cross_ratios& cmap,
const Anchor& anchor)
{
// Because of the anchor, we must operate the copy ourself // Because of the anchor, we must operate the copy ourself
_combinatorial_map.clear(); _combinatorial_map.clear();
// Copy the triangles and fill the darts conversion table // Copy the triangles and fill the darts conversion table
std::map<Dart_const_descriptor, Dart_descriptor> darts_table; std::map<Dart_const_descriptor, Dart_descriptor> darts_table;
for (typename Face_const_range::const_iterator it=cmap.template one_dart_per_cell<2>().begin(); it!=cmap.template one_dart_per_cell<2>().end(); ++it){ for (typename Face_const_range::const_iterator it=cmap.template one_dart_per_cell<2>().begin(); it!=cmap.template one_dart_per_cell<2>().end(); ++it) {
Dart_descriptor new_dart = _combinatorial_map.make_combinatorial_polygon(3); Dart_descriptor new_dart = _combinatorial_map.make_combinatorial_polygon(3);
darts_table[it] = new_dart; darts_table[it] = new_dart;
darts_table[cmap.beta(it,0)] = _combinatorial_map.beta(new_dart,0); darts_table[cmap.beta(it,0)] = _combinatorial_map.beta(new_dart,0);
@ -706,7 +773,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::copy_from(Combin
} }
// Sew the edges and set their cross-ratios // Sew the edges and set their cross-ratios
for (typename Edge_const_range::const_iterator it=cmap.template one_dart_per_cell<1>().begin(); it!=cmap.template one_dart_per_cell<1>().end(); ++it){ for (typename Edge_const_range::const_iterator it=cmap.template one_dart_per_cell<1>().begin(); it!=cmap.template one_dart_per_cell<1>().end(); ++it) {
Dart_descriptor dart_1 = darts_table[it]; Dart_descriptor dart_1 = darts_table[it];
Dart_descriptor dart_2 = darts_table[cmap.opposite(it)]; Dart_descriptor dart_2 = darts_table[cmap.opposite(it)];
Complex_number cratio = cmap.template info_of_attribute<1>(cmap.template attribute<1>(it)); Complex_number cratio = cmap.template info_of_attribute<1>(cmap.template attribute<1>(it));
@ -719,7 +786,7 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::copy_from(Combin
// Set the anchor // Set the anchor
_anchor.dart = darts_table[anchor.dart]; _anchor.dart = darts_table[anchor.dart];
for (int k=0; k<3; ++k){ for (int k=0; k<3; ++k) {
_anchor.vertices[k] = anchor.vertices[k]; _anchor.vertices[k] = anchor.vertices[k];
} }
_has_anchor = true; _has_anchor = true;
@ -728,7 +795,10 @@ void Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::copy_from(Combin
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Traits::Complex Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::cross_ratio(const Point& a, const Point& b, const Point& c, const Point& d) const{ typename Traits::Complex
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
cross_ratio(const Point& a, const Point& b, const Point& c, const Point& d) const
{
Complex_number za (a.x(), a.y()); Complex_number za (a.x(), a.y());
Complex_number zb (b.x(), b.y()); Complex_number zb (b.x(), b.y());
Complex_number zc (c.x(), c.y()); Complex_number zc (c.x(), c.y());
@ -737,11 +807,15 @@ typename Traits::Complex Triangulation_on_hyperbolic_surface_2<Traits, Attribute
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::fourth_point_from_cross_ratio(const Point& a, const Point& b, const Point& c, const Complex_number& cratio) const{ typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Point
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
fourth_point_from_cross_ratio(const Point& a, const Point& b, const Point& c,
const Complex_number& cratio) const
{
Complex_number za (a.x(), a.y()); Complex_number za (a.x(), a.y());
Complex_number zb (b.x(), b.y()); Complex_number zb (b.x(), b.y());
Complex_number zc (c.x(), c.y()); Complex_number zc (c.x(), c.y());
Complex_number result = ( cratio*za*(zc-zb) + zb*(za-zc) ) / ( cratio*(zc-zb) + (za-zc) ); Complex_number result = ( cratio*za*(zc-zb) + zb*(za-zc) ) / ( cratio*(zc-zb) + (za-zc));
return Point(result.real(), result.imag()); return Point(result.real(), result.imag());
} }

View File

@ -10,35 +10,38 @@
// //
// Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud // Author(s) : Vincent Despré, Loïc Dubois, Marc Pouget, Monique Teillaud
// This file contains the declaration and the implementation of the input/output
// functions for the package Triangulation_on_hyperbolic_surface_2
#ifndef CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_IO_H #ifndef CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_IO_H
#define CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_IO_H #define CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_IO_H
#include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/basic.h>
#include <CGAL/assertions.h>
#include <iostream> #include <iostream>
namespace CGAL { namespace CGAL {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain){ std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<Traits>& domain)
{
CGAL_precondition(domain.is_valid()); CGAL_precondition(domain.is_valid());
return domain.to_stream(s); return domain.to_stream(s);
} }
template<class Traits> template<class Traits>
std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain){ std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain)
{
return domain.from_stream(s); return domain.from_stream(s);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits> template<class Traits>
std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry){ std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry)
for (int k=0; k<4; ++k){ {
for (int k=0; k<4; ++k) {
s << isometry.get_coefficient(k); s << isometry.get_coefficient(k);
} }
return s; return s;
@ -46,13 +49,15 @@ std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& i
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class Traits, class Attributes> template<class Traits, class Attributes>
std::ostream& operator<<(std::ostream& s, const Triangulation_on_hyperbolic_surface_2<Traits, Attributes>& triangulation){ std::ostream& operator<<(std::ostream& s, const Triangulation_on_hyperbolic_surface_2<Traits, Attributes>& triangulation)
{
triangulation.to_stream(s); triangulation.to_stream(s);
return s; return s;
} }
template<class Traits, class Attributes> template<class Traits, class Attributes>
void operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits, Attributes>& triangulation){ void operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits, Attributes>& triangulation)
{
triangulation.from_stream(s); triangulation.from_stream(s);
} }

View File

@ -1,15 +1,11 @@
# Created by the script cgal_create_cmake_script # Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application. # This is the CMake script for compiling a CGAL application.
cmake_minimum_required(VERSION 3.12...3.29) cmake_minimum_required(VERSION 3.12...3.31)
project(Triangulation_on_hyperbolic_surface_2_Tests) project(Triangulation_on_hyperbolic_surface_2_Tests)
find_package(CGAL REQUIRED) find_package(CGAL REQUIRED)
set(CMAKE_BUILD_TYPE "Debug")
include_directories(../../include/)
# create a target per cppfile # create a target per cppfile
file( file(
GLOB cppfiles GLOB cppfiles

View File

@ -12,6 +12,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <vector>
typedef CGAL::Circular_kernel_2<CGAL::Cartesian<CGAL::Exact_rational>,CGAL::Algebraic_kernel_for_circles_2_2<CGAL::Exact_rational>> Kernel; typedef CGAL::Circular_kernel_2<CGAL::Cartesian<CGAL::Exact_rational>,CGAL::Algebraic_kernel_for_circles_2_2<CGAL::Exact_rational>> Kernel;
typedef CGAL::Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits; typedef CGAL::Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
@ -22,15 +23,16 @@ typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Tria
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
int main() { int main()
{
Factory factory; Factory factory;
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459); Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459);
Triangulation triangulation0 = Triangulation(domain); Triangulation triangulation0 = Triangulation(domain);
assert( triangulation0.is_valid() ); assert(triangulation0.is_valid());
Triangulation triangulation (triangulation0); Triangulation triangulation (triangulation0);
assert( triangulation.has_anchor() ); assert(triangulation.has_anchor());
std::stringstream buffer; std::stringstream buffer;
buffer << triangulation; buffer << triangulation;
@ -44,7 +46,7 @@ int main() {
triangulation.make_Delaunay(); triangulation.make_Delaunay();
assert( triangulation.is_Delaunay() ); assert(triangulation.is_Delaunay());
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered;
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered;
@ -55,9 +57,9 @@ int main() {
Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map(); Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map();
Triangulation::Anchor& anchor = triangulation.anchor(); Triangulation::Anchor& anchor = triangulation.anchor();
assert( cmap.is_dart_used(anchor.dart) ); assert(cmap.is_dart_used(anchor.dart));
std::cout << "printing triangulation for test purposes : " << std::endl << triangulation; std::cout << "printing triangulation for test purposes: " << std::endl << triangulation;
return 0; return 0;
} }

View File

@ -10,13 +10,14 @@ typedef CGAL::Interval_nt<> Interval;
typedef CGAL::Complex_number<Exact_rational> Complex_rational; typedef CGAL::Complex_number<Exact_rational> Complex_rational;
typedef CGAL::Complex_number<Interval> Complex_interval; typedef CGAL::Complex_number<Interval> Complex_interval;
int main() { int main()
{
// Complex_rational tests : // Complex_rational tests :
Complex_rational zero_rational = Complex_rational (); Complex_rational zero_rational = Complex_rational ();
assert( zero_rational == Complex_rational(Exact_rational(0), Exact_rational(0)) ); assert(zero_rational == Complex_rational(Exact_rational(0), Exact_rational(0)));
Complex_rational one_rational (Exact_rational(1)); Complex_rational one_rational (Exact_rational(1));
assert( one_rational == Complex_rational(Exact_rational(1), Exact_rational(0)) ); assert(one_rational == Complex_rational(Exact_rational(1), Exact_rational(0)));
Complex_rational z1_rational (Exact_rational(1,2), Exact_rational(-3)); Complex_rational z1_rational (Exact_rational(1,2), Exact_rational(-3));
z1_rational = - z1_rational; z1_rational = - z1_rational;
@ -26,13 +27,13 @@ int main() {
z2_rational.imag(Exact_rational(11,13)); z2_rational.imag(Exact_rational(11,13));
z2_rational = conj(z2_rational) + z1_rational - one_rational; z2_rational = conj(z2_rational) + z1_rational - one_rational;
assert( - z1_rational * z1_rational / z2_rational == -Complex_rational(Exact_rational(855491,632146), Exact_rational(844298,316073)) ); assert(- z1_rational * z1_rational / z2_rational == -Complex_rational(Exact_rational(855491,632146), Exact_rational(844298,316073)));
assert( z1_rational.real() == Exact_rational(-1,2) ); assert(z1_rational.real() == Exact_rational(-1,2));
assert( z1_rational.imag() == Exact_rational(3) ); assert(z1_rational.imag() == Exact_rational(3));
assert( norm(z1_rational) == Exact_rational(37,4) ); assert(norm(z1_rational) == Exact_rational(37,4));
assert( z1_rational != z2_rational); assert(z1_rational != z2_rational);
assert( z2_rational == z2_rational ); assert(z2_rational == z2_rational);
assert( z2_rational == Complex_rational(Exact_rational(-31,14), Exact_rational(28,13)) ); assert(z2_rational == Complex_rational(Exact_rational(-31,14), Exact_rational(28,13)));
std::cout << "printing a complex for test purposes : " << std::endl << z2_rational << std::endl; std::cout << "printing a complex for test purposes : " << std::endl << z2_rational << std::endl;
@ -40,11 +41,11 @@ int main() {
std::stringstream buffer; std::stringstream buffer;
buffer << z2_rational; buffer << z2_rational;
buffer >> z3_rational; buffer >> z3_rational;
assert( z3_rational == z2_rational ); assert(z3_rational == z2_rational);
// Complex_interval test : // Complex_interval test :
Complex_interval z_interval (Interval(1, 2), Interval(1, 2)); Complex_interval z_interval (Interval(1, 2), Interval(1, 2));
assert( norm(z_interval * z_interval / Complex_interval(Interval(5, 6))) < Interval(10,20) ); assert(norm(z_interval * z_interval / Complex_interval(Interval(5, 6))) < Interval(10,20));
return 0; return 0;
} }

View File

@ -7,6 +7,7 @@
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h> #include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <iostream> #include <iostream>
#include <vector>
typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel; typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel;
typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits; typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
@ -18,7 +19,8 @@ typedef typename Traits::Hyperbolic_point_2 Point;
typedef typename Traits::Complex Complex; typedef typename Traits::Complex Complex;
int main() { int main()
{
std::vector<Point> vertices; std::vector<Point> vertices;
Point z0 = Point(FT("4881/5000"),FT("0")); Point z0 = Point(FT("4881/5000"),FT("0"));
Point z1 = Point(FT("9211/10000"),FT("2733/10000")); Point z1 = Point(FT("9211/10000"),FT("2733/10000"));
@ -38,39 +40,39 @@ int main() {
vertices.push_back(z7); vertices.push_back(z7);
std::vector<int> pairings; std::vector<int> pairings;
for (std::size_t k=0; k<8; ++k){ for (std::size_t k=0; k<8; ++k) {
pairings.push_back((k+4)%8); pairings.push_back((k+4)%8);
} }
Domain domain = Domain(vertices, pairings); Domain domain = Domain(vertices, pairings);
assert( domain.size()==8 ); assert(domain.size()==8);
for (std::size_t k=0; k<8; ++k){ for (std::size_t k=0; k<8; ++k) {
assert( domain.vertex(k)==vertices[k] ); assert(domain.vertex(k)==vertices[k]);
assert( domain.paired_side(k)==(k+4)%8 ); assert(domain.paired_side(k)==(k+4)%8);
assert( domain.side_pairing(k).evaluate(domain.vertex((k+4)%8))==domain.vertex((k+1)%8) ); assert(domain.side_pairing(k).evaluate(domain.vertex((k+4)%8))==domain.vertex((k+1)%8));
assert( domain.side_pairing(k).evaluate(domain.vertex((k+5)%8))==domain.vertex(k) ); assert(domain.side_pairing(k).evaluate(domain.vertex((k+5)%8))==domain.vertex(k));
} }
assert( domain.is_valid() ); assert(domain.is_valid());
Domain domain_prime = Domain(vertices, pairings); Domain domain_prime = Domain(vertices, pairings);
assert( domain_prime.size()==8 ); assert(domain_prime.size()==8);
for (std::size_t k=0; k<8; ++k){ for (std::size_t k=0; k<8; ++k) {
assert( domain_prime.vertex(k)==vertices[k]); assert(domain_prime.vertex(k)==vertices[k]);
assert( domain_prime.paired_side(k)==(k+4)%8 ); assert(domain_prime.paired_side(k)==(k+4)%8);
assert( domain_prime.side_pairing(k).evaluate(domain_prime.vertex((k+4)%8))==domain_prime.vertex((k+1)%8) ); assert(domain_prime.side_pairing(k).evaluate(domain_prime.vertex((k+4)%8))==domain_prime.vertex((k+1)%8));
assert( domain_prime.side_pairing(k).evaluate(domain_prime.vertex((k+5)%8))==domain_prime.vertex(k) ); assert(domain_prime.side_pairing(k).evaluate(domain_prime.vertex((k+5)%8))==domain_prime.vertex(k));
} }
Domain domain_ter = Domain(); Domain domain_ter = Domain();
std::stringstream buffer; std::stringstream buffer;
buffer << domain; buffer << domain;
buffer >> domain_ter; buffer >> domain_ter;
assert( domain_ter.size()==8 ); assert(domain_ter.size()==8);
for (std::size_t k=0; k<8; ++k){ for (std::size_t k=0; k<8; ++k) {
assert( domain_ter.vertex(k)==vertices[k]); assert(domain_ter.vertex(k)==vertices[k]);
assert( domain_ter.paired_side(k)==(k+4)%8 ); assert(domain_ter.paired_side(k)==(k+4)%8);
} }
std::cout << "printing a domain for test purposes : " << std::endl << domain << std::endl; std::cout << "printing a domain for test purposes : " << std::endl << domain << std::endl;

View File

@ -6,6 +6,7 @@
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h> #include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <iostream> #include <iostream>
#include <vector>
typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel; typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel;
typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits; typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
@ -17,8 +18,8 @@ typedef typename Traits::FT FT;
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
typedef typename Traits::Complex Complex; typedef typename Traits::Complex Complex;
int main()
int main() { {
Factory factory; Factory factory;
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459); Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459);
@ -40,10 +41,10 @@ int main() {
vertices.push_back(z6); vertices.push_back(z6);
vertices.push_back(z7); vertices.push_back(z7);
assert( domain.size()==8 ); assert(domain.size()==8);
for (std::size_t k=0; k<8; ++k){ for (std::size_t k=0; k<8; ++k) {
assert( domain.vertex(k)==vertices[k]); assert(domain.vertex(k)==vertices[k]);
assert( domain.paired_side(k)==(k+4)%8 ); assert(domain.paired_side(k)==(k+4)%8);
} }
return 0; return 0;

View File

@ -17,69 +17,69 @@ typedef typename Traits::FT FT;
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
typedef typename Traits::Complex Complex; typedef typename Traits::Complex Complex;
int main()
int main() { {
Isometry identity_1 = Isometry (); Isometry identity_1 = Isometry ();
assert( identity_1.get_coefficient(0)==Complex(FT(1)) ); assert(identity_1.get_coefficient(0)==Complex(FT(1)));
assert( identity_1.get_coefficient(1)==Complex(FT(0)) ); assert(identity_1.get_coefficient(1)==Complex(FT(0)));
assert( identity_1.get_coefficient(2)==Complex(FT(0)) ); assert(identity_1.get_coefficient(2)==Complex(FT(0)));
assert( identity_1.get_coefficient(3)==Complex(FT(1)) ); assert(identity_1.get_coefficient(3)==Complex(FT(1)));
Isometry identity_2; Isometry identity_2;
identity_2.set_to_identity(); identity_2.set_to_identity();
assert( identity_2.get_coefficient(0)==Complex(FT(1)) ); assert(identity_2.get_coefficient(0)==Complex(FT(1)));
assert( identity_2.get_coefficient(1)==Complex(FT(0)) ); assert(identity_2.get_coefficient(1)==Complex(FT(0)));
assert( identity_2.get_coefficient(2)==Complex(FT(0)) ); assert(identity_2.get_coefficient(2)==Complex(FT(0)));
assert( identity_2.get_coefficient(3)==Complex(FT(1)) ); assert(identity_2.get_coefficient(3)==Complex(FT(1)));
Isometry f; Isometry f;
f.set_coefficient(0, Complex(FT(-12,17), FT(1,3))); f.set_coefficient(0, Complex(FT(-12,17), FT(1,3)));
f.set_coefficient(1, Complex(FT(56,7), FT(21,5))); f.set_coefficient(1, Complex(FT(56,7), FT(21,5)));
f.set_coefficient(2, Complex(FT(56,7), FT(-21,5))); f.set_coefficient(2, Complex(FT(56,7), FT(-21,5)));
f.set_coefficient(3, Complex(FT(-12,17), FT(-1,3))); f.set_coefficient(3, Complex(FT(-12,17), FT(-1,3)));
assert( f.get_coefficient(0)==Complex(FT(-12,17), FT(1,3)) ); assert(f.get_coefficient(0)==Complex(FT(-12,17), FT(1,3)));
assert( f.get_coefficient(1)==Complex(FT(56,7), FT(21,5)) ); assert(f.get_coefficient(1)==Complex(FT(56,7), FT(21,5)));
assert( f.get_coefficient(2)==Complex(FT(56,7), FT(-21,5)) ); assert(f.get_coefficient(2)==Complex(FT(56,7), FT(-21,5)));
assert( f.get_coefficient(3)==Complex(FT(-12,17), FT(-1,3)) ); assert(f.get_coefficient(3)==Complex(FT(-12,17), FT(-1,3)));
Isometry g; Isometry g;
g.set_coefficients(Complex(FT(-12,17), FT(1,3)), Complex(FT(56,7), FT(21,5)), Complex(FT(56,7), FT(-21,5)), Complex(FT(-12,17), FT(-1,3))); g.set_coefficients(Complex(FT(-12,17), FT(1,3)), Complex(FT(56,7), FT(21,5)), Complex(FT(56,7), FT(-21,5)), Complex(FT(-12,17), FT(-1,3)));
assert( g.get_coefficient(0)==Complex(FT(-12,17), FT(1,3)) ); assert(g.get_coefficient(0)==Complex(FT(-12,17), FT(1,3)));
assert( g.get_coefficient(1)==Complex(FT(56,7), FT(21,5)) ); assert(g.get_coefficient(1)==Complex(FT(56,7), FT(21,5)));
assert( g.get_coefficient(2)==Complex(FT(56,7), FT(-21,5)) ); assert(g.get_coefficient(2)==Complex(FT(56,7), FT(-21,5)));
assert( g.get_coefficient(3)==Complex(FT(-12,17), FT(-1,3)) ); assert(g.get_coefficient(3)==Complex(FT(-12,17), FT(-1,3)));
Isometry h = f*g; Isometry h = f*g;
assert( h.get_coefficient(0) == Complex(FT(5333816,65025),FT(-8,17)) ); assert(h.get_coefficient(0) == Complex(FT(5333816,65025),FT(-8,17)));
assert( h.get_coefficient(1) == Complex(FT(-192,17),FT(-504,85)) ); assert(h.get_coefficient(1) == Complex(FT(-192,17),FT(-504,85)));
assert( h.get_coefficient(2) == Complex(FT(-192,17),FT(504,85)) ); assert(h.get_coefficient(2) == Complex(FT(-192,17),FT(504,85)));
assert( h.get_coefficient(3) == Complex(FT(5333816,65025),FT(8,17)) ); assert(h.get_coefficient(3) == Complex(FT(5333816,65025),FT(8,17)));
Point point (FT(3,11),FT(-1,73)); Point point (FT(3,11),FT(-1,73));
Point image_point = h.evaluate(point); Point image_point = h.evaluate(point);
assert( image_point==Point(FT(9146011623056232,66567955527962869), FT(-12617302915955411,133135911055925738)) ); assert(image_point==Point(FT(9146011623056232,66567955527962869), FT(-12617302915955411,133135911055925738)));
std::cout << "printing an isometry for test purposes : " << std::endl << h; std::cout << "printing an isometry for test purposes : " << std::endl << h;
Isometry tau_1 = CGAL::hyperbolic_translation<Traits>(point); Isometry tau_1 = CGAL::hyperbolic_translation<Traits>(point);
Isometry tau_1_prime = CGAL::hyperbolic_translation<Traits>(Point (FT(-3,11),FT(1,73)), true); Isometry tau_1_prime = CGAL::hyperbolic_translation<Traits>(Point (FT(-3,11),FT(1,73)), true);
Isometry tau_1_inv = CGAL::hyperbolic_translation<Traits>(point, true); Isometry tau_1_inv = CGAL::hyperbolic_translation<Traits>(point, true);
assert( tau_1.evaluate(image_point) == tau_1_prime.evaluate(image_point) ); assert(tau_1.evaluate(image_point) == tau_1_prime.evaluate(image_point));
assert( (tau_1*tau_1_inv).evaluate(image_point) == image_point ); assert((tau_1*tau_1_inv).evaluate(image_point) == image_point);
Point p (FT(2,15),FT(0)); Point p (FT(2,15),FT(0));
Point q (FT(0),FT(17,93)); Point q (FT(0),FT(17,93));
Isometry rotation = CGAL::hyperbolic_rotation<Traits>(p, q); Isometry rotation = CGAL::hyperbolic_rotation<Traits>(p, q);
Isometry rotation_prime = CGAL::hyperbolic_rotation<Traits>(q, p, true); Isometry rotation_prime = CGAL::hyperbolic_rotation<Traits>(q, p, true);
Isometry rotation_inv = CGAL::hyperbolic_rotation<Traits>(p, q, true); Isometry rotation_inv = CGAL::hyperbolic_rotation<Traits>(p, q, true);
assert( rotation.evaluate(image_point) == rotation_prime.evaluate(image_point) ); assert(rotation.evaluate(image_point) == rotation_prime.evaluate(image_point));
assert( (rotation*rotation_inv).evaluate(image_point) == image_point ); assert((rotation*rotation_inv).evaluate(image_point) == image_point);
Point p_imag = rotation.evaluate(p); Point p_imag = rotation.evaluate(p);
Point q_imag = rotation.evaluate(q); Point q_imag = rotation.evaluate(q);
Isometry pairing = CGAL::isometry_pairing_the_sides<Traits>(p, q, p_imag, q_imag); Isometry pairing = CGAL::isometry_pairing_the_sides<Traits>(p, q, p_imag, q_imag);
assert( pairing.evaluate(p) == p_imag ); assert(pairing.evaluate(p) == p_imag);
assert( pairing.evaluate(q) == q_imag ); assert(pairing.evaluate(q) == q_imag);
return 0; return 0;
} }

View File

@ -2,13 +2,16 @@
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h> #include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <iostream>
#include <sstream>
#include <CGAL/Exact_rational.h> #include <CGAL/Exact_rational.h>
#include <CGAL/Lazy_exact_nt.h> #include <CGAL/Lazy_exact_nt.h>
#include <CGAL/Cartesian.h> #include <CGAL/Cartesian.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <iostream>
#include <sstream>
#include <tuple>
#include <vector>
typedef CGAL::Cartesian<CGAL::Lazy_exact_nt<CGAL::Exact_rational>> Kernel; typedef CGAL::Cartesian<CGAL::Lazy_exact_nt<CGAL::Exact_rational>> Kernel;
typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits; typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
@ -19,15 +22,16 @@ typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Tr
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
int main() { int main()
{
Factory factory; Factory factory;
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459); Domain domain = factory.make_hyperbolic_fundamental_domain_g2(3459);
Triangulation triangulation0 = Triangulation(domain); Triangulation triangulation0 = Triangulation(domain);
assert( triangulation0.is_valid() ); assert(triangulation0.is_valid());
Triangulation triangulation (triangulation0); Triangulation triangulation (triangulation0);
assert( triangulation.has_anchor() ); assert(triangulation.has_anchor());
std::stringstream buffer; std::stringstream buffer;
buffer << triangulation; buffer << triangulation;
@ -41,7 +45,7 @@ int main() {
triangulation.make_Delaunay(); triangulation.make_Delaunay();
assert( triangulation.is_Delaunay() ); assert(triangulation.is_Delaunay());
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered;
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered;
@ -49,12 +53,11 @@ int main() {
output_not_centered = triangulation.lift(false); output_not_centered = triangulation.lift(false);
output_centered = triangulation.lift(); output_centered = triangulation.lift();
Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map(); Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map();
Triangulation::Anchor& anchor = triangulation.anchor(); Triangulation::Anchor& anchor = triangulation.anchor();
assert( cmap.is_dart_used(anchor.dart) ); assert(cmap.is_dart_used(anchor.dart));
std::cout << "printing triangulation for test purposes : " << std::endl << triangulation; std::cout << "printing triangulation for test purposes: " << std::endl << triangulation;
return 0; return 0;
} }

View File

@ -1,13 +1,14 @@
#include <CGAL/Hyperbolic_surface_traits_2.h> #include <CGAL/Hyperbolic_surface_traits_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
#include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h> #include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <CGAL/Exact_rational.h> #include <CGAL/Exact_rational.h>
#include <CGAL/Cartesian.h> #include <CGAL/Cartesian.h>
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <vector>
typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel; typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel;
typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits; typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
@ -19,33 +20,35 @@ typedef typename Traits::FT FT;
typedef typename Traits::Hyperbolic_point_2 Point; typedef typename Traits::Hyperbolic_point_2 Point;
typedef typename Traits::Complex Complex; typedef typename Traits::Complex Complex;
Domain build_domain(){ Domain build_domain()
{
std::vector<Point> vertices; std::vector<Point> vertices;
vertices.push_back( Point(FT(809,10000),FT(0)) ); vertices.push_back( Point(FT(809,10000),FT(0)));
vertices.push_back( Point(FT(7359,10000),FT(1877,10000)) ); vertices.push_back( Point(FT(7359,10000),FT(1877,10000)));
vertices.push_back( Point(FT(-999,2500),FT(881,1000)) ); vertices.push_back( Point(FT(-999,2500),FT(881,1000)));
vertices.push_back( Point(FT("-22088524601252853411192791001942853611410938513/24711029456888649611435724068315791591836010000"),FT("9482675065452890527617859332378101016513362487/24711029456888649611435724068315791591836010000")) ); vertices.push_back( Point(FT("-22088524601252853411192791001942853611410938513/24711029456888649611435724068315791591836010000"),FT("9482675065452890527617859332378101016513362487/24711029456888649611435724068315791591836010000")));
vertices.push_back( Point(FT(-809,10000),FT(0)) ); vertices.push_back( Point(FT(-809,10000),FT(0)));
vertices.push_back( Point(FT(-7359,10000),FT(-1877,10000)) ); vertices.push_back( Point(FT(-7359,10000),FT(-1877,10000)));
vertices.push_back( Point(FT(999,2500),FT(-881,1000)) ); vertices.push_back( Point(FT(999,2500),FT(-881,1000)));
vertices.push_back( Point(FT("22088524601252853411192791001942853611410938513/24711029456888649611435724068315791591836010000"),FT("-9482675065452890527617859332378101016513362487/24711029456888649611435724068315791591836010000")) ); vertices.push_back( Point(FT("22088524601252853411192791001942853611410938513/24711029456888649611435724068315791591836010000"),FT("-9482675065452890527617859332378101016513362487/24711029456888649611435724068315791591836010000")));
std::vector<int> pairings; std::vector<int> pairings;
for (int k=0; k<8; ++k){ for (int k=0; k<8; ++k) {
pairings.push_back((k+4)%8); pairings.push_back((k+4)%8);
} }
return Domain(vertices, pairings); return Domain(vertices, pairings);
} }
int main() { int main()
{
Domain domain = build_domain(); Domain domain = build_domain();
Triangulation triangulation0 = Triangulation(domain); Triangulation triangulation0 = Triangulation(domain);
assert( triangulation0.is_valid() ); assert(triangulation0.is_valid());
Triangulation triangulation (triangulation0); Triangulation triangulation (triangulation0);
assert( triangulation.has_anchor() ); assert(triangulation.has_anchor());
std::stringstream buffer; std::stringstream buffer;
buffer << triangulation; buffer << triangulation;
@ -59,7 +62,7 @@ int main() {
triangulation.make_Delaunay(); triangulation.make_Delaunay();
assert( triangulation.is_Delaunay() ); assert(triangulation.is_Delaunay());
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_not_centered;
std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered; std::vector<std::tuple<typename Triangulation::Combinatorial_map_with_cross_ratios::Dart_const_handle,Point,Point,Point>> output_centered;
@ -69,9 +72,9 @@ int main() {
Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map(); Triangulation::Combinatorial_map_with_cross_ratios& cmap = triangulation.combinatorial_map();
Triangulation::Anchor& anchor = triangulation.anchor(); Triangulation::Anchor& anchor = triangulation.anchor();
assert( cmap.is_dart_used(anchor.dart) ); assert(cmap.is_dart_used(anchor.dart));
std::cout << "printing triangulation for test purposes : " << std::endl << triangulation; std::cout << "printing triangulation for test purposes: " << std::endl << triangulation;
return 0; return 0;
} }