mirror of https://github.com/CGAL/cgal
Merge 21b63cf7a9 into 26a5fc70e4
This commit is contained in:
commit
84dbd555f3
|
|
@ -714,6 +714,23 @@ note="Conference version: Symp. on Geometry Processing 2003"
|
|||
publisher={ACM New York, NY, USA}
|
||||
}
|
||||
|
||||
@InProceedings{cgal:dlpt-naihs-25,
|
||||
author = {Despr\'{e}, Vincent and Lanuel, Camille and Pouget, Marc and Teillaud, Monique},
|
||||
title = {{\epsilon-Net Algorithm Implementation on Hyperbolic Surfaces}},
|
||||
booktitle = {33rd Annual European Symposium on Algorithms (ESA 2025)},
|
||||
pages = {61:1--61:18},
|
||||
series = {Leibniz International Proceedings in Informatics (LIPIcs)},
|
||||
ISBN = {978-3-95977-395-9},
|
||||
ISSN = {1868-8969},
|
||||
year = {2025},
|
||||
volume = {351},
|
||||
editor = {Benoit, Anne and Kaplan, Haim and Wild, Sebastian and Herman, Grzegorz},
|
||||
publisher = {Schloss Dagstuhl -- Leibniz-Zentrum f{\"u}r Informatik},
|
||||
address = {Dagstuhl, Germany},
|
||||
doi = {10.4230/LIPIcs.ESA.2025.61},
|
||||
annote = {Keywords: Hyperbolic surface, Delaunay triangulation, Data structure, Combinatorial map, Implementation, CGAL}
|
||||
}
|
||||
|
||||
@article{cgal:dfg-cvtaa-99t,
|
||||
title={{Centroidal Voronoi Tessellations: Applications and Algorithms}},
|
||||
author={Du, Q. and Faber, V. and Gunzburger, M.},
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public:
|
|||
A predicate object. Must provide the function operator
|
||||
|
||||
`Oriented_side operator()(Hyperbolic_point_2 p, Hyperbolic_point_2 q, Hyperbolic_point_2 query),`
|
||||
which returns the position of the point `query` relative to the oriented hyperbolic
|
||||
which returns the position of the point `query` relative to the circle supporting the hyperbolic
|
||||
segment with vertices `p` and `q`.
|
||||
*/
|
||||
typedef unspecified_type Side_of_oriented_hyperbolic_segment_2;
|
||||
|
|
@ -105,6 +105,17 @@ public:
|
|||
*/
|
||||
typedef unspecified_type Is_Delaunay_hyperbolic;
|
||||
|
||||
/*!
|
||||
A predicate object. Must provide the function operator
|
||||
|
||||
`Orientation operator()(Hyperbolic_point_2 p, Hyperbolic_point_2 q, Hyperbolic_point_2 query),`
|
||||
|
||||
which returns the position of the point `query` relative to the oriented hyperbolic
|
||||
segment with vertices `p` and `q`.
|
||||
|
||||
*/
|
||||
typedef unspecified_type Hyperbolic_orientation_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Construction Types
|
||||
|
|
@ -167,6 +178,7 @@ public:
|
|||
Side_of_oriented_circle_2 side_of_oriented_circle_2_object();
|
||||
Side_of_oriented_hyperbolic_segment_2 side_of_oriented_hyperbolic_segment_2_object();
|
||||
Is_Delaunay_hyperbolic is_Delaunay_hyperbolic_object();
|
||||
Hyperbolic_orientation_2 hyperbolic_orientation_2();
|
||||
/// @}
|
||||
|
||||
/// \name
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ namespace internal {
|
|||
const Hyperbolic_point_2& q,
|
||||
const Hyperbolic_point_2& r) const
|
||||
{
|
||||
|
||||
Construct_circle_or_line_supporting_bisector<Traits> cclsb(_gt);
|
||||
|
||||
Hyperbolic_point_2 po(CGAL::ORIGIN);
|
||||
|
|
@ -76,6 +75,7 @@ namespace internal {
|
|||
typedef typename CK2_Intersection_traits<Traits, Circle_2, Circle_2>::type Intersection_result;
|
||||
std::vector< Intersection_result > inters;
|
||||
intersection(*c_pq, *c_qr, std::back_inserter(inters));
|
||||
CGAL_assertion(inters.size() != 0);
|
||||
|
||||
CGAL_assertion_code(bool ok=)
|
||||
assign(pair, inters[0]);
|
||||
|
|
@ -107,6 +107,7 @@ namespace internal {
|
|||
typedef typename CK2_Intersection_traits<Traits, Euclidean_line_2, Circle_2>::type Intersection_result;
|
||||
std::vector< Intersection_result > inters;
|
||||
intersection(*l, *c, std::back_inserter(inters));
|
||||
CGAL_assertion(inters.size() != 0);
|
||||
|
||||
CGAL_assertion_code(bool ok=)
|
||||
assign(pair,inters[0]);
|
||||
|
|
@ -366,6 +367,7 @@ public:
|
|||
typedef typename internal::Construct_circle_or_line_supporting_bisector<Self> Construct_circle_or_line_supporting_bisector;
|
||||
typedef internal::Construct_hyperbolic_segment_2<Self> Construct_hyperbolic_segment_2;
|
||||
typedef typename Base::Construct_segment_2 Construct_segment_2;
|
||||
typedef typename internal::Hyperbolic_orientation_2<Self> Hyperbolic_orientation_2;
|
||||
|
||||
public:
|
||||
Hyperbolic_Delaunay_triangulation_CK_traits_2(const Base& kernel = Base()) : Base(kernel) {}
|
||||
|
|
@ -411,6 +413,10 @@ public:
|
|||
compute_squared_Euclidean_distance_2_object() const
|
||||
{ return this->Base::compute_squared_distance_2_object(); }
|
||||
|
||||
Hyperbolic_orientation_2
|
||||
hyperbolic_orientation_2() const
|
||||
{ return Hyperbolic_orientation_2(*this); }
|
||||
|
||||
};
|
||||
|
||||
// Take out the code below to some separate file
|
||||
|
|
|
|||
|
|
@ -492,6 +492,7 @@ public:
|
|||
typedef internal::Construct_hyperbolic_bisector_2<Self> Construct_hyperbolic_bisector_2;
|
||||
typedef internal::Is_Delaunay_hyperbolic<Self> Is_Delaunay_hyperbolic;
|
||||
typedef internal::Side_of_oriented_hyperbolic_segment_2<Self> Side_of_oriented_hyperbolic_segment_2;
|
||||
typedef typename internal::Hyperbolic_orientation_2<Self> Hyperbolic_orientation_2;
|
||||
|
||||
// Needed for P4HT2
|
||||
typedef typename Kernel::Construct_bisector_2 Construct_Euclidean_bisector_2;
|
||||
|
|
@ -549,6 +550,10 @@ public:
|
|||
compute_squared_Euclidean_distance_2_object() const
|
||||
{ return this->Base::compute_squared_distance_2_object(); }
|
||||
|
||||
Hyperbolic_orientation_2
|
||||
hyperbolic_orientation_2() const
|
||||
{ return Hyperbolic_orientation_2(*this); }
|
||||
|
||||
}; // class Hyperbolic_Delaunay_triangulation_traits_2
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -258,6 +258,45 @@ private:
|
|||
const Traits& _gt;
|
||||
};
|
||||
|
||||
template <typename Traits>
|
||||
class Hyperbolic_orientation_2
|
||||
{
|
||||
typedef typename Traits::FT FT;
|
||||
typedef typename Traits::Hyperbolic_point_2 Hyperbolic_point_2;
|
||||
typedef typename Traits::Side_of_oriented_hyperbolic_segment_2 Side_of_oriented_hyperbolic_segment_2;
|
||||
|
||||
public:
|
||||
Hyperbolic_orientation_2(const Traits& gt = Traits()) : _gt(gt) {}
|
||||
|
||||
Orientation operator()(const Hyperbolic_point_2& p,
|
||||
const Hyperbolic_point_2& q,
|
||||
const Hyperbolic_point_2& query) const
|
||||
{
|
||||
Hyperbolic_point_2 origin = Hyperbolic_point_2(FT(0), FT(0));
|
||||
Orientation orientation_to_origin = orientation(p, origin, q);
|
||||
if (orientation_to_origin == COLLINEAR) {
|
||||
return orientation(p, q, query);
|
||||
}
|
||||
|
||||
Side_of_oriented_hyperbolic_segment_2 orientation_test = _gt.side_of_oriented_hyperbolic_segment_2_object();
|
||||
Oriented_side orientation_to_disk = orientation_test(p, q, query);
|
||||
if (orientation_to_disk == ON_POSITIVE_SIDE) {
|
||||
return orientation_to_origin;
|
||||
} else if (orientation_to_disk == ON_NEGATIVE_SIDE) {
|
||||
if (orientation_to_origin == LEFT_TURN) {
|
||||
return RIGHT_TURN;
|
||||
} else {
|
||||
return LEFT_TURN;
|
||||
}
|
||||
} else {
|
||||
return COLLINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Traits& _gt;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace CGAL
|
||||
|
|
|
|||
|
|
@ -12,15 +12,32 @@ set(CMAKE_AUTOMOC ON)
|
|||
# CGAL and its components
|
||||
find_package(CGAL REQUIRED COMPONENTS Core Qt6)
|
||||
find_package(Qt6 QUIET COMPONENTS Widgets)
|
||||
find_package(Qt6 QUIET COMPONENTS Svg)
|
||||
|
||||
if (NOT CGAL_Qt6_FOUND OR NOT Qt6_FOUND)
|
||||
message(STATUS "This project requires the Qt6 library, and will not be compiled.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Boost and its components
|
||||
find_package( Boost REQUIRED )
|
||||
|
||||
if ( NOT Boost_FOUND )
|
||||
message(STATUS "This project requires the Boost library, and will not be compiled.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# ui files, created with Qt Designer
|
||||
qt6_wrap_ui(UIS drawing_window_description.ui)
|
||||
|
||||
add_executable( Triangulation_on_hyperbolic_surface_2_demo Triangulation_on_hyperbolic_surface_2_demo.cpp window.cpp ${UIS})
|
||||
target_link_libraries(Triangulation_on_hyperbolic_surface_2_demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt6 Qt6::Widgets )
|
||||
target_link_libraries(Triangulation_on_hyperbolic_surface_2_demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt6 Qt6::Widgets Qt6::Svg)
|
||||
cgal_add_compilation_test(Triangulation_on_hyperbolic_surface_2_demo)
|
||||
|
||||
add_executable( Delaunay_triangulation_on_hyperbolic_surface_2_demo Delaunay_triangulation_on_hyperbolic_surface_2_demo.cpp window.cpp ${UIS})
|
||||
target_link_libraries(Delaunay_triangulation_on_hyperbolic_surface_2_demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt6 Qt6::Widgets Qt6::Svg)
|
||||
|
||||
add_executable( Hyperbolic_Dirichlet_domain_2_demo Hyperbolic_Dirichlet_domain_2_demo.cpp window.cpp ${UIS})
|
||||
target_link_libraries(Hyperbolic_Dirichlet_domain_2_demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt6 Qt6::Widgets Qt6::Svg)
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
#include "window.h"
|
||||
|
||||
#include <CGAL/Gmpq.h>
|
||||
#include <CGAL/Circular_kernel_2.h>
|
||||
#include <CGAL/Algebraic_kernel_for_circles_2_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
|
||||
using namespace CGAL;
|
||||
|
||||
typedef Gmpq NumberType;
|
||||
typedef Circular_kernel_2<Simple_cartesian<NumberType>,Algebraic_kernel_for_circles_2_2<NumberType>> Kernel;
|
||||
typedef Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
typedef Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
|
||||
typedef Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef Hyperbolic_isometry_2<Traits> Isometry;
|
||||
typedef Hyperbolic_fundamental_domain_factory_2<Traits> Factory;
|
||||
typedef Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_triangulation;
|
||||
|
||||
/*
|
||||
HOW TO USE THIS DEMO
|
||||
./Delaunay_triangulation_on_hyperbolic_surface_2_demo [epsilon] [surface seed] [precision]
|
||||
Without arguments, uses the default values defined below.
|
||||
*/
|
||||
|
||||
// DEFAULT VALUES
|
||||
double epsilon = 0.25;
|
||||
int seed = time(NULL);
|
||||
int p = 1;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc == 1) {
|
||||
std::cout << "HOW TO USE THIS DEMO:\n"
|
||||
<< "./Delaunay_triangulation_on_hyperbolic_surface_2_demo [epsilon] [surface seed] [precision]\n"
|
||||
<< "Without arguments, uses default values: epsilon = 0.25, random seed, precision = 1.\n"
|
||||
<< "WARNING: when not using the CGAL::Gmpq number type, precision is ignored and, instead, to_double is used to round coordinates of circumcenters.\n"
|
||||
<< "--------------------"
|
||||
<< std::endl;
|
||||
}
|
||||
// 1. Parse args and generate the input
|
||||
if (argc > 1) {
|
||||
epsilon = std::stod(argv[1]);
|
||||
}
|
||||
|
||||
Domain domain;
|
||||
if (argc <= 2) {
|
||||
std::cout << "Using random seed " << seed << std::endl;
|
||||
} else {
|
||||
seed = atoi(argv[2]);
|
||||
}
|
||||
Factory factory;
|
||||
std::cout << "Generating surface with seed " << seed << "..." << std::endl;
|
||||
domain = factory.make_hyperbolic_fundamental_domain_g2(seed);
|
||||
Delaunay_triangulation dt = Delaunay_triangulation(domain);
|
||||
|
||||
if (argc > 3) {
|
||||
p = atoi(argv[3]);
|
||||
}
|
||||
|
||||
// 2. Get a vertex
|
||||
// So that if you run the demo on a same surface but with different values of epsilon,
|
||||
// the drawing will be centered at the same vertex and it will look similar.
|
||||
Point v0 = dt.anchor().vertices[0];
|
||||
|
||||
// 3. Compute epsilon-net and display useful info
|
||||
if constexpr(!std::is_same<NumberType, Gmpq>::value) {
|
||||
std::cout << "WARNING: Not using the CGAL::Gmpq number type. Precision will be ignored and to_double approximation will be used instead." << std::endl;
|
||||
}
|
||||
std::cout << "Computing a " << epsilon << "-net with floating-point precision " << p*53 << "..." << std::endl;
|
||||
Timer timer;
|
||||
timer.start();
|
||||
std::cout << "Is epsilon-net? " << dt.epsilon_net(epsilon, p) << std::endl;
|
||||
timer.stop();
|
||||
std::cout << "Done in " << timer.time() << " seconds." << std::endl;
|
||||
dt.combinatorial_map().display_characteristics(std::cout) << std::endl;
|
||||
|
||||
// 4. SET THE FIRST ANCHOR OF THE DRAWING
|
||||
Anchor anchor = dt.locate(v0);
|
||||
int index = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (v0 == anchor.vertices[i]) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
Anchor start = Anchor();
|
||||
start.dart = anchor.dart;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
start.vertices[i] = anchor.vertices[(i + index) % 3];
|
||||
if (i < index) {
|
||||
start.dart = dt.Base::ccw(start.dart);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. DRAW
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("Delaunay triangulation on hyperbolic surface 2 Demo");
|
||||
DemoWindow window;
|
||||
window.item().draw_triangulation(dt, start);
|
||||
window.show();
|
||||
QStringList args = app.arguments();
|
||||
args.removeAt(0);
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include "window.h"
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Circular_kernel_2.h>
|
||||
#include <CGAL/Algebraic_kernel_for_circles_2_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
|
||||
#include <CGAL/Hyperbolic_Dirichlet_domain_2.h>
|
||||
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
|
||||
|
||||
typedef CGAL::Gmpq NumberType;
|
||||
typedef CGAL::Circular_kernel_2<CGAL::Simple_cartesian<NumberType>,CGAL::Algebraic_kernel_for_circles_2_2<NumberType>> Kernel;
|
||||
typedef CGAL::Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
typedef CGAL::Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
|
||||
typedef CGAL::Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef CGAL::Hyperbolic_fundamental_domain_factory_2<Traits> Factory;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int seed = time(NULL);
|
||||
std::cout << "Using seed " << seed << std::endl;
|
||||
Factory factory;
|
||||
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(seed);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("Hyperbolic Dirichlet domain 2 Demo");
|
||||
DemoWindow window;
|
||||
window.item().draw_Dirichlet(domain);
|
||||
window.show();
|
||||
QStringList args = app.arguments();
|
||||
args.removeAt(0);
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -1,17 +1,22 @@
|
|||
#include "window.h"
|
||||
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Gmpq.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
|
||||
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
using namespace CGAL;
|
||||
|
||||
typedef Simple_cartesian<Exact_rational> Kernel;
|
||||
typedef Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
|
||||
typedef Gmpq NumberType;
|
||||
typedef Circular_kernel_2<Simple_cartesian<NumberType>, Algebraic_kernel_for_circles_2_2<NumberType>> Kernel;
|
||||
typedef Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
|
||||
// typedef Simple_cartesian<NumberType> Kernel;
|
||||
// typedef Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
|
||||
typedef Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef Hyperbolic_fundamental_domain_factory_2<Traits> Factory;
|
||||
|
|
@ -31,7 +36,7 @@ int main(int argc, char** argv)
|
|||
|
||||
// 2. Draw the triangulation
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("Hyperbolic surfaces triangulation 2 Demo");
|
||||
app.setApplicationName("Triangulation on hyperbolic surface 2 Demo");
|
||||
|
||||
DemoWindow window;
|
||||
window.item().draw_triangulation(triangulation);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>720</height>
|
||||
<width>665</width>
|
||||
<height>710</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>771</width>
|
||||
<height>671</height>
|
||||
<width>650</width>
|
||||
<height>650</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -38,6 +38,34 @@
|
|||
</widget>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>665</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuSave_As">
|
||||
<property name="title">
|
||||
<string>Save As...</string>
|
||||
</property>
|
||||
<addaction name="actionSave_as_SVG"/>
|
||||
<addaction name="actionSave_as_PNG"/>
|
||||
</widget>
|
||||
<addaction name="menuSave_As"/>
|
||||
</widget>
|
||||
<action name="actionSave_as_SVG">
|
||||
<property name="text">
|
||||
<string>Save as SVG</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_as_PNG">
|
||||
<property name="text">
|
||||
<string>Save as PNG</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -17,15 +17,20 @@ DemoWindowItem::DemoWindowItem()
|
|||
{
|
||||
// Clear
|
||||
edges_.clear();
|
||||
dirichlet_edges_.clear();
|
||||
|
||||
// Prepare the pens
|
||||
poincare_disk_pen_.setStyle(Qt::SolidLine);
|
||||
poincare_disk_pen_.setWidth(8);
|
||||
poincare_disk_pen_.setWidth(4);
|
||||
poincare_disk_pen_.setBrush(Qt::black);
|
||||
|
||||
edges_pen_.setStyle(Qt::SolidLine);
|
||||
edges_pen_.setWidth(6);
|
||||
edges_pen_.setWidth(4);
|
||||
edges_pen_.setBrush(Qt::blue);
|
||||
|
||||
dirichlet_pen_.setStyle(Qt::SolidLine);
|
||||
dirichlet_pen_.setWidth(4);
|
||||
dirichlet_pen_.setBrush(Qt::red);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -34,6 +39,8 @@ void DemoWindowItem::paint(QPainter *painter,
|
|||
const QStyleOptionGraphicsItem*,
|
||||
QWidget*)
|
||||
{
|
||||
painter->setRenderHints(QPainter::Antialiasing); // for a smoother drawing ;)
|
||||
|
||||
// 1. Draw the poincaré disk
|
||||
QRectF circle_rect = QRectF(-poincare_disk_radius_in_pixels_-3,
|
||||
-poincare_disk_radius_in_pixels_-3,
|
||||
|
|
@ -49,6 +56,13 @@ void DemoWindowItem::paint(QPainter *painter,
|
|||
for (std::size_t i=0; i<edges_.size(); i++) {
|
||||
draw_edge(painter, edges_[i].first, edges_[i].second);
|
||||
}
|
||||
|
||||
// 3. Draw the Dirichlet domain, if any
|
||||
painter->setBrush(QBrush());
|
||||
painter->setPen(dirichlet_pen_);
|
||||
for (std::size_t i = 0; i < dirichlet_edges_.size(); i++) {
|
||||
draw_edge(painter, dirichlet_edges_[i].first, dirichlet_edges_[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
QRectF DemoWindowItem::boundingRect() const {
|
||||
|
|
@ -82,13 +96,57 @@ void DemoWindowItem::draw_triangulation(Triangulation& triangulation)
|
|||
}
|
||||
}
|
||||
|
||||
void DemoWindowItem::draw_triangulation(Delaunay_triangulation & triangulation, Anchor & anchor)
|
||||
{
|
||||
typedef std::vector < std::tuple < typename Delaunay_triangulation::Dart_const_descriptor, Point,
|
||||
Point, Point >> RealizationVector;
|
||||
RealizationVector realized_triangles;
|
||||
realized_triangles = triangulation.lift(anchor);
|
||||
|
||||
Point point_1, point_2, point_3;
|
||||
for (typename RealizationVector::iterator it = realized_triangles.begin(); it != realized_triangles.end(); ++it) {
|
||||
point_1 = std::get < 1 > (*it);
|
||||
point_2 = std::get < 2 > (*it);
|
||||
point_3 = std::get < 3 > (*it);
|
||||
|
||||
edges_.push_back(std::make_pair(point_1, point_2));
|
||||
edges_.push_back(std::make_pair(point_2, point_3));
|
||||
edges_.push_back(std::make_pair(point_3, point_1));
|
||||
}
|
||||
}
|
||||
|
||||
void DemoWindowItem::draw_triangles(std::vector < Anchor > anchors)
|
||||
{
|
||||
for (std::size_t i = 0; i < anchors.size(); i++) {
|
||||
Point p0 = anchors[i].vertices[0];
|
||||
Point p1 = anchors[i].vertices[1];
|
||||
Point p2 = anchors[i].vertices[2];
|
||||
|
||||
edges_.push_back(std::make_pair(p0, p1));
|
||||
edges_.push_back(std::make_pair(p1, p2));
|
||||
edges_.push_back(std::make_pair(p2, p0));
|
||||
}
|
||||
}
|
||||
|
||||
void DemoWindowItem::draw_Dirichlet(Domain & domain)
|
||||
{
|
||||
std::vector < Voronoi_point > vertices = CGAL::Dirichlet_vertices<Traits>(domain);
|
||||
int n = vertices.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Point v0 = Point(CGAL::to_double(vertices[i].x()), CGAL::to_double(vertices[i].y()));
|
||||
Point v1 =
|
||||
Point(CGAL::to_double(vertices[(i + 1) % n].x()), CGAL::to_double(vertices[(i + 1) % n].y()));
|
||||
dirichlet_edges_.push_back(std::make_pair(v0, v1));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DemoWindowItem::draw_point(QPainter* painter, Point position)
|
||||
{
|
||||
// First convert the point in doubles, well-scaled
|
||||
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()); // Take the opposite so that the drawing is not upside down
|
||||
|
||||
// Then draw a small circle
|
||||
QRectF circle_rect = QRectF(point_x-1, point_y-1, 3, 3);
|
||||
|
|
@ -100,10 +158,10 @@ void DemoWindowItem::draw_edge(QPainter* painter, Point source, Point target)
|
|||
// First convert the points coordinates to doubles
|
||||
|
||||
double src_x = CGAL::to_double(source.x());
|
||||
double src_y = CGAL::to_double(source.y());
|
||||
double src_y = - CGAL::to_double(source.y()); // Take the opposite so that the drawing is not upside down
|
||||
|
||||
double tar_x = CGAL::to_double(target.x());
|
||||
double tar_y = CGAL::to_double(target.y());
|
||||
double tar_y = - CGAL::to_double(target.y()); // Take the opposite so that the drawing is not upside down
|
||||
|
||||
// 0. If src and tar are too colinear or too close from each other then draw a line
|
||||
|
||||
|
|
@ -256,7 +314,7 @@ DemoWindow::DemoWindow() : DemosMainWindow()
|
|||
scene_.setSceneRect(-600, -600, 1200, 1200);
|
||||
item_ = new DemoWindowItem();
|
||||
scene_.addItem(item_);
|
||||
this->graphicsView->scale(0.5, -0.5); // Y-axis inversion
|
||||
this->graphicsView->scale(0.5, 0.5);
|
||||
|
||||
setWindowTitle("Hyperbolic surfaces triangulation 2 Demo");
|
||||
}
|
||||
|
|
@ -267,3 +325,58 @@ DemoWindowItem& DemoWindow::item()
|
|||
}
|
||||
|
||||
void DemoWindow::keyPressEvent(QKeyEvent*) {}
|
||||
|
||||
void DemoWindow::on_actionSave_as_SVG_triggered()
|
||||
{
|
||||
QString newPath = QFileDialog::getSaveFileName(this, tr("Save SVG"),
|
||||
path_, tr("SVG files (*.svg)"));
|
||||
|
||||
if (newPath.isEmpty())
|
||||
return;
|
||||
|
||||
path_ = newPath;
|
||||
|
||||
QRectF newSceneRect;
|
||||
QGraphicsScene *tempScene = new QGraphicsScene(scene_.sceneRect());
|
||||
tempScene->setBackgroundBrush(QBrush(Qt::transparent));
|
||||
tempScene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
|
||||
foreach(QGraphicsItem * item, scene_.items()) {
|
||||
newSceneRect |= item->mapToScene(item->boundingRect()).boundingRect();
|
||||
tempScene->addItem(item);
|
||||
}
|
||||
tempScene->setSceneRect(newSceneRect);
|
||||
tempScene->clearSelection();
|
||||
QSize sceneSize = newSceneRect.size().toSize();
|
||||
|
||||
QSvgGenerator generator;
|
||||
generator.setFileName(path_);
|
||||
generator.setSize(sceneSize);
|
||||
generator.setViewBox(QRect(-3, -3, 2 * sceneSize.width(), 2 * sceneSize.height()));
|
||||
generator.setDescription(QObject::tr("My canvas exported to Svg"));
|
||||
generator.setTitle(path_);
|
||||
QPainter painter;
|
||||
painter.begin(&generator);
|
||||
tempScene->render(&painter);
|
||||
painter.end();
|
||||
|
||||
tempScene->clear();
|
||||
delete tempScene;
|
||||
}
|
||||
|
||||
void DemoWindow::on_actionSave_as_PNG_triggered()
|
||||
{
|
||||
QString newPath = QFileDialog::getSaveFileName(this, tr("Save PNG"),
|
||||
path_, tr("PNG files (*.png)"));
|
||||
|
||||
if (newPath.isEmpty())
|
||||
return;
|
||||
|
||||
path_ = newPath;
|
||||
|
||||
QImage img(808, 808, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(Qt::white);
|
||||
QPainter p(&img);
|
||||
scene_.render(&p);
|
||||
p.end();
|
||||
img.save(path_, "PNG");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,21 +18,30 @@
|
|||
#include <CGAL/Qt/GraphicsItem.h>
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
|
||||
#include <QSvgGenerator>
|
||||
|
||||
// UI generated header
|
||||
#include "ui_drawing_window_description.h"
|
||||
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
#include <CGAL/Hyperbolic_Dirichlet_domain_2.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<CGAL::Exact_rational> Kernel;
|
||||
typedef CGAL::Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
|
||||
typedef CGAL::Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef Traits::Hyperbolic_point_2 Point;
|
||||
typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation;
|
||||
typedef CGAL::Gmpq NumberType;
|
||||
typedef CGAL::Circular_kernel_2<CGAL::Simple_cartesian<NumberType>,CGAL::Algebraic_kernel_for_circles_2_2<NumberType>> Kernel;
|
||||
typedef CGAL::Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
typedef CGAL::Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef Traits::Hyperbolic_point_2 Point;
|
||||
typedef typename Traits::Hyperbolic_Voronoi_point_2 Voronoi_point;
|
||||
typedef CGAL::Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangulation;
|
||||
typedef CGAL::Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_triangulation;
|
||||
typedef typename Delaunay_triangulation::Anchor Anchor;
|
||||
|
||||
class DemoWindowItem
|
||||
: public CGAL::Qt::GraphicsItem
|
||||
|
|
@ -45,10 +54,12 @@ private:
|
|||
|
||||
// Edges to draw
|
||||
std::vector<std::pair<Point,Point> > edges_;
|
||||
std::vector<std::pair<Point,Point> > dirichlet_edges_;
|
||||
|
||||
// Pens for drawing
|
||||
QPen poincare_disk_pen_;
|
||||
QPen edges_pen_;
|
||||
QPen dirichlet_pen_;
|
||||
|
||||
// radius of the poincaré disk
|
||||
const int poincare_disk_radius_in_pixels_ = 600;
|
||||
|
|
@ -67,8 +78,11 @@ public:
|
|||
QRectF boundingRect() const;
|
||||
void modelChanged();
|
||||
|
||||
// Drawing method
|
||||
// Drawing methods
|
||||
void draw_triangulation(Triangulation& triangulation);
|
||||
void draw_triangulation(Delaunay_triangulation& triangulation, Anchor& anchor);
|
||||
void draw_triangles(std::vector<Anchor> anchors);
|
||||
void draw_Dirichlet(Domain& domain);
|
||||
|
||||
private:
|
||||
// Sub-methods for drawing edges and vertices
|
||||
|
|
@ -95,6 +109,7 @@ class DemoWindow
|
|||
private:
|
||||
QGraphicsScene scene_;
|
||||
DemoWindowItem* item_;
|
||||
QString path_;
|
||||
|
||||
public:
|
||||
DemoWindow();
|
||||
|
|
@ -102,6 +117,10 @@ public:
|
|||
|
||||
// Events handling
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
public Q_SLOTS:
|
||||
void on_actionSave_as_SVG_triggered();
|
||||
void on_actionSave_as_PNG_triggered();
|
||||
};
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_DEMO_WINDOW
|
||||
|
|
|
|||
|
|
@ -0,0 +1,211 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
|
||||
|
||||
This item defines attributes for edges and faces.
|
||||
Edge attributes are of type `Complex_number` representing cross-ratios.
|
||||
Face attributes attributes are of type `Anchor` representing a lift of a triangle.
|
||||
|
||||
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
|
||||
|
||||
\cgalModels{GenericMapItems}
|
||||
*/
|
||||
template<class Traits>
|
||||
struct Delaunay_triangulation_attributes {
|
||||
template<class CMap>
|
||||
struct Dart_wrapper{
|
||||
typedef Cell_attribute<CMap, Complex_number<typename Traits::FT>> Edge_attrib;
|
||||
typedef Cell_attribute<CMap, typename Triangulation_on_hyperbolic_surface_2<Traits,Delaunay_triangulation_attributes<Traits>>::Anchor> Face_attrib;
|
||||
typedef std::tuple<void,Edge_attrib,Face_attrib> Attributes;
|
||||
};
|
||||
};
|
||||
|
||||
/*!
|
||||
\ingroup PkgHyperbolicSurfaceTriangulation2MainClasses
|
||||
|
||||
represents a Delaunay triangulation of a closed orientable hyperbolic surface.
|
||||
|
||||
The class provides functions such as the generation of the Delaunay triangulation from a convex fundamental domain,
|
||||
the location of a point in the lifted triangulation, the insertion of a point in the Delaunay triangulation, and the \f$ \varepsilon \f$-net algorithm.
|
||||
|
||||
\tparam Traits must be a model of `HyperbolicSurfaceTraits_2`.
|
||||
|
||||
\sa `Triangulation_on_hyperbolic_surface_2<Traits, Attributes>`
|
||||
*/
|
||||
template<class Traits>
|
||||
class Delaunay_triangulation_on_hyperbolic_surface_2: public Triangulation_on_hyperbolic_surface_2<Traits, Delaunay_triangulation_attributes<Traits>> {
|
||||
public:
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
typedef Triangulation_on_hyperbolic_surface_2<Traits,Delaunay_triangulation_attributes<Traits>> Base;
|
||||
/*!
|
||||
Type of combinatorial map whose edges are decorated with complex numbers and faces are decorated with anchors.
|
||||
*/
|
||||
typedef Combinatorial_map<2,Delaunay_triangulation_attributes<Traits>> CMap;
|
||||
typedef typename Triangulation_on_hyperbolic_surface_2<Traits,Delaunay_triangulation_attributes<Traits>>::Anchor Anchor;
|
||||
|
||||
typedef typename Traits::FT Number;
|
||||
typedef typename Traits::Complex Complex_number;
|
||||
|
||||
|
||||
/*!
|
||||
Point in the Poincaré disk.
|
||||
*/
|
||||
typedef typename Traits::Hyperbolic_point_2 Point;
|
||||
|
||||
typedef typename CMap::Dart_descriptor Dart_descriptor;
|
||||
typedef typename CMap::Dart_range Dart_range;
|
||||
typedef typename CMap::template One_dart_per_cell_range<0> Vertex_range;
|
||||
typedef typename CMap::template One_dart_per_cell_range<1> Edge_range;
|
||||
typedef typename CMap::template One_dart_per_cell_range<2> Face_range;
|
||||
typedef typename CMap::Dart_const_descriptor Dart_const_descriptor;
|
||||
typedef typename CMap::Dart_const_range Dart_const_range;
|
||||
typedef typename CMap::template One_dart_per_cell_const_range<1> Edge_const_range;
|
||||
typedef typename CMap::template One_dart_per_cell_const_range<2> Face_const_range;
|
||||
/// @}
|
||||
|
||||
/// \name Enums
|
||||
/// @{
|
||||
|
||||
/*
|
||||
The enumeration `Locate_type` is defined to specify which case occurs when locating a point in the lifted triangulation.
|
||||
*/
|
||||
enum Locate_type {
|
||||
VERTEX = 0,
|
||||
EDGE,
|
||||
FACE,
|
||||
OUTSIDE
|
||||
};
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
/// Calls the corresponding constructor from #Base and sets an #Anchor for each face.
|
||||
/// @{
|
||||
Delaunay_triangulation_on_hyperbolic_surface_2() {};
|
||||
Delaunay_triangulation_on_hyperbolic_surface_2(CMap & cmap, Anchor & anch);
|
||||
Delaunay_triangulation_on_hyperbolic_surface_2(Hyperbolic_fundamental_domain_2<Traits> const & domain);
|
||||
Delaunay_triangulation_on_hyperbolic_surface_2(Base & triangulation);
|
||||
/// @}
|
||||
|
||||
/// \name Access Functions
|
||||
/// @{
|
||||
/*!
|
||||
\return the anchor associated with the given dart.
|
||||
*/
|
||||
Anchor & anchor(Dart_descriptor const dart);
|
||||
/*!
|
||||
\return the anchor associated with the given dart.
|
||||
*/
|
||||
Anchor const & anchor(Dart_const_descriptor const dart) const;
|
||||
/*!
|
||||
\return an anchor of the triangulation.
|
||||
*/
|
||||
Anchor & anchor();
|
||||
/*!
|
||||
\return an anchor of the triangulation.
|
||||
*/
|
||||
Anchor const & anchor() const;
|
||||
/*!
|
||||
\return the index of the given dart in its face. The index is `0` if `dart` is the dart of its associated anchor.
|
||||
*/
|
||||
unsigned index_in_anchor(Dart_const_descriptor const dart) const;
|
||||
/*!
|
||||
\return the `i`-th dart of the face associated with `anch`, where `anch.dart` is the `0`-th dart of the face.
|
||||
*/
|
||||
Dart_descriptor ith_dart(unsigned i, Anchor const & anch);
|
||||
/// @}
|
||||
|
||||
/// \name Validity
|
||||
/*!
|
||||
\return a Boolean that indicates whether the triangulation is a valid Delaunay triangulation.
|
||||
*/
|
||||
bool is_valid() const;
|
||||
|
||||
/// \name Point location and insertion
|
||||
/// @{
|
||||
/*!
|
||||
\return a `Locate_type` that indicates whether `query` lies on a vertex, an edge, inside or outside the lifted triangle described by the given anchor.
|
||||
|
||||
If `query` lies on a vertex or an edge, the index `li` is set to the index of the vertex or edge on which `query` lies.
|
||||
|
||||
If `query` lies inside the triangle, `li` is set to `-1`.
|
||||
|
||||
If `query` lies outside the triangle, `li` is set to the index of the first edge such that `query` and the third point of the triangle lies on different sides.
|
||||
*/
|
||||
Locate_type relative_position(Point const & query, unsigned & li, Anchor const & anch) const;
|
||||
|
||||
/*!
|
||||
\return the anchor representing the lift of the triangle in which `query` lies.
|
||||
|
||||
Locates `query` in the Delaunay triangulation.
|
||||
|
||||
The Boolean `use_visibility` indicates whether the visibility walk algorithm is used for the point location. When `false`, the straight walk algorithm is used.
|
||||
*/
|
||||
Anchor locate(Point const & query, bool use_visibility = false); // const ?
|
||||
/*!
|
||||
Same as above.
|
||||
|
||||
Additionally, the point location algorithm starts from `hint` and `ld` is set to the number or triangle travarsed by the walk used for the point location algorithm.
|
||||
|
||||
The variables `lt` and `li` contains information about the triangle in which `query` has been found.
|
||||
|
||||
\sa relative_position
|
||||
*/
|
||||
Anchor locate(Point const & query, Locate_type & lt, unsigned & li, unsigned & ld, Anchor const & hint, bool use_visibility = false); // const ?
|
||||
|
||||
/*!
|
||||
Inserts `query` in the Delaunay triangulation after having located it, starting from `hint`.
|
||||
|
||||
\pre <code>is_valid()</code> and <code>norm(Complex_number(query.x(), query.y())) < Number(1)</code>
|
||||
*/
|
||||
void insert(Point const & query, Anchor & hint);
|
||||
|
||||
/*!
|
||||
Inserts `query` in the Delaunay triangulation.
|
||||
*/
|
||||
void insert(Point const & query);
|
||||
/// @}
|
||||
|
||||
/// \name \f$ \varepsilon \f$-net
|
||||
/// @{
|
||||
/*!
|
||||
\return a Boolean that indicates whether the vertices of the Delaunay triangulation form a certified `epsilon`-net of the surface.
|
||||
|
||||
Tries to compute an `epsilon`-net of the surface.
|
||||
|
||||
When `Number` is `CGAL::Gmpq`, the algorithm rounds the coordinate of circumcenters to `CGAL::Gmpfr` with precision `p*53`.
|
||||
When `Number` is <em>not</em> `CGAL::Gmpq`, `p` is ignored.
|
||||
|
||||
\pre <code>is_epsilon_packing(epsilon)</code> and <code>p > 0</code>
|
||||
*/
|
||||
bool epsilon_net(double const epsilon, unsigned const p = 1);
|
||||
/*!
|
||||
\return a Boolean that indicates whether the vertices of the Delaunay triangulation form a certified `epsilon`-covering of the surface.
|
||||
*/
|
||||
bool is_epsilon_covering(const double epsilon) const;
|
||||
/*!
|
||||
\return a Boolean that indicates whether the vertices of the Delaunay triangulation form a certified `epsilon`-packing of the surface.
|
||||
*/
|
||||
bool is_epsilon_packing(const double epsilon) const;
|
||||
/*!
|
||||
\return a Boolean that indicates whether the vertices of the Delaunay triangulation form a certified `epsilon`-net of the surface.
|
||||
*/
|
||||
bool is_epsilon_net(const double epsilon) const;
|
||||
/// @}
|
||||
|
||||
/// \name Other functions
|
||||
/// @{
|
||||
/*!
|
||||
\return a `double` approximation of the length of the shortest geodesic loop edge in the Delaunay triangulation. Returns 0 (NULL) if there is no loop edge.
|
||||
*/
|
||||
double shortest_loop_edge() const;
|
||||
/*!
|
||||
\return a `double` approximation of the length of the shortest non-loop edge in the Delaunay triangulation. Returns 0 (NULL) if all edges are loops.
|
||||
*/
|
||||
double shortest_non_loop_edge() const;
|
||||
/// @}
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
\ingroup PkgHyperbolicSurfaceTriangulation2DirichletDomain
|
||||
|
||||
\return a vector with the vertices of a Dirichlet domain whose base point is translated to the origin of the Poincaré disk.
|
||||
|
||||
@param domain must be a fundamental domain whose vertices represent a same point on the corresponding hyperbolic surface.
|
||||
*/
|
||||
std::vector<typename Traits::Hyperbolic_Voronoi_point_2> Dirichlet_vertices(Hyperbolic_fundamental_domain_2<Traits> & domain);
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -126,16 +126,6 @@ public:
|
|||
|
||||
/// @}
|
||||
|
||||
/// \name Assignment
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
\pre <code> other.is_valid() </code>
|
||||
*/
|
||||
Triangulation_on_hyperbolic_surface_2& operator=(Triangulation_on_hyperbolic_surface_2 other);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Access Functions
|
||||
/// @{
|
||||
|
||||
|
|
@ -233,7 +223,18 @@ Vertex_range vertices_range();
|
|||
|
||||
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.
|
||||
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 the first vertex of the given anchor is translated to the origin \f$ 0 \f$.
|
||||
|
||||
\pre <code> is_valid() </code>
|
||||
*/
|
||||
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > lift(Anchor const & anchor, bool center=true) const;
|
||||
|
||||
/*!
|
||||
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.
|
||||
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 the first vertex of the anchor is translated to the origin \f$ 0 \f$.
|
||||
|
||||
\pre <code> is_valid() && has_anchor() </code>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace CGAL {
|
|||
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.
|
||||
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 two lines on which the cross ratio of \f$ e \f$ is printed.
|
||||
|
||||
\pre <code> Triangulation_on_hyperbolic_surface_2<Traits>::is_valid() </code>
|
||||
*/
|
||||
|
|
@ -24,7 +24,7 @@ std::ostream& operator<<(std::ostream& s, const Triangulation_on_hyperbolic_surf
|
|||
|
||||
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 is the same as the format of the output of
|
||||
the '<<' operator for Triangulation_on_hyperbolic_surface_2.
|
||||
*/
|
||||
std::istream& operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits>& triangulation);
|
||||
|
|
@ -48,7 +48,7 @@ std::ostream& operator<<(std::ostream& s, const Hyperbolic_fundamental_domain_2<
|
|||
|
||||
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 is the same as the format of the output of
|
||||
the '<<' operator for Hyperbolic_fundamental_domain_2.
|
||||
*/
|
||||
std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits>& domain);
|
||||
|
|
@ -60,4 +60,31 @@ std::istream& operator>>(std::istream& s, Hyperbolic_fundamental_domain_2<Traits
|
|||
*/
|
||||
std::ostream& operator<<(std::ostream& s, const Hyperbolic_isometry_2<Traits>& isometry);
|
||||
|
||||
/*!
|
||||
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
|
||||
|
||||
inserts the Delaunay triangulation in a stream.
|
||||
|
||||
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.
|
||||
The first line contains the number \f$ n \f$ of darts.
|
||||
Then, for every triangle \f$ t \f$, the indices of the three darts of \f$ t \f$ are printed on three distinct lines.
|
||||
The coordinates of the three vertices of its anchor are printed on the next six 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 two lines on which the cross ratio of \f$ e \f$ is printed.
|
||||
|
||||
\pre <code> Triangulation_on_hyperbolic_surface_2<Traits>::is_valid() </code>
|
||||
*/
|
||||
std::istream& operator>>(std::istream& s, Delaunay_triangulation_on_hyperbolic_surface_2<Traits>& triangulation);
|
||||
|
||||
/*!
|
||||
\ingroup PkgHyperbolicSurfaceTriangulation2InputOutput
|
||||
|
||||
extracts the Delaunay triangulation from a stream.
|
||||
|
||||
The format of the input is the same as the format of the output of
|
||||
the '<<' operator for Delaunay_triangulation_on_hyperbolic_surface_2.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& s, const Delaunay_triangulation_on_hyperbolic_surface_2<Traits>& triangulation);
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ public:
|
|||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Field number type.
|
||||
*/
|
||||
typedef unspecified_type FT;
|
||||
|
||||
/*!
|
||||
represents a complex number, model of `ComplexNumber`,
|
||||
over the field `HyperbolicSurfaceTraits_2::FT` for its real and imaginary parts.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
/// \defgroup PkgHyperbolicSurfaceTriangulation2InputOutput Input/Output Functions
|
||||
/// \ingroup PkgHyperbolicSurfaceTriangulation2Ref
|
||||
|
||||
/// \defgroup PkgHyperbolicSurfaceTriangulation2DirichletDomain Dirichlet Domain Function
|
||||
/// \ingroup PkgHyperbolicSurfaceTriangulation2Ref
|
||||
|
||||
/*!
|
||||
\addtogroup PkgHyperbolicSurfaceTriangulation2Ref
|
||||
|
||||
|
|
@ -19,8 +22,8 @@
|
|||
\cgalPkgPicture{cover.svg}
|
||||
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Vincent Despré, Loïc Dubois, Marc Pouget and Monique Teillaud}
|
||||
\cgalPkgDesc{This package enables building and handling triangulations of closed orientable hyperbolic surfaces. It offers functions for 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 Poincaré disk. A method is offered that generates such domains in genus two.}
|
||||
\cgalPkgAuthors{Vincent Despré, Loïc Dubois, Camille Lanuel, Marc Pouget and Monique Teillaud}
|
||||
\cgalPkgDesc{This package enables building and handling triangulations or Delaunay triangulations of closed orientable hyperbolic surfaces. It offers functions for 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 Poincaré disk. A method is offered that generates such domains in genus two.}
|
||||
\cgalPkgManuals{Chapter_Hyperbolic_Surface_Triangulations,PkgHyperbolicSurfaceTriangulation2Ref}
|
||||
\cgalPkgSummaryEnd
|
||||
|
||||
|
|
@ -43,7 +46,9 @@
|
|||
|
||||
\cgalCRPSection{Classes}
|
||||
|
||||
- `CGAL::Triangulation_on_hyperbolic_surface_2` represents a triangulation of a closed orientable hyperbolic surface. It offers functions for 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 Poincaré disk.
|
||||
- `CGAL::Triangulation_on_hyperbolic_surface_2` represents a triangulation of a closed orientable hyperbolic surface. It offers functions for 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 Poincaré disk.
|
||||
|
||||
- `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2` represents a Delaunay triangulation of a closed orientable hyperbolic surface. It offers functions for the generation of the Delaunay triangulation from a convex fundamental domain, the insertion of a point in the Delaunay triangulation, two point location algorithms and the \f$ \varepsilon \f$-net algorithm.
|
||||
|
||||
- `CGAL::Hyperbolic_fundamental_domain_2` represents a fundamental domain of a closed orientable hyperbolic surface.
|
||||
|
||||
|
|
@ -57,4 +62,8 @@ Models for `HyperbolicSurfaceTraits_2` and `ComplexNumber` are provided: `CGAL::
|
|||
|
||||
- `operator<<` and `operator>>` are overloaded for several classes of the package.
|
||||
|
||||
\cgalCRPSection{Dirichlet Domain Function}
|
||||
|
||||
- `CGAL::Dirichlet_vertices` computes the vertices of a Dirichlet domain from a fundamental domain whose vertices represent a same point on the corresponding hyperbolic surface.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,15 +8,18 @@ namespace CGAL {
|
|||
\anchor Chapter_Hyperbolic_Surface_Triangulations
|
||||
|
||||
\cgalAutoToc
|
||||
\authors Vincent Despré, Loïc Dubois, Marc Pouget and Monique Teillaud
|
||||
\authors Vincent Despré, Loïc Dubois, Camille Lanuel, Marc Pouget and Monique Teillaud
|
||||
|
||||
<center>
|
||||
<img src="header.svg" style="max-width:80%; width:80%;"/>
|
||||
</center>
|
||||
|
||||
This package introduces a data structure and algorithms for triangulations of closed orientable hyperbolic surfaces. The triangulation is represented by an enriched CGAL::Combinatorial_map with complex number attributes on edges.
|
||||
Such a triangulation can be constructed from a surface given by a convex fundamental domain (see Section \ref Section_Hyperbolic_Surface_Triangulations_domains "Fundamental Domains and Triangulations"). A method is offered that randomly generates such domains for surfaces of genus two. On the other hand, the package works for any genus surface that may be provided by the user either as a fundamental domain or as an already computed triangulation.
|
||||
Functionalities are offered such as the Delaunay flip algorithm and the construction of a portion of the lift of the triangulation in the Poincaré disk model of the hyperbolic plane.
|
||||
This package introduces a data structure and algorithms for triangulations and Delaunay triangulation of closed orientable hyperbolic surfaces.
|
||||
A triangulation is represented by an enriched CGAL::Combinatorial_map with complex number attributes on edges.
|
||||
<span style="color:red">Additionally, a Delaunay triangulation has anchor attributes, representing lifts of triangles, on faces.</span>
|
||||
Such triangulations can be constructed from a surface given by a convex fundamental domain (see Section \ref Section_Hyperbolic_Surface_Triangulations_domains "Fundamental Domains and Triangulations"). A method is offered that randomly generates such domains for surfaces of genus two. On the other hand, the package works for any genus surface that may be provided by the user either as a fundamental domain or as an already computed triangulation.
|
||||
For triangulations, functionalities are offered such as the Delaunay flip algorithm and the construction of a portion of the lift of the triangulation in the Poincaré disk model of the hyperbolic plane.
|
||||
<span style="color:red">For Delaunay triangulations, additional functionalities include point location, point insertion, and the computation of an \f$ \varepsilon \f$-net of the hyperbolic surface.</span>
|
||||
|
||||
For the case of the Bolza surface, which is the most symmetric surface of genus two, we refer the user to the specific package \ref Chapter_2D_Periodic_Hyperbolic_Triangulations "2D Periodic Hyperbolic Triangulations".
|
||||
|
||||
|
|
@ -102,6 +105,13 @@ See \cgalCite{despre2022experimental} for details.
|
|||
Computation of the cross ratio of an edge.
|
||||
\cgalFigureCaptionEnd
|
||||
|
||||
\subsection Subsection_Hyperbolic_Surface_Triangulations_DS_Delaunay_Triangulations Data Structure for Delaunay Triangulations
|
||||
|
||||
<div style="color:red">
|
||||
The data structure is enriched for Delaunay triangulations in order to be more convenient and more time efficient for the \f$ \varepsilon \f$-net algorithm or other algorithms that often have to access lifts of triangles in \f$ \mathbb{D} \f$.
|
||||
In order to have constant time access to a lift of any triangle, an anchor is associated with <em>each</em> face of the triangulation. Note that the anchors associated with adjacent triangles do not necessarily correspond to adjacent lifts
|
||||
in \f$ \mathbb{D} \f$. This implies that, when working with a lift of a triangle, if an operation requires the third vertex of an adjacent lift, its coordinates must first be computed using the cross-ratio of their common edge.
|
||||
</div>
|
||||
|
||||
\subsection Subsection_Hyperbolic_Surface_Triangulations_Delaunay Delaunay Flip Algorithm
|
||||
|
||||
|
|
@ -114,15 +124,49 @@ When a flip occurs, the cross ratios of the involved edges are modified via simp
|
|||
The <em>Delaunay flip algorithm</em> flips edges that do not satisfy the Delaunay until no more edges violate the criterion, with no preference on the order of the flips.
|
||||
This algorithm terminates, and outputs a Delaunay triangulation of \f$ S \f$ \cgalCite{despre2020flipping}.
|
||||
|
||||
\section Section_Hyperbolic_Surface_Triangulations_Epsilon_Nets ε-nets
|
||||
|
||||
<span style="color:red">NEW SECTION</span>
|
||||
|
||||
\subsection Subsection_Hyperbolic_Surface_Triangulations_Epsilon_Net_Definition Definition
|
||||
|
||||
The notion of \f$ \varepsilon \f$-net formalizes the idea of a "well-distributed" sampling of a metic space, in our case, a hyperbolic surface.
|
||||
|
||||
Let \f$ (X, d) \f$ be a metric space and \f$ \varepsilon > 0 \f$. A subset \f$ P \subset X \f$ is:
|
||||
|
||||
- an \f$ \varepsilon \f$-covering if \f$ d(x, P) \leq \varepsilon \f$ for all \f$ x \in X \f$, that is, the closed balls of radius \f$ \varepsilon \f$ centered at the points of \f$ P \f$ cover \f$ X \f$;
|
||||
- an \f$ \varepsilon \f$-packing if \f$ d(p, q) \geq \varepsilon \f$ for all \f$ p \neq q \in P \f$, that is, the open balls of radius \f$ \varepsilon/2 \f$ centered at the points of \f$ P \f$ are pairwise disjoint;
|
||||
- an \f$ \varepsilon \f$-net if it is both an \f$ \varepsilon \f$-covering and an \f$ \varepsilon \f$-packing.
|
||||
|
||||
The `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2` class contains the `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2::epsilon_net()` method that tries to compute an \f$ \varepsilon \f$-net of a hyperbolic surface, starting from an \f$ \varepsilon \f$-packing (usually, a Delaunay triangulation with a single vertex). The construction might not result in an \f$ \varepsilon \f$-net (see next section), but the method returns a Boolean indicating whether the result is a certified \f$ \varepsilon \f$-net.
|
||||
|
||||
If the result is not a certified \f$ \varepsilon \f$-net, the `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2::is_epsilon_covering()` and `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2::is_epsilon_packing()` methods can be used to diagnose which property fails. Additionally, the `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2::shortest_non_loop_edge()` can be used to know the distance between the closest pair of points.
|
||||
|
||||
|
||||
\subsection Subsection_Hyperbolic_Surface_Triangulations_Epsilon_Net_Numbers Number Type
|
||||
|
||||
The algorithm is a Delaunay refinement algorithm that inserts the circumcenter of triangles whose circumradius is larger than \f$ \varepsilon \f$ until there is none. To ensure robustness and efficiency, this method should be used with a rational number type, such as `CGAL::Exact_rational` or `CGAL::Gmpq`.
|
||||
|
||||
To avoid cascading square roots, each coordinate of a circumcenter is rounded to the number type provided by the user. There are two cases:
|
||||
|
||||
- When the number type is <em>not</em> `CGAL::Gmpq`, each coordinate is rounded to a double precision number using the `CGAL::to_double()` function, and is then converted to the number type chosen by the user.
|
||||
- When the number type is `CGAL::Gmpq`, each coordinates is rounded to a fixed precision floating-point number `CGAL::Gmpfr`. The precision of the `CGAL::Gmpfr` numbers involved is \f$ p\times 53 \f$, where \f$ p \f$ is an integer given to the `CGAL::Delaunay_triangulation_on_hyperbolic_surface_2::epsilon_net()` method and 53 is the precision of a `double`. When \f$ p = 1 \f$, it is thus equivalent to using the `CGAL::to_double()` approximation.
|
||||
|
||||
The algorithm does not check whether the construction is correct on the go. Instead, it only checks the correctness at the end. This is why it can happen that the result is not a certified \f$ \varepsilon \f$-net.
|
||||
The rounding method using the `CGAL::to_double()` approximation usually works for hyperbolic surfaces of genus 2 or 3 with a lage systole, but a higher precision is required to obtain a valid \f$ \varepsilon \f$-net on surfaces of higher genus.
|
||||
|
||||
|
||||
\section Section_Hyperbolic_Surface_Triangulations_Software_Design Software Design
|
||||
|
||||
The concept `ComplexNumber` describes a complex number type modeled by `CGAL::Complex_number`. Complex numbers are used to encode the cross ratios, for the coefficients of isometries and implicitly to work with points in the Poincaré disk.
|
||||
The concept `ComplexNumber` describes a complex number type modeled by `CGAL::Complex_number`. Complex numbers are used to encode the cross ratios, for the coefficients of isometries and implicitly to work with points in the Poincaré disk.
|
||||
Most classes of the package are templated by the concept `HyperbolicSurfaceTraits_2`. It is a refinement of `HyperbolicDelaunayTriangulationTraits_2` and is modeled by `CGAL::Hyperbolic_surface_traits_2`. It defines the geometric objects (points, segments...) forming the lifted triangulation in the Poincaré disk.
|
||||
|
||||
|
||||
The package offers three main classes:
|
||||
The package offers <span style="color:red">four</span> main classes:
|
||||
- `CGAL::Triangulation_on_hyperbolic_surface_2` represents a triangulation of a hyperbolic surface. It offers functions for 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 Poincaré disk.
|
||||
|
||||
- <span style="color:red">`CGAL::Delaunay_triangulation_on_hyperbolic_surface_2` represents a Delaunay triangulation of a closed orientable hyperbolic surface. It offers functions for the generation of the Delaunay triangulation from a convex fundamental domain, the insertion of a point in the Delaunay triangulation, two point location algorithms and the \f$ \varepsilon \f$-net algorithm.</span>
|
||||
|
||||
- `CGAL::Hyperbolic_fundamental_domain_2` represents a convex fundamental domain of a hyperbolic surface.
|
||||
|
||||
- `CGAL::Hyperbolic_fundamental_domain_factory_2` generates random convex fundamental domains of surfaces of genus two.
|
||||
|
|
@ -130,18 +174,42 @@ The package offers three main classes:
|
|||
The secondary class `CGAL::Hyperbolic_isometry_2` defines isometries in the Poincaré disk together with operations to work with them.
|
||||
|
||||
|
||||
\section Visualization_Triangulation_lift Visualization of a Triangulation
|
||||
\section Visualization Visualization
|
||||
|
||||
The function `CGAL::Triangulation_on_hyperbolic_surface_2::lift()` computes the lift of each triangle in the hyperbolic plane, enabling its visualization (see \cgalFigureRef{THS2-demo-output}). This package contains a demo (found in the folder Triangulation_on_hyperbolic_surface_2/demo), which can be used to display triangulations.
|
||||
<div style="color:red">changé titre (Visualization of a Triangulation -> Visualization)</div>
|
||||
<div style="color:red">This package contains several demos (found in the folder Triangulation_on_hyperbolic_surface_2/demo), which displays triangulations.</div>
|
||||
|
||||
The function `CGAL::Triangulation_on_hyperbolic_surface_2::lift()` computes the lift of each triangle in the hyperbolic plane, enabling its visualization (see \cgalFigureRef{THS2-demo-output}).
|
||||
|
||||
\cgalFigureAnchor{THS2-demo-output}
|
||||
<center>
|
||||
<img src="demo-output.png" style="max-width:25%; width:25%; display: inline-block;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{THS2-demo-output}
|
||||
Lift, in the Poincaré disk, of a Delaunay triangulation of a genus two hyperbolic surface with one vertex.
|
||||
Lift, in the Poincaré disk, of a Delaunay triangulation of a genus two hyperbolic surface with one vertex (from Triangulation_on_hyperbolic_surface_2_demo.cpp).
|
||||
\cgalFigureCaptionEnd
|
||||
|
||||
<div style="color:red">
|
||||
\cgalFigureAnchor{DTHS2-demo-output}
|
||||
<center>
|
||||
<img src="123_01.svg" style="max-width:25%; width:25%; display: inline-block;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{DTHS2-demo-output}
|
||||
Lift, in the Poincaré disk, of the Delaunay triangulation of a 0.1-net of a genus two hyperbolic surface with seed 123 (from Delaunay_triangulation_on_hyperbolic_surface_2_demo.cpp).
|
||||
\cgalFigureCaptionEnd
|
||||
</div>
|
||||
|
||||
<div style="color:red">Additionally, the `CGAL::Dirichlet_vertices()` function can be used to display a Dirichlet domain.</div>
|
||||
|
||||
<div style="color:red">
|
||||
\cgalFigureAnchor{HDD2-demo-output}
|
||||
<center>
|
||||
<img src="dirichlet.svg" style="max-width:25%; width:25%; display: inline-block;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{HDD2-demo-output}
|
||||
Lift, in the Poincaré disk, of a Dirichlet domain of a genus two surface (from Hyperbolic_Dirichlet_domain_2_demo.cpp).
|
||||
\cgalFigureCaptionEnd
|
||||
</div>
|
||||
|
||||
\section Section_Hyperbolic_Surface_Triangulations_Example Example
|
||||
|
||||
|
|
@ -152,8 +220,9 @@ The example below generates a convex fundamental domain of a surface of genus tw
|
|||
|
||||
This package implements the Delaunay flip algorithm described in the hyperbolic setting by Vincent Despré, Jean-Marc Schlenker and Monique Teillaud in \cgalCite{despre2020flipping} using the data structure for representing triangulations presented in \cgalCite{despre2022experimental}).
|
||||
It also implements the generation of domains described by Vincent Despré, Loïc Dubois, Benedikt Kolbe and Monique Teillaud in \cgalCite{despre2022experimental}, based on results of Aline Aigon-Dupuy, Peter Buser, Michel Cibils, Alfred F Künzle and Frank Steiner \cgalCite{aigon2005hyperbolic}.
|
||||
The code and the documentation of the package were written by Loïc Dubois, under regular discussions with Vincent Despré, Marc Pouget and Monique Teillaud.
|
||||
The authors acknowledge support from the grants <a href="https://sos.loria.fr/">SoS</a> and <a href="https://perso.math.u-pem.fr/sabourau.stephane/min-max/min-max.html">MIN-MAX</a> of the French National Research Agency ANR.
|
||||
<span style="color:red">It also implements the \f$ \varepsilon \f$-net algorithm presented by Vincent Despré, Camille Lanuel, Marc Pouget and Monique Teillaud in \cgalCite{cgal:dlpt-naihs-25}. TODO: citer thèse plutôt ?</span>
|
||||
The code and the documentation of the package were written by Loïc Dubois <span style="color:red">and Camille Lanuel</span>, under regular discussions with Vincent Despré, Marc Pouget and Monique Teillaud.
|
||||
The authors acknowledge support from the grants <a href="https://sos.loria.fr/">SoS</a>, <a href="https://perso.math.u-pem.fr/sabourau.stephane/min-max/min-max.html">MIN-MAX</a> <span style="color:red">and <a href="https://homepages.loria.fr/VDespre/Abysm/">Abysm</a></span> of the French National Research Agency ANR.
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
Manual
|
||||
Stream_support
|
||||
Number_types
|
||||
Kernel_23
|
||||
Combinatorial_map
|
||||
Hyperbolic_triangulation_2
|
||||
Algebraic_foundations
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/*!
|
||||
\example Triangulation_on_hyperbolic_surface_2/Triangulation_on_hyperbolic_surface_2.cpp
|
||||
|
||||
\example Triangulation_on_hyperbolic_surface_2/Delaunay_triangulation_on_hyperbolic_surface_2.cpp
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 547 KiB |
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="213.783mm" height="213.783mm"
|
||||
viewBox="-3 -3 1212 1212"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
|
||||
<title>/home/clanuel/Documents/cgal/cgal/Triangulation_on_hyperbolic_surface_2/doc/Triangulation_on_hyperbolic_surface_2/fig/dirichlet.svg</title>
|
||||
<desc>My canvas exported to Svg</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="#000000" fill-opacity="0" stroke="none" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
<rect x="-603" y="-603" width="606" height="606"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="4" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
<circle cx="0" cy="0" r="603"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#ff0000" stroke-opacity="1" stroke-width="4" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-255.389,-436.227 C-221.636,-415.294 -181.821,-403.208 -139.183,-403.208 C-61.9497,-403.208 6.02188,-442.864 45.481,-502.925 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M45.6097,-503.239 C52.3304,-504.193 58.849,-505.774 65.1043,-507.923 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M65.2385,-508.022 C69.3262,-504.852 73.6422,-501.963 78.1577,-499.383 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M78.1323,-499.427 C98.2912,-483.549 123.731,-474.075 151.383,-474.075 C158.02,-474.075 164.528,-474.621 170.867,-475.67 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M170.866,-476.157 C162.002,-431.637 157.353,-385.597 157.353,-338.471 C157.353,-104.151 272.284,103.324 448.85,230.659 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M449.538,231.078 C449.084,235.151 448.85,239.29 448.85,243.485 C448.85,244.538 448.865,245.589 448.894,246.635 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M448.878,246.612 C416.978,263.615 394.115,295.343 389.362,332.724 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M389.412,332.702 C383.221,335.343 377.332,338.555 371.809,342.27 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M371.637,342.374 C317.072,348.063 271.969,385.572 255.212,436.017 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M255.389,436.227 C221.636,415.294 181.821,403.208 139.183,403.208 C61.9497,403.208 -6.02188,442.864 -45.481,502.925 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-45.6097,503.239 C-52.3304,504.193 -58.849,505.774 -65.1043,507.923 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-65.2385,508.022 C-69.3262,504.852 -73.6422,501.963 -78.1577,499.383 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-78.1323,499.427 C-98.2912,483.549 -123.731,474.075 -151.383,474.075 C-158.02,474.075 -164.528,474.621 -170.867,475.67 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-170.866,476.157 C-162.002,431.637 -157.353,385.597 -157.353,338.471 C-157.353,104.151 -272.284,-103.324 -448.85,-230.659 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-449.538,-231.078 C-449.084,-235.151 -448.85,-239.29 -448.85,-243.485 C-448.85,-244.538 -448.865,-245.589 -448.894,-246.635 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-448.878,-246.612 C-416.978,-263.615 -394.115,-295.343 -389.362,-332.724 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-389.412,-332.702 C-383.221,-335.343 -377.332,-338.555 -371.809,-342.27 "/>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-371.637,-342.374 C-317.072,-348.063 -271.969,-385.572 -255.212,-436.017 "/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,603,603)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Cantarell" font-size="12" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
|
@ -0,0 +1,39 @@
|
|||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Circular_kernel_2.h>
|
||||
#include <CGAL/Algebraic_kernel_for_circles_2_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
#include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h>
|
||||
#include <CGAL/Hyperbolic_fundamental_domain_factory_2.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
typedef CGAL::Exact_rational Rational;
|
||||
typedef CGAL::Circular_kernel_2<CGAL::Simple_cartesian<Rational>,CGAL::Algebraic_kernel_for_circles_2_2<Rational>> Kernel;
|
||||
typedef CGAL::Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
typedef CGAL::Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef CGAL::Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef CGAL::Hyperbolic_fundamental_domain_factory_2<Traits> Factory;
|
||||
typedef CGAL::Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_triangulation;
|
||||
|
||||
int main() {
|
||||
// Generates the domain:
|
||||
Factory factory = Factory();
|
||||
Domain domain = factory.make_hyperbolic_fundamental_domain_g2(time(NULL)); // get a random seed with time(NULL)
|
||||
|
||||
// Triangulates the domain:
|
||||
Delaunay_triangulation dt = Delaunay_triangulation(domain);
|
||||
|
||||
// Saves the triangulation:
|
||||
std::ofstream output_file = std::ofstream ("OutputDelaunayTriangulation.txt");
|
||||
output_file << dt;
|
||||
output_file.close();
|
||||
|
||||
// Prints the triangulation:
|
||||
std::cout << dt << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ int main() {
|
|||
|
||||
// Applies the Delaunay flip algorithm to the triangulation:
|
||||
triangulation.make_Delaunay();
|
||||
std::cout << "delaunay" << std::endl;
|
||||
|
||||
// Saves the triangulation:
|
||||
std::ofstream output_file = std::ofstream ("OutputTriangulation.txt");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) 2025
|
||||
// INRIA Nancy (France), and Université de Lorraine (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Vincent Despré, Camille Lanuel, Marc Pouget, Monique Teillaud
|
||||
|
||||
#ifndef CGAL_HYPERBOLIC_DIRICHLET_DOMAIN_2
|
||||
#define CGAL_HYPERBOLIC_DIRICHLET_DOMAIN_2
|
||||
|
||||
#include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
// Input: triangulation with a single vertex v
|
||||
// Output: lift of this triangulation with one lift of v mapped to the origin of the Poincaré disk and all its incident triangles arout it.
|
||||
template<class Traits>
|
||||
std::vector<std::tuple<typename Delaunay_triangulation_on_hyperbolic_surface_2<Traits>::Dart_const_descriptor, typename Traits::Point_2, typename Traits::Point_2, typename Traits::Point_2>>
|
||||
unfold(Delaunay_triangulation_on_hyperbolic_surface_2<Traits> & triangulation)
|
||||
{
|
||||
typedef typename Traits::Complex Complex;
|
||||
typedef typename Traits::Point_2 Point;
|
||||
typedef Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_Triangulation;
|
||||
typedef typename Delaunay_Triangulation::Anchor Anchor;
|
||||
typedef typename Delaunay_Triangulation::CMap CMap;
|
||||
typedef typename Delaunay_Triangulation::Dart_const_descriptor Dart_const_descriptor;
|
||||
typedef CGAL::Hyperbolic_isometry_2<Traits> Isometry;
|
||||
|
||||
Anchor & anchor = triangulation.anchor();
|
||||
CMap & cmap = triangulation.combinatorial_map();
|
||||
|
||||
std::vector<std::tuple<Dart_const_descriptor,Point,Point,Point>> lifted_triangles; // vector of lifted triangles (future output)
|
||||
std::map<Dart_const_descriptor, Point> positions; // map that will contain the computed lift of the vertex of each dart
|
||||
|
||||
// create a mark for visited darts
|
||||
size_t visited = cmap.get_new_mark();
|
||||
cmap.unmark_all(visited);
|
||||
|
||||
// translate the first vertex of the anchor to the origin of the Poincaré disk, and add the positions of the translated vertices of the anchor
|
||||
Isometry center_the_drawing = hyperbolic_translation<Traits>(anchor.vertices[0]);
|
||||
positions[anchor.dart] = center_the_drawing.evaluate(anchor.vertices[0]);
|
||||
positions[triangulation.const_ccw(anchor.dart)] = center_the_drawing.evaluate(anchor.vertices[1]);
|
||||
positions[triangulation.const_cw(anchor.dart)] = center_the_drawing.evaluate(anchor.vertices[2]);
|
||||
cmap.mark(anchor.dart, visited);
|
||||
|
||||
// add the first triangle (the translated anchor) to the vector of triangles
|
||||
std::tuple<Dart_const_descriptor,Point,Point,Point> value = std::make_tuple(anchor.dart, positions[anchor.dart], positions[triangulation.const_ccw(anchor.dart)], positions[triangulation.const_cw(anchor.dart)]);
|
||||
lifted_triangles.push_back(value);
|
||||
|
||||
// visit all the darts one by one by turning around the central vertex
|
||||
Dart_const_descriptor invader = anchor.dart;
|
||||
while( cmap.number_of_unmarked_darts(visited) > 1 ){ // >1 because the first triangle appears twice
|
||||
Dart_const_descriptor invaded = triangulation.const_opposite(invader);
|
||||
|
||||
// get the positions of the vertices of the invader's triangle
|
||||
Point a = positions[triangulation.const_ccw(invader)];
|
||||
Point b = positions[triangulation.const_cw(invader)];
|
||||
Point c = positions[invader];
|
||||
Complex cross_ratio = triangulation.get_cross_ratio(invader);
|
||||
|
||||
// retieve the positions of the invaded's triangle
|
||||
positions[invaded] = a;
|
||||
positions[triangulation.const_ccw(invaded)] = c;
|
||||
Point d = triangulation.fourth_point_from_cross_ratio(a, b, c, cross_ratio);
|
||||
positions[triangulation.const_cw(invaded)] = d;
|
||||
|
||||
// add the three vertices to the vector of lifted triangles
|
||||
value = std::make_tuple(invaded, a, c, d);
|
||||
lifted_triangles.push_back(value);
|
||||
cmap.mark(invaded, visited);
|
||||
|
||||
invader = triangulation.const_ccw(invaded);
|
||||
}
|
||||
|
||||
cmap.free_mark(visited);
|
||||
return lifted_triangles;
|
||||
}
|
||||
|
||||
// Input: Fundamental domain whose vertices are the same point on the surface
|
||||
// Output: vertices of a Dirichlet domain centered at the origin of the Poincaré disk
|
||||
template<class Traits>
|
||||
std::vector<typename Traits::Hyperbolic_Voronoi_point_2> Dirichlet_vertices(Hyperbolic_fundamental_domain_2<Traits> & domain)
|
||||
{
|
||||
typedef typename Traits::Point_2 Point;
|
||||
typedef typename Traits::Hyperbolic_Voronoi_point_2 Voronoi_point;
|
||||
typedef Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_Triangulation;
|
||||
typedef typename Delaunay_Triangulation::Dart_const_descriptor Dart_const_descriptor;
|
||||
|
||||
Delaunay_Triangulation triangulation = Delaunay_Triangulation(domain);
|
||||
|
||||
std::vector<std::tuple<Dart_const_descriptor,Point,Point,Point>> realized_triangles = unfold<Traits>(triangulation);
|
||||
std::vector<Voronoi_point> dirichlet_vertices;
|
||||
|
||||
Traits gt;
|
||||
typename Traits::Construct_hyperbolic_circumcenter_2 chc = gt.construct_hyperbolic_circumcenter_2_object();
|
||||
for (std::tuple<Dart_const_descriptor, Point, Point, Point>& triangle : realized_triangles){
|
||||
Voronoi_point circumcenter = chc(std::get<1>(triangle), std::get<2>(triangle), std::get<3>(triangle));
|
||||
dirichlet_vertices.push_back(circumcenter);
|
||||
}
|
||||
return dirichlet_vertices;
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_HYPERBOLIC_DIRICHLET_DOMAIN_2
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*
|
||||
|
|
@ -108,6 +110,7 @@ public:
|
|||
void flip(Dart_descriptor dart);
|
||||
bool is_Delaunay() const;
|
||||
int make_Delaunay();
|
||||
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > lift(Anchor const & anchor, bool center=true) const;
|
||||
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > lift(bool center=true) const;
|
||||
|
||||
bool is_valid() const;
|
||||
|
|
@ -151,6 +154,7 @@ protected:
|
|||
Combinatorial_map_with_cross_ratios combinatorial_map_;
|
||||
bool has_anchor_ = false;
|
||||
Anchor anchor_;
|
||||
// std::optional<Anchor> anchor_ = std::nullopt;
|
||||
|
||||
Dart_descriptor pick_edge_to_flip();
|
||||
Dart_const_descriptor pick_edge_to_flip() const;
|
||||
|
|
@ -198,7 +202,7 @@ Triangulation_on_hyperbolic_surface_2(const Domain& domain)
|
|||
}
|
||||
|
||||
// Sew the boundary edges and set their cross ratios
|
||||
for (std::size_t k1=0; k1<size; k1++) {
|
||||
for (std::size_t k1=0; k1<size; k1++) {
|
||||
std::size_t k2 = domain.paired_side(k1);
|
||||
|
||||
p0 = domain.vertex((k1+1)%size);
|
||||
|
|
@ -326,22 +330,24 @@ flip(Dart_descriptor dart)
|
|||
Complex_number cross_ratio_DA = get_cross_ratio(c);
|
||||
Complex_number cross_ratio_AC = get_cross_ratio(a);
|
||||
|
||||
// Modify the anchor
|
||||
// Modify the anchor, if any
|
||||
|
||||
if (anchor_.dart == a) {
|
||||
if(has_anchor_) {
|
||||
if (anchor_.dart == a) {
|
||||
anchor_.dart = e;
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
anchor_.dart = b;
|
||||
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) {
|
||||
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) {
|
||||
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 == b) {
|
||||
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) {
|
||||
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) {
|
||||
anchor_.dart = b;
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
|
|
@ -427,9 +433,9 @@ std::vector<std::tuple<typename Triangulation_on_hyperbolic_surface_2<Traits, At
|
|||
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
|
||||
lift(typename Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::Anchor const & anchor, bool center) const
|
||||
{
|
||||
CGAL_precondition(is_valid() && has_anchor());
|
||||
CGAL_precondition(is_valid());
|
||||
|
||||
std::vector<std::tuple<Dart_const_descriptor, Point, Point, Point> > realizations;
|
||||
|
||||
|
|
@ -452,39 +458,39 @@ lift(bool center) const
|
|||
|
||||
Dart_const_range darts = combinatorial_map_.darts();
|
||||
|
||||
combinatorial_map_.mark(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(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);
|
||||
|
||||
if (center) {
|
||||
Isometry center_the_drawing = hyperbolic_translation<Traits>(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_cw(anchor_.dart)] = center_the_drawing.evaluate(anchor_.vertices[2]);
|
||||
Isometry center_the_drawing = hyperbolic_translation<Traits>(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_cw(anchor.dart)] = center_the_drawing.evaluate(anchor.vertices[2]);
|
||||
} else {
|
||||
positions[anchor_.dart] = anchor_.vertices[0];
|
||||
positions[const_ccw(anchor_.dart)] = anchor_.vertices[1];
|
||||
positions[const_cw(anchor_.dart)] = anchor_.vertices[2];
|
||||
positions[anchor.dart] = anchor_.vertices[0];
|
||||
positions[const_ccw(anchor.dart)] = anchor.vertices[1];
|
||||
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::make_tuple(anchor.dart,
|
||||
positions[anchor.dart],
|
||||
positions[const_ccw(anchor.dart)],
|
||||
positions[const_cw(anchor.dart)]);
|
||||
realizations.push_back(value);
|
||||
|
||||
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_z2(anchor_.vertices[2].x(), anchor_.vertices[2].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_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_ccw_anchor_dart = CGAL::to_double(norm(anchor_z1) + norm(anchor_z2));
|
||||
double weight_of_cw_anchor_dart = CGAL::to_double(norm(anchor_z2) + norm(anchor_z0));
|
||||
|
||||
queue.push(std::make_pair(anchor_.dart, weight_of_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(anchor.dart, weight_of_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));
|
||||
|
||||
while (! queue.empty()) {
|
||||
Dart_const_descriptor invader = queue.top().first;
|
||||
|
|
@ -530,6 +536,18 @@ lift(bool center) const
|
|||
return realizations;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
CGAL_precondition(is_valid() && has_anchor());
|
||||
return lift(anchor_, center);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Traits, class Attributes>
|
||||
|
|
@ -578,7 +596,7 @@ void
|
|||
Triangulation_on_hyperbolic_surface_2<Traits, Attributes>::
|
||||
to_stream(std::ostream& s) const
|
||||
{
|
||||
CGAL_precondition(is_valid() && has_anchor());
|
||||
CGAL_precondition(is_valid());
|
||||
|
||||
// Give indices to the darts
|
||||
std::map<Dart_const_descriptor, int> darts_indices;
|
||||
|
|
@ -832,4 +850,4 @@ fourth_point_from_cross_ratio(const Point& a, const Point& b, const Point& c,
|
|||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H
|
||||
#endif // CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_H
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2024
|
||||
// INRIA Nancy (France), and Université Gustave Eiffel Marne-la-Vallee (France).
|
||||
// INRIA Nancy (France), Université de Lorraine (France), and Université Gustave Eiffel Marne-la-Vallee (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#include <CGAL/license/Triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
#include <CGAL/Triangulation_on_hyperbolic_surface_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
|
||||
|
|
@ -61,6 +62,21 @@ void operator>>(std::istream& s, Triangulation_on_hyperbolic_surface_2<Traits, A
|
|||
triangulation.from_stream(s);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<class Traits>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& s, const Delaunay_triangulation_on_hyperbolic_surface_2<Traits>& triangulation)
|
||||
{
|
||||
triangulation.to_stream(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Traits>
|
||||
void operator>>(std::istream& s, Delaunay_triangulation_on_hyperbolic_surface_2<Traits>& triangulation)
|
||||
{
|
||||
triangulation.from_stream(s);
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_HYPERBOLIC_SURFACE_2_IO_H
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
INRIA Nancy -- France
|
||||
Université de Lorraine -- France
|
||||
Université Gustave Eiffel Marne-la-Vallee -- France
|
||||
Université Gustave Eiffel Marne-la-Vallée -- France
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
Package Triangulation_on_hyperbolic_surface_2 : provides
|
||||
triangulations of closed oriented hyperbolic surfaces,
|
||||
Delaunay flip algorithm on those triangulations,
|
||||
Delaunay triangulations of closed oriented hyperbolic surfaces,
|
||||
point location,
|
||||
point insertion,
|
||||
construction of the triangulations from convex geodesic fundamental domains,
|
||||
construction of such domains for genus 2 surfaces
|
||||
construction of such domains for genus 2 surfaces,
|
||||
construction of an epsilon-net of a closed oriented hyperbolic surface
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
Vincent Despré <vincent.despre@loria.fr>
|
||||
Loïc Dubois <loic.dubois@univ-eiffel.fr>
|
||||
Monique Teillaud <monique.teillaud@inria.fr>
|
||||
Marc Pouget <marc.pouget@inria.fr>
|
||||
Monique Teillaud <monique.teillaud@inria.fr>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
#include <CGAL/Triangulation_on_hyperbolic_surface_2_IO.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace CGAL;
|
||||
|
||||
|
||||
typedef Simple_cartesian<CGAL::Exact_rational> Kernel;
|
||||
typedef Hyperbolic_Delaunay_triangulation_traits_2<Kernel> ParentTraits;
|
||||
|
||||
typedef Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_triangulation;
|
||||
typedef typename Delaunay_triangulation::Anchor Anchor;
|
||||
typedef typename Delaunay_triangulation::CMap CMap;
|
||||
|
||||
typedef typename Traits::FT FT;
|
||||
typedef typename Traits::Hyperbolic_point_2 Point;
|
||||
|
||||
Domain build_domain()
|
||||
{
|
||||
std::vector<Point> vertices;
|
||||
Point z0 = Point(FT("4881/5000"),FT("0"));
|
||||
Point z1 = Point(FT("9211/10000"),FT("2733/10000"));
|
||||
Point z2 = Point(FT("1709/5000"),FT("7253/10000"));
|
||||
Point z3 = Point(FT("-427262704257582473474868322141310044732400799603/1267155016747148041260345910894159385550919570000"),FT("582571804584198065321856347012850217722442509611/1267155016747148041260345910894159385550919570000"));
|
||||
Point z4 = Point(FT("-4881/5000"),FT("0"));
|
||||
Point z5 = Point(FT("-9211/10000"),FT("-2733/10000"));
|
||||
Point z6 = Point(FT("-1709/5000"),FT("-7253/10000"));
|
||||
Point z7 = Point(FT("427262704257582473474868322141310044732400799603/1267155016747148041260345910894159385550919570000"),FT("-582571804584198065321856347012850217722442509611/1267155016747148041260345910894159385550919570000"));
|
||||
vertices.push_back(z0);
|
||||
vertices.push_back(z1);
|
||||
vertices.push_back(z2);
|
||||
vertices.push_back(z3);
|
||||
vertices.push_back(z4);
|
||||
vertices.push_back(z5);
|
||||
vertices.push_back(z6);
|
||||
vertices.push_back(z7);
|
||||
|
||||
std::vector<std::size_t> pairings;
|
||||
for (std::size_t k=0; k<8; ++k) {
|
||||
pairings.push_back((k+4)%8);
|
||||
}
|
||||
return Domain(vertices, pairings);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Domain domain = build_domain();
|
||||
Delaunay_triangulation dt = Delaunay_triangulation(domain);
|
||||
|
||||
assert(dt.is_valid());
|
||||
|
||||
std::cout << "printing triangulation for test purposes: " << std::endl << dt;
|
||||
|
||||
Anchor a0 = dt.locate(Point(0.5, 0.5)); // straight walk
|
||||
Anchor a1 = dt.locate(Point(0.5, 0.5), true); // visibility walk
|
||||
|
||||
assert(dt.anchor(a0.dart).dart == dt.anchor(a1.dart).dart); //check that both anchors correspond to the same triangle
|
||||
|
||||
bool same_vertices = true;
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
bool found = false;
|
||||
for (unsigned j = 0; j < 3; ++j) {
|
||||
if (a0.vertices[i] == a1.vertices[j]) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
same_vertices = same_vertices && found;
|
||||
}
|
||||
|
||||
assert(same_vertices);
|
||||
|
||||
assert(dt.shortest_loop_edge() != 0);
|
||||
assert(dt.shortest_non_loop_edge() == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Circular_kernel_2.h>
|
||||
#include <CGAL/Algebraic_kernel_for_circles_2_2.h>
|
||||
#include <CGAL/Hyperbolic_Delaunay_triangulation_CK_traits_2.h>
|
||||
#include <CGAL/Hyperbolic_surface_traits_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_hyperbolic_surface_2.h>
|
||||
|
||||
using namespace CGAL;
|
||||
|
||||
typedef Gmpq NumberType;
|
||||
typedef Circular_kernel_2<Simple_cartesian<NumberType>, Algebraic_kernel_for_circles_2_2<NumberType>> Kernel;
|
||||
typedef Hyperbolic_Delaunay_triangulation_CK_traits_2<Kernel> ParentTraits;
|
||||
typedef Hyperbolic_surface_traits_2<ParentTraits> Traits;
|
||||
typedef Hyperbolic_fundamental_domain_2<Traits> Domain;
|
||||
typedef Delaunay_triangulation_on_hyperbolic_surface_2<Traits> Delaunay_triangulation;
|
||||
|
||||
typedef typename Traits::FT FT;
|
||||
typedef typename Traits::Hyperbolic_point_2 Point;
|
||||
|
||||
double epsilon = 0.25;
|
||||
int p = 2;
|
||||
|
||||
Domain build_domain()
|
||||
{
|
||||
std::vector<Point> vertices;
|
||||
Point z0 = Point(FT("4881/5000"),FT("0"));
|
||||
Point z1 = Point(FT("9211/10000"),FT("2733/10000"));
|
||||
Point z2 = Point(FT("1709/5000"),FT("7253/10000"));
|
||||
Point z3 = Point(FT("-427262704257582473474868322141310044732400799603/1267155016747148041260345910894159385550919570000"),FT("582571804584198065321856347012850217722442509611/1267155016747148041260345910894159385550919570000"));
|
||||
Point z4 = Point(FT("-4881/5000"),FT("0"));
|
||||
Point z5 = Point(FT("-9211/10000"),FT("-2733/10000"));
|
||||
Point z6 = Point(FT("-1709/5000"),FT("-7253/10000"));
|
||||
Point z7 = Point(FT("427262704257582473474868322141310044732400799603/1267155016747148041260345910894159385550919570000"),FT("-582571804584198065321856347012850217722442509611/1267155016747148041260345910894159385550919570000"));
|
||||
vertices.push_back(z0);
|
||||
vertices.push_back(z1);
|
||||
vertices.push_back(z2);
|
||||
vertices.push_back(z3);
|
||||
vertices.push_back(z4);
|
||||
vertices.push_back(z5);
|
||||
vertices.push_back(z6);
|
||||
vertices.push_back(z7);
|
||||
|
||||
std::vector<std::size_t> pairings;
|
||||
for (std::size_t k=0; k<8; ++k) {
|
||||
pairings.push_back((k+4)%8);
|
||||
}
|
||||
|
||||
return Domain(vertices, pairings);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Domain domain = build_domain();
|
||||
Delaunay_triangulation dt = Delaunay_triangulation(domain);
|
||||
|
||||
assert(dt.is_valid());
|
||||
|
||||
bool is_eps_net = dt.epsilon_net(epsilon, p);
|
||||
|
||||
assert(is_eps_net);
|
||||
assert(dt.is_valid());
|
||||
assert(dt.shortest_non_loop_edge() != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ typedef CGAL::Triangulation_on_hyperbolic_surface_2<Traits> Triangul
|
|||
|
||||
typedef typename Traits::FT FT;
|
||||
typedef typename Traits::Hyperbolic_point_2 Point;
|
||||
typedef typename Traits::Complex Complex;
|
||||
|
||||
Domain build_domain()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue