mirror of https://github.com/CGAL/cgal
288 lines
10 KiB
C++
288 lines
10 KiB
C++
// Copyright (c) 1997 Tel-Aviv University (Israel).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
//
|
|
// Author(s) : Eti Ezra <estere@post.tau.ac.il>
|
|
#ifndef CGAL_HOLES_SPLIT_H
|
|
#define CGAL_HOLES_SPLIT_H
|
|
|
|
#ifndef CGAL_ASSERTIONS_H
|
|
#include <CGAL/assertions.h>
|
|
#endif
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
template <class Planar_map_, class Notifier_>
|
|
class Holes_split {
|
|
//typedef enum { EPSILON=0.01 };
|
|
static const int EPSILON=1; //change it to work on VC++.
|
|
|
|
typedef Planar_map_ Planar_map;
|
|
typedef Notifier_ Notifier;
|
|
|
|
typedef typename Planar_map_::Traits Traits;
|
|
typedef typename Traits::Point Point;
|
|
typedef typename Traits::X_curve X_curve;
|
|
typedef typename Traits::Curve Curve;
|
|
|
|
typedef typename Planar_map::Vertex Vertex;
|
|
typedef typename Planar_map::Face Face;
|
|
typedef typename Planar_map::Halfedge Halfedge;
|
|
typedef typename Planar_map::Vertex_handle Vertex_handle;
|
|
typedef typename Planar_map::Halfedge_handle Halfedge_handle;
|
|
typedef typename Planar_map::Face_handle Face_handle;
|
|
typedef typename Planar_map::Vertex_const_handle Vertex_const_handle;
|
|
typedef typename Planar_map::Halfedge_const_handle Halfedge_const_handle;
|
|
typedef typename Planar_map::Face_const_handle Face_const_handle;
|
|
typedef typename Planar_map::Vertex_iterator Vertex_iterator;
|
|
typedef typename Planar_map::Vertex_const_iterator Vertex_const_iterator;
|
|
typedef typename Planar_map::Halfedge_iterator Halfedge_iterator;
|
|
typedef typename Planar_map::Halfedge_const_iterator
|
|
Halfedge_const_iterator;
|
|
typedef typename Planar_map::Face_iterator Face_iterator;
|
|
typedef typename Planar_map::Face_const_iterator Face_const_iterator;
|
|
typedef typename Planar_map::Ccb_halfedge_circulator
|
|
Ccb_halfedge_circulator;
|
|
typedef typename Planar_map::Ccb_halfedge_const_circulator
|
|
Ccb_halfedge_const_circulator;
|
|
typedef typename Planar_map::Halfedge_around_vertex_circulator
|
|
Halfedge_around_vertex_circulator;
|
|
typedef typename Planar_map::Holes_iterator Holes_iterator;
|
|
typedef typename Planar_map::Holes_const_iterator Holes_const_iterator;
|
|
typedef typename Planar_map::Locate_type Locate_type;
|
|
typedef typename Planar_map::Traits_wrap Traits_wrap;
|
|
|
|
//typedef typename Point::R Kernel;
|
|
//typedef Ray_2<Kernel> Ray;
|
|
|
|
class less_xy_Vertex_handle {
|
|
public:
|
|
|
|
inline bool operator()(Vertex_handle v1,
|
|
Vertex_handle v2) const
|
|
{
|
|
return CGAL::compare_lexicographically_xy(
|
|
v1->point(),v2->point()) == CGAL::SMALLER;
|
|
}
|
|
};
|
|
|
|
|
|
bool has_decomposing_edge(Vertex_handle v)
|
|
{
|
|
Halfedge_around_vertex_circulator circ = v->incident_halfedges();
|
|
|
|
do
|
|
{
|
|
if (circ->decomposing())
|
|
return true;
|
|
} while(++circ!=v->incident_halfedges());
|
|
|
|
return false;
|
|
}
|
|
|
|
template <class OutputIterator>
|
|
bool get_decomposing_edge(Vertex_handle v, OutputIterator halfedges)
|
|
{
|
|
bool b=false;
|
|
Halfedge_around_vertex_circulator circ = v->incident_halfedges();
|
|
|
|
do
|
|
{
|
|
if (circ->decomposing()){
|
|
b=true;
|
|
*halfedges++ = circ;
|
|
}
|
|
} while(++circ!=v->incident_halfedges());
|
|
|
|
return b;
|
|
}
|
|
|
|
void add_vertical_curve(Vertex_handle v,
|
|
Planar_map& pm,
|
|
Notifier& notf,
|
|
bool up)
|
|
{
|
|
// debugging.
|
|
//cout<< "In add_vertical_curve" <<endl;
|
|
//cout<< v->point().xcoordD()<<","<<v->point().ycoordD() << endl;
|
|
|
|
Locate_type lt;
|
|
//int eps = up? EPSILON: -EPSILON;
|
|
//Point pertrubed_p = Point(v->point().x(),
|
|
// v->point().y() + eps);
|
|
//cout<<"pertrubed_p="<< pertrubed_p.xcoordD()<<","<<pertrubed_p.ycoordD()
|
|
// << endl;
|
|
|
|
// we have to raise p since the function
|
|
// vertical_ray_shoot will return the vertex of of in
|
|
// pmwx (that's how it is defined when we shoot a vertical ray
|
|
// from a feature that exists in the map.
|
|
Halfedge_handle h = pm.vertical_ray_shoot(v->point(), lt, up);
|
|
|
|
if (h->face()->is_unbounded())
|
|
return; // what we should do here is using the bbox and adding
|
|
// a vertical curve upward (downward) will it hits the bbox.
|
|
|
|
//Ray ray(v->point(), pertrubed_p);
|
|
//Point hitting_point;
|
|
|
|
Point hitting_point = traits_->calc_hitting_point(h->curve(),
|
|
v->point());
|
|
|
|
//if (!bops_traits_->intersection(h->curve(), ray, hitting_point))
|
|
// return;
|
|
|
|
notf.set_decomposing_edge(true);
|
|
//pm.non_intersecting_insert_from_vertex(Curve(v->point(),hitting_point),
|
|
// v,up,¬f);
|
|
|
|
Traits traits;
|
|
X_curve c1,c2;
|
|
|
|
traits.curve_split(h->curve(), c1, c2, hitting_point);
|
|
//Halfedge_handle split_h =
|
|
pm.split_edge(h,c1,c2,¬f);
|
|
CGAL_assertion(v->point() != hitting_point);
|
|
pm.insert(Curve(v->point(),hitting_point),¬f);
|
|
|
|
notf.set_decomposing_edge(false);
|
|
}
|
|
|
|
void set_faces_in_holes(Planar_map& pm)
|
|
{
|
|
for (Face_iterator f_iter=pm.faces_begin();
|
|
f_iter!=pm.faces_end(); ++f_iter){
|
|
|
|
if (f_iter->is_unbounded())
|
|
continue;
|
|
|
|
for (Holes_iterator holes_it = f_iter->holes_begin();
|
|
holes_it != f_iter->holes_end(); ++holes_it)
|
|
// set the face inside the hole to true.
|
|
(*holes_it)->twin()->face()->set_in_hole(true);
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
Holes_split() {}
|
|
|
|
Holes_split(Traits* traits) : traits_(traits) {}
|
|
|
|
// This function splits the holes in pm.
|
|
// Here, pm has a special structure of one face with possibly many holes.
|
|
void split_holes(Planar_map& pm,
|
|
Notifier& notf)
|
|
{
|
|
set_faces_in_holes(pm);
|
|
|
|
for (Face_iterator f_iter=pm.faces_begin();
|
|
f_iter!=pm.faces_end(); ++f_iter){
|
|
Face_handle face= f_iter;
|
|
|
|
if (face->is_unbounded())
|
|
continue; // splitting only bounded faces.
|
|
|
|
// keeping all Ccb in a seperate vector, since face is going to be
|
|
// changed.
|
|
std::vector<Ccb_halfedge_circulator>
|
|
holes(face->holes_begin(),face->holes_end());
|
|
|
|
//for (Holes_iterator holes_it = face->holes_begin();
|
|
// holes_it != face->holes_end(); ++holes_it) {
|
|
for (typename std::vector<Ccb_halfedge_circulator>::iterator holes_it =
|
|
holes.begin();
|
|
holes_it != holes.end(); ++holes_it)
|
|
{
|
|
Ccb_halfedge_circulator face_cc(*holes_it);
|
|
|
|
// finding the leftmost and the rightmost points of the hole.
|
|
std::vector<Vertex_handle> vertices_cc;
|
|
do
|
|
{
|
|
vertices_cc.push_back(face_cc->source());
|
|
} while (++face_cc != *holes_it);
|
|
|
|
std::sort(vertices_cc.begin(),
|
|
vertices_cc.end(),
|
|
less_xy_Vertex_handle() );
|
|
|
|
Vertex_handle leftlow_most = vertices_cc[0];
|
|
Vertex_handle lefthigh_most = vertices_cc[0];
|
|
|
|
// updating lefthigh_most to have the highest value of y.
|
|
for (unsigned int i=0; i < vertices_cc.size() - 1 &&
|
|
vertices_cc[i]->point().x() == vertices_cc[i+1]->point().x();
|
|
++i)
|
|
lefthigh_most=vertices_cc[i+1];
|
|
|
|
Vertex_handle righthigh_most = vertices_cc.back();
|
|
Vertex_handle rightlow_most = vertices_cc.back();
|
|
|
|
// updating rightlow_most to have the lowest value of y.
|
|
for (unsigned int i=vertices_cc.size() - 1; i > 1 &&
|
|
vertices_cc[i]->point().x() == vertices_cc[i-1]->point().x();
|
|
--i)
|
|
lefthigh_most=vertices_cc[i-1];
|
|
|
|
/*Vertex_handle leftlow_most=face_cc->source();
|
|
Vertex_handle lefthigh_most=face_cc->source();
|
|
Vertex_handle rightlow_most=face_cc->source();
|
|
Vertex_handle righthigh_most=face_cc->source();
|
|
do {
|
|
if (face_cc->source()->point().xcoord() <
|
|
leftmost->point().xcoord())
|
|
lefthigh_most=leftlow_most=face_cc->source();
|
|
else if (face_cc->source()->point().xcoord() ==
|
|
leftmost->point().xcoord()){
|
|
|
|
}
|
|
if (face_cc->source()->point().xcoord() >
|
|
rightmost->point().xcoord())
|
|
rightmost=face_cc->source();
|
|
} while (++face_cc != *holes_it);*/
|
|
|
|
bool b_lefthigh=has_decomposing_edge(lefthigh_most);
|
|
bool b_leftlow=has_decomposing_edge(leftlow_most);
|
|
bool b_righthigh=has_decomposing_edge(righthigh_most);
|
|
bool b_rightlow=has_decomposing_edge(rightlow_most);
|
|
|
|
if (!b_lefthigh)
|
|
add_vertical_curve(lefthigh_most, pm, notf, true);
|
|
|
|
//bool b_leftlow=has_decomposing_edge(leftlow_most);
|
|
if (!b_leftlow)
|
|
add_vertical_curve(leftlow_most, pm, notf, false);
|
|
|
|
//bool b_righthigh=has_decomposing_edge(righthigh_most);
|
|
if (!b_righthigh)
|
|
add_vertical_curve(righthigh_most, pm, notf, true);
|
|
|
|
//bool b_rightlow=has_decomposing_edge(rightlow_most);
|
|
if (!b_rightlow)
|
|
add_vertical_curve(rightlow_most, pm, notf, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
Traits* traits_;
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif
|