cgal/Visibility_complex/include/CGAL/Visibility_complex_function...

308 lines
13 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
#ifndef CGAL_VISIBILITY_COMPLEX_FUNCTION_OBJECTS
#define CGAL_VISIBILITY_COMPLEX_FUNCTION_OBJECTS
CGAL_BEGIN_NAMESPACE
// -----------------------------------------------------------------------------
template < class _Gtr >
struct Less_bitangent {
typedef typename _Gtr::Bitangent_2 Bitangent_2;
bool operator()(const Bitangent_2& a, const Bitangent_2& b) const {
// ---------------------------------------------------------------------
if (a == b) return false;
// ---------------------------------------------------------------------
// If this and b have the same source and target object we sometimes
// don't need to compute a determinant. This solves some degenerate
// cases.
if (a.source_object() == b.source_object() &&
a.target_object() == b.target_object()) {
if (a.is_right_left() || b.is_left_right()) return true;
if (a.is_left_right() || b.is_right_left()) return false;
// Case where the left-left and right-right bitangents are
// geometrically equal. Arbitrary choice ll < rr.
typename _Gtr::Equal_as_segments equal_as_segments;
if (equal_as_segments(a,b)) return (a.is_left_left());
}
// ---------------------------------------------------------------------
// Chi2 predicate from geometric traits class
typename _Gtr::Orientation_object orientation;
Orientation chi2ab = orientation(a,b);
// ---------------------------------------------------------------------
// Non degenerate cases.
if (chi2ab == RIGHT_TURN){ return false;}
if (chi2ab == LEFT_TURN) { return true; }
// ---------------------------------------------------------------------
// Treatment of degenerate case when two bitangents are parallel.
// ---------------------------------------------------------------------
typename _Gtr::Is_upward_directed is_upward_directed;
bool upa = is_upward_directed(a);
bool upb = is_upward_directed(b);
// ---------------------------------------------------------------------
// Treating the case where a and b do not have the same angle.
// Their angle difference is \pi
if (!upa && upb) return false;
else if (upa && !upb) return true;
// Now a and b have the same angle
// ---------------------------------------------------------------------
// a and b have distinct types
if (a.type() != b.type()) {
if (a.is_right_left() || b.is_left_right()) return true;
if (a.is_left_right() || b.is_right_left()) return false;
return (a.is_left_left());
}
// ---------------------------------------------------------------------
// Final case : a and b have the same angle and same type
typename _Gtr::Orientation_infinite chi3;
Orientation op = chi3(a,b);
if (op == RIGHT_TURN) return false;
else if (op == LEFT_TURN) return true;
else {
if (a.target_object() == b.source_object() &&
a.is_xx_left() == b.is_left_xx()) return a.is_xx_left();
if (a.source_object() == b.target_object() &&
a.is_left_xx() == b.is_xx_left()) return a.is_right_xx();
typename _Gtr::Compare_extreme_yx compare;
if (a.target_object() == b.target_object()) // a or b is not free
return (compare(a.is_left_xx(),*a.source_object(),
b.is_left_xx(),*b.source_object()) == LARGER);
if (a.source_object() == b.source_object()) // a or b is not free
return (compare(a.is_left_xx(),*a.source_object(),
b.is_left_xx(),*b.source_object()) == SMALLER);
Comparison_result cmp;
if (upa) cmp = compare(a.is_xx_left(),*a.target_object(),
b.is_xx_left(),*b.target_object());
else cmp = compare(!b.is_left_xx(),*b.source_object(),
!a.is_left_xx(),*a.source_object());
CGAL_precondition(cmp != EQUAL);
return (a.is_xx_right()) ? (cmp == LARGER) : (cmp == SMALLER);
}
// ---------------------------------------------------------------------
}
};
template < class _Gtr >
struct Greater_bitangent {
typedef typename _Gtr::Bitangent_2 Bitangent_2;
bool operator()(const Bitangent_2& a, const Bitangent_2& b) {
if (a == b) return false;
return Less_bitangent<_Gtr>()(b,a);
}
};
// -----------------------------------------------------------------------------
template <class _Gtr>
class Less_object {
private:
// -------------------------------------------------------------------------
typedef typename _Gtr::Disk Disk;
typedef typename _Gtr::Bitangent_2 Bitangent_2;
typedef Bitangent_2 BT;
typedef typename _Gtr::Is_upward_directed Is_upward_directed;
typedef typename _Gtr::Compare_extreme_yx Compare;
typedef typename _Gtr::Orientation_infinite Orientation_infinite;
// -------------------------------------------------------------------------
public:
// -------------------------------------------------------------------------
bool operator() (const Disk& o1, const Disk& o2) const {
// ---------------------------------------------------------------------
if (&o1 == &o2) return false;
BT rl(BT::RL,&o1,&o2);
return !Is_upward_directed()(rl);
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
bool operator() (const Disk& o, const Bitangent_2& b) const {
// ---------------------------------------------------------------------
Is_upward_directed is_upward_directed;
CGAL_precondition(is_upward_directed(b));
// ---------------------------------------------------------------------
// o is the source or target object of b.
if (b.source_object() == &o) return b.is_left_xx();
if (b.target_object() == &o) return b.is_xx_left();
// ---------------------------------------------------------------------
// Otherwise o and b involve three convex objects.
Comparison_result cmp = Compare()(false,o,false,b);
CGAL_precondition(cmp != EQUAL);
Orientation_infinite chi3;
if (cmp == SMALLER) return (chi3(b,o) == LEFT_TURN);
else return (chi3(o,b) == RIGHT_TURN);
// Find somtething better than the above not using chi3...
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
bool operator() (const Bitangent_2& b, const Disk& o) const
{ return !operator()(o,b); }
// -------------------------------------------------------------------------
bool operator() (const Bitangent_2& b1, const Bitangent_2& b2) const {
// ---------------------------------------------------------------------
if (b1 == b2) return false;
// ---------------------------------------------------------------------
Is_upward_directed is_upward_directed;
CGAL_precondition(is_upward_directed(b1));
CGAL_precondition(is_upward_directed(b2));
// ---------------------------------------------------------------------
// b1 and b2 involve two objects
if ((b1.source_object() == b2.source_object() &&
b1.target_object() == b2.target_object()) ||
(b1.source_object() == b2.target_object() &&
b1.target_object() == b2.source_object()))
return (b1.is_right_right() || b2.is_left_left());
// ---------------------------------------------------------------------
// Some cases when b1 and b2 involve three objects
//if (b1.target_object() == b2.source_object()) return b2.is_left_xx();
//if (b1.source_object() == b2.target_object()) return b1.is_right_xx();
Less_bitangent<_Gtr> chi1;
if (b1.target_object() == b2.target_object()) {
if (b1.is_xx_left() == b2.is_xx_left()) return chi1(b1,b2);
else return b1.is_xx_right();
}
if (b1.source_object() == b2.source_object()) {
if (b1.is_left_xx() == b2.is_left_xx()) return chi1(b2,b1);
else return b1.is_right_xx();
}
// ---------------------------------------------------------------------
// The remaining cases.
Comparison_result cmp = Compare()(false,b1,false,b2);
CGAL_precondition(cmp != EQUAL);
Orientation_infinite chi3;
if (cmp == SMALLER) return (chi3(b2,b1) == LEFT_TURN);
else return (chi3(b1,b2) == RIGHT_TURN);
// Find somtething better than the above not using chi3...
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
};
// -----------------------------------------------------------------------------
template < class _Vc >
struct Less_face_handle {
template < class Face_handle >
bool operator() (const Face_handle& e1, const Face_handle& e2) const {
if (e1 == e2 || e1->front_view() == 0) return false;
if (e2->front_view() == 0) return true;
typedef typename _Vc::Gt _Gtr;
typedef typename _Vc::Edge_handle Edge_handle;
Edge_handle e = e1->front_view();
Edge_handle f = e2->front_view();
if (e->object() == 0 && f->object() == 0)
return Less_object<_Gtr>()(*e->sup(),*f->sup());
else if (e->object() == 0 && f->object() != 0)
return Less_object<_Gtr>()(*e->sup(),*f->object());
else if (e->object() != 0 && f->object() == 0)
return Less_object<_Gtr>()(*e->object(),*f->sup());
return Less_object<_Gtr>()(*e->object(), *f->object());
}
};
// -----------------------------------------------------------------------------
template < class _Vc >
struct Do_intersect {
template < class Edge_handle >
bool operator()(const Edge_handle& e, const Edge_handle& f) const {
if (e == 0 || f == 0) return false;
typedef typename _Vc::Gt Gt;
typename Gt::Do_intersect do_intersect;
if (e->object() == 0 && f->object() == 0)
return do_intersect(*e->sup(),*f->sup());
if (e->object() != 0 && f->object() == 0)
return do_intersect(*e->object(),*f->sup());
if (e->object() == 0 && f->object() != 0)
return do_intersect(*e->sup(),*f->object());
return do_intersect(*e->object(),*f->object());
}
};
// -----------------------------------------------------------------------------
template < class _Gtr >
struct Less_edge_handle {
typedef bool result_type;
template < class Edge_handle >
bool operator () (const Edge_handle& e1, const Edge_handle& e2) const
{
// ---------------------------------------------------------------------
// Trivial cases not needing geometry
if (e1 == e2) { return false; }
if (e1->object() != 0 && e1->object() == e2->object())
return (e1->sign() && !e2->sign());
// ---------------------------------------------------------------------
// Otherwise use predicate from geometric traits class
// to compare lexicographically the base points
typename _Gtr::Compare_extreme_yx compare;
Comparison_result cmp;
if (e1->object() != 0) {
if (e2->object() != 0) cmp = compare(e1->sign(),*e1->object(),
e2->sign(),*e2->object());
else cmp = compare(e1->sign(),*e1->object(),
e2->sign(),*e2->sup());
}
else {
if (e2->object() != 0) cmp = compare(e1->sign(),*e1->sup(),
e2->sign(),*e2->object());
else cmp = compare(e1->sign(),*e1->sup(),
e2->sign(),*e2->sup());
}
// ---------------------------------------------------------------------
// distinct base points
if (cmp != EQUAL) return (cmp == SMALLER) ? true : false;
// ---------------------------------------------------------------------
// equal base points and e1 or e2 is a constraint edge
if (e1->object() != 0 && e2->object() == 0) return e1->sign();
if (e1->object() == 0 && e2->object() != 0) return !e2->sign();
if (e1->object() == 0 && e2->object() == 0) {
bool e1_is_left = (( e1->sign() && e1->sup()->is_left_xx()) ||
(!e1->sign() && e1->sup()->is_xx_left()));
bool e2_is_left = (( e2->sign() && e2->sup()->is_left_xx()) ||
(!e2->sign() && e2->sup()->is_xx_left()));
if (e1_is_left && !e2_is_left) return true;
if (!e1_is_left && e2_is_left) return false;
Less_bitangent<_Gtr> chi2;
if (e1_is_left && e2_is_left) {
if (*e1->sup() == *e2->sup())
return (long(e1->sup()) < long(e2->sup()));
return chi2(*e1->sup(),*e2->sup());
}
if (!e1_is_left && !e2_is_left) {
if (*e1->sup() == *e2->sup())
return (long(e2->sup()) < long(e1->sup()));
return chi2(*e2->sup(),*e1->sup());
}
}
// ---------------------------------------------------------------------
// equal base points and e1, e2 are regular edges
return Less_object<_Gtr>()(*e1->object(),*e2->object());
// ---------------------------------------------------------------------
}
};
// -----------------------------------------------------------------------------
CGAL_END_NAMESPACE
#endif // VISIBILITY_COMPLEX_FUNCTION_OBJECTS