Skip to content

Commit

Permalink
Merge pull request CGAL#8201 from afabri/ToS-IO-GF
Browse files Browse the repository at this point in the history
Triangulation on Sphere: Fix I/O
  • Loading branch information
sloriot committed Jun 5, 2024
2 parents 96385d1 + f8abb83 commit c36ede0
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,16 @@ class TriangulationOnSphereFaceBase_2

/// provides write access to a Boolean used to indicate if the face is a ghost face.
void set_ghost(const bool b);

/*!
inputs the non-combinatorial information given by the face:
its ghost status and other possible information.
*/
std::istream& operator>>(std::istream& is, TriangulationOnSphereFaceBase_2& v);

/*!
outputs the non combinatorial operation given by the face:
its ghost status and other possible information.
*/
std::ostream& operator<<(std::ostream& os, const TriangulationOnSphereFaceBase_2& v);
};
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,8 @@ class Delaunay_triangulation_on_sphere_2
Arc_on_sphere_2 dual_on_sphere(const All_edges_iterator ei) const { return dual_on_sphere(*ei); }

// Validity
bool is_plane() const;
bool is_valid(bool verbose = false, int level = 0) const;
bool is_valid_face(Face_handle fh, bool verbose = false, int level = 0) const;
bool is_valid(bool verbose = false, int level = 0) const;
};

// ------------------------ PREDICATES / CONSTRUCTIONS --------------------------------//
Expand Down Expand Up @@ -1090,39 +1089,6 @@ dual_on_sphere(const Edge& e) const

//-------------------------------------------CHECK------------------------------------------------//

// checks whether a given triangulation is plane (all points are coplanar)
template <typename Gt, typename Tds>
bool
Delaunay_triangulation_on_sphere_2<Gt, Tds>::
is_plane() const
{
if(number_of_vertices() <= 3)
return true;

bool plane = true;

Vertices_iterator it1 = vertices_begin(), it2(it1), it3(it1), it4(it1);
std::advance(it2, 1);
std::advance(it3, 2);
std::advance(it4, 3);

while(it4 != vertices_end())
{
Orientation s = side_of_oriented_circle(point(it1), point(it2), point(it3), point(it4));
plane = plane && s == ON_ORIENTED_BOUNDARY;

if(!plane)
return false;

++it1;
++it2;
++it3;
++it4;
}

return true;
}

template <typename Gt, typename Tds>
bool
Delaunay_triangulation_on_sphere_2<Gt, Tds>::
Expand Down Expand Up @@ -1154,47 +1120,19 @@ bool
Delaunay_triangulation_on_sphere_2<Gt, Tds>::
is_valid(bool verbose, int level) const
{
bool result = true;

if(!tds().is_valid(verbose, level))
// in any dimension
if(verbose)
{
if(verbose)
std::cerr << "invalid data structure" << std::endl;

CGAL_assertion(false);
return false;
std::cerr << " number of vertices " << number_of_vertices() << "\t" << std::endl;
std::cerr << " number of faces " << number_of_faces() << "\t" << std::endl;
}

bool result = Base::is_valid(verbose, level);
CGAL_assertion(result);

for(All_faces_iterator fit=all_faces_begin(); fit!=all_faces_end(); ++fit)
result = result && is_valid_face(fit, verbose, level);

for(Vertices_iterator vit=vertices_begin(); vit!=vertices_end(); ++vit)
result = result && Base::is_valid_vertex(vit, verbose, level);

switch(dimension())
{
case 0:
break;
case 1:
CGAL_assertion(this->is_plane());
break;
case 2:
for(All_faces_iterator it=all_faces_begin(); it!=all_faces_end(); ++it)
{
Orientation s = orientation_on_sphere(point(it, 0), point(it, 1), point(it, 2));
result = result && (s != NEGATIVE || it->is_ghost());
CGAL_assertion(result);
}

result = result && (number_of_faces() == 2 * number_of_vertices() - 4);
CGAL_assertion(result);
break;
}

// in any dimension
if(verbose)
std::cerr << " number of vertices " << number_of_vertices() << "\t" << std::endl;

CGAL_assertion(result);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Point_with_scale
mutable Base_point proj_pt;

public:
Point_with_scale() : Base_point() { } // vertex base wants a default constructor
Point_with_scale() : Base_point(), cached(false) { } // vertex base wants a default constructor
Point_with_scale(const Base_point& p) : Base_point(p), cached(false) { }

const Base_point& get_projection(const Base_point& center,
Expand Down
65 changes: 50 additions & 15 deletions Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ class Triangulation_on_sphere_2

//-----------------------DEBUG--------------------------------------------------------------------
void check_neighboring_faces() const;

bool is_plane() const;
bool is_valid_vertex(Vertex_handle fh, bool verbose = false, int level = 0) const;
bool is_valid(bool verbose = false, int level = 0) const;

Expand Down Expand Up @@ -1239,6 +1239,39 @@ check_neighboring_faces() const
}
}

// checks whether a given triangulation is plane (all points are coplanar)
template <typename Gt, typename Tds>
bool
Triangulation_on_sphere_2<Gt, Tds>::
is_plane() const
{
if(number_of_vertices() <= 3)
return true;

bool is_plane = true;

Vertices_iterator it1 = vertices_begin(), it2(it1), it3(it1), it4(it1);
std::advance(it2, 1);
std::advance(it3, 2);
std::advance(it4, 3);

while(it4 != vertices_end())
{
Orientation s = orientation(point(it1), point(it2), point(it3), point(it4));
is_plane = is_plane && s == COPLANAR;

if(!is_plane)
return false;

++it1;
++it2;
++it3;
++it4;
}

return true;
}

template <typename Gt, typename Tds>
bool
Triangulation_on_sphere_2<Gt, Tds>::
Expand Down Expand Up @@ -1274,27 +1307,21 @@ is_valid(bool verbose,
if(dimension() <= 0 || (dimension() == 1 && number_of_vertices() == 2))
return result;

for(Vertices_iterator vit=vertices_begin(); vit!=vertices_end(); ++vit)
result = result && is_valid_vertex(vit, verbose, level);

if(dimension() == 1)
{
Vertices_iterator it1 = vertices_begin(), it2(it1), it3(it1);
std::advance(it2, 1);
std::advance(it3, 2);
while(it3 != vertices_end())
{
const Orientation s = orientation(point(it1), point(it2), point(it3));
result = result && (s == COLLINEAR);
CGAL_assertion(result);
++it1; ++it2; ++it3;
}
result = result && this->is_plane();
CGAL_assertion(result);
}
else // dimension() == 2
{
for(All_faces_iterator it=all_faces_begin(); it!=all_faces_end(); ++it)
{
const Orientation s = orientation_on_sphere(point(it, 0), point(it, 1), point(it, 2));
CGAL_assertion(s == LEFT_TURN || is_ghost(it));

result = result && (s == LEFT_TURN || is_ghost(it));
CGAL_assertion(result);
}

// check number of faces. This cannot be done by the TDS,
Expand All @@ -1314,6 +1341,7 @@ void
Triangulation_on_sphere_2<Gt, Tds>::
file_output(std::ostream& os) const
{
os << _gt.center() << " " << _gt.radius() << "\n";
_tds.file_output(os, Vertex_handle(), true);
}

Expand All @@ -1323,7 +1351,15 @@ Triangulation_on_sphere_2<Gt, Tds>::
file_input(std::istream& is)
{
clear();
Vertex_handle v = _tds.file_input(is, true);

Point_3 center;
FT radius;
is >> center >> radius;
_gt.set_center(center);
_gt.set_radius(radius);

Vertex_handle v = _tds.file_input(is, false);
CGAL_assertion(is_valid());
return v;
}

Expand All @@ -1340,7 +1376,6 @@ std::istream&
operator>>(std::istream& is, Triangulation_on_sphere_2<Gt, Tds>& tr)
{
tr.file_input(is);
CGAL_assertion(tr.is_valid());
return is;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,27 @@ class Triangulation_on_sphere_face_base_2
bool _ghost_flag;
};

template < class Gt, class Fb >
std::ostream&
operator<<(std::ostream &os, const Triangulation_on_sphere_face_base_2<Gt, Fb> &f)
{
// non combinatorial information. Default = point
os << static_cast<const Fb&>(f);
os << (f.is_ghost() ? " 1" : " 0");
return os;
}

template < class Gt, class Fb >
std::istream&
operator>>(std::istream &is, Triangulation_on_sphere_face_base_2<Gt, Fb> &f)
{
int g = -1;
is >> static_cast<Fb&>(f);
is >> g;
f.set_ghost(g == 1);
return is;
}

} // namespace CGAL

#endif //CGAL_TRIANGULATION_ON_SPHERE_FACE_BASE_2_H
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ create_single_source_cgal_program( "test_dtos2_remove.cpp" )
create_single_source_cgal_program( "test_dtos_illegal_points.cpp" )
create_single_source_cgal_program( "test_dtos_projection_traits.cpp" )
create_single_source_cgal_program( "test_dtos_traits.cpp" )
create_single_source_cgal_program( "issue_8200.cpp" )

if (CGAL_Core_FOUND OR LEDA_FOUND)
create_single_source_cgal_program( "test_dtos_degenerate_cases.cpp" )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
#include <CGAL/Projection_on_sphere_traits_3.h>
#include <fstream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;

typedef CGAL::Projection_on_sphere_traits_3<K> Traits;
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;

typedef Traits::Point_3 Point_3;

int main(int, char**)
{
std::vector<Point_3> points;
points.emplace_back( 3, 1, 1);
points.emplace_back(-8, 1, 1);
points.emplace_back( 1, 2, 1);
points.emplace_back( 1, -2, 1);
points.emplace_back( 1, 1, 10);

Traits traits(Point_3(4,1,1)); // radius is 1 by default
DToS2 dtos(traits);

Traits::Construct_point_on_sphere_2 cst = traits.construct_point_on_sphere_2_object();

for(const auto& pt : points)
{
std::cout << "----- Inserting (" << pt
<< ") at squared distance " << CGAL::squared_distance(pt, traits.center())
<< " from the center of the sphere" << std::endl;
dtos.insert(cst(pt));

std::cout << "The triangulation now has dimension: " << dtos.dimension() << " and\n";
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
std::cout << dtos.number_of_edges() << " edges" << std::endl;
std::cout << dtos.number_of_solid_faces() << " solid faces" << std::endl;
std::cout << dtos.number_of_ghost_faces() << " ghost faces" << std::endl;
}

assert(dtos.is_valid());
std::ofstream out("dtos.txt");
out.precision(17);
out << dtos << std::endl;
out.close();

CGAL::IO::write_OFF("dtos.off", dtos, CGAL::parameters::stream_precision(17));

DToS2 dtos2;
std::ifstream in("dtos.txt");
in >> dtos2;
in.close();
assert(dtos2.is_valid());

std::cout << "DTOS2 center: " << dtos2.geom_traits().center() << " radius: " << dtos2.geom_traits().radius() << std::endl;
std::cout << "DTOS2 has dimension: " << dtos2.dimension() << " and\n";
std::cout << dtos2.number_of_vertices() << " vertices" << std::endl;
std::cout << dtos2.number_of_edges() << " edges" << std::endl;
std::cout << dtos2.number_of_solid_faces() << " solid faces" << std::endl;
std::cout << dtos2.number_of_ghost_faces() << " ghost faces" << std::endl;

CGAL::IO::write_OFF("dtos2.off", dtos2, CGAL::parameters::stream_precision(17));

assert(dtos.number_of_vertices() == dtos2.number_of_vertices());
assert(dtos.number_of_edges() == dtos2.number_of_edges());
assert(dtos.number_of_solid_faces() == dtos2.number_of_solid_faces());
assert(dtos.number_of_ghost_faces() == dtos2.number_of_ghost_faces());

std::cout << "Done." << std::endl;

return EXIT_SUCCESS;
}

0 comments on commit c36ede0

Please sign in to comment.