mirror of https://github.com/CGAL/cgal
making a surface xy monotone
This commit is contained in:
parent
66917a69b3
commit
4e2878a16d
|
|
@ -441,6 +441,7 @@ Developers_manual/doc_tex/Developers_manual/fig/reference_counting.pdf -text svn
|
||||||
Developers_manual/doc_tex/Developers_manual/fig/use_real.eps -text
|
Developers_manual/doc_tex/Developers_manual/fig/use_real.eps -text
|
||||||
Developers_manual/doc_tex/Developers_manual/fig/use_real.gif -text svneol=unset#unset
|
Developers_manual/doc_tex/Developers_manual/fig/use_real.gif -text svneol=unset#unset
|
||||||
Developers_manual/doc_tex/Developers_manual/fig/use_real.pdf -text svneol=unset#unset
|
Developers_manual/doc_tex/Developers_manual/fig/use_real.pdf -text svneol=unset#unset
|
||||||
|
Envelope_3/examples/Envelope_3/make_xy_mon.C -text
|
||||||
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.eps -text
|
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.eps -text
|
||||||
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.fig -text
|
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.fig -text
|
||||||
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.gif -text svneol=unset#unset
|
ExternalMemoryStructures/doc_tex/ExternalMemoryStructures/ExternalMemoryStructures_ref/rtree-classes4.gif -text svneol=unset#unset
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,446 @@
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <CGAL/Simple_cartesian.h>
|
||||||
|
#include <CGAL/Quotient.h>
|
||||||
|
#include <CGAL/MP_Float.h>
|
||||||
|
#include <CGAL/Polyhedron_3.h>
|
||||||
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <CGAL/Unique_hash_map.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Sweep_line_2_algorithms.h>
|
||||||
|
#include <CGAL/Timer.h>
|
||||||
|
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/IO/Arr_iostream.h>
|
||||||
|
|
||||||
|
//typedef double NT;
|
||||||
|
typedef CGAL::Quotient<CGAL::MP_Float> NT;
|
||||||
|
typedef CGAL::Simple_cartesian<NT> Kernel;
|
||||||
|
typedef Kernel::RT RT;
|
||||||
|
typedef Kernel::Point_3 Point_3;
|
||||||
|
typedef Kernel::Point_2 Point_2;
|
||||||
|
typedef Kernel::Plane_3 Plane_3;
|
||||||
|
typedef Kernel::Line_2 Line_2;
|
||||||
|
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||||
|
typedef Polyhedron::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef Polyhedron::Facet_const_iterator Facet_const_iterator;
|
||||||
|
typedef Polyhedron::Halfedge_around_facet_const_circulator
|
||||||
|
Halfedge_around_facet_const_circulator;
|
||||||
|
|
||||||
|
typedef Kernel::Oriented_side_2 Oriented_side_2;
|
||||||
|
typedef Kernel::Construct_line_2 Construct_line_2;
|
||||||
|
typedef Kernel::Construct_projected_xy_point_2
|
||||||
|
Construct_projected_xy_point_2;
|
||||||
|
typedef Kernel::Construct_plane_3 Construct_plane_3;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef Arrangement_2::Halfedge_handle Arr_halfedge;
|
||||||
|
|
||||||
|
|
||||||
|
class Make_xy_monotone
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef std::list<Arrangement_2*> XY_surfaces_list;
|
||||||
|
|
||||||
|
std::queue<Facet_const_iterator> m_queue;
|
||||||
|
CGAL::Unique_hash_map<Facet_const_iterator, bool> m_status_map;
|
||||||
|
CGAL::Unique_hash_map<Halfedge_const_handle, Arr_halfedge> m_edges_map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void operator()(const Polyhedron& p, XY_surfaces_list& xy_surfaces)
|
||||||
|
{
|
||||||
|
m_status_map =
|
||||||
|
CGAL::Unique_hash_map<Facet_const_iterator, bool>(false, p.size_of_facets());
|
||||||
|
|
||||||
|
m_edges_map = CGAL::Unique_hash_map<Halfedge_const_handle,
|
||||||
|
Arr_halfedge>(Arr_halfedge());
|
||||||
|
|
||||||
|
for (Facet_const_iterator f = p.facets_begin(); f != p.facets_end(); ++f)
|
||||||
|
{
|
||||||
|
if (! m_status_map[f])
|
||||||
|
bfs(f, xy_surfaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bfs(Facet_const_iterator f, XY_surfaces_list& xy_surfaces)
|
||||||
|
{
|
||||||
|
m_edges_map.clear(); // clear the previous data of the edges map
|
||||||
|
|
||||||
|
m_status_map[f] = true;
|
||||||
|
if(is_vertical(f))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Arrangement_2* arr = new Arrangement_2;
|
||||||
|
xy_surfaces.push_back(arr);
|
||||||
|
m_queue.push(f);
|
||||||
|
while(!m_queue.empty())
|
||||||
|
{
|
||||||
|
f = m_queue.front();
|
||||||
|
m_queue.pop();
|
||||||
|
|
||||||
|
// add f to current xy_surface
|
||||||
|
add_facet_to_arr(*arr, f);
|
||||||
|
Halfedge_around_facet_const_circulator haf = f->facet_begin();
|
||||||
|
Halfedge_around_facet_const_circulator curr = haf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(curr->opposite()->is_border())
|
||||||
|
{
|
||||||
|
++curr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Facet_const_iterator neighbour_f = curr->opposite()->face();
|
||||||
|
|
||||||
|
bool& is_done = m_status_map[neighbour_f];
|
||||||
|
if (!is_done)
|
||||||
|
{
|
||||||
|
if(is_vertical(neighbour_f))
|
||||||
|
{
|
||||||
|
is_done = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(are_xy_mon(curr, f, neighbour_f))
|
||||||
|
{
|
||||||
|
is_done = true;
|
||||||
|
m_queue.push(neighbour_f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++curr;
|
||||||
|
} while(curr != haf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_vertical(Facet_const_iterator f)
|
||||||
|
{
|
||||||
|
CGAL_assertion(f->facet_degree() > 2);
|
||||||
|
Halfedge_const_handle he = f->halfedge();
|
||||||
|
const Point_3& p1 = he->vertex()->point();
|
||||||
|
const Point_3& p2 = he->next()->vertex()->point();
|
||||||
|
const Point_3& p3 = he->next()->next()->vertex()->point();
|
||||||
|
Kernel k;
|
||||||
|
return (k.collinear_2_object()(project_xy(p1),
|
||||||
|
project_xy(p2),
|
||||||
|
project_xy(p3)));
|
||||||
|
}
|
||||||
|
bool are_xy_mon(Halfedge_const_handle he, Facet_const_iterator f1, Facet_const_iterator f2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* t
|
||||||
|
* *|*
|
||||||
|
* * | *
|
||||||
|
* * ^| *
|
||||||
|
* * || *
|
||||||
|
* p1 * he|| * p2
|
||||||
|
* * f1|| f2 *
|
||||||
|
* * || *
|
||||||
|
* * | *
|
||||||
|
* * | *
|
||||||
|
* *|*
|
||||||
|
* s
|
||||||
|
*/
|
||||||
|
|
||||||
|
CGAL_assertion(!is_vertical(f1) && !is_vertical(f2));
|
||||||
|
|
||||||
|
const Point_2& s = project_xy(he->opposite()->vertex()->point());
|
||||||
|
const Point_2& t = project_xy(he->vertex()->point());
|
||||||
|
|
||||||
|
const Point_2& p1 = project_xy(he->next()->vertex()->point());
|
||||||
|
const Point_2& p2 = project_xy(he->opposite()->next()->vertex()->point());
|
||||||
|
|
||||||
|
Kernel k;
|
||||||
|
Line_2 l = k.construct_line_2_object()(s, t);
|
||||||
|
CGAL::Oriented_side os1, os2;
|
||||||
|
|
||||||
|
os1 = k.oriented_side_2_object()(l, p1);
|
||||||
|
os2 = k.oriented_side_2_object()(l, p2);
|
||||||
|
|
||||||
|
CGAL_assertion(os1 != CGAL::ON_ORIENTED_BOUNDARY &&
|
||||||
|
os2 != CGAL::ON_ORIENTED_BOUNDARY);
|
||||||
|
|
||||||
|
return (os1 != os2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*Point_2 project_xy (const Point_3& p)
|
||||||
|
{
|
||||||
|
Kernel k;
|
||||||
|
Plane_3 xy_plane = k.construct_plane_3_object()(RT(0), RT(0), RT(1), RT(0));
|
||||||
|
return (k.construct_projected_xy_point_2_object()(xy_plane, p));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
Point_2 project_xy (const Point_3& p)
|
||||||
|
{
|
||||||
|
return (Point_2(p.x(), p.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_back_facet(Facet_const_iterator f)
|
||||||
|
{
|
||||||
|
Kernel k;
|
||||||
|
Plane_3 supp_plane =
|
||||||
|
k.construct_plane_3_object()(f->halfedge()->vertex()->point(),
|
||||||
|
f->halfedge()->next()->vertex()->point(),
|
||||||
|
f->halfedge()->next()->next()->vertex()->point());
|
||||||
|
|
||||||
|
return (supp_plane.c() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_facet_to_arr(Arrangement_2& arr, Facet_const_iterator f)
|
||||||
|
{
|
||||||
|
//static int i=1;
|
||||||
|
bool is_back = is_back_facet(f);
|
||||||
|
Halfedge_around_facet_const_circulator haf = f->facet_begin();
|
||||||
|
Halfedge_around_facet_const_circulator curr = haf;
|
||||||
|
|
||||||
|
Kernel k;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Halfedge_const_handle he = curr;
|
||||||
|
|
||||||
|
// look for that polyhedron's halfedge at the edges map
|
||||||
|
Arr_halfedge arr_he = m_edges_map[he->opposite()];
|
||||||
|
Arr_halfedge prev_he;
|
||||||
|
|
||||||
|
if(arr_he == Arr_halfedge())
|
||||||
|
{
|
||||||
|
// this edge was not inserted to the arrangement yet
|
||||||
|
|
||||||
|
const Point_2& s = project_xy(curr->opposite()->vertex()->point());
|
||||||
|
const Point_2& t = project_xy(curr->vertex()->point());
|
||||||
|
|
||||||
|
X_monotone_curve_2 cv(s, t);
|
||||||
|
|
||||||
|
Arr_halfedge next_he = find_halfedge_before_cw(he, is_back);
|
||||||
|
if(prev_he == Arr_halfedge())
|
||||||
|
prev_he = find_halfedge_before_cw(he->opposite(), is_back);
|
||||||
|
|
||||||
|
bool next_exist = (next_he!=Arr_halfedge());
|
||||||
|
bool prev_exist = (prev_he!=Arr_halfedge());
|
||||||
|
|
||||||
|
CGAL::Comparison_result res = k.compare_xy_2_object()(s, t);
|
||||||
|
|
||||||
|
if(!next_exist && !prev_exist)
|
||||||
|
{
|
||||||
|
//std::cout<<"("<<i++<<")"<<"insert_in_face_interior: " << cv<<"\n";
|
||||||
|
prev_he = arr.insert_in_face_interior(cv, arr.unbounded_face());
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(!next_exist && prev_exist)
|
||||||
|
{
|
||||||
|
if(res == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
//std::cout<<"("<<i++<<")"<<"insert_from_left_vertex: " << cv<<"\n";
|
||||||
|
prev_he = arr.insert_from_left_vertex(cv, prev_he);
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::cout<<"("<<i++<<")"<<"insert_from_right_vertex: " << cv<<"\n";
|
||||||
|
prev_he = arr.insert_from_right_vertex(cv, prev_he);
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(next_exist && !prev_exist)
|
||||||
|
{
|
||||||
|
if(res == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
// std::cout<<"("<<i++<<")"<<"insert_from_right_vertex: " << cv<<"\n";
|
||||||
|
prev_he = arr.insert_from_right_vertex(cv, next_he);
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::cout<<"("<<i++<<")"<<"insert_from_left_vertex: " << cv<<"\n";
|
||||||
|
prev_he = arr.insert_from_left_vertex(cv, next_he);
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::cout<<"("<<i++<<")"<<"insert_at_vertices: " << cv<<"\n";
|
||||||
|
//std::cout<<"prev_he: " <<prev_he->source()->point()<<" --> "<< prev_he->target()->point()<<"\n";
|
||||||
|
//std::cout<<"next_he: " <<next_he->source()->point()<<" --> "<< next_he->target()->point()<<"\n";
|
||||||
|
//TODO: can be done much more efficient using the Arr_accessor !!
|
||||||
|
prev_he = arr.insert_at_vertices(cv, prev_he, next_he);
|
||||||
|
if(prev_he->direction() != res)
|
||||||
|
prev_he = prev_he->twin();
|
||||||
|
}
|
||||||
|
//map 'he' of the polyhderon to 'prev_he'
|
||||||
|
m_edges_map[he] = prev_he;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev_he = arr_he->twin();
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_assertion(prev_he->source()->point() ==
|
||||||
|
project_xy(he->opposite()->vertex()->point()));
|
||||||
|
CGAL_assertion(prev_he->target()->point() ==
|
||||||
|
project_xy(he->vertex()->point()));
|
||||||
|
|
||||||
|
|
||||||
|
++curr;
|
||||||
|
} while(curr != haf);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Arr_halfedge find_halfedge_before_cw(Halfedge_const_handle he, bool is_back_face)
|
||||||
|
{
|
||||||
|
// iterate the halfedges around the target vertex of 'he' counter-clockwise
|
||||||
|
// and find the first halfedge that was inserterd to the arrangement.
|
||||||
|
Halfedge_const_handle curr;
|
||||||
|
if(is_back_face)
|
||||||
|
curr = he->prev_on_vertex();
|
||||||
|
else
|
||||||
|
curr = he->next_on_vertex();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Arr_halfedge res = m_edges_map[curr];
|
||||||
|
if(res != Arr_halfedge())
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = m_edges_map[curr->opposite()];
|
||||||
|
if(res != Arr_halfedge())
|
||||||
|
return res->twin();
|
||||||
|
|
||||||
|
if(is_back_face)
|
||||||
|
curr = curr->prev_on_vertex();
|
||||||
|
else
|
||||||
|
curr = curr->next_on_vertex();
|
||||||
|
} while(curr != he);
|
||||||
|
|
||||||
|
return Arr_halfedge();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Point_2 project_xy (const Point_3& p)
|
||||||
|
{
|
||||||
|
return (Point_2(p.x(), p.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_xy_mon(std::vector<Facet_const_iterator>& surf)
|
||||||
|
{
|
||||||
|
CGAL::Unique_hash_map<Halfedge_const_handle, bool> edges_hash(false);
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits;
|
||||||
|
typedef Traits::Curve_2 Curve_2;
|
||||||
|
std::list<Curve_2> curves;
|
||||||
|
for(unsigned int i=0; i< surf.size(); ++i)
|
||||||
|
{
|
||||||
|
Facet_const_iterator curr_f = surf[i];
|
||||||
|
Halfedge_around_facet_const_circulator haf = curr_f->facet_begin();
|
||||||
|
Halfedge_around_facet_const_circulator curr = haf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Halfedge_const_handle he = curr;
|
||||||
|
if(!edges_hash[he] && !edges_hash[he->opposite()])
|
||||||
|
{
|
||||||
|
Curve_2 cv(project_xy(he->vertex()->point()),
|
||||||
|
project_xy(he->opposite()->vertex()->point()));
|
||||||
|
curves.push_back(cv);
|
||||||
|
edges_hash[he] = edges_hash[he->opposite()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
++curr;
|
||||||
|
}while(curr != haf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_x = CGAL::do_curves_intersect(curves.begin(), curves.end());
|
||||||
|
return (!do_x);
|
||||||
|
}
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if(argc<2)
|
||||||
|
{
|
||||||
|
std::cout<<"Missing off file\n";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream off_file(argv[1]);
|
||||||
|
if(!off_file.is_open())
|
||||||
|
{
|
||||||
|
std::cout<<"Failed to open file\n";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL::Timer t;
|
||||||
|
Polyhedron p;
|
||||||
|
//off_file >> p;
|
||||||
|
// reads a polyhedron from `in' and appends it to P.
|
||||||
|
t.start();
|
||||||
|
CGAL::scan_OFF(off_file, p, true);
|
||||||
|
t.stop();
|
||||||
|
|
||||||
|
if ( (off_file.rdstate() & std::ios::badbit ) != 0 )
|
||||||
|
std::cerr << "Error opening "<<argv[1] <<"\n";
|
||||||
|
|
||||||
|
std::cout<<"Reading OFF file took: " <<t.time()<<" seconds\n";
|
||||||
|
t.reset();
|
||||||
|
if(p.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Facet_const_iterator f = p.facets_begin();
|
||||||
|
|
||||||
|
std::cout << "|V| = " <<p.size_of_vertices()<<std::endl;
|
||||||
|
std::cout << "|E| = " <<p.size_of_halfedges()<<std::endl;
|
||||||
|
std::cout << "|F| = " <<p.size_of_facets()<<std::endl;
|
||||||
|
|
||||||
|
std::list<Arrangement_2*> xy_surfs;
|
||||||
|
typedef std::list<Arrangement_2*>::iterator Xy_surf_itr;
|
||||||
|
Make_xy_monotone make_xy;
|
||||||
|
t.start();
|
||||||
|
make_xy(p, xy_surfs);
|
||||||
|
t.stop();
|
||||||
|
std::cout<<"Making the surface xy-monotone took: " <<t.time()<<" seconds\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout<<"There are: " << xy_surfs.size() << " xy-surfaces\n";
|
||||||
|
unsigned int i=1;
|
||||||
|
for(Xy_surf_itr itr = xy_surfs.begin(); itr != xy_surfs.end(); ++itr, ++i)
|
||||||
|
{
|
||||||
|
std::cout<<"#" <<i<<" surface : "<<std::endl;
|
||||||
|
std::cout<<" |V| = "<<(*itr)->number_of_vertices()<<std::endl;
|
||||||
|
std::cout<<" |E| = "<<(*itr)->number_of_edges()<<std::endl;
|
||||||
|
std::cout<<" |F| = "<<(*itr)->number_of_faces()<<std::endl;
|
||||||
|
|
||||||
|
char buffer[33];
|
||||||
|
buffer[0] = '1' + i-1;
|
||||||
|
buffer[1] = '\0';
|
||||||
|
std::string prog_name (argv[1]);
|
||||||
|
std::string filename("surface");
|
||||||
|
std::string prefix (buffer);
|
||||||
|
std::string temp(".arr");
|
||||||
|
prefix += temp;
|
||||||
|
filename += prefix;
|
||||||
|
std::cout << filename<<"\n";
|
||||||
|
std::ofstream arr_file(filename.c_str());
|
||||||
|
if(!arr_file.is_open())
|
||||||
|
std::cout<<"Failed to open: " << filename<<"\n";
|
||||||
|
arr_file << **itr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue