mirror of https://github.com/CGAL/cgal
3306 lines
123 KiB
C++
3306 lines
123 KiB
C++
// Copyright (c) 2001-2004 ENS of Paris (France).
|
|
// 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) : Pierre Angelier, Michel Pocchiola, Luc Habert
|
|
|
|
|
|
#ifndef CGAL_VISIBILITY_COMPLEX_2_ANTICHAIN_H
|
|
#define CGAL_VISIBILITY_COMPLEX_2_ANTICHAIN_H
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <CGAL/Visibility_complex_2/function_objects.h>
|
|
|
|
#include <CGAL/In_place_list.h>
|
|
|
|
#include <CGAL/Multiset.h>
|
|
|
|
#include <CGAL/Visibility_complex_2/Items.h>
|
|
#include <CGAL/Visibility_complex_2/Flip_traits.h>
|
|
#include <CGAL/Visibility_complex_2/antichain_iterators.h>
|
|
#include <CGAL/Visibility_complex_2/ccw_cw_traits.h>
|
|
#include <CGAL/Visibility_complex_2/function_objects.h>
|
|
#include <CGAL/Visibility_complex_2/Sweep_iterator.h>
|
|
#include <CGAL/Visibility_complex_2/Bitangent_2.h>
|
|
|
|
|
|
#include <queue>
|
|
#include <list>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
namespace Visibility_complex_2_details {
|
|
|
|
template<class T> class VC_in_place_list_base: public In_place_list_base<T> {
|
|
public:
|
|
VC_in_place_list_base() {
|
|
this->next_link=0;
|
|
this->prev_link=0;
|
|
}
|
|
~VC_in_place_list_base() {
|
|
if (this->next_link) {
|
|
this->next_link->prev_link=this->prev_link;
|
|
}
|
|
if (this->prev_link) {
|
|
this->prev_link->next_link=this->next_link;
|
|
}
|
|
this->next_link=0;
|
|
this->prev_link=0;
|
|
}
|
|
};
|
|
|
|
template < class Vertex_base_>
|
|
class Vertex
|
|
: public Vertex_base_,
|
|
public VC_in_place_list_base< Vertex<Vertex_base_> >
|
|
{
|
|
typedef Vertex< Vertex_base_> Self;
|
|
public:
|
|
typedef typename Vertex_base_::Vertex_handle Vertex_handle;
|
|
typedef typename Vertex_base_::Edge_handle Edge_handle;
|
|
typedef typename Vertex_base_::Disk_handle Disk_handle;
|
|
typedef typename Vertex_base_::Bitangent_2 Bitangent_2;
|
|
typedef typename Vertex_base_::Type Type;
|
|
|
|
Vertex() {}
|
|
Vertex(Type t , Disk_handle start ,
|
|
Disk_handle finish)
|
|
: Vertex_base_(t,start,finish),final_antichain_(false) {}
|
|
Vertex(Edge_handle start , Edge_handle finish)
|
|
: Vertex_base_(start,finish),final_antichain_(false) {}
|
|
Vertex(const Bitangent_2& b)
|
|
: Vertex_base_(b),final_antichain_(false) {}
|
|
Vertex( const Vertex_base_& v) // down cast
|
|
: Vertex_base_(v),final_antichain_(false) {}
|
|
Vertex(const Vertex&sibling,bool reverse,Type t)
|
|
: Vertex_base_(sibling,reverse,t),final_antichain_(false) {}
|
|
Self& operator=( const Self& v) {
|
|
this->Vertex_base_::operator=(v);
|
|
final_antichain_=v.final_antichain_;
|
|
return *this;
|
|
}
|
|
// Wether this vertex is the pi of a vertex of the original antichain,
|
|
// in which case the sweep should not go beyond.
|
|
bool final_antichain() const {
|
|
return final_antichain_;
|
|
}
|
|
void set_final_antichain(bool b) {
|
|
final_antichain_=b;
|
|
}
|
|
private:
|
|
bool final_antichain_;
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
template <class Edge_base_>
|
|
class Edge
|
|
: public Edge_base_,
|
|
public VC_in_place_list_base< Edge<Edge_base_> >
|
|
{
|
|
typedef Edge<Edge_base_> Self;
|
|
public:
|
|
typedef typename Edge_base_::Vertex_handle Vertex_handle;
|
|
typedef typename Edge_base_::Disk_handle Disk_handle;
|
|
|
|
Edge() {}
|
|
Edge(bool s, Disk_handle p)
|
|
: Edge_base_(s,p) {}
|
|
Edge(Vertex_handle v0 , Vertex_handle v1 ,
|
|
Disk_handle p)
|
|
: Edge_base_(v0,v1,p) {}
|
|
Edge( const Edge_base_& h)
|
|
: Edge_base_(h) {}
|
|
Self& operator=( const Self& e) {
|
|
this->Edge_base_::operator=(e);
|
|
return *this;
|
|
}
|
|
bool is_in_antichain() const {
|
|
|
|
return this->next_link;
|
|
}
|
|
};
|
|
|
|
|
|
template < class Face_base_>
|
|
class Face
|
|
: public Face_base_ {
|
|
private:
|
|
bool in_initial_antichain;
|
|
typedef Face< Face_base_> Self;
|
|
public:
|
|
Face() : in_initial_antichain(false) {}
|
|
bool is_in_initial_antichain() const {
|
|
return in_initial_antichain;
|
|
}
|
|
void set_in_initial_antichain(bool b) {
|
|
in_initial_antichain=b;
|
|
}
|
|
};
|
|
|
|
|
|
template<class T, bool b> class VC_in_place_list
|
|
:public In_place_list<T,b> {
|
|
typedef In_place_list<T,b> Base;
|
|
private:
|
|
// Prevent copy.
|
|
VC_in_place_list(const VC_in_place_list&) {}
|
|
VC_in_place_list& operator=(const VC_in_place_list&) {}
|
|
public:
|
|
VC_in_place_list() {}
|
|
void erase(T* pos) {
|
|
CGAL_precondition(pos->next_link&&pos->prev_link);
|
|
Base::erase(pos);
|
|
pos->next_link=0;
|
|
pos->prev_link=0;
|
|
}
|
|
typename Base::iterator insert(typename Base::iterator pos, T& x) {
|
|
CGAL_precondition(x.next_link==0&&x.prev_link==0);
|
|
return Base::insert(pos, x);
|
|
}
|
|
};
|
|
|
|
template < class Gtr_ ,
|
|
class It = Items ,
|
|
class Flip = Flip_traits >
|
|
class Antichain
|
|
: public VC_in_place_list<
|
|
Visibility_complex_2_details::Edge<
|
|
typename It::template Edge_wrapper<
|
|
Antichain<Gtr_, It, Flip>
|
|
>::Edge>, false>
|
|
{
|
|
public:
|
|
// -------------------------------------------------------------------------
|
|
typedef Gtr_ Gt;
|
|
typedef typename Gtr_::Disk Disk;
|
|
typedef typename Gtr_::Point_2 Point_2;
|
|
typedef typename Gtr_::Bitangent_2 Bitangent_2;
|
|
typedef typename Bitangent_2::Disk_handle Disk_handle;
|
|
|
|
typedef Antichain<Gtr_,It,Flip> Self;
|
|
|
|
typedef Left_ccw_traits_tp<Self> Left_ccw_traits;
|
|
typedef Right_ccw_traits_tp<Self> Right_ccw_traits;
|
|
typedef Left_cw_traits_tp<Self> Left_cw_traits;
|
|
typedef Right_cw_traits_tp<Self> Right_cw_traits;
|
|
typedef Right_ccw_traits Ccw_traits;
|
|
typedef Right_cw_traits Cw_traits;
|
|
private:
|
|
typedef typename Flip::template Flip_wrapper<Self> Flip_wrapper;
|
|
typedef typename Flip_wrapper::Flip_traits Flip_traits;
|
|
|
|
typedef typename It::template Vertex_wrapper<Self> Vertex_wrapper;
|
|
typedef typename Vertex_wrapper::Vertex Vertex_base;
|
|
public:
|
|
typedef Visibility_complex_2_details::Vertex<Vertex_base> Vertex;
|
|
typedef Vertex* Vertex_handle;
|
|
typedef const Vertex* Vertex_const_handle;
|
|
typedef typename VC_in_place_list<Vertex,false>::iterator Minimals_iterator;
|
|
private:
|
|
typedef typename It::template Edge_wrapper<Self> Edge_wrapper;
|
|
typedef typename Edge_wrapper::Edge Edge_base;
|
|
public:
|
|
typedef Visibility_complex_2_details::Edge<Edge_base> Edge;
|
|
typedef Edge* Edge_handle;
|
|
typedef const Edge* Edge_const_handle;
|
|
private:
|
|
typedef VC_in_place_list<Edge,false> Base;
|
|
public:
|
|
typedef typename VC_in_place_list<Edge,false>::iterator Edge_iterator;
|
|
typedef typename VC_in_place_list<Edge,false>::reverse_iterator Edge_reverse_iterator;
|
|
typedef typename VC_in_place_list<Edge,false>::const_iterator Edge_const_iterator;
|
|
private:
|
|
typedef typename It::template Face_wrapper<Self> Face_wrapper;
|
|
typedef typename Face_wrapper::Face Face_base;
|
|
public:
|
|
typedef Visibility_complex_2_details::Face< Face_base> Face;
|
|
typedef Face* Face_handle;
|
|
typedef const Face* Face_const_handle;
|
|
typedef Antichain_face_iterator<Self,Face,
|
|
Face&,Face_handle> Face_iterator;
|
|
typedef Antichain_face_iterator<Self,Face,
|
|
const Face&,const Face_handle>
|
|
Face_const_iterator;
|
|
// -------------------------------------------------------------------------
|
|
typedef Antichain_vertex_iterator<Self,Vertex, Vertex&,
|
|
Vertex_handle, typename Ccw_traits::Sup>
|
|
Vertex_iterator;
|
|
typedef Antichain_vertex_iterator<Self,Vertex, const Vertex&,
|
|
const Vertex_handle,
|
|
typename Ccw_traits::Sup>
|
|
Vertex_const_iterator;
|
|
typedef Antichain_vertex_iterator<Self,Vertex, Vertex&,
|
|
Vertex_handle, typename Cw_traits::Sup>
|
|
Vertex_cw_iterator;
|
|
typedef Antichain_vertex_iterator<Self,Vertex, const Vertex&,
|
|
const Vertex_handle,
|
|
typename Cw_traits::Sup>
|
|
Vertex_cw_const_iterator;
|
|
// -------------------------------------------------------------------------
|
|
typedef Visibility_complex_2_details::Linear_sweep_iterator<Antichain,Vertex,
|
|
Vertex&,Vertex_handle,
|
|
typename Gt::Is_upward_directed>
|
|
Linear_sweep_iterator;
|
|
typedef Visibility_complex_2_details::Linear_sweep_iterator<Self,Vertex,
|
|
const Vertex&,const Vertex_handle,
|
|
typename Gt::Is_upward_directed>
|
|
Linear_sweep_const_iterator;
|
|
// -------------------------------------------------------------------------
|
|
typedef Visibility_complex_2_details::Sweep_iterator<Self,Vertex,
|
|
Vertex&,Vertex_handle>
|
|
Sweep_iterator;
|
|
typedef Visibility_complex_2_details::Sweep_iterator<Self,Vertex,
|
|
const Vertex&,const Vertex_handle>
|
|
Sweep_const_iterator;
|
|
// -------------------------------------------------------------------------
|
|
typedef typename Bitangent_2::Type_util Type_util;
|
|
// -------------------------------------------------------------------------
|
|
using Base::destroy;
|
|
using Base::begin;
|
|
using Base::end;
|
|
using Base::rbegin;
|
|
using Base::rend;
|
|
|
|
typedef Visibility_complex_2_details::Constraint_input Constraint_input;
|
|
typedef typename std::vector<Disk_handle>::const_iterator
|
|
Disk_const_iterator;
|
|
typedef typename std::vector<Vertex>::const_iterator
|
|
Constraint_const_iterator;
|
|
typedef typename std::vector<Disk_handle>::iterator Disk_iterator;
|
|
typedef typename std::vector<Vertex>::iterator Constraint_iterator;
|
|
|
|
Disk_iterator disks_begin() {
|
|
return disks.begin();
|
|
}
|
|
Disk_iterator disks_end() {
|
|
return disks.end();
|
|
}
|
|
Constraint_iterator constraints_begin() {
|
|
return constraints.begin();
|
|
}
|
|
Constraint_iterator constraints_end() {
|
|
return constraints.end();
|
|
}
|
|
Disk_const_iterator disks_begin() const {
|
|
return disks.begin();
|
|
}
|
|
Disk_const_iterator disks_end() const {
|
|
return disks.end();
|
|
}
|
|
Constraint_const_iterator constraints_begin() const {
|
|
return constraints.begin();
|
|
}
|
|
Constraint_const_iterator constraints_end() const {
|
|
return constraints.end();
|
|
}
|
|
private:
|
|
public:
|
|
bool valid_;
|
|
bool straight_sweep_;
|
|
bool linear_space_;
|
|
Face_handle infinite_face_;
|
|
VC_in_place_list<Vertex,false> minimals_ccw_;
|
|
VC_in_place_list<Vertex,false> minimals_cw_;
|
|
std::vector<Disk_handle> disks;
|
|
std::vector<Vertex> constraints;
|
|
|
|
#if 0
|
|
std::map<long,int> Key;
|
|
#endif
|
|
|
|
public :
|
|
|
|
// -------------------------------------------------------------------------
|
|
Antichain()
|
|
: valid_(false) , straight_sweep_(false) , linear_space_(true),
|
|
infinite_face_(0)
|
|
{ }
|
|
template < class DiskIterator ,class ConstraintIterator >
|
|
Antichain(bool linear,DiskIterator first, DiskIterator last,
|
|
ConstraintIterator firstc,ConstraintIterator lastc);
|
|
// -------------------------------------------------------------------------
|
|
// Options when sweeping
|
|
bool is_valid() const { return valid_; }
|
|
bool is_straight() const { return straight_sweep_; }
|
|
void make_straight() { straight_sweep_ = true; }
|
|
bool linear_space() const { return linear_space_; }
|
|
void set_linear_space(bool b) { linear_space_ = b; }
|
|
// -------------------------------------------------------------------------
|
|
// Identifying convex-hull vertices
|
|
Face_handle infinite_face() const { return infinite_face_; }
|
|
void create_infinite_face() { infinite_face_ = new Face; }
|
|
bool is_on_convex_hull(Vertex_handle v) const;
|
|
// -------------------------------------------------------------------------
|
|
// Iterator pairs for trversing the sink of the faces of the antichain
|
|
// These vertices form the Greedy pseudo-triangulation
|
|
Vertex_iterator vertices_begin()
|
|
{ return Vertex_iterator(this,begin()); }
|
|
Vertex_const_iterator vertices_begin() const
|
|
{ return Vertex_const_iterator(this,begin()); }
|
|
Vertex_iterator vertices_end()
|
|
{ return Vertex_iterator(this,end()); }
|
|
Vertex_const_iterator vertices_end() const
|
|
{ return Vertex_const_iterator(this,end()); }
|
|
// -------------------------------------------------------------------------
|
|
// Iterator pairs for trversing the sources of the faces of the antichain
|
|
// These vertices form the dual Greedy pseudo-triangulation
|
|
Vertex_cw_iterator cw_vertices_begin()
|
|
{ return Vertex_cw_iterator(this,begin()); }
|
|
Vertex_cw_const_iterator cw_vertices_begin() const
|
|
{ return Vertex_cw_const_iterator(this,begin()); }
|
|
Vertex_cw_iterator cw_vertices_end()
|
|
{ return Vertex_cw_iterator(this,end()); }
|
|
Vertex_cw_const_iterator cw_vertices_end() const
|
|
{ return Vertex_cw_const_iterator(this,end()); }
|
|
// -------------------------------------------------------------------------
|
|
Edge_iterator edges_begin() { return begin(); }
|
|
Edge_const_iterator edges_begin() const { return begin(); }
|
|
Edge_iterator edges_end() { return end(); }
|
|
Edge_const_iterator edges_end() const { return end(); }
|
|
Edge_reverse_iterator edges_rbegin() { return rbegin(); }
|
|
Edge_reverse_iterator edges_rend() { return rend(); }
|
|
// -------------------------------------------------------------------------
|
|
Face_iterator faces_begin() {return Face_iterator(this,begin());}
|
|
Face_const_iterator faces_begin()const{return Face_iterator(this,begin());}
|
|
Face_iterator faces_end() { return Face_iterator(this,end()); }
|
|
Face_const_iterator faces_end() const{ return Face_iterator(this,end()); }
|
|
// -------------------------------------------------------------------------
|
|
Minimals_iterator minimals_begin() { return minimals_ccw_.begin(); }
|
|
Minimals_iterator minimals_end() { return minimals_ccw_.end(); }
|
|
Minimals_iterator cw_minimals_begin() { return minimals_cw_.begin(); }
|
|
Minimals_iterator cw_minimals_end() { return minimals_cw_.end(); }
|
|
Minimals_iterator minimals_begin(Ccw_traits) { return minimals_begin(); }
|
|
Minimals_iterator minimals_end (Ccw_traits) { return minimals_end(); }
|
|
Minimals_iterator minimals_begin(Cw_traits) { return cw_minimals_begin(); }
|
|
Minimals_iterator minimals_end (Cw_traits) { return cw_minimals_end(); }
|
|
// -------------------------------------------------------------------------
|
|
// Iterator pair for linear sweep
|
|
Linear_sweep_iterator sweep_begin()
|
|
{ return Linear_sweep_iterator(this); }
|
|
Linear_sweep_const_iterator sweep_begin() const
|
|
{ return Linear_sweep_const_iterator(this); }
|
|
Linear_sweep_iterator sweep_end()
|
|
{ return Linear_sweep_iterator(this,0); }
|
|
Linear_sweep_const_iterator sweep_end() const
|
|
{ return Linear_sweep_const_iterator(this,0); }
|
|
// -------------------------------------------------------------------------
|
|
// Testing minimality
|
|
template < class Tr >
|
|
bool is_minimal(const Vertex_handle& v, Tr tr) const;
|
|
bool is_minimal(const Vertex_handle& v) const
|
|
{ return is_minimal(v,Ccw_traits()); }
|
|
template < class Tr >
|
|
bool is_xx_minimal(const Vertex_handle& v,Tr tr) const;
|
|
bool is_right_minimal(const Vertex_handle& v) const
|
|
{ return is_xx_minimal(v,Right_ccw_traits()); }
|
|
bool is_left_minimal(const Vertex_handle& v) const
|
|
{ return is_xx_minimal(v,Left_ccw_traits()); }
|
|
// -------------------------------------------------------------------------
|
|
Vertex_handle pop_minimal(bool finite = false);
|
|
template < class Tr >
|
|
bool is_swept_regular(const Vertex_handle& v , Tr tr) const;
|
|
template < class Tr >
|
|
bool is_swept_constraint(const Vertex_handle& v , Tr tr) const;
|
|
template < class Tr >
|
|
bool is_swept(const Vertex_handle& v , Tr tr) const;
|
|
bool is_swept(const Vertex_handle& v) const
|
|
{ return is_swept(v,Ccw_traits()); }
|
|
// -------------------------------------------------------------------------
|
|
// Adding a minimal
|
|
void push_back_minimal(Vertex_handle v ,Ccw_traits);
|
|
void push_back_minimal(Vertex_handle v ,Cw_traits);
|
|
void push_back_minimal(Vertex_handle v) {push_back_minimal(v,Ccw_traits());}
|
|
// -------------------------------------------------------------------------
|
|
// Removing a minimal
|
|
void erase_minimal(Vertex_handle v, Ccw_traits) { minimals_ccw_.erase(v); }
|
|
void erase_minimal(Vertex_handle v, Cw_traits) { minimals_cw_.erase(v); }
|
|
void erase_minimal(Vertex_handle v) { erase_minimal(v, Ccw_traits()); }
|
|
// Depreciated - for backward compatibility
|
|
template < class Tr >
|
|
void erase_minimal(Minimals_iterator v,Tr tr) { erase_minimal(&(*v),tr); }
|
|
void erase_minimal(Minimals_iterator v) { erase_minimal(v,Ccw_traits()); }
|
|
// -------------------------------------------------------------------------
|
|
// Removing all minimals
|
|
template < class Tr > void clear_minimals(Tr tr);
|
|
void clear_minimals() { clear_minimals(Ccw_traits()); }
|
|
// -------------------------------------------------------------------------
|
|
// Sweeping - flipping operations
|
|
template < class Tr > void sweep(Vertex_handle v, Tr tr);
|
|
template < class Tr > void sweep_good(Vertex_handle v , Tr tr);
|
|
template < class Tr > void sweep_all_minimals(Tr tr);
|
|
template < class Tr > void sweep_good_all_minimals(Tr tr);
|
|
void sweep(Vertex_handle v) { sweep(v,Ccw_traits()); }
|
|
void sweep_all_minimals() { sweep_all_minimals(Ccw_traits()); }
|
|
// -------------------------------------------------------------------------
|
|
void set_constraint(Vertex_handle v);
|
|
void unset_constraint(Vertex_handle v);
|
|
void add_constraint(Vertex_handle v);
|
|
void remove_constraint(Vertex_handle v);
|
|
// -------------------------------------------------------------------------
|
|
protected:
|
|
// -------------------------------------------------------------------------
|
|
// Compute the flipped bitangent phi(v). Moved inside the class, because
|
|
// some compilers don't understand the return type otherwise.
|
|
template < class Tr >
|
|
Vertex_handle compute_phi(Vertex_handle v , Tr tr) {
|
|
// -------------------------------------------------------------------------
|
|
typename Tr::Sup sup;
|
|
typename Tr::Inf inf;
|
|
typename Tr::Set_sup set_sup; typename Tr::Set_inf set_inf;
|
|
typename Tr::Splice splice;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::CcL ccL; typename Tr::CcR ccR;
|
|
typename Tr::Is_left_xx is_left_xx;
|
|
// -------------------------------------------------------------------------
|
|
Vertex_handle phiv; // The new Vertex that we must compute
|
|
// -------------------------------------------------------------------------
|
|
// Vertex has already been swept.
|
|
if (sup(v) != 0) {
|
|
phiv = sup(sup(v));
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// The pi of the Vertex has already been swept. We use the formula:
|
|
// phi(v)->pi() = phi(v->pi()).
|
|
else if (!linear_space()&&
|
|
sup(v->pi()) != 0) {
|
|
if (is_on_convex_hull(v)) {
|
|
if (is_left_xx(v) && ccL(v->pi()) != 0)
|
|
ccR(v)->set_pi(ccL(v->pi()));
|
|
if (!is_left_xx(v) && ccR(v->pi()) != 0)
|
|
ccL(v)->set_pi(ccR(v->pi()));
|
|
}
|
|
phiv = sup(sup(v->pi()))->pi();
|
|
} else if (linear_space()&&is_on_convex_hull(v)) {
|
|
phiv=v;
|
|
do
|
|
if (is_left_xx(phiv)) phiv=ccR(phiv); else phiv=ccL(phiv);
|
|
while (phiv->is_constraint());
|
|
phiv=phiv->pi();
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// We flip v in the current pseudo-triangulation.
|
|
// To compute phi(v) we walk on the incident pseudo-triangles.
|
|
//else phiv = Chi2_strategy(this)(v,tr);
|
|
else phiv = Flip_traits(this)(v,tr);
|
|
// -------------------------------------------------------------------------
|
|
// We splice the arcs left and right if b is not on the convex hull
|
|
//if (!is_on_convex_hull(v)) { splice(right,phiv); splice(left,phiv); }
|
|
// -------------------------------------------------------------------------
|
|
// Creating a new face with source v and sink phi(v)
|
|
if (sup(v) == 0) set_sup(v,new Face);
|
|
set_inf(sup(v),v);
|
|
set_sup(sup(v),phiv);
|
|
// -------------------------------------------------------------------------
|
|
// Creating a new face with source pi(v) and sink pi(phi(v))
|
|
if (!linear_space()) {
|
|
Vertex_handle vv=inf(cw_source_edge(phiv));
|
|
if (cw_source_edge(phiv)==ccw_target_edge(vv)) {
|
|
splice(ccw_source_edge(vv->pi()),phiv->pi());
|
|
} else {
|
|
CGAL_assertion(cw_source_edge(phiv)==ccw_source_edge(vv));
|
|
splice(ccw_target_edge(vv->pi()),phiv->pi());
|
|
}
|
|
vv=inf(cw_target_edge(phiv));
|
|
if (cw_target_edge(phiv)==ccw_target_edge(vv)) {
|
|
splice(ccw_source_edge(vv->pi()),phiv->pi());
|
|
} else {
|
|
CGAL_assertion(cw_target_edge(phiv)==ccw_source_edge(vv));
|
|
splice(ccw_target_edge(vv->pi()),phiv->pi());
|
|
}
|
|
if (sup(v->pi()) == 0) set_sup(v->pi(),new Face);
|
|
set_inf(sup(v->pi()),v->pi());
|
|
set_sup(sup(v->pi()),phiv?phiv->pi():0);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
CGAL_postcondition(sup(v) != 0 && (sup(sup(v)) != 0));
|
|
return phiv;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// Update the antichain while adding a constraint
|
|
template < class Tr > void sweep_constraint(const Vertex_handle& v, const Tr&,bool opposite=false) const;
|
|
template < class Tr > void sweep_regular (const Vertex_handle& v, const Tr&,bool opposite=false) const;
|
|
// -------------------------------------------------------------------------
|
|
// Initialisation methods
|
|
template<class DiskIterator , class ConstraintIterator>
|
|
void compute_graph(DiskIterator first, DiskIterator last,
|
|
ConstraintIterator firstc,ConstraintIterator lastc);
|
|
struct compute_gr_aux;
|
|
template<class DiskIterator , class ConstraintIterator>
|
|
void compute_gr(DiskIterator first, DiskIterator last,
|
|
ConstraintIterator firstc,ConstraintIterator lastc);
|
|
template < class Tr > void compute_minimals(Tr tr);
|
|
template < class Tr > void compute_vertices(Tr tr);
|
|
template < class Tr > void fix_extreme_edges(Tr tr) const;
|
|
// template < class Tr > void glue_ccw_cw(Tr tr) const;
|
|
void glue();
|
|
template < class Tr > void initialize_convex_hull(Tr tr) const;
|
|
// -------------------------------------------------------------------------
|
|
// Method used during intialization, to compute candidates during the
|
|
// Bentley-Ottmann rotational sweep.
|
|
// template<class Tr> bool is_candidate(const Face_handle& fa) const;
|
|
template < class Tr >
|
|
bool
|
|
is_candidate(const Face_handle& f, const Tr&) const
|
|
{
|
|
typename Tr::Dl dl; typename Tr::Ur ur; typename Tr::Sup sup;
|
|
if (f == 0 || f->top_edge() == 0 || f->bottom_edge() == 0) return false;
|
|
if (sup(f) != 0 && sup(f)->is_constraint()) return is_minimal(sup(f),Tr());
|
|
if (f->top_edge()->object() == 0 || f->bottom_edge()->object() == 0)
|
|
return false;
|
|
return (ur(f->bottom_edge()) == f && dl(f->top_edge()) == f);
|
|
}
|
|
|
|
#if 0
|
|
|
|
template<class OutputStream> OutputStream& node(OutputStream &o,Edge_handle e) {
|
|
o<<"edge_node_"<<std::hex<<((size_t) e)<<std::dec;
|
|
return o;
|
|
}
|
|
template<class OutputStream> OutputStream& node(OutputStream &o,Face_handle f,bool b=false) {
|
|
if (f==0) f=infinite_face_;
|
|
if (f!=infinite_face_)
|
|
o<<"face_node_"<<std::hex<<((size_t) f)<<std::dec;
|
|
else
|
|
o<<"face_node_inf_"<<(b?"below":"above")<<std::hex<<((size_t) f)<<std::dec;
|
|
|
|
return o;
|
|
}
|
|
|
|
template<class OutputStream> void graphviz_print(OutputStream& o) {
|
|
|
|
o<<"digraph {ranksep=0.2\n";
|
|
o<<"subgraph{ordering=in;\n";
|
|
for (Edge_iterator i=edges_begin();i!=edges_end();++i) {
|
|
if (i->object()&&i->sign()) node(o,&*i)<<"[label=\""<<std::hex<<((size_t) &*i)<<std::dec<<"\",shape=invtriangle,width=0.3,height=0.2]"<<";\n";
|
|
}
|
|
o<<"\n}\nsubgraph{ordering=out;\n";
|
|
for (Edge_iterator i=edges_begin();i!=edges_end();++i) {
|
|
if (i->object()&&!i->sign()) node(o,&*i)<<"[label=\""<<std::hex<<((size_t) &*i)<<std::dec<<"\",shape=triangle,width=0.3,height=0.2]"<<";\n";
|
|
}
|
|
o<<"\n}\n";
|
|
|
|
|
|
for (Face_iterator i=faces_begin();i!=faces_end();++i) {
|
|
node(o,&*i)<<"[label=\""<<std::hex<<((size_t) &*i)<<std::dec<<"\",shape=rectangle]"<<";\n";
|
|
}
|
|
node(o,infinite_face_,true)<<"[label=\"inf-"<<std::hex<<((size_t)infinite_face_)<<std::dec<<"\",shape=point]"<<";\n";
|
|
node(o,infinite_face_,false)<<"[label=\"inf+"<<std::hex<<((size_t)infinite_face_)<<std::dec<<"\",shape=point]"<<";\n";
|
|
|
|
|
|
for (Edge_iterator i=edges_begin();i!=edges_end();++i) {
|
|
if (!i->object()) {
|
|
if (i->sign()) node(node(o,i->ul()?i->ul():i->ur())<<"->",&*i)<<"[arrowhead=none];"; else node(node(o,&*i)<<"->",i->dl()?i->dl():i->dr())<<"[arrowhead=none];";
|
|
} else {
|
|
node(node(o,&*i)<<"->",i->dl(),true)<<"[arrowhead=none];";
|
|
if (i->sign()) node(node(o,i->ul(),false)<<"->",&*i)<<"[arrowhead=none];";
|
|
else node(node(o,&*i)<<"->",i->dr(),true)<<"[arrowhead=none];";
|
|
node(node(o,i->ur(),false)<<"->",&*i)<<"[arrowhead=none];";
|
|
}
|
|
o<<"\n";
|
|
}
|
|
o<<"}\n";
|
|
}
|
|
|
|
public:void graphviz_view() {
|
|
std::ostringstream fn;
|
|
fn<<"antichain"<<getpid();
|
|
std::ostringstream fnd;
|
|
fnd<<fn.str()<<".dot";
|
|
std::ostringstream fnp;
|
|
fnp<<fn.str()<<".ps";
|
|
std::ostringstream cmd;
|
|
cmd<<"(dot -Tps -o "<<fnp.str()<<" "<<fnd.str()<<";gv "<<fnp.str()<<";rm "<<fnd.str()<<" "<<fnp.str()<<")&";
|
|
std::ofstream out(fnd.str().c_str());
|
|
graphviz_print(out);
|
|
out.close();
|
|
system(cmd.str().c_str());
|
|
}
|
|
#endif
|
|
// -------------------------------------------------------------------------
|
|
#if 0
|
|
public:
|
|
|
|
|
|
void print(Vertex_handle v) {
|
|
//std::cout << v << " " << flush;
|
|
if (v == 0) return;
|
|
std::cout << *v << " , (";
|
|
if (v->is_left_xx()) std::cout << "+"; else std::cout << "-";
|
|
std::cout << Key[long(v->source_object())] << ",";
|
|
if (v->is_xx_left()) std::cout << "+"; else std::cout << "-";
|
|
std::cout << Key[long(v->target_object())] << ")" ;
|
|
/*
|
|
std::cout << " minLR(" << flush
|
|
<< is_xx_minimal(v,Left_ccw_traits()) << "," << flush
|
|
<< is_xx_minimal(v,Right_ccw_traits()) << ")";
|
|
std::cout << " cw_minLR(" << flush
|
|
<< is_xx_minimal(v,Left_cw_traits()) << "," << flush
|
|
<< is_xx_minimal(v,Right_cw_traits()) << ")";
|
|
if (is_swept(v)) std::cout << " swept";
|
|
else std::cout << " not swept";
|
|
*/
|
|
}
|
|
void print(Edge_handle e, bool coord = true) {
|
|
std::cout << e << " " << flush;
|
|
if (e == 0) return;
|
|
if (e->object() == 0) {
|
|
if (e == e->sup()->target_cusp_edge())
|
|
std::cout << "-" << Key[long(e->sup()->target_object())] << "c";
|
|
else std::cout << "+" << Key[long(e->sup()->source_object())] << "c";
|
|
}
|
|
else {
|
|
if (e->sign()) std::cout << "+"; else std::cout << "-";
|
|
std::cout << Key[long(e->object())] ;
|
|
}
|
|
std::cout << " {";
|
|
if (e->sign())
|
|
std::cout << e->dl() << ","
|
|
<< e->ur() << ","
|
|
<< e->ul();
|
|
else std::cout << e->dl() << ","
|
|
<< e->dr() << ","
|
|
<< e->ul();
|
|
std::cout << "}";
|
|
if (coord) {
|
|
std::cout << " [";
|
|
std::cout << *e->begin() << "," << *--e->end() << "]";
|
|
}
|
|
}
|
|
void print(Face_handle f) {
|
|
std::cout << f << " " << flush;
|
|
if (f == 0) return;
|
|
std::cout << "[" ;
|
|
print(f->bottom_edge()); std::cout << ",";
|
|
print(f->top_edge()); std::cout << "]";
|
|
std::cout << " inf = " << f->inf() << " , sup = " << f->sup();
|
|
}
|
|
template < class Tr >
|
|
void print_left_minimal(Vertex_handle v ,Tr tr);
|
|
template < class Tr >
|
|
void print_right_minimal(Vertex_handle v ,Tr tr);
|
|
#endif
|
|
// -------------------------------------------------------------------------
|
|
public:
|
|
|
|
#if 0
|
|
// Debugging stuff, requires Qt_widget, and unistd.h.
|
|
void view_disks() {
|
|
double ru=900;
|
|
if (fork()==0) {
|
|
int zero=0;
|
|
QApplication app(zero,(char**)0);
|
|
Qt_widget* w;
|
|
w = new CGAL::Qt_widget();
|
|
app.setMainWidget( w );
|
|
w->resize(900, 900);
|
|
w->set_window(0, to_double(ru),0, to_double(ru));
|
|
w->show();
|
|
w->lock();
|
|
{
|
|
int j=0;
|
|
*w<<GREEN;
|
|
for (typename std::vector<Disk_handle>::iterator first=disks.begin();first!=disks.end();first++,j++) {
|
|
*w<<**first;
|
|
Bbox_2 bb=(*first)->bbox();
|
|
typename CGAL::Point_2<CGAL::Simple_cartesian<double> >
|
|
A((bb.xmin()+bb.xmax())/2,(bb.ymin()+bb.ymax())/2);
|
|
std::ostringstream n;
|
|
n<<j;
|
|
w->get_painter().drawText(w->x_pixel(A.x())-15,w->y_pixel(A.y()),n.str());
|
|
} }
|
|
w->unlock();;
|
|
app.exec();
|
|
std::exit(0);
|
|
}
|
|
}
|
|
void view_bit(Vertex_handle v) {
|
|
double ru=900;
|
|
if (fork()==0) {
|
|
int zero=0;
|
|
QApplication app(zero,(char**)0);
|
|
Qt_widget* w;
|
|
w = new CGAL::Qt_widget();
|
|
app.setMainWidget( w );
|
|
w->resize(900, 900);
|
|
w->set_window(0, to_double(ru),0, to_double(ru));
|
|
w->show();
|
|
w->lock();
|
|
{
|
|
int j=0;
|
|
*w<<GREEN;
|
|
for (typename std::vector<Disk_handle>::iterator first=disks.begin();first!=disks.end();first++,j++) {
|
|
*w<<**first;
|
|
Bbox_2 bb=(*first)->bbox();
|
|
typename CGAL::Point_2<CGAL::Simple_cartesian<double> >
|
|
A((bb.xmin()+bb.xmax())/2,(bb.ymin()+bb.ymax())/2);
|
|
std::ostringstream n;
|
|
n<<j;
|
|
w->get_painter().drawText(w->x_pixel(A.x())-15,w->y_pixel(A.y()),n.str());
|
|
}
|
|
}
|
|
*w<<BLACK;
|
|
*w<<static_cast<typename Gt::Segment_2>(*v);
|
|
*w<<typename Gt::R::Circle_2(v->source(),100);
|
|
w->unlock();
|
|
app.exec();
|
|
std::exit(0);
|
|
}
|
|
}
|
|
template <class ii> void view_pt(ii i,ii ie,Vertex_handle v=0) {
|
|
double ru=900;
|
|
int pid=fork();
|
|
if (pid==0) {
|
|
int zero=0;
|
|
QApplication app(zero,(char**)0);
|
|
Qt_widget* w;
|
|
w = new CGAL::Qt_widget();
|
|
app.setMainWidget( w );
|
|
w->resize(900, 900);
|
|
w->set_window(0, to_double(ru),0, to_double(ru));
|
|
w->show();
|
|
w->lock();
|
|
{
|
|
*w<<GREEN;
|
|
int j=0;
|
|
for (typename std::vector<Disk_handle>::iterator first=disks.begin();first!=disks.end();first++,j++) {
|
|
*w<<(*(*first));
|
|
Bbox_2 bb=(*first)->bbox();
|
|
typename CGAL::Point_2<CGAL::Simple_cartesian<double> >
|
|
A((bb.xmin()+bb.xmax())/2,(bb.ymin()+bb.ymax())/2);
|
|
std::ostringstream n;
|
|
n<<j;
|
|
w->get_painter().drawText(w->x_pixel(A.x())-15,w->y_pixel(A.y()),n.str());
|
|
} }
|
|
*w<<BLACK;
|
|
for (;i!=ie;++i) {
|
|
*w<<static_cast<typename Gt::Segment_2>(*i);
|
|
*w<<typename Gt::R::Circle_2((i)->source(),100);
|
|
}
|
|
if (v) {
|
|
*w<<BLUE;
|
|
*w<<static_cast<typename Gt::Segment_2>(*v);
|
|
*w<<typename Gt::R::Circle_2(v->source(),100);
|
|
if (!v->is_constraint()) {
|
|
*w<<RED;
|
|
*w<<static_cast<typename Gt::Segment_2>(*v->sup()->sup());
|
|
*w<<typename Gt::R::Circle_2(v->sup()->sup()->source(),100);
|
|
}
|
|
}
|
|
w->unlock();
|
|
app.exec();
|
|
std::exit(0);
|
|
}
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Computing the Antichain using a Bentley-Ottman sweep
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class DiskIterator , class ConstraintIterator >
|
|
Antichain<Gtr_,It,Flip>::
|
|
Antichain(bool linear,DiskIterator first, DiskIterator last ,
|
|
ConstraintIterator firstc,ConstraintIterator lastc)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// Default values : linear space topological sweep
|
|
straight_sweep_ = false;
|
|
linear_space_ = linear;
|
|
infinite_face_=0;
|
|
for (DiskIterator i=first;i!=last;++i) disks.push_back(&*i);
|
|
for (ConstraintIterator i=firstc;i!=lastc;++i) {
|
|
constraints.push_back(Vertex(i->type(),disks.begin()[i->source()],
|
|
disks.begin()[i->target()]));
|
|
}
|
|
|
|
if (first == last) { valid_ = false; return; }
|
|
compute_gr(first,last,
|
|
constraints.begin(),constraints.end());
|
|
|
|
if (!is_valid()) return;
|
|
// -------------------------------------------------------------------------
|
|
compute_vertices(Ccw_traits());
|
|
compute_vertices(Cw_traits());
|
|
|
|
fix_extreme_edges(Ccw_traits());
|
|
fix_extreme_edges(Cw_traits());
|
|
// -------------------------------------------------------------------------
|
|
// glue_ccw_cw(Ccw_traits());
|
|
// glue_ccw_cw(Cw_traits());
|
|
|
|
glue();
|
|
// -------------------------------------------------------------------------
|
|
initialize_convex_hull(Ccw_traits());
|
|
initialize_convex_hull(Cw_traits());
|
|
// -------------------------------------------------------------------------
|
|
compute_minimals(Ccw_traits());
|
|
compute_minimals(Cw_traits());
|
|
|
|
for (Face_iterator f=faces_begin();f!=faces_end();++f)
|
|
f->set_in_initial_antichain(true);
|
|
|
|
// Create symetrical faces for the initial antichain.
|
|
if (!linear_space()) for (Edge_iterator e=begin();e!=end();++e) {
|
|
if (!e->object()) continue;
|
|
Face_handle fs[3]={e->dl(),e->sign()?e->ur():e->dr(),e->ul()};
|
|
for (int i=0;i<3;++i) {
|
|
if (fs[i]==infinite_face()) continue;
|
|
CGAL_assertion(fs[i]->inf()&&fs[i]->sup());
|
|
Vertex_handle v1=fs[i]->inf()->pi();
|
|
Vertex_handle v2=fs[i]->sup()->pi();
|
|
Face_handle f=v1->sup();
|
|
if (!f) {
|
|
if (v1->is_constraint()) {
|
|
if (fs[i]==v1->source_cusp_face())
|
|
f=v2->target_cusp_face();
|
|
else
|
|
f=v2->source_cusp_face();
|
|
} else {
|
|
f=new Face();
|
|
v1->set_sup(f);
|
|
f->set_inf(v1);
|
|
v2->set_inf(f);
|
|
f->set_sup(v2);
|
|
}
|
|
}
|
|
Edge_handle eo;
|
|
if (e.operator->()==e->inf()->ccw_source_edge())
|
|
eo=e->inf()->pi()->ccw_target_edge();
|
|
else
|
|
eo=e->inf()->pi()->ccw_source_edge();
|
|
Face_handle f1=eo->dl();
|
|
Face_handle f2=eo->sign()?eo->ur():eo->dr();
|
|
Face_handle f3=eo->ul();
|
|
switch (i) {
|
|
case 0: if (e->sign()) f3=f; else f2=f; break;
|
|
case 1: if (e->sign()) f1=f; else f3=f; break;
|
|
case 2: if (e->sign()) f2=f; else f1=f; break;
|
|
}
|
|
eo->set_adjacent_faces(f1,f2,f3);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
struct Antichain<Gtr_,It,Flip>::compute_gr_aux {
|
|
|
|
|
|
struct constraint_entry;
|
|
typedef std::vector<constraint_entry*> VV;
|
|
|
|
template<class chain> struct wrapper {
|
|
//to x-compare a chain with an object along the sweep-line
|
|
struct Less_chain {
|
|
// position of the sweep line
|
|
Edge_handle edg;
|
|
typename Gtr_::Is_upward_directed is_upward_directed;
|
|
Less_bitangent<Gtr_> lb;
|
|
chain* left_neighbour;
|
|
chain* right_neighbour;
|
|
chain* currently_inserted;
|
|
Less_chain() : edg(0),left_neighbour(0), right_neighbour(0),
|
|
currently_inserted(0) {}
|
|
void set_currently_inserted(chain *a) {
|
|
currently_inserted=a;
|
|
}
|
|
void set_left_neighbour(chain *a) {
|
|
left_neighbour=a;
|
|
}
|
|
void set_right_neighbour(chain *a) {
|
|
right_neighbour=a;
|
|
}
|
|
void set_pos(Edge_handle e) {
|
|
edg=e;
|
|
}
|
|
bool leftp(Disk_handle d2) const {
|
|
Bitangent_2 b(Bitangent_2::RL,edg->object(),d2);
|
|
return is_upward_directed(b);
|
|
}
|
|
Comparison_result auxl (Disk_handle d,Disk_handle,
|
|
Vertex_handle v2, Bitangent_2* blr) const {
|
|
if (!v2||lb(*v2,*blr)) return SMALLER; else {
|
|
if (v2->is_right_right()) {
|
|
Bitangent_2 b2(Bitangent_2::LR,d,v2->target_object());
|
|
if (is_upward_directed(b2)&&lb(b2,*v2))
|
|
return SMALLER; else return LARGER;
|
|
} else {
|
|
Bitangent_2 b2(Bitangent_2::RL,d,v2->target_object());
|
|
if (is_upward_directed(b2)&&lb(*v2,b2))
|
|
return LARGER; else return SMALLER;
|
|
}
|
|
}
|
|
}
|
|
|
|
Comparison_result auxr (Disk_handle d,Disk_handle,
|
|
Vertex_handle v2, Bitangent_2* brl) const {
|
|
if (!v2||lb(*brl,*v2)) return LARGER; else {
|
|
if (v2->is_left_left()) {
|
|
Bitangent_2 b2(Bitangent_2::RL,d,v2->target_object());
|
|
if (is_upward_directed(b2)&&lb(*v2,b2))
|
|
return LARGER; else return SMALLER;
|
|
} else {
|
|
Bitangent_2 b2(Bitangent_2::LR,d,v2->target_object());
|
|
if (is_upward_directed(b2)&&lb(b2,*v2))
|
|
return SMALLER; else return LARGER;
|
|
}
|
|
}
|
|
}
|
|
|
|
Comparison_result operator()(const chain *a, const chain * b) const {
|
|
CGAL_precondition(a==currently_inserted);
|
|
if (a==b) return EQUAL;
|
|
|
|
if (a->t==chain::REGULAR_CHAIN) {
|
|
// should not occur, except if insert_before and insert_after
|
|
// perform assertion checking.
|
|
if (b==left_neighbour) return LARGER;
|
|
if (b==right_neighbour) return SMALLER;
|
|
CGAL_error();
|
|
}
|
|
// a is the chain of the disk being inserted
|
|
if (b->t==chain::OBJECT) {
|
|
if (leftp(b->d)) return LARGER; else return SMALLER;
|
|
} else {
|
|
switch (b->st) {
|
|
case chain::Vtx: {
|
|
Vertex_handle v=b->iplb[0].v->vtx;
|
|
if (v->target_object()==a->d) {
|
|
if (v->is_xx_left()) return SMALLER; else return LARGER;
|
|
}
|
|
if (v->is_xx_left()) {
|
|
Bitangent_2 bt(Bitangent_2::RL,a->d,v->target_object());
|
|
if (is_upward_directed(bt)&&lb(*v,bt)) return LARGER; else
|
|
return SMALLER;
|
|
} else {
|
|
Bitangent_2 bt(Bitangent_2::LR,a->d,v->target_object());
|
|
if (is_upward_directed(bt)&&lb(bt,*v)) return SMALLER; else
|
|
return LARGER;
|
|
}
|
|
}
|
|
case chain::VtxArcVtx:
|
|
{
|
|
constraint_entry *v1=b->iplb[0].v;
|
|
constraint_entry *v2=b->iplb[1].v;
|
|
if (v2&&v2->vtx->target_object()==a->d) {
|
|
if (v2->vtx->is_xx_left()) return SMALLER; else return LARGER;
|
|
}
|
|
|
|
Disk_handle d=
|
|
v1?v1->vtx->target_object():v2->vtx->source_object();
|
|
|
|
if ((v1?v1->vtx->is_xx_left():v2->vtx->is_left_xx())) {
|
|
Bitangent_2 brl(Bitangent_2::RL,a->d,d);
|
|
if (!is_upward_directed(brl)) return SMALLER;
|
|
if (!v1||lb(*(v1->vtx),brl))
|
|
return auxr(a->d,d,v2?v2->vtx:0,&brl);
|
|
else
|
|
return SMALLER;
|
|
} else {
|
|
Bitangent_2 blr(Bitangent_2::LR,a->d,d);
|
|
if (!is_upward_directed(blr)) return LARGER;
|
|
if (!v1||lb(blr,*(v1->vtx)))
|
|
return auxl(a->d,d,v2?v2->vtx:0,&blr);
|
|
else
|
|
return LARGER;
|
|
}
|
|
}
|
|
case chain::VtxArcVtxArcVtx:
|
|
{
|
|
constraint_entry *v1=b->iplb[0].v;
|
|
Vertex_handle v2=b->iplb[1].v->vtx;
|
|
constraint_entry *v3=b->iplb[2].v;
|
|
if (v3&&v3->vtx->target_object()==a->d) {
|
|
if (v3->vtx->is_xx_left()) return SMALLER; else return LARGER;
|
|
}
|
|
Disk_handle d1=v2->source_object();
|
|
Disk_handle d2=v2->target_object();
|
|
|
|
if (v2->is_left_right()) {
|
|
Bitangent_2 brl1(Bitangent_2::RL,a->d,d1);
|
|
if (is_upward_directed(brl1)) {
|
|
Bitangent_2 blr2(Bitangent_2::LR,a->d,d2);
|
|
if (is_upward_directed(blr2)) {
|
|
if (lb(*v2,blr2)) return LARGER; else {
|
|
if (lb(brl1,*v2)) {
|
|
if (v1&&lb(brl1,*(v1->vtx))) return SMALLER; else return LARGER;
|
|
} else return auxl(a->d,d2,v3?v3->vtx:0,&blr2);
|
|
}
|
|
} else return LARGER;
|
|
} else return SMALLER;
|
|
} else {
|
|
Bitangent_2 blr1(Bitangent_2::LR,a->d,d1);
|
|
if (is_upward_directed(blr1)) {
|
|
Bitangent_2 brl2(Bitangent_2::RL,a->d,d2);
|
|
if (is_upward_directed(brl2)) {
|
|
if (lb(brl2,*v2)) return SMALLER; else {
|
|
if (lb(*v2,blr1)) {
|
|
if (v1&&lb(*(v1->vtx),blr1)) return LARGER; else return SMALLER;
|
|
} else return auxr(a->d,d2,v3?v3->vtx:0,&brl2);
|
|
}
|
|
} else return SMALLER;
|
|
} else return LARGER;
|
|
}
|
|
}
|
|
default:
|
|
return EQUAL; // silence silly compiler
|
|
}
|
|
}
|
|
}
|
|
};
|
|
typedef Multiset<chain *, Less_chain> Ystructure;
|
|
};
|
|
struct chain {
|
|
|
|
typedef typename wrapper<chain>::Ystructure Ystructure;
|
|
|
|
enum window_type {
|
|
Vtx,VtxArcVtx,VtxArcVtxArcVtx
|
|
};
|
|
window_type st;
|
|
|
|
struct IPLB : In_place_list_base<IPLB> {
|
|
chain * super; // points to the chain
|
|
constraint_entry * v; // points to a vertex
|
|
IPLB(chain * c) : super(c),v(0) {};
|
|
IPLB() {super=0;v=0;}
|
|
};
|
|
|
|
IPLB iplb[3]; // one IPLB for each vertex in the window
|
|
|
|
enum chain_type {
|
|
OBJECT, REGULAR_CHAIN
|
|
};
|
|
|
|
Face_handle left;
|
|
Face_handle right;
|
|
|
|
Disk_handle d;
|
|
chain_type t;
|
|
int status; // -1 not met yet, 0 intersected, 1 past history
|
|
typename Ystructure::iterator position; // position in the ystructure
|
|
chain(Disk_handle d_) {
|
|
iplb[0]=iplb[1]=iplb[2]=IPLB(this);
|
|
status=-1;
|
|
st=VtxArcVtx;
|
|
t=OBJECT;
|
|
d=d_;
|
|
}
|
|
chain(constraint_entry*){
|
|
iplb[0]=iplb[1]=iplb[2]=IPLB(this);
|
|
status=-1;
|
|
t=REGULAR_CHAIN;
|
|
st=VtxArcVtx;
|
|
left=0;right=0;d=0;
|
|
}
|
|
chain& operator=(const chain& c) {
|
|
st=c.st;
|
|
for (int i=0;i<3;i++) {
|
|
iplb[i]=c.iplb[i];
|
|
iplb[i].super=this;
|
|
}
|
|
left=c.left; right=c.right;
|
|
d=c.d;
|
|
t=c.t;
|
|
status=c.status;
|
|
position=c.position;
|
|
return *this;
|
|
}
|
|
chain() {
|
|
iplb[0]=iplb[1]=iplb[2]=IPLB(this);
|
|
};
|
|
};
|
|
|
|
typedef typename wrapper<chain>::Less_chain Less_chain;
|
|
typedef typename wrapper<chain>::Ystructure Ystructure;
|
|
|
|
struct disk_entry {
|
|
Disk_handle d;
|
|
|
|
struct side {
|
|
VV constraints;
|
|
};
|
|
|
|
side lhs; // left hand side constraints
|
|
side rhs; // right hand side constraints
|
|
|
|
chain ch;
|
|
|
|
Edge_handle pos,neg;
|
|
|
|
int status;
|
|
|
|
disk_entry() {}
|
|
|
|
disk_entry(Disk_handle dd) {
|
|
d=dd;
|
|
pos=new Edge(true,d);
|
|
neg=new Edge(false,d);
|
|
// pos->set_opposite(neg);
|
|
ch=chain(d);
|
|
status=-1;
|
|
}
|
|
};
|
|
|
|
struct constraint_entry {
|
|
Vertex_handle vtx;
|
|
// the first constraint that leaves the object this constraint is
|
|
// entering above the entry point
|
|
constraint_entry* target_next_out;
|
|
// positions in the constraint lists of the objects adjacent to this
|
|
// constraint
|
|
typename VV::iterator source_cycle;
|
|
typename VV::iterator target_cycle;
|
|
chain source_chain; // the chain this bitangent is the first
|
|
// bitangent of
|
|
typedef In_place_list<typename chain::IPLB,false> IPL;
|
|
IPL ipl[3]; // ipl[i] contains the list of the chains whose window has
|
|
// this constraint as ith vertex.
|
|
// the iterators have to be initialised with a non-singular value, so
|
|
// I pass a bogus iterator...
|
|
constraint_entry(typename VV::iterator i) :
|
|
source_cycle(i),target_cycle(i) {}
|
|
};
|
|
|
|
struct Less_constraintl {
|
|
Less_bitangent<Gtr_> lb;
|
|
bool operator() (const constraint_entry* a, const constraint_entry* b) {
|
|
return lb(*(b->vtx),*(a->vtx));
|
|
}
|
|
};
|
|
struct Less_constraintr {
|
|
Less_bitangent<Gtr_> lb;
|
|
bool operator() (const constraint_entry* a, const constraint_entry* b) {
|
|
return lb(*(a->vtx),*(b->vtx));
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class DiskIterator , class ConstraintIterator >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
compute_gr(DiskIterator first, DiskIterator last,
|
|
ConstraintIterator firstc,ConstraintIterator lastc) {
|
|
valid_=true;
|
|
|
|
typedef typename compute_gr_aux::constraint_entry constraint_entry;
|
|
typedef typename compute_gr_aux::VV VV;
|
|
typedef typename compute_gr_aux::chain chain;
|
|
typedef typename compute_gr_aux::Less_chain Less_chain;
|
|
typedef typename compute_gr_aux::Ystructure Ystructure;
|
|
typedef typename compute_gr_aux::disk_entry disk_entry;
|
|
typedef typename compute_gr_aux::Less_constraintl Less_constraintl;
|
|
typedef typename compute_gr_aux::Less_constraintr Less_constraintr;
|
|
|
|
|
|
|
|
typedef std::vector<Edge_handle> Xstructure;
|
|
Xstructure XE; // the events
|
|
|
|
|
|
typedef std::vector<chain> CV;
|
|
|
|
|
|
|
|
Less_constraintl lctl;
|
|
Less_constraintr lctr;
|
|
|
|
|
|
typename Ccw_traits::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
|
|
|
|
typedef std::map<Disk_handle,disk_entry> DDEM;
|
|
DDEM dem;
|
|
for (;first!= last;++first) {
|
|
typename DDEM::iterator j=
|
|
dem.insert(
|
|
typename DDEM::value_type(&*first,
|
|
disk_entry(&*first))).first;
|
|
push_back(*(j->second.neg));
|
|
push_back(*(j->second.pos));
|
|
set_adjacent_faces(j->second.pos,0,new Face,new Face);
|
|
j->second.pos->ul()->set_front_view(j->second.pos);
|
|
j->second.pos->ur()->set_back_view(j->second.pos);
|
|
set_adjacent_faces(j->second.neg,0,0,new Face);
|
|
}
|
|
|
|
|
|
|
|
|
|
typename Gtr_::Is_upward_directed is_upward_directed;
|
|
typedef std::map<Vertex_handle,constraint_entry> VCEM;
|
|
VCEM vcem;
|
|
|
|
|
|
VV bogusvv;
|
|
typename VV::iterator bogusvvi=bogusvv.end();
|
|
|
|
for (;firstc!=lastc;++firstc) {
|
|
Vertex_handle c=&*firstc;
|
|
if (!c->is_constraint()) set_constraint(&(*c));
|
|
if (!c->pi()->is_constraint()) set_constraint(c->pi());
|
|
if (!is_upward_directed(*c)) c=c->pi();
|
|
typename DDEM::iterator desi=dem.find(c->source_object());
|
|
CGAL_precondition(desi!=dem.end());
|
|
disk_entry * des=&(desi->second);
|
|
typename DDEM::iterator deti=dem.find(c->target_object());
|
|
CGAL_precondition(deti!=dem.end());
|
|
disk_entry * det=&(deti->second);
|
|
typename VCEM::iterator i=
|
|
vcem.insert(
|
|
typename VCEM::value_type(c,constraint_entry(bogusvvi))).first;
|
|
i->second.vtx=c;
|
|
|
|
((c->is_left_xx())?&des->rhs:&des->lhs)->constraints.push_back(&i->second);
|
|
((c->is_xx_left())?&det->rhs:&det->lhs)->constraints.push_back(&i->second);
|
|
|
|
push_back(*c->target_cusp_edge());
|
|
push_back(*c->source_cusp_edge());
|
|
}
|
|
|
|
|
|
|
|
|
|
// sorting bottom-up the constraint lists for each object, and splicing
|
|
// the edges
|
|
for (typename DDEM::iterator dei=dem.begin();dei!=dem.end();++dei) {
|
|
std::sort(dei->second.lhs.constraints.begin(),
|
|
dei->second.lhs.constraints.end(),lctl);
|
|
std::sort(dei->second.rhs.constraints.begin(),
|
|
dei->second.rhs.constraints.end(),lctr);
|
|
|
|
typename Ccw_traits::Splice splice_ccw;
|
|
typename Cw_traits::Splice splice_cw;
|
|
|
|
Edge_handle e;
|
|
e=dei->second.pos;
|
|
for (typename VV::iterator i=dei->second.rhs.constraints.begin();
|
|
i!=dei->second.rhs.constraints.end();
|
|
++i,e=e->sup()->ccw_edge(e->object())) {
|
|
splice_ccw(e,(*i)->vtx);
|
|
}
|
|
e=dei->second.pos;
|
|
for (typename VV::iterator i=dei->second.lhs.constraints.begin();
|
|
i!=dei->second.lhs.constraints.end();
|
|
++i,e=e->inf()->cw_edge(e->object())) {
|
|
splice_cw(e,(*i)->vtx->pi());
|
|
}
|
|
e=dei->second.neg;
|
|
for (typename VV::reverse_iterator i=dei->second.lhs.constraints.rbegin();
|
|
i!=dei->second.lhs.constraints.rend();
|
|
++i,e=e->sup()->ccw_edge(e->object())) {
|
|
splice_ccw(e,(*i)->vtx);
|
|
}
|
|
e=dei->second.neg;
|
|
for (typename VV::reverse_iterator i=dei->second.rhs.constraints.rbegin();
|
|
i!=dei->second.rhs.constraints.rend();
|
|
++i,e=e->inf()->cw_edge(e->object())) {
|
|
splice_cw(e,(*i)->vtx->pi());
|
|
}
|
|
|
|
constraint_entry * prev_out_constraint=0;
|
|
chain * prev_out_chain=&dei->second.ch;
|
|
|
|
|
|
if (!dei->second.rhs.constraints.empty()) {
|
|
typename VV::iterator i=dei->second.rhs.constraints.end();
|
|
do {
|
|
--i;
|
|
if ((*i)->vtx->source_object()==dei->second.d) {
|
|
(*i)->source_chain=chain(*i);
|
|
Edge_handle e=(*i)->vtx->source_cusp_edge();
|
|
Face_handle f=e->ul();
|
|
f->set_back_view((*i)->vtx->ccw_source_edge());
|
|
prev_out_chain->right=f;
|
|
prev_out_chain=&((*i)->source_chain);
|
|
prev_out_chain->left=f;
|
|
prev_out_constraint=*i;
|
|
(*i)->source_cycle=i;
|
|
}
|
|
else {
|
|
(*i)->target_next_out=prev_out_constraint;
|
|
(*i)->target_cycle=i;
|
|
}
|
|
} while (i!=dei->second.rhs.constraints.begin());
|
|
}
|
|
prev_out_chain->right=dei->second.pos->ur();
|
|
|
|
prev_out_constraint=0;
|
|
prev_out_chain=&(dei->second.ch);
|
|
if (!dei->second.lhs.constraints.empty()) {
|
|
typename VV::iterator i=dei->second.lhs.constraints.end();
|
|
do {
|
|
--i;
|
|
if ((*i)->vtx->source_object()==dei->second.d) {
|
|
(*i)->source_chain=chain(*i);
|
|
Edge_handle e=(*i)->vtx->source_cusp_edge();
|
|
Face_handle f=e->ur();
|
|
f->set_front_view((*i)->vtx->cw_source_edge());
|
|
prev_out_chain->left=f;
|
|
prev_out_chain=&((*i)->source_chain);
|
|
prev_out_chain->right=f;
|
|
prev_out_constraint=*i;
|
|
(*i)->source_cycle=i;
|
|
}
|
|
else {
|
|
(*i)->target_next_out=prev_out_constraint;
|
|
(*i)->target_cycle=i;
|
|
}
|
|
} while (i!=dei->second.lhs.constraints.begin());
|
|
}
|
|
prev_out_chain->left=dei->second.pos->ul();
|
|
|
|
XE.push_back(dei->second.pos);
|
|
XE.push_back(dei->second.neg);
|
|
}
|
|
std::sort(XE.begin(),XE.end(),Less_edge_handle<Gtr_>());
|
|
|
|
|
|
Ystructure YE; // the chains intersected by the sweep line
|
|
Less_chain& LC=YE.key_comp();
|
|
|
|
struct utils {
|
|
VCEM& vcem;
|
|
DDEM& dem;
|
|
Xstructure& XE;
|
|
Ystructure& YE;
|
|
Less_chain& LC;
|
|
utils(VCEM& v,DDEM& d, Xstructure& xe, Ystructure& ye, Less_chain& lc) :
|
|
vcem(v), dem(d), XE(xe), YE(ye), LC(lc) {};
|
|
typename Ccw_traits::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
|
|
// installs v as the ith vertex in c's window
|
|
void set_chain_constraint(constraint_entry *v,chain *c,int i) {
|
|
if (v) {
|
|
for (int j=0;j<3;j++) if (c->iplb[j].v==v) {
|
|
if (i==j) return;
|
|
c->iplb[j].v=0;
|
|
v->ipl[j].erase(c->iplb+j);
|
|
}
|
|
}
|
|
if (c->iplb[i].v) c->iplb[i].v->ipl[i].erase(c->iplb+i);
|
|
c->iplb[i].v=v;
|
|
if (v) v->ipl[i].push_front(c->iplb[i]);
|
|
}
|
|
|
|
// called when the bottom of the window passes the first cusp
|
|
void remove_chain(chain *ch) {
|
|
if (ch->status!=0) return;
|
|
|
|
constraint_entry *v=ch->iplb[0].v;
|
|
Edge_handle cusp=v->vtx->target_cusp_edge();
|
|
Face_handle fdead,fcusp;
|
|
if (v->vtx->is_xx_right()) {
|
|
fcusp=cusp->dr();
|
|
fdead=ch->right;
|
|
typename Ystructure::iterator a=ch->position;
|
|
++a;
|
|
(*a)->left=ch->left;
|
|
} else {
|
|
fcusp=cusp->dl();
|
|
fdead=ch->left;
|
|
typename Ystructure::iterator a=ch->position;
|
|
--a;
|
|
(*a)->right=ch->right;
|
|
}
|
|
Edge_handle edead=fdead->bottom_edge();
|
|
if (edead) {
|
|
if (edead->sign()) {
|
|
set_adjacent_faces(edead,edead->dl(),
|
|
edead->ur()==fdead?fcusp:edead->ur(),
|
|
edead->ul()==fdead?fcusp:edead->ul());
|
|
} else {
|
|
set_adjacent_faces(edead,edead->dl(),edead->dr(),fcusp);
|
|
}
|
|
delete fdead;
|
|
}
|
|
YE.erase(ch->position);
|
|
ch->position=YE.end();
|
|
set_chain_constraint(0,ch,0);
|
|
set_chain_constraint(0,ch,1);
|
|
set_chain_constraint(0,ch,2);
|
|
}
|
|
// makes ch a VtxArcVtx with v1 and v2; removes ch if its window passes
|
|
// a cusp; returns true iff ch was not removed
|
|
bool f1(chain * ch,constraint_entry *v1,constraint_entry* v2) {
|
|
if (v1==0||ch==&v1->source_chain) {
|
|
set_chain_constraint(v1,ch,0);
|
|
set_chain_constraint(v2,ch,1);
|
|
set_chain_constraint(0,ch,2);
|
|
ch->st=chain::VtxArcVtx;
|
|
return true;
|
|
} else {
|
|
remove_chain(ch
|
|
);
|
|
ch->status=1;
|
|
return false;
|
|
}
|
|
}
|
|
// makes ch a Vtx; removes ch if its window passes a cusp; returns true
|
|
// iff ch was not removed
|
|
bool f2(chain *ch,constraint_entry * v) {
|
|
if (ch==&v->source_chain) {
|
|
set_chain_constraint(v,ch,0);
|
|
set_chain_constraint(0,ch,1);
|
|
set_chain_constraint(0,ch,2);
|
|
ch->st=chain::Vtx;
|
|
return true;
|
|
} else {
|
|
remove_chain(ch
|
|
);
|
|
ch->status=1;
|
|
return false;
|
|
}
|
|
}
|
|
// check whether a VtxArcVtx must be extented into a VtxArcVtxArcVtx,
|
|
// possibly advancing the bottom of the window and removing the chain
|
|
bool f3(chain * ch) {
|
|
constraint_entry * v2=ch->iplb[1].v;
|
|
if (!v2||v2->vtx->is_external()) return true;
|
|
Disk_handle d3=v2->vtx->target_object();
|
|
disk_entry * de3=&(dem[d3]);
|
|
if (de3->status==0) {
|
|
constraint_entry* v3=v2->target_next_out; disk_entry * de4;
|
|
bool b; Edge_handle e;
|
|
if (!v3||v3->vtx->is_external()) goto extend;
|
|
de4=&(dem[v3->vtx->target_object()]);
|
|
if (de4->status!=0) goto extend;
|
|
e=LC.edg;
|
|
LC.set_pos(de4->pos);
|
|
b=LC.leftp(v2->vtx->source_object());
|
|
LC.set_pos(e);
|
|
if (v2->vtx->is_right_left()) b=!b;
|
|
if (b) {
|
|
if (f1(ch,v2,v3)) {
|
|
set_chain_constraint(v3->target_next_out,ch,3);
|
|
ch->st=chain::VtxArcVtxArcVtx;
|
|
return true;
|
|
} else return false;
|
|
}
|
|
extend:
|
|
set_chain_constraint(v2->target_next_out,ch,2);
|
|
ch->st=chain::VtxArcVtxArcVtx;
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
utils U(vcem,dem,XE,YE,LC);
|
|
|
|
|
|
|
|
Face lower_outer_face;
|
|
Face_handle upper_outer_face=&lower_outer_face;
|
|
|
|
for (typename Xstructure::iterator ei=XE.begin();ei!=XE.end();ei++) {
|
|
Edge_handle e=*ei;
|
|
|
|
disk_entry *de;
|
|
{
|
|
typename DDEM::iterator i=dem.find(e->object());
|
|
de=&(i->second);
|
|
}
|
|
|
|
LC.set_pos(e);
|
|
|
|
if (e->sign()) {
|
|
// finding where to insert the new chains
|
|
LC.set_currently_inserted(&de->ch);
|
|
typename Ystructure::iterator rc=YE.upper_bound(&(de->ch));
|
|
LC.set_currently_inserted(0);
|
|
typename Ystructure::iterator lc=YE.end();
|
|
Face_handle f;
|
|
if (rc==YE.end()&&YE.empty()) {
|
|
f=upper_outer_face;
|
|
upper_outer_face=0;
|
|
} else if (rc==YE.begin()) {
|
|
f=(*rc)->left;
|
|
} else {
|
|
lc=rc;--lc;
|
|
f=(*lc)->right;
|
|
}
|
|
|
|
if (rc!=YE.end()) {
|
|
LC.set_right_neighbour(*rc);
|
|
(*rc)->left=e->ur();
|
|
} else LC.set_right_neighbour(0);
|
|
if (lc!=YE.end()) {
|
|
LC.set_left_neighbour(*lc);
|
|
(*lc)->right=e->ul();
|
|
} else LC.set_left_neighbour(0);
|
|
|
|
e->ur()->set_front_view(f->front_view());
|
|
e->ul()->set_back_view(f->back_view());
|
|
|
|
set_adjacent_faces(e,f,e->ur(),e->ul());
|
|
|
|
LC.set_currently_inserted(&de->ch);
|
|
typename Ystructure::iterator k=YE.insert_before(rc,&de->ch);
|
|
LC.set_currently_inserted(0);
|
|
de->ch.position=k;
|
|
de->ch.status=0;
|
|
de->status=0;
|
|
LC.set_right_neighbour(&de->ch);
|
|
for (typename VV::reverse_iterator i=de->lhs.constraints.rbegin();
|
|
i!=de->lhs.constraints.rend();++i) {
|
|
// a new chain
|
|
if ((*i)->vtx->source_object()==de->d) {
|
|
U.f1(&(*i)->source_chain,0,(*i));
|
|
U.f3(&(*i)->source_chain);
|
|
LC.set_currently_inserted(&(*i)->source_chain);
|
|
k=YE.insert_before(k,&(*i)->source_chain);
|
|
LC.set_currently_inserted(0);
|
|
LC.set_right_neighbour(&(*i)->source_chain);
|
|
(*i)->source_chain.position=k;
|
|
(*i)->source_chain.status=0;
|
|
} else { // a chain whose window ends on i
|
|
constraint_entry * ve=(*i);
|
|
Vertex_handle v=ve->vtx;
|
|
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
// the window was a single constraint
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[0].begin();
|
|
j!=ve->ipl[0].end();j++) {
|
|
U.set_chain_constraint(ve->target_next_out,j->super,1);
|
|
j->super->st=chain::VtxArcVtx;
|
|
U.f3(j->super);
|
|
}
|
|
// the window was a VtxArcVtx
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
|
|
if (v->is_right_right()) {
|
|
if (!LC.leftp(v->source_object())) {
|
|
if (U.f1(j->super,ve,ve->target_next_out)) U.f3(j->super);
|
|
}
|
|
} else U.f3(j->super);
|
|
}
|
|
// the window was a VtxArcVtxArcVtx
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[2].begin();
|
|
j!=ve->ipl[2].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
if (v->is_right_right()) {
|
|
if (!LC.leftp(v->source_object())) {
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v))
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
}
|
|
} else {
|
|
if (!LC.leftp(j->super->iplb[1].v->vtx->source_object())) {
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v))
|
|
U.f3(j->super);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// same with right hand side constraints
|
|
k=de->ch.position;
|
|
LC.set_left_neighbour(&de->ch);
|
|
LC.set_right_neighbour(rc!=YE.end()?*rc:0);
|
|
for (typename VV::reverse_iterator i=de->rhs.constraints.rbegin();
|
|
i!=de->rhs.constraints.rend();++i) {
|
|
if ((*i)->vtx->source_object()==de->d) {
|
|
U.f1(&(*i)->source_chain,0,(*i));
|
|
U.f3(&(*i)->source_chain);
|
|
LC.set_currently_inserted(&(*i)->source_chain);
|
|
k=YE.insert_after(k,&(*i)->source_chain);
|
|
LC.set_currently_inserted(0);
|
|
LC.set_left_neighbour(&(*i)->source_chain);
|
|
(*i)->source_chain.position=k;
|
|
(*i)->source_chain.status=0;
|
|
} else {
|
|
constraint_entry * ve=(*i);
|
|
Vertex_handle v=ve->vtx;
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[0].begin();
|
|
j!=ve->ipl[0].end();j++) {
|
|
U.set_chain_constraint(ve->target_next_out,j->super,1);
|
|
j->super->st=chain::VtxArcVtx;
|
|
U.f3(j->super);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j;++tmp;
|
|
if (v->is_left_left()) {
|
|
if (LC.leftp(v->source_object())) {
|
|
if (U.f1(j->super,ve,ve->target_next_out)) U.f3(j->super);
|
|
}
|
|
} else U.f3(j->super);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[2].begin();
|
|
j!=ve->ipl[2].end();j=tmp) {
|
|
tmp=j;++tmp;
|
|
if (v->is_left_left()) {
|
|
if (LC.leftp(v->source_object())) {
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v))
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
}
|
|
} else {
|
|
if (LC.leftp(j->super->iplb[1].v->vtx->source_object())) {
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v))
|
|
U.f3(j->super);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LC.set_left_neighbour(0);
|
|
LC.set_right_neighbour(0);
|
|
} else {
|
|
// leaving an object
|
|
for (typename VV::reverse_iterator i=de->lhs.constraints.rbegin();
|
|
i!=de->lhs.constraints.rend();++i) {
|
|
constraint_entry * ve=(*i);
|
|
Vertex_handle v=ve->vtx;
|
|
if ((*i)->vtx->source_object()==de->d) {
|
|
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
|
|
// nothing to be done with ipl[0]: the window is already beyond
|
|
// the disk
|
|
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
if (dem[v->target_object()].status==0) {
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
} else U.f2(j->super,ve);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[2].begin();
|
|
j!=ve->ipl[2].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v)) {
|
|
if (dem[v->target_object()].status==0) {
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
} else U.f2(j->super,ve);
|
|
}
|
|
}
|
|
} else {
|
|
// entering constraints, all their chains have seen or are seeing
|
|
// their windows pass a cusp, and can therefore be removed
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[0].begin();
|
|
j!=ve->ipl[0].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
U.remove_chain(j->super);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
// pass the cusp
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.remove_chain(j->super);
|
|
}
|
|
// ve->ipl[2] must be empty
|
|
}
|
|
}
|
|
// same thing with rhs constraints
|
|
for (typename VV::reverse_iterator i=de->rhs.constraints.rbegin();
|
|
i!=de->rhs.constraints.rend();++i) {
|
|
constraint_entry * ve=(*i);
|
|
Vertex_handle v=ve->vtx;
|
|
if ((*i)->vtx->source_object()==de->d) {
|
|
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
if (dem[v->target_object()].status==0) {
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
} else U.f2(j->super,ve);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[2].begin();
|
|
j!=ve->ipl[2].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
if (U.f1(j->super,j->super->iplb[1].v,j->super->iplb[2].v)) {
|
|
if (dem[v->target_object()].status==0) {
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.f3(j->super);
|
|
} else U.f2(j->super,ve);
|
|
}
|
|
}
|
|
} else {
|
|
// entering constraints, all their chains have seen or are seeing
|
|
// their windows pass a cusp, and can therefore be removed
|
|
typename constraint_entry::IPL::iterator tmp;
|
|
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[0].begin();
|
|
j!=ve->ipl[0].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
U.remove_chain(j->super);
|
|
}
|
|
for (typename constraint_entry::IPL::iterator j=ve->ipl[1].begin();
|
|
j!=ve->ipl[1].end();j=tmp) {
|
|
tmp=j; ++tmp;
|
|
// pass the cusp
|
|
if (U.f1(j->super,ve,ve->target_next_out))
|
|
U.remove_chain(j->super);
|
|
}
|
|
// ve->ipl[2] must be empty
|
|
}
|
|
}
|
|
de->ch.status=1;
|
|
de->status=1;
|
|
set_adjacent_faces(e,de->ch.left,de->ch.right,e->ul());
|
|
e->ul()->set_back_view(de->ch.left->back_view());
|
|
e->ul()->set_front_view(de->ch.right->front_view());
|
|
if (de->ch.position!=YE.begin()) {
|
|
typename Ystructure::iterator lc=de->ch.position;
|
|
--lc;
|
|
(*lc)->right=e->ul();
|
|
}
|
|
typename Ystructure::iterator rc=de->ch.position;
|
|
++rc;
|
|
if (rc!=YE.end()) (*rc)->left=e->ul();
|
|
YE.erase(de->ch.position);
|
|
if (YE.empty()) {
|
|
upper_outer_face=e->ul();
|
|
}
|
|
}
|
|
}
|
|
infinite_face_=upper_outer_face;
|
|
infinite_face_->set_top_edge(lower_outer_face.top_edge());
|
|
set_adjacent_faces(infinite_face_->top_edge(),0,
|
|
infinite_face_->top_edge()->ur(),
|
|
infinite_face_->top_edge()->ul());
|
|
set_adjacent_faces(infinite_face_->bottom_edge(),
|
|
infinite_face_->bottom_edge()->dl(),
|
|
infinite_face_->bottom_edge()->dr(),0);
|
|
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class DiskIterator , class ConstraintIterator >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
compute_graph(DiskIterator first, DiskIterator last,
|
|
ConstraintIterator firstc,ConstraintIterator lastc)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// The pseudo-triangulation is valid if no pair of objects intersect
|
|
CGAL_expensive_precondition_code( Do_intersect<Self> do_intersect; );
|
|
valid_ = true;
|
|
// -------------------------------------------------------------------------
|
|
// X-structure containing the nodes of the antichain == edges of
|
|
// Visibility graph
|
|
typedef std::priority_queue<Edge_handle,
|
|
std::vector<Edge_handle>,
|
|
Less_edge_handle<Gtr_> > Xstructure;
|
|
Xstructure XE;
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Map to keep track of the edge with opposite sign
|
|
std::map<Edge_handle,Edge_handle> opposite;
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Creating the edges and pushing them in the priority queue
|
|
typename Ccw_traits::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
// Regular edges - two per disk
|
|
for (DiskIterator it = first; it != last ; ++it ) {
|
|
Edge_handle neg = new Edge(false,&(*it));
|
|
Edge_handle pos = new Edge(true,&(*it));
|
|
push_back(*neg); push_back(*pos);
|
|
XE.push(neg); XE.push(pos);
|
|
set_adjacent_faces(neg,new Face,new Face,0);
|
|
set_adjacent_faces(pos,new Face,0,0);
|
|
neg->dl()->set_front_view(neg);
|
|
neg->dr()->set_back_view(pos);
|
|
opposite[(neg)] = pos;
|
|
opposite[(pos)] = neg;
|
|
// neg->set_opposite(pos);
|
|
}
|
|
// Constraint edges - two per constraint
|
|
// We make sure the constraint is upward directed
|
|
typename Gtr_::Is_upward_directed is_upward_directed;
|
|
for (ConstraintIterator c = firstc; c != lastc ; ++c ) {
|
|
CGAL_precondition(c->sup() == 0);
|
|
if (!c->is_constraint()) set_constraint(&(*c));
|
|
if (!c->pi()->is_constraint()) set_constraint(c->pi());
|
|
Vertex_handle d = (is_upward_directed(*c)) ? &(*c) : c->pi();
|
|
push_back(*d->target_cusp_edge());
|
|
push_back(*d->source_cusp_edge());
|
|
XE.push(d->target_cusp_edge());
|
|
XE.push(d->source_cusp_edge());
|
|
}
|
|
if (XE.size() == 2) { valid_ = false; return; }
|
|
// -------------------------------------------------------------------------
|
|
#if 0
|
|
int index = 1;
|
|
for (Edge_iterator e = edges_begin(); e != edges_end(); ++e)
|
|
{
|
|
if (!e->sign()) {
|
|
Key[long(e->object())] = index;
|
|
Key[long(&(*e))] = -index;
|
|
}
|
|
else {
|
|
Key[long(&(*e))] = +index;
|
|
++index;
|
|
}
|
|
}
|
|
#endif
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Y-structure containing at each moment the ordered list of object
|
|
// intersected by the sweeping line.
|
|
// The faces are ordered by their front view
|
|
// An object is represented by a pair of faces (f1,f2) such that
|
|
// f1->front_object() == f2->back_object()
|
|
typedef std::set<Face_handle,Less_face_handle<Self> > Ystructure;
|
|
Ystructure YE;
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Splice function object used when inserting a constraint
|
|
typename Ccw_traits::Splice splice_ccw;
|
|
typename Cw_traits::Splice splice_cw;
|
|
// -------------------------------------------------------------------------
|
|
// The infinite face helps us to identify the convex-hull vertices
|
|
infinite_face_ = new Face;
|
|
infinite_face_->set_bottom_edge(XE.top());
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Start of the Bentley-Ottman sweep
|
|
Face_handle infinite = NULL;
|
|
while ( !XE.empty() && valid_ ) {
|
|
Edge_handle pe = XE.top(); XE.pop();
|
|
// ---------------------------------------------------------------------
|
|
// Treating a node with in_degree 2 and out_degree 1
|
|
if (!pe->sign()) {
|
|
// -----------------------------------------------------------------
|
|
// Inserting a Regular Edge
|
|
if (pe->object() != 0) { // regular Edge
|
|
// -------------------------------------------------------------
|
|
// Insert two new faces in YE
|
|
Face_handle upleft = new Face; upleft->set_front_view(pe);
|
|
typename Ystructure::iterator upleft_it = YE.upper_bound(upleft);
|
|
delete upleft;
|
|
if ( upleft_it == YE.end() ) upleft = infinite;
|
|
else { upleft = *upleft_it; YE.erase(upleft_it); }
|
|
set_adjacent_faces(pe,pe->dl(),pe->dr(),upleft);
|
|
if (upleft != 0) {
|
|
// ---------------------------------------------------------
|
|
CGAL_expensive_precondition_code(
|
|
valid_ = !do_intersect(pe->ul()->back_view(),pe);
|
|
if (valid_ == false) return;
|
|
valid_ = !do_intersect(pe->ul()->front_view(),pe);
|
|
if (valid_ == false) return;
|
|
);
|
|
// ---------------------------------------------------------
|
|
pe->dr()->set_front_view(pe->ul()->front_view());
|
|
pe->dl()->set_back_view (pe->ul()->back_view());
|
|
}
|
|
YE.insert(pe->dl()); YE.insert(pe->dr());
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
// Inserting a cusp Edge from an xx-left constraint
|
|
else if (pe->sup()->is_xx_left()) {
|
|
// -------------------------------------------------------------
|
|
// Find the place where to insert the constraint
|
|
Face_handle right = new Face; right->set_front_view(pe);
|
|
typename Ystructure::iterator right_it = YE.upper_bound(right);
|
|
CGAL_precondition( right_it != YE.end() );
|
|
delete right; right = *right_it;
|
|
// -------------------------------------------------------------
|
|
CGAL_expensive_precondition_code(
|
|
valid_ = !do_intersect(right->front_view(),pe);
|
|
if (valid_ == false) return;
|
|
);
|
|
// -------------------------------------------------------------
|
|
// Splitting the boundary of the target object of pe->sup()
|
|
CGAL_precondition(right->back_view()->object() != 0);
|
|
splice_ccw(right->back_view(),pe->sup());
|
|
// -------------------------------------------------------------
|
|
pe->dl()->set_back_view (pe->sup()->cw_target_edge());
|
|
pe->dl()->set_front_view(pe);
|
|
right->set_back_view(pe);
|
|
YE.insert(pe->dl());
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
// Inserting a cusp Edge from an xx-right constraint
|
|
else {
|
|
// -------------------------------------------------------------
|
|
// Find the place where to insert the constraint
|
|
Face_handle left = new Face; left->set_front_view(pe);
|
|
typename Ystructure::iterator left_it = YE.upper_bound(left);
|
|
CGAL_precondition( left_it != YE.end() );
|
|
delete left; left = *left_it;
|
|
YE.erase(left_it);
|
|
// -------------------------------------------------------------
|
|
CGAL_expensive_precondition_code(
|
|
valid_ = !do_intersect(left->back_view(),pe);
|
|
if (valid_ == false) return;
|
|
);
|
|
// -------------------------------------------------------------
|
|
CGAL_precondition(left->front_view()->object() != 0);
|
|
splice_ccw(left->front_view(),pe->sup());
|
|
// -------------------------------------------------------------
|
|
pe->dr()->set_back_view (pe);
|
|
pe->dr()->set_front_view(pe->sup()->ccw_target_edge());
|
|
left->set_front_view(pe);
|
|
YE.insert(left); YE.insert(pe->dr());
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
}
|
|
// ---------------------------------------------------------------------
|
|
// Treating a node with in_degree 1 and out_degree 2
|
|
else {
|
|
// -----------------------------------------------------------------
|
|
// Inserting a regular Edge
|
|
if (pe->object() != 0) {
|
|
// -------------------------------------------------------------
|
|
// Find the two adjacent faces in YE that connect to pe and
|
|
// erase them from YE.
|
|
Face_handle tmpf = new Face; tmpf->set_front_view(pe);
|
|
typename Ystructure::iterator it1 = YE.find(tmpf);
|
|
typename Ystructure::iterator it2 = it1; ++it2;
|
|
Face_handle upleft = *it1; Face_handle upright = *it2;
|
|
delete tmpf; YE.erase(it1); YE.erase(it2);
|
|
// -------------------------------------------------------------
|
|
// Update existing faces
|
|
if ( XE.empty() ) {
|
|
delete pe->dl();
|
|
set_adjacent_faces(pe,0,upright,upleft);
|
|
}
|
|
else {
|
|
set_adjacent_faces(pe,pe->dl(),upright,upleft);
|
|
pe->dl()->set_front_view(upright->front_view());
|
|
pe->dl()->set_back_view (upleft->back_view());
|
|
// ---------------------------------------------------------
|
|
CGAL_expensive_precondition_code(
|
|
valid_ = !do_intersect(pe->dl()->back_view(),
|
|
pe->dl()->front_view());
|
|
if (valid_ == false) return;
|
|
);
|
|
// ---------------------------------------------------------
|
|
YE.insert(pe->dl());
|
|
}
|
|
// -------------------------------------------------------------
|
|
infinite = pe->dl();
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
// Inserting a tail cusp Edge from an left-xx constraint
|
|
else if (pe->sup()->is_left_xx()) {
|
|
// -------------------------------------------------------------
|
|
// Find the face in YE with pe->sup() as a front view.
|
|
Face_handle upleft = new Face;
|
|
upleft->set_front_view(pe->sup()->target_cusp_edge());
|
|
typename Ystructure::iterator upleft_it = YE.find(upleft);
|
|
typename Ystructure::iterator right = upleft_it; ++right;
|
|
delete upleft; upleft = *upleft_it;
|
|
YE.erase(upleft_it);
|
|
// -------------------------------------------------------------
|
|
// Update degenerate face emanating from edge.
|
|
upleft->set_sup(pe->sup());
|
|
upleft->set_inf(pe->sup()->pi());
|
|
CGAL_precondition(upleft->back_view()->object() != 0);
|
|
splice_ccw(upleft->back_view(),pe->sup());
|
|
// -------------------------------------------------------------
|
|
/* delete pe->ul(); */ set_adjacent_faces(pe,0,0,upleft);
|
|
CGAL_precondition(pe->dl() == 0 && pe->ur() == 0);
|
|
// -------------------------------------------------------------
|
|
// Update the back view of right.
|
|
(*right)->set_back_view(pe->sup()->cw_source_edge());
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
// Inserting a tail cusp Edge from a right-xx constraint
|
|
else {
|
|
// -------------------------------------------------------------
|
|
// Find the face in YE with pe->sup() as a front view.
|
|
Face_handle left = new Face;
|
|
left->set_front_view(pe->sup()->target_cusp_edge());
|
|
typename Ystructure::iterator left_it = YE.find(left);
|
|
typename Ystructure::iterator upright = left_it; ++upright;
|
|
delete left; left = *left_it;
|
|
// -------------------------------------------------------------
|
|
// Set upright as the degenerate face of the edge pe.
|
|
(*upright)->set_sup(pe->sup());
|
|
(*upright)->set_inf(pe->sup()->pi());
|
|
CGAL_precondition((*upright)->front_view()->object() != 0);
|
|
splice_ccw((*upright)->front_view(),pe->sup());
|
|
// -------------------------------------------------------------
|
|
/* delete pe->ur(); */ set_adjacent_faces(pe,0,*upright,0);
|
|
CGAL_precondition(pe->dl() == 0 && pe->ul() == 0);
|
|
// -------------------------------------------------------------
|
|
// Update the back view of left and insert the face.
|
|
YE.erase(left_it); YE.erase(upright);
|
|
left->set_front_view(pe->sup()->ccw_source_edge());
|
|
YE.insert(left);
|
|
// -------------------------------------------------------------
|
|
}
|
|
// -----------------------------------------------------------------
|
|
}
|
|
if (XE.empty()) infinite_face_->set_top_edge(pe);
|
|
} // end while ( !XE.empty() )
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Splicing the boundary of objects by inserting the pi of the constraints
|
|
// The fact that the edges come in pairs allows us to recover the edge with
|
|
// opposite sign on the same disk.
|
|
for (Edge_iterator e = edges_begin(); e != edges_end() ; ++e) {
|
|
if (e->object() != 0 && e->sup() != 0) {
|
|
Edge_handle eo = opposite[(&(*e))];
|
|
// CGAL_precondition(eo == e->opposite());
|
|
|
|
Vertex_handle v = e->sup();
|
|
splice_cw(eo,v->pi());
|
|
while (v->ccw_edge(e->object())->sup() != 0) {
|
|
splice_cw(v->pi()->ccw_edge(e->object()),
|
|
v->ccw_edge(e->object())->sup()->pi());
|
|
v = v->ccw_edge(e->object())->sup();
|
|
}
|
|
}
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
#endif
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
void
|
|
Antichain<Gtr_,It,Flip>::compute_vertices(Tr)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// All the operators from this methods are taken from the algorithm traits
|
|
// class Tr. Two traits classes are given : Ccw_traits and Cw_traits to
|
|
// compute G and G_* respectively
|
|
typename Tr::Sup sup; typename Tr::Inf inf;
|
|
typename Tr::Set_sup set_sup;// typename Tr::Set_inf set_inf;
|
|
typename Tr::Vertex_creator vc;
|
|
typename Tr::Set_adjacent_faces set_adjacent_old_faces;
|
|
typename Tr::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
typename Tr::Dr dr; typename Tr::Dl dl;
|
|
typename Tr::Ur ur; typename Tr::Ul ul;
|
|
typename Tr::Sign sign;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Splice splice;
|
|
typedef Tr TR;
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Saving the Edge --> Face pointers because we will lose them during the
|
|
// rotational sweep below.
|
|
std::vector<Face_handle> aaa;
|
|
aaa.reserve(3*this->size());
|
|
for (Edge_iterator e = edges_begin(); e != edges_end() ; ++e) {
|
|
aaa.push_back(dl(&*e));
|
|
aaa.push_back(sign(&*e)?ur(&*e):dr(&*e));
|
|
aaa.push_back(ul(&*e));
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// death is the event queue.
|
|
// It contains the vertices which are about to appear.
|
|
// Pushing first candidates to initialize death vertices
|
|
std::set<Vertex_handle,typename Tr::Less_vertex_handle> death;
|
|
|
|
for (Face_iterator fit = faces_begin() ; fit != faces_end() ; ++fit) {
|
|
Face_handle f = &(*fit);
|
|
if (is_candidate(f, Tr())) { // af: gcc needs it, for bcc it must not be there
|
|
if (sup(f) == 0) {
|
|
set_sup(f,vc(f->bottom_edge(),f->top_edge()));
|
|
}
|
|
death.insert(sup(f));
|
|
}
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Rotational sweep a la Bentley-Otman
|
|
while ( death.size() != 0 ) {
|
|
Vertex_handle vmin = *death.begin();
|
|
death.erase(death.begin());
|
|
// ---------------------------------------------------------------------
|
|
Edge_handle top = (vmin->is_constraint()) ? cw_target_edge(vmin) :
|
|
inf(vmin)->top_edge();
|
|
Edge_handle bot = (vmin->is_constraint()) ? cw_source_edge(vmin) :
|
|
inf(vmin)->bottom_edge();
|
|
// ---------------------------------------------------------------------
|
|
// A new Vertex ( == bitangent) has been found
|
|
// splice the two edges defining it
|
|
if (vmin != sup(top)) splice(top,vmin);
|
|
if (vmin != sup(bot)) splice(bot,vmin);
|
|
// ---------------------------------------------------------------------
|
|
// The two possible adjacent candidates must be erased
|
|
Face_handle ef[6];
|
|
if (bot->sign()) { ef[0] = dl(bot); ef[1] = ur(bot); ef[2] = ul(bot); }
|
|
else { ef[0] = dl(bot); ef[1] = dr(bot); ef[2] = ul(bot); }
|
|
if (top->sign()) { ef[3] = dl(top); ef[4] = ur(top); ef[5] = ul(top); }
|
|
else { ef[3] = dl(top); ef[4] = dr(top); ef[5] = ul(top); }
|
|
for (int i = 0 ; i < 6 ; i++)
|
|
if (is_candidate(ef[i], Tr()) && sup(ef[i]) != vmin) {
|
|
death.erase(sup(ef[i]));
|
|
if (!sup(ef[i])->is_constraint()) {
|
|
delete sup(ef[i]);
|
|
set_sup(ef[i],0);
|
|
}
|
|
}
|
|
// ---------------------------------------------------------------------
|
|
// Update the antichain
|
|
CGAL_precondition(sup(vmin) == 0);
|
|
sweep_constraint(vmin, Tr());
|
|
set_adjacent_old_faces(top,0,0,0);
|
|
set_adjacent_old_faces(bot,0,0,0);
|
|
// ---------------------------------------------------------------------
|
|
// Computing new candidates by looking at the adjacent faces of
|
|
// bot and top.
|
|
bot = ccw_source_edge(vmin);
|
|
top = ccw_target_edge(vmin);
|
|
if (sup(bot) != 0 && sup(bot)->is_constraint() // &&
|
|
// is_minimal(sup(bot),tr)
|
|
)
|
|
death.insert(sup(bot));
|
|
if (sup(top) != 0 && sup(top)->is_constraint() // &&
|
|
// is_minimal(sup(top),tr)
|
|
)
|
|
death.insert(sup(top));
|
|
Face_handle af[] = { dl(bot) , ur(bot) , dl(top) , ur(top) };
|
|
for (int i = 0 ; i < 4 ; i++)
|
|
if (is_candidate(af[i], Tr()) &&
|
|
sup(af[i]) != vmin && sup(af[i]) != vmin->pi()) {
|
|
if (sup(af[i]) == 0) set_sup(af[i],vc(af[i]->bottom_edge(),
|
|
af[i]->top_edge()));
|
|
death.insert(sup(af[i]));
|
|
}
|
|
// ---------------------------------------------------------------------
|
|
} // end while (death.size() != 0)
|
|
|
|
// Recovering the initial Edge --> Face pointers with a
|
|
{
|
|
typename std::vector<Face_handle>::iterator ia = aaa.begin();
|
|
for (Edge_iterator e = edges_begin(); e != edges_end() ; ++e,ia+=3) {
|
|
set_adjacent_faces(&*e,ia[0],ia[1],ia[2]);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
void
|
|
Antichain<Gtr_,It,Flip>::compute_minimals(Tr tr)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// Operators used in this method.
|
|
typename Tr::Sup sup;
|
|
typedef typename Tr::Right_traits Right_traits;
|
|
typename Right_traits::Target_cusp_edge target_cusp_edge;
|
|
typename Right_traits::Top_edge top_edge;
|
|
// -------------------------------------------------------------------------
|
|
// Computing the set of minimal bitangents
|
|
Vertex_handle ll = 0, rr = 0;
|
|
for (Face_iterator fi = faces_begin(); fi != faces_end() ; ++fi) {
|
|
Face_handle f = &(*fi);
|
|
if (sup(f) != 0 && is_minimal(sup(f),tr)) {
|
|
if (!sup(f)->is_constraint() ||
|
|
top_edge(f) == target_cusp_edge(sup(f))) {
|
|
Vertex_handle v = sup(f);
|
|
if (v != ll && v != rr) push_back_minimal(sup(f),tr);
|
|
if (ll == 0 && v->is_left_left() &&
|
|
is_on_convex_hull(v)) ll = v;
|
|
else if (rr == 0 && v->is_right_right() &&
|
|
is_on_convex_hull(v)) rr = v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Find topmost and bottommost edge.
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
initialize_convex_hull(Tr /*tr*/) const
|
|
{
|
|
typename Tr::Set_adjacent_faces set_adjacent_faces;
|
|
typename Tr::Dr dr; typename Tr::Dl dl;
|
|
typename Tr::Ur ur; typename Tr::Ul ul;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Sup sup;
|
|
typename Tr::Inf inf;
|
|
|
|
Edge_handle e = infinite_face()->bottom_edge();
|
|
do {
|
|
e = ccw_source_edge(sup(e));
|
|
set_adjacent_faces(e,dl(e),dr(e),infinite_face());
|
|
} while (sup(e)&&e != infinite_face()->bottom_edge());
|
|
|
|
if (!sup(e)) {
|
|
e=infinite_face()->bottom_edge();
|
|
do {
|
|
e = cw_target_edge(inf(e));
|
|
set_adjacent_faces(e,dl(e),dr(e),infinite_face());
|
|
} while (inf(e));
|
|
}
|
|
|
|
e = infinite_face()->top_edge();
|
|
do {
|
|
e = ccw_target_edge(sup(e));
|
|
set_adjacent_faces(e,infinite_face(), ur(e),ul(e));
|
|
} while (sup(e)&&e != infinite_face()->top_edge());
|
|
|
|
if (!sup(e)) {
|
|
e=infinite_face()->top_edge();
|
|
do {
|
|
e = cw_source_edge(inf(e));
|
|
set_adjacent_faces(e,dl(e),dr(e),infinite_face());
|
|
} while (inf(e));
|
|
}
|
|
}
|
|
|
|
// The antichain has 3n-1 faces whereas the pseudo-triangulation has only 3n-3
|
|
// bitangents. There are two faces which do not have their sup pointer set at
|
|
// this point. These are ul(bottommost) and dr(topmost). This function sets the
|
|
// sink of the two supplementary faces.
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::fix_extreme_edges(Tr /*tr*/) const // warning tr is never used
|
|
{
|
|
//--------------------------------------------------------------------------
|
|
// Operators used in this method.
|
|
typename Tr::Sup sup; typename Tr::Inf inf;
|
|
typename Tr::Set_sup set_sup; typename Tr::Set_inf set_inf;
|
|
typename Tr::Dr dr; typename Tr::Dl dl;
|
|
typename Tr::Ur ur; typename Tr::Ul ul;
|
|
typename Tr::CcL ccL; typename Tr::CcR ccR;
|
|
typename Tr::Set_adjacent_faces set_adjacent_faces;
|
|
// -------------------------------------------------------------------------
|
|
Edge_handle bot = infinite_face()->top_edge(); // Bottommost edge
|
|
Edge_handle top = infinite_face()->bottom_edge(); // Topmost edge
|
|
set_adjacent_faces(bot,infinite_face(),ur(bot),ul(bot));
|
|
set_adjacent_faces(top,dl(top),dr(top),infinite_face());
|
|
// -------------------------------------------------------------------------
|
|
// A face may appear twice in the antichain due to our identification
|
|
// v = v->pi()->pi(). If this is the case, delete one of the two and update
|
|
// pointers.
|
|
if (ur(bot) == dr(top) && ul(bot) != dl(top)) {
|
|
Face_handle f = ul(bot);
|
|
Edge_handle t = f->top_edge();
|
|
set_inf(dl(top),inf(f));
|
|
set_sup(inf(f),dl(top));
|
|
set_adjacent_faces(t,dl(top),ur(t),ul(t));
|
|
set_adjacent_faces(bot,dl(bot),ur(bot),dl(top));
|
|
delete f;
|
|
}
|
|
else if (ul(bot) == dl(top) && ur(bot) != dr(top)) {
|
|
Face_handle f = dr(top);
|
|
Edge_handle t = f->bottom_edge();
|
|
set_inf(ur(bot),inf(f));
|
|
set_sup(inf(f),ur(bot));
|
|
set_adjacent_faces(t,dl(t),dr(t),ur(bot));
|
|
set_adjacent_faces(top,dl(top),ur(bot),ul(top));
|
|
delete f;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// Set the sink of the two faces on the convex-hull.
|
|
if (sup(ur(bot)) != 0 && sup(ul(bot)) == 0) {
|
|
Vertex_handle v = sup(ur(bot));
|
|
Vertex_handle w = inf(dr(top));
|
|
if (*v == *w->pi()) set_sup(ul(bot),w);
|
|
else {
|
|
do { v = ccR(v); } while (v->is_constraint());
|
|
CGAL_precondition(v != 0 && inf(v) != 0);
|
|
set_sup(ul(bot),inf(inf(v)));
|
|
}
|
|
sup(ur(bot))->set_pi(sup(ul(bot)));
|
|
}
|
|
if (sup(dl(top)) != 0 && sup(dr(top)) == 0) {
|
|
Vertex_handle v = sup(dl(top));
|
|
Vertex_handle w = inf(ul(bot));
|
|
if (*v == *w->pi()) set_sup(dr(top),w);
|
|
else {
|
|
do { v = ccL(v); } while (v->is_constraint());
|
|
CGAL_precondition(v != 0 && inf(v) != 0);
|
|
set_sup(dr(top),inf(inf(v)));
|
|
}
|
|
sup(dl(top))->set_pi(sup(dr(top)));
|
|
}
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::glue()
|
|
{
|
|
Less_bitangent<Gtr_> lb;
|
|
typename Ccw_traits::Splice splice_ccw;
|
|
typename Cw_traits::Splice splice_cw;
|
|
typename Ccw_traits::Set_adjacent_faces saj;
|
|
|
|
for (Edge_iterator e = edges_begin(); e != edges_end() ; ++e) {
|
|
if (e->object() != 0) {
|
|
Edge_iterator eo = e; if (e->sign()) --eo; else ++eo;
|
|
Edge_handle e1=&*e;
|
|
Edge_handle e2=&*eo;
|
|
Edge_handle e20=e2;
|
|
Vertex_handle v1=e1->sup();
|
|
bool chiv1e1=false;
|
|
bool chiv1e2=false;
|
|
while (e2->inf()) {
|
|
e2=e2->inf()->cw_edge(e2->object());
|
|
}
|
|
while (e1->sup()&&e2->sup()) {
|
|
if (e1->sup()==e2->sup()->pi()) {
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
e2=e2->sup()->ccw_edge(e2->object());
|
|
if (e1->sup()) chiv1e1=lb(*v1,*e1->sup());
|
|
if (e2->sup()) chiv1e2=lb(*v1,*e2->sup()->pi());
|
|
continue;
|
|
}
|
|
if (*e1->sup()==*e2->sup()->pi()) {
|
|
e1->sup()->set_pi(e2->sup());
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
e2=e2->sup()->ccw_edge(e2->object());
|
|
if (e1->sup()) chiv1e1=lb(*v1,*e1->sup());
|
|
if (e2->sup()) chiv1e2=lb(*v1,*e2->sup()->pi());
|
|
continue;
|
|
}
|
|
if (e1->sup()==v1) {
|
|
if (v1->ccw_edge(e1->object())->sup()) chiv1e1=lb(*v1,*v1->ccw_edge(e1->object())->sup());
|
|
chiv1e2=lb(*v1,*e2->sup()->pi());
|
|
splice_cw(e2,e1->sup()->pi());
|
|
saj(e2->inf()->cw_edge(e2->object()),e2->dl(),
|
|
e2->sign()?e2->ur():e2->dr(),e2->ul());
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
continue;
|
|
}
|
|
if (chiv1e1? (chiv1e2?lb(*e1->sup(),*e2->sup()->pi()):true)
|
|
: (chiv1e2?false:lb(*e1->sup(),*e2->sup()->pi()))
|
|
) {
|
|
splice_cw(e2,e1->sup()->pi());
|
|
saj(e2->inf()->cw_edge(e2->object()),e2->dl(),
|
|
e2->sign()?e2->ur():e2->dr(),e2->ul());
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
if (e1->sup()) chiv1e1=lb(*v1,*e1->sup());
|
|
} else {
|
|
splice_ccw(e1,e2->sup()->pi());
|
|
saj(e1->sup()->ccw_edge(e1->object()),e1->dl(),
|
|
e1->sign()?e1->ur():e1->dr(),e1->ul());
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
e2=e2->sup()->ccw_edge(e2->object());
|
|
if (e2->sup()) chiv1e2=lb(*v1,*e2->sup()->pi());
|
|
}
|
|
}
|
|
for (;e1->sup();e1=e1->sup()->ccw_edge(e1->object()))
|
|
splice_cw(e2,e1->sup()->pi());
|
|
for (;e2!=e20&&e2->sup();e2=e2->sup()->ccw_edge(e2->object())) {
|
|
splice_ccw(e1,e2->sup()->pi());
|
|
e1=e1->sup()->ccw_edge(e1->object());
|
|
}
|
|
}
|
|
}
|
|
for (Edge_iterator e = edges_begin(); e != edges_end() ; ++e) {
|
|
if (e->object()) {
|
|
if (e->sup()) {
|
|
e->sup()->pi()->set_final_antichain(true);
|
|
}
|
|
Edge_handle e1,e2;
|
|
for (e1=&*e;e1->sup();) e1=e1->sup()->ccw_edge(e1->object());
|
|
for (e2=&*e;e2->inf();) e2=e2->inf()->cw_edge(e2->object());
|
|
if (e1!=&*e) {
|
|
e2->set_inf(e1->inf());
|
|
e2->inf()->set_ccw_edge(e2,e2->object());
|
|
saj(e2,e1->dl()?e1->dl():e2->dl(),
|
|
e2->sign()?(e1->ur()?e1->ur():e2->ur()):
|
|
(e1->dr()?e1->dr():e2->dr()),
|
|
e1->ul()?e1->ul():e2->ul());
|
|
delete e1;
|
|
} else {
|
|
e1->set_sup(e2->sup());
|
|
e1->sup()->set_cw_edge(e1,e1->object());
|
|
saj(e1,e1->dl()?e1->dl():e2->dl(),
|
|
e2->sign()?(e1->ur()?e1->ur():e2->ur()):
|
|
(e1->dr()?e1->dr():e2->dr()),
|
|
e1->ul()?e1->ul():e2->ul());
|
|
delete e2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
// Identifying vertices of the convex-hull
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
inline bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_on_convex_hull(Vertex_handle v) const
|
|
{
|
|
return ((v->is_left_left() && v->cw_source_edge() != 0 &&
|
|
v->cw_source_edge()->dr() == infinite_face()) ||
|
|
(v->is_right_right() && v->cw_target_edge() != 0 &&
|
|
v->cw_target_edge()->ul() == infinite_face()));
|
|
}
|
|
|
|
|
|
// Minimality Testing
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
inline bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_minimal(const Vertex_handle& v, Tr /*tr*/) const
|
|
{
|
|
typename Tr::Left_traits lt;
|
|
typename Tr::Right_traits rt;
|
|
return (is_xx_minimal(v,lt) &&
|
|
is_xx_minimal(v,rt));
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
inline bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_xx_minimal(const Vertex_handle& v, Tr /*tr*/ ) const
|
|
{
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
if (v == 0 || cw_source_edge(v) == 0) return false;
|
|
|
|
return cw_source_edge(v)->is_in_antichain();
|
|
}
|
|
|
|
// Methods to manage the list of minimals
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::clear_minimals(Tr tr) {
|
|
Minimals_iterator first = minimals_begin(tr);
|
|
Minimals_iterator last = minimals_end(tr);
|
|
while (first != last) erase_minimal(first++,tr);
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
push_back_minimal(Vertex_handle v,Ccw_traits)
|
|
{
|
|
Less_bitangent<Gtr_> lv;
|
|
Minimals_iterator w = (is_straight()) ? std::lower_bound(minimals_begin(),
|
|
minimals_end(),
|
|
*v,lv) :
|
|
minimals_end();
|
|
minimals_ccw_.insert(w,*v);
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
push_back_minimal(Vertex_handle v,Cw_traits)
|
|
{
|
|
Greater_bitangent<Gtr_> lv;
|
|
Minimals_iterator w = (is_straight()) ? std::lower_bound(cw_minimals_begin(),
|
|
cw_minimals_end(),
|
|
*v,lv) :
|
|
cw_minimals_end();
|
|
minimals_cw_.insert(w,*v);
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
typename Antichain<Gtr_,It,Flip>::Vertex_handle
|
|
Antichain<Gtr_,It,Flip>::pop_minimal(bool finite/* = false*/)
|
|
{
|
|
if (minimals_begin() == minimals_end()) return 0;
|
|
if (finite == false) {
|
|
Vertex_handle min = &(*minimals_begin());
|
|
return min;
|
|
}
|
|
else {
|
|
Vertex_handle min = pop_minimal(false);
|
|
if (min != 0 && is_on_convex_hull(min)) return min;
|
|
while (minimals_begin() != minimals_end() &&
|
|
min->sup() != 0 && !is_on_convex_hull(min)) {
|
|
erase_minimal(min);
|
|
min = pop_minimal(false);
|
|
}
|
|
if (min != 0 && is_on_convex_hull(min)) return min;
|
|
return (min == 0 || min->sup() != 0) ? 0 : min;
|
|
}
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::sweep(Vertex_handle v , Tr tr)
|
|
{
|
|
//--------------------------------------------------------------------------
|
|
// Operators used in this method.
|
|
typename Tr::Inf inf;// typename Tr::Sup sup;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Source_cusp_edge source_cusp_edge;
|
|
typename Tr::Target_cusp_edge target_cusp_edge;
|
|
typename Tr::CcR ccR; typename Tr::CcL ccL;
|
|
typename Tr::CwR cwR; typename Tr::CwL cwL;
|
|
typename Tr::Merge merge(this);
|
|
typename Tr::Ul ul;
|
|
typename Tr::Dl dl;
|
|
typename Tr::Ur ur;
|
|
typename Tr::Dr dr;
|
|
|
|
// std::cout<<"beuh"<<v<<"\n";
|
|
|
|
CGAL_precondition(is_minimal(v,tr));
|
|
CGAL_precondition(cwL(v) != 0 && cwR(v) != 0);
|
|
CGAL_precondition(v->is_constraint()||inf(v));
|
|
bool dont_delete_inf_v=
|
|
(inf(v)==ul(infinite_face()->top_edge())&&
|
|
inf(v)==dl(infinite_face()->bottom_edge())) ||
|
|
(inf(v)==ur(infinite_face()->top_edge())&&
|
|
inf(v)==dr(infinite_face()->bottom_edge()));
|
|
// -------------------------------------------------------------------------
|
|
// Removing cwR(v) and cwL(v) from the minimal list corresponding to the
|
|
// opposite orientation. Adding v.
|
|
typename Tr::Cw_traits cw_traits;
|
|
erase_minimal(v,tr); push_back_minimal(v,cw_traits);
|
|
CGAL_assertion(v!=cwR(v)&&v!=cwL(v));
|
|
if (is_minimal(cwL(v),cw_traits)) erase_minimal(cwL(v),cw_traits);
|
|
if (cwR(v) != cwL(v) && is_minimal(cwR(v),cw_traits))
|
|
erase_minimal(cwR(v),cw_traits);
|
|
//--------------------------------------------------------------------------
|
|
// Flipping v and updating the antichain
|
|
if (v->is_constraint()) {
|
|
sweep_constraint(v, Tr());
|
|
if (!linear_space()) sweep_constraint(v->pi(),Tr(),true);
|
|
}
|
|
else {
|
|
compute_phi(v,tr); // Flip bitangent in pseudo-triangulation
|
|
sweep_regular(v, Tr()); // Modify the antichain
|
|
if (!linear_space()) sweep_regular(v->pi(),Tr(),true);
|
|
}
|
|
erase(cw_source_edge(v));
|
|
erase(cw_target_edge(v));
|
|
if (v->is_constraint()) {
|
|
erase(target_cusp_edge(v));
|
|
erase(source_cusp_edge(v));
|
|
push_back(*target_cusp_edge(v->pi()));
|
|
push_back(*source_cusp_edge(v->pi()));
|
|
}
|
|
//--------------------------------------------------------------------------
|
|
// Pushing the two new created edges
|
|
push_back(*ccw_source_edge(v));
|
|
push_back(*ccw_target_edge(v));
|
|
//--------------------------------------------------------------------------
|
|
// Updating minimals
|
|
if (ccL(v)&&is_minimal(ccL(v),tr)) push_back_minimal(ccL(v),tr);
|
|
if (ccR(v)&&ccR(v) != ccL(v) && is_minimal(ccR(v),tr))
|
|
push_back_minimal(ccR(v),tr);
|
|
|
|
// Deleting (inf(v)), along with its vertices that are no longer adjacent
|
|
// to any face.
|
|
if (linear_space()&&!dont_delete_inf_v) {
|
|
Face_handle faces[3]={0,0,0};
|
|
if (v->is_constraint()) {
|
|
faces[0]=v->source_cusp_face();
|
|
faces[1]=v->target_cusp_face();
|
|
} else {
|
|
// std::cout<<"meuh"<<v<<"\n";
|
|
faces[0]=v->inf();
|
|
}
|
|
for (int fi=0;faces[fi];++fi) {
|
|
std::vector<Vertex_handle> vv;
|
|
Edge_handle prev=0;
|
|
for (typename Face::Border_iterator i=--(faces[fi]->top_end());
|
|
i!=faces[fi]->top_end()&&i.operator->()!=prev;--i) {
|
|
vv.push_back(inf(i.operator->()));
|
|
prev=i.operator->();
|
|
CGAL_assertion(!i->is_in_antichain());
|
|
}
|
|
prev=0;
|
|
for (typename Face::Border_iterator i=--(faces[fi]->bottom_end());
|
|
i!=faces[fi]->top_end()&&i.operator->()!=prev;--i) {
|
|
if (inf(i.operator->())!=inf(faces[fi]))
|
|
vv.push_back(inf(i.operator->()));
|
|
prev=i.operator->();
|
|
CGAL_assertion(!i->is_in_antichain());
|
|
}
|
|
delete faces[fi];
|
|
|
|
for (typename std::vector<Vertex_handle>::iterator i=vv.begin();
|
|
i!=vv.end();++i) {
|
|
if (is_on_convex_hull(*i)||(*i)->is_constraint()||
|
|
(*i)->final_antichain())
|
|
continue;
|
|
Face_handle adj[4][3];
|
|
Edge_handle e[4]={cw_source_edge(*i),cw_target_edge(*i),
|
|
ccw_source_edge(*i),ccw_target_edge(*i)};
|
|
for (int j=0;j<4;j++) {
|
|
adj[j][0]=e[j]->dl();
|
|
adj[j][1]=e[j]->sign()?e[j]->ur():e[j]->dr();
|
|
adj[j][2]=e[j]->ul();
|
|
}
|
|
bool skip=false;
|
|
for (int k=0;k==0;k=1) {
|
|
for (int l=0;l<3;l++) skip=skip||adj[k][l]!=adj[k+2][l];
|
|
}
|
|
if (!skip) {
|
|
merge(cw_source_edge(*i),ccw_source_edge(*i));
|
|
merge(cw_target_edge(*i),ccw_target_edge(*i));
|
|
delete *i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::sweep_all_minimals(Tr tr)
|
|
{
|
|
std::list<Vertex_handle> mins;
|
|
for (Minimals_iterator m = minimals_begin(tr); m != minimals_end(tr); ++m)
|
|
mins.push_back(&(*m));
|
|
typename std::list<Vertex_handle>::iterator clic = mins.begin();
|
|
for ( ; clic != mins.end() ; ++clic)
|
|
if (is_minimal(*clic,tr)) sweep(*clic,tr);
|
|
}
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::sweep_good(Vertex_handle v,Tr tr)
|
|
{
|
|
typename Tr::CcR ccR; typename Tr::CcL ccL; typename Tr::Sup sup;
|
|
// typename Tr::CwR cwR; typename Tr::CwL cwL;
|
|
// -------------------------------------------------------------------------
|
|
sweep(v,tr);
|
|
// -------------------------------------------------------------------------
|
|
// If ccR(v) and/or ccL(v) are geometrically equal to v and if ccR(v) and/or
|
|
// ccL(v) are minimal, we sweep them.
|
|
CGAL_precondition(ccR(v) != 0 && ccL(v) != 0 && sup(sup(v)) != 0);
|
|
Vertex_handle w[] = { ccR(v) , ccL(v) , sup(sup(v)) };
|
|
typename Gtr_::Equal_as_segments equal_as_segments;
|
|
for (int i = 0; i < 3 ; i++)
|
|
if (equal_as_segments(*v,*w[i]) && is_minimal(w[i],tr))
|
|
sweep(w[i],tr);
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::sweep_good_all_minimals(Tr tr)
|
|
{
|
|
std::list<Vertex_handle> mins;
|
|
for (Minimals_iterator m = minimals_begin(tr); m != minimals_end(tr); ++m)
|
|
mins.push_back(&(*m));
|
|
typename std::list<Vertex_handle>::iterator clic = mins.begin();
|
|
for ( ; clic != mins.end() ; ++clic)
|
|
if (is_minimal(*clic,tr)) sweep_good(*clic,tr);
|
|
}
|
|
|
|
#if 0
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr >
|
|
Vertex_handle
|
|
Antichain<Gtr_,It,Flip>::compute_phi(Vertex_handle v, Tr tr)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
typename Tr::Sup sup;
|
|
typename Tr::Inf inf;
|
|
typename Tr::Set_sup set_sup; typename Tr::Set_inf set_inf;
|
|
typename Tr::Splice splice;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::CcL ccL; typename Tr::CcR ccR;
|
|
typename Tr::Is_left_xx is_left_xx;
|
|
// -------------------------------------------------------------------------
|
|
Vertex_handle phiv; // The new Vertex that we must compute
|
|
// -------------------------------------------------------------------------
|
|
// Vertex has already been swept.
|
|
if (sup(v) != 0) {
|
|
phiv = sup(sup(v));
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// The pi of the Vertex has already been swept. We use the formula:
|
|
// phi(v)->pi() = phi(v->pi()).
|
|
else if (!linear_space()&&
|
|
sup(v->pi()) != 0) {
|
|
if (is_on_convex_hull(v)) {
|
|
if (is_left_xx(v) && ccL(v->pi()) != 0)
|
|
ccR(v)->set_pi(ccL(v->pi()));
|
|
if (!is_left_xx(v) && ccR(v->pi()) != 0)
|
|
ccL(v)->set_pi(ccR(v->pi()));
|
|
}
|
|
phiv = sup(sup(v->pi()))->pi();
|
|
} else if (linear_space()&&is_on_convex_hull(v)) {
|
|
phiv=v;
|
|
do
|
|
if (is_left_xx(phiv)) phiv=ccR(phiv); else phiv=ccL(phiv);
|
|
while (phiv->is_constraint());
|
|
phiv=phiv->pi();
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// We flip v in the current pseudo-triangulation.
|
|
// To compute phi(v) we walk on the incident pseudo-triangles.
|
|
//else phiv = Chi2_strategy(this)(v,tr);
|
|
else phiv = Flip_traits(this)(v,tr);
|
|
// -------------------------------------------------------------------------
|
|
// We splice the arcs left and right if b is not on the convex hull
|
|
//if (!is_on_convex_hull(v)) { splice(right,phiv); splice(left,phiv); }
|
|
// -------------------------------------------------------------------------
|
|
// Creating a new face with source v and sink phi(v)
|
|
if (sup(v) == 0) set_sup(v,new Face);
|
|
set_inf(sup(v),v);
|
|
set_sup(sup(v),phiv);
|
|
// -------------------------------------------------------------------------
|
|
// Creating a new face with source pi(v) and sink pi(phi(v))
|
|
if (!linear_space()) {
|
|
Vertex_handle vv=inf(cw_source_edge(phiv));
|
|
if (cw_source_edge(phiv)==ccw_target_edge(vv)) {
|
|
splice(ccw_source_edge(vv->pi()),phiv->pi());
|
|
} else {
|
|
CGAL_assertion(cw_source_edge(phiv)==ccw_source_edge(vv));
|
|
splice(ccw_target_edge(vv->pi()),phiv->pi());
|
|
}
|
|
vv=inf(cw_target_edge(phiv));
|
|
if (cw_target_edge(phiv)==ccw_target_edge(vv)) {
|
|
splice(ccw_source_edge(vv->pi()),phiv->pi());
|
|
} else {
|
|
CGAL_assertion(cw_target_edge(phiv)==ccw_source_edge(vv));
|
|
splice(ccw_target_edge(vv->pi()),phiv->pi());
|
|
}
|
|
if (sup(v->pi()) == 0) set_sup(v->pi(),new Face);
|
|
set_inf(sup(v->pi()),v->pi());
|
|
set_sup(sup(v->pi()),phiv?phiv->pi():0);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
CGAL_postcondition(sup(v) != 0 && (sup(sup(v)) != 0));
|
|
return phiv;
|
|
}
|
|
#endif
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::set_constraint(Vertex_handle v)
|
|
{
|
|
typedef Ccw_traits Tr;
|
|
typename Tr::Set_sup set_sup; typename Tr::Set_inf set_inf;
|
|
typename Tr::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
typename Tr::Set_target_cusp_edge set_target_cusp_edge;
|
|
typename Tr::Set_source_cusp_edge set_source_cusp_edge;
|
|
typename Tr::Target_cusp_edge target_cusp_edge;
|
|
typename Tr::Source_cusp_edge source_cusp_edge;
|
|
typename Tr::Is_left_xx is_left_xx;
|
|
typename Tr::Is_xx_left is_xx_left;
|
|
// -------------------------------------------------------------------------
|
|
typename Tr::Sup sup; typename Tr::Inf inf;
|
|
Face_handle fs = sup(v); Face_handle fi = inf(v);
|
|
Face_handle pifs = sup(v->pi()); Face_handle pifi = inf(v->pi());
|
|
// -------------------------------------------------------------------------
|
|
// New edge for rays emanating from b->target() where b = this
|
|
// with angle \theta such that \theta(b) - \pi < \theta < \theta(b)
|
|
// New edge for rays emanating from b->source() where b = this
|
|
// with angle \theta such that \theta(b) - \pi < \theta < \theta(b)
|
|
set_target_cusp_edge(v,new Edge);
|
|
set_source_cusp_edge(v,new Edge);
|
|
target_cusp_edge(v)->set_sign(false);
|
|
set_sup(target_cusp_edge(v),v);
|
|
set_inf(target_cusp_edge(v),v->pi());
|
|
source_cusp_edge(v)->set_sign(true);
|
|
set_sup(source_cusp_edge(v),v);
|
|
set_inf(source_cusp_edge(v),v->pi());
|
|
// -------------------------------------------------------------------------
|
|
// New face directed from b->target_object() to b, the sink is b
|
|
Face_handle f0 = new Face;
|
|
set_sup(f0,v);
|
|
set_inf(f0,v->pi());
|
|
f0->set_top_edge(target_cusp_edge(v));
|
|
if (is_xx_left(v)) set_adjacent_faces(target_cusp_edge(v),f0,0,0);
|
|
else set_adjacent_faces(target_cusp_edge(v),0,f0,0);
|
|
// New face directed from b->source_object() to b, the sink is b
|
|
Face_handle f1 = new Face;
|
|
set_sup(f1,v);
|
|
set_inf(f1,v->pi());
|
|
f1->set_bottom_edge(source_cusp_edge(v));
|
|
if (is_left_xx(v)) set_adjacent_faces(source_cusp_edge(v),0,0,f1);
|
|
else set_adjacent_faces(source_cusp_edge(v),0,f1,0);
|
|
// -------------------------------------------------------------------------
|
|
set_sup(v,fs); set_inf(v,fi);
|
|
set_sup(v->pi(),pifs); set_inf(v->pi(),pifi);
|
|
// -------------------------------------------------------------------------
|
|
// Do the same with b->pi()
|
|
//if (!v->pi()->is_constraint()) set_constraint(v->pi());
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::remove_constraint(Vertex_handle v)
|
|
{
|
|
if (!v->is_constraint()) return;
|
|
// -------------------------------------------------------------------------
|
|
// erase(v->target_cusp_edge());
|
|
// erase(v->source_cusp_edge());
|
|
unset_constraint(v);
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::add_constraint(Vertex_handle v)
|
|
{
|
|
if (v->is_constraint()) return;
|
|
// -------------------------------------------------------------------------
|
|
set_constraint(v);
|
|
set_constraint(v->pi());
|
|
//push_back(*v->target_cusp_edge());
|
|
//push_back(*v->source_cusp_edge());
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
void
|
|
Antichain<Gtr_,It,Flip>::unset_constraint(Vertex_handle v)
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
delete v->target_cusp_face(); delete v->source_cusp_face();
|
|
delete v->target_cusp_edge(); delete v->source_cusp_edge();
|
|
// if (v->pi()->is_constraint()) unset_constraint(v->pi());
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
sweep_regular(const Vertex_handle& v, const Tr&,bool opposite) const
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// The operators used by this method
|
|
typename Tr::Sup sup; typename Tr::Inf inf;
|
|
typename Tr::Set_inf set_inf;
|
|
typename Tr::Set_adjacent_faces_one_to_one set_adjacent_faces_one_to_one;
|
|
typename Tr::Set_adjacent_faces set_adjacent_faces;
|
|
typename Tr::Dl dl; typename Tr::Dr dr;
|
|
typename Tr::Ul ul; typename Tr::Ur ur;
|
|
typename Tr::Is_left_xx is_left_xx;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
// -------------------------------------------------------------------------
|
|
// The four edges adjacent to v
|
|
Edge_handle e = cw_source_edge(v);
|
|
Edge_handle ep = ccw_source_edge(v);
|
|
Edge_handle f = cw_target_edge(v);
|
|
Edge_handle fp = ccw_target_edge(v);
|
|
// -------------------------------------------------------------------------
|
|
// The six faces adjacent to v.
|
|
Face_handle f0,f1,f2,f3;
|
|
if (e->sign()) { f0 = ul(e); f1 = dl(e); }
|
|
else {
|
|
f0 = dl(e); if (f0 == 0 || sup(f0) == v) f0 = dl(f);
|
|
f1 = dr(e);
|
|
}
|
|
if (f->sign()) {
|
|
f2 = ur(f); if (f2 == 0 || sup(f2) == v) f2 = ur(e);
|
|
f3 = ul(f);
|
|
}
|
|
else { f2 = dr(f); f3 = ul(f); }
|
|
Face_handle f4 = sup(v); set_inf(f4,v);
|
|
Face_handle f5 = inf(v);
|
|
// -------------------------------------------------------------------------
|
|
// Due to our identification pi^2(v) == v, a face can appear twice in the
|
|
// antichain. As a consequence a face can appear twice in the antichain.
|
|
// This implies that the pointers Edge <---> Face are not necessarily
|
|
// reversible.
|
|
// Our solution: make the Edge --> Face pointers correct and use the
|
|
// infinite face and the two Edges below.
|
|
Edge_handle botf4 = f4->bottom_edge();
|
|
Edge_handle topf4 = f4->top_edge();
|
|
// -------------------------------------------------------------------------
|
|
// Updating the Edge <--> Face pointers for the two new edges of the
|
|
// antichain.
|
|
if (0&&linear_space() && !is_on_convex_hull(v)) {
|
|
set_adjacent_faces_one_to_one(e,0,0,0);
|
|
set_adjacent_faces_one_to_one(f,0,0,0);
|
|
}
|
|
if (opposite) {
|
|
if (is_left_xx(v)) set_adjacent_faces(ep,f4,f3,f0);
|
|
else set_adjacent_faces(ep,f0,f4,f3);
|
|
set_adjacent_faces(fp,f1,f2,f4);
|
|
return;
|
|
} else {
|
|
if (is_left_xx(v)) set_adjacent_faces_one_to_one(ep,f4,f3,f0);
|
|
else set_adjacent_faces_one_to_one(ep,f0,f4,f3);
|
|
set_adjacent_faces_one_to_one(fp,f1,f2,f4);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// Fix the pointers due to the problem mentionned above. This only occurs
|
|
// for faces whose sink are on the convex-hull.
|
|
CGAL_precondition(f4 != 0);
|
|
CGAL_precondition(f5 != 0);
|
|
if (is_on_convex_hull(v)) {
|
|
if (f2 == f4) { f4->set_top_edge(ep); f4->set_bottom_edge(fp); }
|
|
else {
|
|
Face_handle w = (is_left_xx(v)) ? f2 : f0;
|
|
if (botf4 != 0 && w->bottom_edge() != botf4)
|
|
f4->set_bottom_edge(botf4);
|
|
if (topf4 != 0 && w->top_edge() != topf4)
|
|
f4->set_top_edge(topf4);
|
|
}
|
|
if (f5->bottom_edge() != e) {
|
|
f5->set_top_edge(infinite_face()->bottom_edge());
|
|
return;
|
|
}
|
|
else if (f5->top_edge() != f) {
|
|
f5->set_bottom_edge(infinite_face()->top_edge());
|
|
return;
|
|
}
|
|
}
|
|
|
|
// // The face inf(v) is no longer swept.
|
|
// f5->set_bottom_edge(0);
|
|
// f5->set_top_edge (0);
|
|
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
void
|
|
Antichain<Gtr_,It,Flip>::
|
|
sweep_constraint(const Vertex_handle& v, const Tr&,bool opposite) const
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
// The operators used by this method
|
|
typename Tr::Sup sup;
|
|
typename Tr::Set_adjacent_faces set_adjacent_old_faces;
|
|
typename Tr::Set_adjacent_faces_one_to_one set_adjacent_faces;
|
|
typename Tr::Dl dl; typename Tr::Dr dr;
|
|
typename Tr::Ul ul; typename Tr::Ur ur;
|
|
typename Tr::Target_cusp_face target_cusp_face;
|
|
typename Tr::Source_cusp_face source_cusp_face;
|
|
typename Tr::Is_left_xx is_left_xx; typename Tr::Is_xx_left is_xx_left;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
// -------------------------------------------------------------------------
|
|
// The four edges adjacent to v
|
|
Edge_handle e = cw_source_edge(v);
|
|
Edge_handle ep = ccw_source_edge(v);
|
|
Edge_handle f = cw_target_edge(v);
|
|
Edge_handle fp = ccw_target_edge(v);
|
|
// -------------------------------------------------------------------------
|
|
// The four regular faces adjacent to v
|
|
Face_handle f0,f1,f2,f3;
|
|
if (e->sign()) { f0 = ul(e); f1 = dl(e); }
|
|
else { f0 = dl(e); if (sup(f0) == v) f0 = dl(f); f1 = dr(e); }
|
|
if (f->sign()) { f2 = ur(f); if (sup(f2) == v) f2 = ur(e); f3 = ul(f); }
|
|
else { f2 = dr(f); f3 = ul(f); }
|
|
// -------------------------------------------------------------------------
|
|
// The four degenerate faces adjacent to v
|
|
Face_handle a = source_cusp_face(v);
|
|
Face_handle ap = source_cusp_face(v->pi());
|
|
Face_handle b = target_cusp_face(v);
|
|
Face_handle bp = target_cusp_face(v->pi());
|
|
// -------------------------------------------------------------------------
|
|
Edge_handle fix = 0;
|
|
if (is_on_convex_hull(v)) {
|
|
if (e->sign() && e != f2->bottom_edge()) fix = f2->bottom_edge();
|
|
else if (!e->sign() && f != f0->top_edge()) fix = f0->top_edge();
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// Updating the Edge <--> Face pointers for the two new edges of the
|
|
// antichain.
|
|
typename Vertex::Type_util type;
|
|
switch (type(is_left_xx(v),is_xx_left(v))) {
|
|
case Vertex::LL:
|
|
set_adjacent_old_faces(e,f1,f2,f0);
|
|
set_adjacent_old_faces(f,a,b,f3);
|
|
if (opposite) {
|
|
set_adjacent_old_faces(ep,ap,f3,bp);
|
|
set_adjacent_old_faces(fp,f1,f2,f0);
|
|
} else {
|
|
set_adjacent_faces(ep,ap,f3,bp);
|
|
set_adjacent_faces(fp,f1,f2,f0);
|
|
}
|
|
break;
|
|
case Vertex::RR:
|
|
set_adjacent_old_faces(e,a,f1,b);
|
|
set_adjacent_old_faces(f,f0,f2,f3);
|
|
if (opposite) {
|
|
set_adjacent_old_faces(ep,f0,f2,f3);
|
|
set_adjacent_old_faces(fp,f1,ap,bp);
|
|
} else {
|
|
set_adjacent_faces(ep,f0,f2,f3);
|
|
set_adjacent_faces(fp,f1,ap,bp);
|
|
}
|
|
break;
|
|
case Vertex::LR:
|
|
set_adjacent_old_faces(e,f1,b,f0);
|
|
set_adjacent_old_faces(f,a,f2,f3);
|
|
if (opposite) {
|
|
set_adjacent_old_faces(ep,f2,f3,bp);
|
|
set_adjacent_old_faces(fp,f1,ap,f0);
|
|
} else {
|
|
set_adjacent_faces(ep,f2,f3,bp);
|
|
set_adjacent_faces(fp,f1,ap,f0);
|
|
}
|
|
break;
|
|
case Vertex::RL:
|
|
set_adjacent_old_faces(e,a,f1,f2);
|
|
set_adjacent_old_faces(f,f0,b,f3);
|
|
if (opposite) {
|
|
set_adjacent_old_faces(ep,f0,ap,f3);
|
|
set_adjacent_old_faces(fp,f1,f2,bp);
|
|
} else {
|
|
set_adjacent_faces(ep,f0,ap,f3);
|
|
set_adjacent_faces(fp,f1,f2,bp);
|
|
}
|
|
break;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
if (is_on_convex_hull(v) && fix != 0) {
|
|
if (fix->sign()) set_adjacent_faces(fix,dl(fix),ur(fix),ul(fix));
|
|
else set_adjacent_faces(fix,dl(fix),dr(fix),ul(fix));
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// if (a != 0) a->set_top_edge(0);
|
|
// if (b != 0) b->set_bottom_edge(0);
|
|
// -------------------------------------------------------------------------
|
|
}
|
|
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_swept_regular(const Vertex_handle& v, Tr /*tr*/) const
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
CGAL_precondition(!v->is_constraint());
|
|
// -------------------------------------------------------------------------
|
|
// The operators used by this method
|
|
typename Tr::Sup sup;
|
|
typename Tr::Dl dl; typename Tr::Dr dr;
|
|
typename Tr::Ul ul; typename Tr::Ur ur;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::Is_left_xx is_left_xx; typename Tr::Is_xx_left is_xx_left;
|
|
// -------------------------------------------------------------------------
|
|
// A vertex v has been swept iff. the two following conditions are
|
|
// satisfied:
|
|
// (1) sup(v) is not 0
|
|
// (2) the faces adjacent to ccw_source_edge(v) and ccw_target_edge(v) are
|
|
// correct. We check this with the help of the faces adjacent to
|
|
// cw_source_edge(v) and cw_target_edge(v) which are assumed to be correct.
|
|
// -------------------------------------------------------------------------
|
|
// Checking (1).
|
|
Face_handle f4 = sup(v);
|
|
if (f4 == 0) return false;
|
|
// -------------------------------------------------------------------------
|
|
// Checking (2).
|
|
// -------------------------------------------------------------------------
|
|
// The four edges adjacent to v
|
|
Edge_handle e = cw_source_edge(v);
|
|
Edge_handle ep = ccw_source_edge(v);
|
|
Edge_handle f = cw_target_edge(v);
|
|
Edge_handle fp = ccw_target_edge(v);
|
|
if (e == 0 || ep == 0 || f == 0 || fp == 0) return false;
|
|
// -------------------------------------------------------------------------
|
|
// The remaining faces adjacent to v different from inf(v).
|
|
Face_handle f0,f1,f2,f3;
|
|
if (e->sign()) { f0 = ul(e); f1 = dl(e); }
|
|
else {
|
|
f0 = dl(e); if (f0 == 0 || sup(f0) == v) f0 = dl(f);
|
|
f1 = dr(e);
|
|
}
|
|
if (f->sign()) {
|
|
f2 = ur(f); if (f2 == 0 || sup(f2) == v) f2 = ur(e);
|
|
f3 = ul(f);
|
|
}
|
|
else { f2 = dr(f); f3 = ul(f); }
|
|
// -------------------------------------------------------------------------
|
|
if (is_left_xx(v)) {
|
|
if (f4 != dl(ep) || f3 != ur(ep) || f0 != ul(ep)) return false;
|
|
}
|
|
else {
|
|
if (f0 != dl(ep) || f4 != dr(ep) || f3 != ul(ep)) return false;
|
|
}
|
|
if (is_xx_left(v)) {
|
|
if (f1 != dl(fp) || f2 != ur(fp) || f4 != ul(fp)) return false;
|
|
}
|
|
else {
|
|
if (f1 != dl(fp) || f2 != dr(fp) || f4 != ul(fp)) return false;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
return true;
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_swept_constraint(const Vertex_handle& v, Tr /*tr*/) const
|
|
{
|
|
// -------------------------------------------------------------------------
|
|
CGAL_precondition(v->is_constraint());
|
|
// -------------------------------------------------------------------------
|
|
// The operators used by this method
|
|
typename Tr::Sup sup;
|
|
typename Tr::Dl dl; typename Tr::Dr dr;
|
|
typename Tr::Ul ul; typename Tr::Ur ur;
|
|
typename Tr::Cw_source_edge cw_source_edge;
|
|
typename Tr::Cw_target_edge cw_target_edge;
|
|
typename Tr::Ccw_source_edge ccw_source_edge;
|
|
typename Tr::Ccw_target_edge ccw_target_edge;
|
|
typename Tr::Target_cusp_face target_cusp_face;
|
|
typename Tr::Source_cusp_face source_cusp_face;
|
|
typename Tr::Is_left_xx is_left_xx; typename Tr::Is_xx_left is_xx_left;
|
|
// -------------------------------------------------------------------------
|
|
// See is_swept_regular for the criterion. As sup(v) is not defined we check
|
|
// only point (2).
|
|
// -------------------------------------------------------------------------
|
|
// The four edges adjacent to v
|
|
Edge_handle e = cw_source_edge(v);
|
|
Edge_handle ep = ccw_source_edge(v);
|
|
Edge_handle f = cw_target_edge(v);
|
|
Edge_handle fp = ccw_target_edge(v);
|
|
if (e == 0 || ep == 0 || f == 0 || fp == 0) return false;
|
|
// -------------------------------------------------------------------------
|
|
// The four regular faces adjacent to v
|
|
Face_handle f0,f1,f2,f3;
|
|
if (e->sign()) {
|
|
if (ul(e) == 0 || ur(e) == 0) return false;
|
|
f0 = ul(e); f1 = dl(e);
|
|
}
|
|
else {
|
|
if (dl(e) == 0 || dr(e) == 0) return false;
|
|
f0 = dl(e); if (sup(f0) == v) f0 = dl(f); f1 = dr(e);
|
|
}
|
|
if (f->sign()) {
|
|
if (ul(f) == 0 || ur(f) == 0) return false;
|
|
f2 = ur(f); if (sup(f2) == v) f2 = ur(e); f3 = ul(f);
|
|
}
|
|
else {
|
|
if (dl(f) == 0 || dr(f) == 0) return false;
|
|
f2 = dr(f); f3 = ul(f);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// The four degenerate faces adjacent to v
|
|
Face_handle a = source_cusp_face(v);
|
|
Face_handle b = target_cusp_face(v);
|
|
Face_handle ap = source_cusp_face(v->pi());
|
|
Face_handle bp = target_cusp_face(v->pi());
|
|
if (a == 0 || b == 0 || ap == 0 || bp == 0) return false;
|
|
// -------------------------------------------------------------------------
|
|
// Updating the Edge <--> Face pointers for the two new edges of the
|
|
// antichain.
|
|
typename Vertex::Type_util type;
|
|
switch (type(is_left_xx(v),is_xx_left(v))) {
|
|
case Vertex::LL:
|
|
if (ap != dl(ep) || f3 != ur(ep) || bp != ul(ep)) return false;
|
|
if (f1 != dl(fp) || f2 != ur(fp) || f0 != ul(fp)) return false;
|
|
break;
|
|
case Vertex::RR:
|
|
if (f0 != dl(ep) || f2 != dr(ep) || f3 != ul(ep)) return false;
|
|
if (f1 != dl(fp) || ap != dr(fp) || bp != ul(fp)) return false;
|
|
break;
|
|
case Vertex::LR:
|
|
if (f2 != dl(ep) || f3 != ur(ep) || bp != ul(ep)) return false;
|
|
if (f1 != dl(fp) || ap != dr(fp) || f0 != ul(fp)) return false;
|
|
break;
|
|
case Vertex::RL:
|
|
if (f0 != dl(ep) || ap != dr(ep) || f3 != ul(ep)) return false;
|
|
if (f1 != dl(fp) || f2 != ur(fp) || bp != ul(fp)) return false;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
template < class Gtr_ , class It , class Flip >
|
|
template < class Tr>
|
|
bool
|
|
Antichain<Gtr_,It,Flip>::
|
|
is_swept(const Vertex_handle& v, Tr tr) const
|
|
{
|
|
if (!v->is_constraint()) return is_swept_regular(v,tr);
|
|
return (is_swept_constraint(v,tr) && is_swept_constraint(v->pi(),tr));
|
|
}
|
|
|
|
}
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif // CGAL_VISIBILITY_COMPLEX_2_ANTICHAIN_H
|