Public source code release

This commit is contained in:
YTKAB0BP
2024-11-01 08:28:55 +03:00
parent 20b730b1c8
commit 0b2ba24c7f
6691 changed files with 2325292 additions and 1 deletions
@@ -0,0 +1,202 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_AABB_FACE_GRAPH_TRIANGLE_PRIMITIVE_H
#define CGAL_AABB_FACE_GRAPH_TRIANGLE_PRIMITIVE_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/AABB_primitive.h>
#include <CGAL/boost/graph/property_maps.h>
#include <CGAL/Default.h>
#include <boost/mpl/if.hpp>
namespace CGAL {
/*!
* \ingroup PkgAABBTreeRef
* Primitive type for a facet of a polyhedral surface.
* It wraps a handle to a facet of a polyhedron to a 3D triangle.
* The polyhedron from which the primitive is built should not be deleted
* while the AABB tree holding the primitive is in use.
* The triangle type of the primitive (`Datum`) is `CGAL::Kernel_traits< boost::property_traits< VertexPointPMap >::%value_type >::%Kernel::Triangle_3`.
*
* \cgalModels `AABBPrimitiveWithSharedData`
*
*\tparam FaceGraph is a model of the face graph concept.
*\tparam VertexPointPMap is a property map with `boost::graph_traits<FaceGraph>::%vertex_descriptor`
* as key type and a \cgal Kernel `Point_3` as value type.
* The default is `typename boost::property_map< FaceGraph,vertex_point_t>::%const_type`.
*\tparam OneFaceGraphPerTree is either `CGAL::Tag_true` or `CGAL::Tag_false`.
* In the former case, we guarantee that all the primitives will be from a
* common `FaceGraph` and some data will be factorized so that the size of
* the primitive is reduced. In the latter case, the primitives can be from
* different graphs and extra storage is required in the primitives. The default is `CGAL::Tag_true`.
*\tparam CacheDatum is either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former case, the datum is stored
* in the primitive, while in the latter it is constructed on the fly to reduce the memory footprint.
* The default is `CGAL::Tag_false` (datum is not stored).
*\sa `AABBPrimitive`
*\sa `AABB_primitive<Id,ObjectPropertyMap,PointPropertyMapPolyhedron,ExternalPropertyMaps,CacheDatum>`
*\sa `AABB_halfedge_graph_segment_primitive<HalfedgeGraph,OneHalfedgeGraphPerTree,CacheDatum>`
*/
template < class FaceGraph,
class VertexPointPMap = Default,
class OneFaceGraphPerTree = Tag_true,
class CacheDatum=Tag_false >
class AABB_face_graph_triangle_primitive
#ifndef DOXYGEN_RUNNING
: public AABB_primitive<typename boost::mpl::if_<OneFaceGraphPerTree,
typename boost::graph_traits<FaceGraph>::face_descriptor,
std::pair<typename boost::graph_traits<FaceGraph>::face_descriptor, const FaceGraph*> >::type,
Triangle_from_face_descriptor_map<
FaceGraph,
typename Default::Get<VertexPointPMap,
typename boost::property_map< FaceGraph,
vertex_point_t>::const_type >::type>,
One_point_from_face_descriptor_map<
FaceGraph,
typename Default::Get<VertexPointPMap,
typename boost::property_map< FaceGraph,
vertex_point_t>::const_type >::type>,
OneFaceGraphPerTree,
CacheDatum >
#endif
{
typedef typename Default::Get<VertexPointPMap, typename boost::property_map< FaceGraph, vertex_point_t>::const_type >::type VertexPointPMap_;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor FD;
typedef typename boost::mpl::if_<OneFaceGraphPerTree, FD, std::pair<FD, const FaceGraph*> >::type Id_;
typedef Triangle_from_face_descriptor_map<FaceGraph,VertexPointPMap_> Triangle_property_map;
typedef One_point_from_face_descriptor_map<FaceGraph,VertexPointPMap_> Point_property_map;
typedef AABB_primitive< Id_,
Triangle_property_map,
Point_property_map,
OneFaceGraphPerTree,
CacheDatum > Base;
FD make_id(FD fd, const FaceGraph&, Tag_true)
{
return fd;
}
std::pair<FD, const FaceGraph*> make_id(FD fd, const FaceGraph& fg, Tag_false)
{
return std::make_pair(fd, &fg);
}
public:
#ifdef DOXYGEN_RUNNING
/// \name Types
/// @{
/*!
The point type.
*/
typedef boost::property_traits<VertexPointPMap>::value_type Point;
/*!
Geometric data type.
*/
typedef Kernel_traits<Point>::Kernel::Triangle_3 Datum;
/*!
Id type:
- `boost::graph_traits<FaceGraph>::%face_descriptor` if `OneFaceGraphPerTree` is `CGAL::Tag_true`
- `std::pair<boost::graph_traits<FaceGraph>::%face_descriptor, const FaceGraph*>` if `OneFaceGraphPerTree` is `CGAL::Tag_false`
*/
unspecified_type Id;
/// @}
/*!
If `OneFaceGraphPerTree` is CGAL::Tag_true, constructs a `Shared_data` object from a reference to the polyhedon `graph`.
*/
static unspecified_type construct_shared_data( FaceGraph& graph );
#else
typedef typename Base::Id Id;
#endif
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
// constructors
#ifdef DOXYGEN_RUNNING
/*!
constructs a primitive.
\tparam Iterator an input iterator with `Id` as value type.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `get(vertex_point, graph)`.
*/
template <class Iterator>
AABB_face_graph_triangle_primitive(Iterator it, const FaceGraph& graph, VertexPointPMap vppm);
/*!
constructs a primitive.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `get(vertex_point, graph)`.
*/
AABB_face_graph_triangle_primitive(face_descriptor fd, const FaceGraph& graph, VertexPointPMap vppm);
#else
template <class Iterator>
AABB_face_graph_triangle_primitive(Iterator it, const FaceGraph& graph, VertexPointPMap_ vppm)
: Base( Id_(make_id(*it, graph, OneFaceGraphPerTree())),
Triangle_property_map(const_cast<FaceGraph*>(&graph),vppm),
Point_property_map(const_cast<FaceGraph*>(&graph),vppm) )
{}
AABB_face_graph_triangle_primitive(face_descriptor fd, const FaceGraph& graph, VertexPointPMap_ vppm)
: Base( Id_(make_id(fd, graph, OneFaceGraphPerTree())),
Triangle_property_map(const_cast<FaceGraph*>(&graph),vppm),
Point_property_map(const_cast<FaceGraph*>(&graph),vppm) )
{}
template <class Iterator>
AABB_face_graph_triangle_primitive(Iterator it, const FaceGraph& graph)
: Base( Id_(make_id(*it, graph, OneFaceGraphPerTree())),
Triangle_property_map(const_cast<FaceGraph*>(&graph)),
Point_property_map(const_cast<FaceGraph*>(&graph)) )
{}
AABB_face_graph_triangle_primitive(face_descriptor fd, const FaceGraph& graph)
: Base( Id_(make_id(fd, graph, OneFaceGraphPerTree())),
Triangle_property_map(const_cast<FaceGraph*>(&graph)),
Point_property_map(const_cast<FaceGraph*>(&graph)) )
{}
#endif
/// \internal
typedef internal::Cstr_shared_data<FaceGraph, Base, Triangle_property_map, Point_property_map, OneFaceGraphPerTree> Cstr_shared_data;
/// \internal
static
typename Cstr_shared_data::Shared_data
construct_shared_data(const FaceGraph& graph)
{
return Cstr_shared_data::construct_shared_data(const_cast<FaceGraph&>(graph));
}
static
typename Cstr_shared_data::Shared_data
construct_shared_data(const FaceGraph& graph, const VertexPointPMap_& vpm)
{
return Cstr_shared_data::construct_shared_data(const_cast<FaceGraph&>(graph), vpm);
}
};
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_FACE_GRAPH_TRIANGLE_PRIMITIVE_H
@@ -0,0 +1,211 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_AABB_HALFEDGE_GRAPH_SEGMENT_PRIMITIVE_H
#define CGAL_AABB_HALFEDGE_GRAPH_SEGMENT_PRIMITIVE_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/AABB_primitive.h>
#include <CGAL/boost/graph/property_maps.h>
#include <iterator>
#include <boost/mpl/and.hpp>
#include <CGAL/is_iterator.h>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/if.hpp>
#include <CGAL/Default.h>
namespace CGAL {
/*!
* \ingroup PkgAABBTreeRef
* Primitive type for a edge of a polyhedral surface.
* It wraps an `edge_descriptor` into a 3D segment.
* The class model of `HalfedgeGraph` from which the primitive is built should not be deleted
* while the AABB tree holding the primitive is in use.
* The type of the 3D segment is taken from the kernel of the point type which is the value type
* of `VertexPointPMap` (using the `Kernel_traits` mechanism).
* The segment type of the primitive (`Datum`) is `CGAL::Kernel_traits< boost::property_traits< VertexPointPMap >::%value_type >::%Kernel::Segment_3`.
*
* \cgalModels `AABBPrimitive` if `OneHalfedgeGraphPerTree` is `CGAL::Tag_false`,
* and `AABBPrimitiveWithSharedData` if `OneHalfedgeGraphPerTree` is `CGAL::Tag_true`.
*
* \tparam HalfedgeGraph is a model of the halfedge graph concept.
* as key type and a \cgal Kernel `Point_3` as value type.
* \tparam VertexPointPMap is a property map with `boost::graph_traits<HalfedgeGraph>::%vertex_descriptor`.
* The default is `typename boost::property_map< HalfedgeGraph,vertex_point_t>::%const_type`.
* \tparam OneHalfedgeGraphPerTree is either `CGAL::Tag_true` or `CGAL::Tag_false`.
* In the former case, we guarantee that all the primitives will be from a
* common `HalfedgeGraph` and some data will be factorized so that the size of
* the primitive is reduced. In the latter case, the primitives can be from
* different graphs and extra storage is required in the primitives. The default is `CGAL::Tag_true`.
* \tparam CacheDatum is either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former case, the datum is
* stored in the primitive, while in the latter it is constructed on the fly to reduce
* the memory footprint. The default is `CGAL::Tag_false` (datum is not stored).
*
* \sa `AABBPrimitive`
* \sa `AABB_primitive<Id,ObjectPropertyMap,PointPropertyMapPolyhedron,ExternalPropertyMaps,CacheDatum>`
* \sa `AABB_face_graph_triangle_primitive<FaceGraph,OneFaceGraphPerTree,CacheDatum>`
* \sa \link BGLPolyGT `boost::graph_traits<Polyhedron>` \endlink
*/
template < class HalfedgeGraph,
class VertexPointPMap = Default,
class OneHalfedgeGraphPerTree = Tag_true,
class CacheDatum = Tag_false >
class AABB_halfedge_graph_segment_primitive
#ifndef DOXYGEN_RUNNING
: public AABB_primitive< typename boost::mpl::if_<OneHalfedgeGraphPerTree,
typename boost::graph_traits<HalfedgeGraph>::edge_descriptor,
std::pair<typename boost::graph_traits<HalfedgeGraph>::edge_descriptor, const HalfedgeGraph*> >::type,
Segment_from_edge_descriptor_map<
HalfedgeGraph,
typename Default::Get<VertexPointPMap,
typename boost::property_map< HalfedgeGraph,
vertex_point_t>::const_type >::type >,
Source_point_from_edge_descriptor_map<
HalfedgeGraph,
typename Default::Get<VertexPointPMap,
typename boost::property_map< HalfedgeGraph,
vertex_point_t>::const_type >::type >,
OneHalfedgeGraphPerTree,
CacheDatum >
#endif
{
typedef typename Default::Get<VertexPointPMap,typename boost::property_map< HalfedgeGraph,vertex_point_t>::const_type >::type VertexPointPMap_;
typedef typename boost::graph_traits<HalfedgeGraph>::edge_descriptor ED;
typedef typename boost::mpl::if_<OneHalfedgeGraphPerTree, ED, std::pair<ED, const HalfedgeGraph*> >::type Id_;
typedef Segment_from_edge_descriptor_map<HalfedgeGraph,VertexPointPMap_> Segment_property_map;
typedef Source_point_from_edge_descriptor_map<HalfedgeGraph,VertexPointPMap_> Point_property_map;
typedef AABB_primitive< Id_,
Segment_property_map,
Point_property_map,
OneHalfedgeGraphPerTree,
CacheDatum > Base;
ED make_id(ED ed, const HalfedgeGraph&, Tag_true)
{
return ed;
}
std::pair<ED, const HalfedgeGraph*> make_id(ED ed, const HalfedgeGraph& fg, Tag_false)
{
return std::make_pair(ed, &fg);
}
public:
#ifdef DOXYGEN_RUNNING
/// \name Types
/// @{
/*!
The point type.
*/
typedef boost::property_traits< boost::property_map< HalfedgeGraph, vertex_point_t>::const_type >::value_type Point;
/*!
Geometric data type.
*/
typedef Kernel_traits<Point>::Kernel::Segment_3 Datum;
/*!
Id type:
- `boost::graph_traits<HalfedgeGraph>::%edge_descriptor` if `OneHalfedgeGraphPerTree` is `Tag_true`
- `std::pair<boost::graph_traits<HalfedgeGraph>::%edge_descriptor, const HalfedgeGraph*>` if `OneHalfedgeGraphPerTree` is `Tag_false`
*/
unspecified_type Id;
/// @}
/*!
If `OneHalfedgeGraphPerTree` is CGAL::Tag_true, constructs a `Shared_data` object from a reference to the halfedge graph.
*/
static unspecified_type construct_shared_data( HalfedgeGraph& graph );
#else
typedef typename Base::Id Id;
#endif
typedef typename boost::graph_traits<HalfedgeGraph>::edge_descriptor edge_descriptor;
#ifdef DOXYGEN_RUNNING
/*!
constructs a primitive.
\tparam Iterator is an input iterator with `Id` as value type.
This \ref AABB_tree/AABB_halfedge_graph_edge_example.cpp "example" gives a way to call this constructor
using the insert-by-range method of the class `AABB_tree<Traits>`.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `boost::get(vertex_point, graph)`.
*/
template <class Iterator>
AABB_halfedge_graph_segment_primitive(Iterator it, const HalfedgeGraph& graph, VertexPointPMap vppm);
/*!
constructs a primitive.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `boost::get(vertex_point, graph)`.
*/
AABB_halfedge_graph_segment_primitive(edge_descriptor ed, const HalfedgeGraph& graph, VertexPointPMap vppm);
#else
template <class Iterator>
AABB_halfedge_graph_segment_primitive(Iterator it, const HalfedgeGraph& graph, VertexPointPMap_ vppm)
: Base( Id_(make_id(*it, graph, OneHalfedgeGraphPerTree())),
Segment_property_map(const_cast<HalfedgeGraph*>(&graph), vppm),
Point_property_map(const_cast<HalfedgeGraph*>(&graph), vppm) )
{}
AABB_halfedge_graph_segment_primitive(edge_descriptor ed, const HalfedgeGraph& graph, VertexPointPMap_ vppm)
: Base( Id_(make_id(ed, graph, OneHalfedgeGraphPerTree())),
Segment_property_map(const_cast<HalfedgeGraph*>(&graph), vppm),
Point_property_map(const_cast<HalfedgeGraph*>(&graph), vppm) )
{}
template <class Iterator>
AABB_halfedge_graph_segment_primitive(Iterator it, const HalfedgeGraph& graph)
: Base( Id_(make_id(*it, graph, OneHalfedgeGraphPerTree())),
Segment_property_map(const_cast<HalfedgeGraph*>(&graph)),
Point_property_map(const_cast<HalfedgeGraph*>(&graph)) ){}
AABB_halfedge_graph_segment_primitive(edge_descriptor ed, const HalfedgeGraph& graph)
: Base( Id_(make_id(ed, graph, OneHalfedgeGraphPerTree())),
Segment_property_map(const_cast<HalfedgeGraph*>(&graph)),
Point_property_map(const_cast<HalfedgeGraph*>(&graph)) ){}
#endif
/// \internal
typedef internal::Cstr_shared_data<HalfedgeGraph, Base, Segment_property_map, Point_property_map, OneHalfedgeGraphPerTree> Cstr_shared_data;
/// \internal
static
typename Cstr_shared_data::Shared_data
construct_shared_data(const HalfedgeGraph& graph)
{
return Cstr_shared_data::construct_shared_data(const_cast<HalfedgeGraph&>(graph));
}
static
typename Cstr_shared_data::Shared_data
construct_shared_data(const HalfedgeGraph& graph, const VertexPointPMap_& vpm)
{
return Cstr_shared_data::construct_shared_data(const_cast<HalfedgeGraph&>(graph), vpm);
}
};
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_HALFEDGE_GRAPH_SEGMENT_PRIMITIVE_H
@@ -0,0 +1,159 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Pierre Alliez, Stephane Tayeb
//
//******************************************************************************
// File Description :
//
//******************************************************************************
#ifndef CGAL_AABB_POLYHEDRON_SEGMENT_PRIMITIVE_H_
#define CGAL_AABB_POLYHEDRON_SEGMENT_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#define CGAL_DEPRECATED_HEADER "<CGAL/AABB_polyhedron_segment_primitive.h>"
#define CGAL_REPLACEMENT_HEADER "<CGAL/AABB_halfedge_graph_segment_primitive.h>"
#include <CGAL/Installation/internal/deprecation_warning.h>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
namespace CGAL {
/// \addtogroup PkgAABBTreeRef
/// @{
/// \deprecated This class is deprecated since \cgal 4.3, the class
/// `AABB_halfedge_graph_segment_primitive` should be used instead.
///
/// Primitive type that wraps a halfedge handle of a
/// polyhedron, which is used as id, and allows the construction
/// of the datum on the fly. Since only the halfedge handle is
/// stored in this primitive, the polyhedron from which the
/// AABB tree is built should not be deleted while the AABB tree
/// is in use.
///
/// \cgalModels `AABBPrimitive`
/// \tparam GeomTraits must provide a \c %Point_3
/// type, used as \c Point, and a \c %Segment_3 type, used as \c
/// Datum and constructible from two arguments of type \c
/// Point.
/// \tparam Polyhedron must be a
/// \c CGAL::Polyhedron_3 whose points have type \c Point.
///
/// \sa `AABBPrimitive`
/// \sa `AABB_polyhedron_triangle_primitive`
template<typename GeomTraits, typename Polyhedron>
class AABB_polyhedron_segment_primitive
{
public:
// AABBTrianglePrimitive types
typedef typename GeomTraits::Point_3 Point;
/// \name Types
/// @{
/// Geometric data type.
typedef typename GeomTraits::Segment_3 Datum;
/// Id type.
typedef typename Polyhedron::Halfedge_handle Id;
/// @}
// Self
typedef AABB_polyhedron_segment_primitive<GeomTraits,Polyhedron> Self;
// Constructor
AABB_polyhedron_segment_primitive() {}
AABB_polyhedron_segment_primitive(const Id& handle)
: m_halfedge_handle(handle) { };
AABB_polyhedron_segment_primitive(const Id* ptr)
: m_halfedge_handle(*ptr) { };
template <class Iterator>
AABB_polyhedron_segment_primitive( Iterator it,
typename boost::enable_if<
boost::is_same<Id,typename Iterator::value_type>
>::type* =0
) : m_halfedge_handle(*it) { }
AABB_polyhedron_segment_primitive(const Self& primitive)
: m_halfedge_handle(primitive.m_halfedge_handle) {}
// Default destructor, copy constructor and assignment operator are ok
// Returns by constructing on the fly the geometric datum wrapped by the primitive
Datum datum() const
{
const Point& a = m_halfedge_handle->vertex()->point();
const Point& b = m_halfedge_handle->opposite()->vertex()->point();
return Datum(a,b); // returns a 3D segment
}
// Returns the identifier
Id& id() { return m_halfedge_handle; }
const Id& id() const { return m_halfedge_handle; }
// Returns a point on the primitive
Point reference_point() const
{
return m_halfedge_handle->vertex()->point();
}
private:
// Id, here a polyhedron halfedge handle
Id m_halfedge_handle;
}; // end class AABB_polyhedron_segment_primitive
///@}
template<typename GeomTraits, typename Polyhedron>
class AABB_const_polyhedron_edge_primitive
{
public:
/// AABBTrianglePrimitive types
typedef typename GeomTraits::Point_3 Point;
typedef typename GeomTraits::Segment_3 Datum;
typedef typename Polyhedron::Halfedge_const_handle Id;
/// Constructor
AABB_const_polyhedron_edge_primitive(const Id& handle)
: m_halfedge_handle(handle) { };
// Default destructor, copy constructor and assignment operator are ok
/// Returns by constructing on the fly the geometric datum wrapped by the primitive
Datum datum() const
{
const Point& a = m_halfedge_handle->vertex()->point();
const Point& b = m_halfedge_handle->opposite()->vertex()->point();
return Datum(a,b); // returns a 3D segment
}
/// Returns the identifier
const Id id() const { return m_halfedge_handle; }
/// Returns a point on the primitive
Point reference_point() const
{
return m_halfedge_handle->vertex()->point();
}
private:
/// Id, here a polyhedron halfedge handle
Id m_halfedge_handle;
}; // end class AABB_const_polyhedron_edge_primitive
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_POLYHEDRON_SEGMENT_PRIMITIVE_H_
@@ -0,0 +1,155 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Stéphane Tayeb, Pierre Alliez
//
#ifndef CGAL_AABB_POLYHEDRON_TRIANGLE_PRIMITIVE_H_
#define CGAL_AABB_POLYHEDRON_TRIANGLE_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#define CGAL_DEPRECATED_HEADER "<CGAL/AABB_polyhedron_triangle_primitive.h>"
#define CGAL_REPLACEMENT_HEADER "<CGAL/AABB_face_graph_triangle_primitive.h>"
#include <CGAL/Installation/internal/deprecation_warning.h>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
namespace CGAL {
/// \ingroup PkgAABBTreeRef
/// \deprecated This class is deprecated since \cgal 4.3, the class
/// `AABB_face_graph_triangle_primitive` should be used instead.
///
/// Primitive type that wraps a facet handle of a polyhedron,
/// which is used as id, and allows the construction of the datum on
/// the fly. Since only the facet handle is stored in this primitive,
/// the polyhedron from which the AABB tree is built should not be
/// deleted while the AABB tree is in use.
///
/// \cgalModels `AABBPrimitive`
/// \tparam GeomTraits must provides a \c %Point_3
/// type, used as \c Point, and a \c %Triangle_3 type, used as \c
/// Datum and constructible from three arguments of type \c
/// Point.
/// \tparam Polyhedron must be a
/// \c CGAL::Polyhedron_3 whose points have type \c Point.
///
/// \sa `AABBPrimitive`
/// \sa `AABB_polyhedron_segment_primitive`
template<typename GeomTraits, typename Polyhedron>
class AABB_polyhedron_triangle_primitive
{
public:
typedef typename GeomTraits::Point_3 Point;
/// \name Types
/// @{
/// Id type.
typedef typename Polyhedron::Facet_handle Id;
/// Geometric data type.
typedef typename GeomTraits::Triangle_3 Datum;
/// @}
// Self
typedef AABB_polyhedron_triangle_primitive<GeomTraits, Polyhedron> Self;
// Constructors
AABB_polyhedron_triangle_primitive() {}
AABB_polyhedron_triangle_primitive(const AABB_polyhedron_triangle_primitive& primitive)
{
m_facet_handle = primitive.id();
}
AABB_polyhedron_triangle_primitive(const Id& handle)
: m_facet_handle(handle) { };
AABB_polyhedron_triangle_primitive(const Id* ptr)
: m_facet_handle(*ptr) { };
template <class Iterator>
AABB_polyhedron_triangle_primitive( Iterator it,
typename boost::enable_if<
boost::is_same<Id,typename Iterator::value_type>
>::type* =0
) : m_facet_handle(*it) { }
// Default destructor, copy constructor and assignment operator are ok
// Returns by constructing on the fly the geometric datum wrapped by the primitive
Datum datum() const
{
const Point& a = m_facet_handle->halfedge()->vertex()->point();
const Point& b = m_facet_handle->halfedge()->next()->vertex()->point();
const Point& c = m_facet_handle->halfedge()->next()->next()->vertex()->point();
return Datum(a,b,c);
}
// Returns a point on the primitive
Point reference_point() const
{
return m_facet_handle->halfedge()->vertex()->point();
}
// Returns the identifier
const Id& id() const { return m_facet_handle; }
Id& id() { return m_facet_handle; }
private:
/// The id, here a polyhedron facet handle
Id m_facet_handle;
}; // end class AABB_polyhedron_triangle_primitive
template<typename GeomTraits, typename Polyhedron>
class AABB_const_polyhedron_triangle_primitive
{
public:
/// AABBPrimitive types
typedef typename GeomTraits::Point_3 Point;
typedef typename GeomTraits::Triangle_3 Datum;
typedef typename Polyhedron::Facet_const_handle Id;
/// Constructors
AABB_const_polyhedron_triangle_primitive(const Id& handle)
: m_facet_handle(handle) { };
// Default destructor, copy constructor and assignment operator are ok
/// Returns by constructing on the fly the geometric datum wrapped by the primitive
Datum datum() const
{
const Point& a = m_facet_handle->halfedge()->vertex()->point();
const Point& b = m_facet_handle->halfedge()->next()->vertex()->point();
const Point& c = m_facet_handle->halfedge()->next()->next()->vertex()->point();
return Datum(a,b,c);
}
/// Returns a point on the primitive
Point reference_point() const
{
return m_facet_handle->halfedge()->vertex()->point();
}
/// Returns the identifier
Id id() const { return m_facet_handle; }
private:
/// The id, here a polyhedron facet handle
Id m_facet_handle;
}; // end class AABB_polyhedron_triangle_primitive
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_POLYHEDRON_TRIANGLE_PRIMITIVE_H_
+254
View File
@@ -0,0 +1,254 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_AABB_PRIMITIVE_H
#define CGAL_AABB_PRIMITIVE_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
#include <CGAL/property_map.h>
#include <CGAL/tags.h>
namespace CGAL {
//class for the typedefs
template < class Id_,
class ObjectPropertyMap,
class PointPropertyMap >
struct AABB_primitive_base
{
typedef typename boost::property_traits< ObjectPropertyMap >::value_type Datum; //datum type
typedef typename boost::property_traits< PointPropertyMap >::value_type Point; //point type
typedef typename boost::property_traits< ObjectPropertyMap >::reference Datum_reference; //reference datum type
typedef typename boost::property_traits< PointPropertyMap >::reference Point_reference; //reference point type
typedef Id_ Id; // Id type
protected:
Id m_id;
public:
// constructors
AABB_primitive_base(Id id) : m_id(id) {}
Id id() const {return m_id;}
};
#ifdef DOXYGEN_RUNNING
/*!
* \ingroup PkgAABBTreeRef
* Generic primitive type.
* The two property maps which are template parameters of the class enable to get the datum and the reference point of
* the primitive from the identifier. The last template parameter controls whether the primitive class holds a copy of the datum.
*
* \cgalModels `AABBPrimitive` if `ExternalPropertyMaps` is `CGAL::Tag_false`,
* and `AABBPrimitiveWithSharedData` if `ExternalPropertyMaps` is `CGAL::Tag_true`.
*
*
* \tparam ObjectPropertyMap is a model of `ReadablePropertyMap` with `Id` as
* `key_type`. It must be a model of `CopyConstructible`, `DefaultConstructible`, and `CopyAssignable`.
* \tparam PointPropertyMap is a model of `ReadablePropertyMap` with `Id` as
* `key_type`. It must be a model of `CopyConstructible`, `DefaultConstructible`, and `CopyAssignable`.
* \tparam ExternalPropertyMaps either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former
* case, the property maps will be stored in the traits class, while
* in the latter they will be stored in the primitive
* (which increases the size of each primitive).
* \tparam CacheDatum either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former case,
* the datum is stored in the primitive, while in the latter
* it is constructed on the fly to reduce the memory footprint.
* The default is `CGAL::Tag_false` (datum is not stored).
*
* \sa `AABBPrimitive`
* \sa `AABB_segment_primitive<Iterator,CacheDatum>`
* \sa `AABB_triangle_primitive<Iterator,CacheDatum>`
* \sa `AABB_halfedge_graph_segment_primitive<HalfedgeGraph,OneHalfedgeGraphPerTree,CacheDatum>`
* \sa `AABB_face_graph_triangle_primitive<FaceGraph,OneFaceGraphPerTree,CacheDatum>`
*/
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap,
class ExternalPropertyMaps,
class CacheDatum>
struct AABB_primitive
{
/// \name Types
/// @{
/*!
The datum type.
*/
typedef boost::property_traits< ObjectPropertyMap >::value_type Datum;
/*!
The point type.
*/
typedef boost::property_traits< PointPropertyMap >::value_type Point;
/*!
The reference datum type.
*/
typedef boost::property_traits< ObjectPropertyMap >::reference Datum_reference;
/*!
The reference point type.
*/
typedef boost::property_traits< PointPropertyMap >::reference Point_reference;
/*!
Id type.
*/
typedef Id Id;
/// @}
/*!
constructs a primitive and initializes the property maps.
*/
AABB_primitive(Id id,
ObjectPropertyMap o_pmap=ObjectPropertyMap(),
PointPropertyMap p_pmap=PointPropertyMap());
/*!
constructs a primitive from an iterator with `Id` as value type
and initializes the property maps.
*/
template <class Iterator>
AABB_primitive(Iterator it,
ObjectPropertyMap o_pmap=ObjectPropertyMap(),
PointPropertyMap p_pmap=PointPropertyMap());
};
#else
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap,
class ExternalPropertyMaps,
class CacheDatum>
class AABB_primitive;
//no caching, property maps internally stored
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap >
class AABB_primitive<Id, ObjectPropertyMap, PointPropertyMap,Tag_false,Tag_false>
: public AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap>
{
typedef AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap> Base;
ObjectPropertyMap m_obj_pmap;
PointPropertyMap m_pt_pmap;
public:
AABB_primitive(Id id, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap pt_pmap=PointPropertyMap())
: Base(id), m_obj_pmap(obj_pmap), m_pt_pmap(pt_pmap) {}
template <class Iterator>
AABB_primitive(Iterator it, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap pt_pmap=PointPropertyMap())
: Base(*it), m_obj_pmap(obj_pmap), m_pt_pmap(pt_pmap) {}
typename Base::Datum_reference
datum() const { return get(m_obj_pmap,this->m_id); }
typename Base::Point_reference
reference_point() const { return get(m_pt_pmap,this->m_id); }
};
//caching, property maps internally stored
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap >
class AABB_primitive<Id, ObjectPropertyMap, PointPropertyMap,Tag_false,Tag_true>
: public AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap>
{
typedef AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap> Base;
typename boost::property_traits< ObjectPropertyMap >::value_type m_datum;
PointPropertyMap m_pt_pmap;
public:
typedef const typename Base::Datum& Datum_reference;
AABB_primitive(Id id, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap pt_pmap=PointPropertyMap())
: Base(id), m_datum( get(obj_pmap,id) ), m_pt_pmap(pt_pmap){}
template <class Iterator>
AABB_primitive(Iterator it, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap pt_pmap=PointPropertyMap())
: Base(*it), m_datum( get(obj_pmap,*it) ), m_pt_pmap(pt_pmap){}
Datum_reference datum() const { return m_datum; }
typename Base::Point_reference
reference_point() const { return get(m_pt_pmap,this->m_id); }
};
//no caching, property maps are stored outside the class
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap >
class AABB_primitive<Id, ObjectPropertyMap, PointPropertyMap,Tag_true,Tag_false>
: public AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap>
{
typedef AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap> Base;
public:
typedef std::pair<ObjectPropertyMap,PointPropertyMap> Shared_data;
AABB_primitive(Id id, ObjectPropertyMap=ObjectPropertyMap(), PointPropertyMap=PointPropertyMap())
: Base(id) {}
template <class Iterator>
AABB_primitive(Iterator it, ObjectPropertyMap=ObjectPropertyMap(), PointPropertyMap=PointPropertyMap())
: Base(*it) {}
typename Base::Datum_reference
datum(const Shared_data& data) const { return get(data.first,this->m_id); }
typename Base::Point_reference
reference_point(const Shared_data& data) const { return get(data.second,this->m_id); }
static Shared_data construct_shared_data(ObjectPropertyMap obj, PointPropertyMap pt) {return Shared_data(obj,pt);}
};
//caching, property map is stored outside the class
template < class Id,
class ObjectPropertyMap,
class PointPropertyMap >
class AABB_primitive<Id, ObjectPropertyMap, PointPropertyMap,Tag_true,Tag_true>
: public AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap>
{
typedef AABB_primitive_base<Id,ObjectPropertyMap,PointPropertyMap> Base;
typename boost::property_traits< ObjectPropertyMap >::value_type m_datum;
public:
typedef PointPropertyMap Shared_data;
typedef const typename Base::Datum& Datum_reference;
AABB_primitive(Id id, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap=PointPropertyMap())
: Base(id), m_datum( get(obj_pmap,id) ) {}
template <class Iterator>
AABB_primitive(Iterator it, ObjectPropertyMap obj_pmap=ObjectPropertyMap(), PointPropertyMap=PointPropertyMap())
: Base(*it), m_datum( get(obj_pmap,*it) ) {}
Datum_reference datum(Shared_data) const { return m_datum; }
typename Base::Point_reference
reference_point(const Shared_data& data) const { return get(data,this->m_id); }
static Shared_data construct_shared_data(ObjectPropertyMap, PointPropertyMap pt) {return pt;}
};
#endif //DOXYGEN_RUNNING
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_PRIMITIVE_H
@@ -0,0 +1,101 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_AABB_SEGMENT_PRIMITIVE_H_
#define CGAL_AABB_SEGMENT_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/AABB_primitive.h>
#include <iterator>
namespace CGAL {
namespace internal {
template <class GeomTraits, class Iterator>
struct Source_of_segment_3_iterator_property_map{
//classical typedefs
typedef Iterator key_type;
typedef typename GeomTraits::Point_3 value_type;
// typedef decltype(
// std::declval<typename GeomTraits::Construct_source_3>()(
// std::declval<typename GeomTraits::Segment_3>())) reference;
typedef decltype(
typename GeomTraits::Construct_source_3()(
*std::declval<key_type&>())) reference;
typedef boost::readable_property_map_tag category;
typedef Source_of_segment_3_iterator_property_map<GeomTraits, Iterator> Self;
inline friend reference
get(Self, key_type it)
{
return typename GeomTraits::Construct_source_3()( *it );
}
};
}//namespace internal
/*!
* \ingroup PkgAABBTreeRef
* Primitive type that uses as identifier an iterator with a 3D segment as `value_type`.
* The iterator from which the primitive is built should not be invalided
* while the AABB tree holding the primitive is in use.
*
* \cgalModels `AABBPrimitive`
*
* \tparam GeomTraits is a traits class providing the nested type `Point_3` and `Segment_3`.
* It also provides the functor `Construct_source_3` that has an operator taking a `Segment_3`
* and returning its source as a type convertible to `Point_3`.
* \tparam Iterator is a model of `ForwardIterator` with its value type convertible to `GeomTraits::Segment_3`
* \tparam CacheDatum is either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former case,
* the datum is stored in the primitive, while in the latter it is
* constructed on the fly to reduce the memory footprint.
* The default is `CGAL::Tag_false` (datum is not stored).
*
* \sa `AABBPrimitive`
* \sa `AABB_primitive<Id,ObjectPropertyMap,PointPropertyMapPolyhedron,ExternalPropertyMaps,CacheDatum>`
* \sa `AABB_triangle_primitive<Iterator,CacheDatum>`
* \sa `AABB_halfedge_graph_segment_primitive<HalfedgeGraph,OneHalfedgeGraphPerTree,CacheDatum>`
* \sa `AABB_face_graph_triangle_primitive<FaceGraph,OneFaceGraphPerTree,CacheDatum>`
*/
template < class GeomTraits,
class Iterator,
class CacheDatum=Tag_false>
class AABB_segment_primitive
#ifndef DOXYGEN_RUNNING
: public AABB_primitive< Iterator,
Input_iterator_property_map<Iterator>,
internal::Source_of_segment_3_iterator_property_map<GeomTraits, Iterator>,
Tag_false,
CacheDatum >
#endif
{
typedef AABB_primitive< Iterator,
Input_iterator_property_map<Iterator>,
internal::Source_of_segment_3_iterator_property_map<GeomTraits, Iterator>,
Tag_false,
CacheDatum > Base;
public:
///constructor from an iterator
AABB_segment_primitive(Iterator it) : Base(it){}
};
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_SEGMENT_PRIMITIVE_H_
+538
View File
@@ -0,0 +1,538 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Stéphane Tayeb, Pierre Alliez, Camille Wormser
//
#ifndef CGAL_AABB_TRAITS_H_
#define CGAL_AABB_TRAITS_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/Default.h>
#include <CGAL/intersections.h>
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
#include <CGAL/AABB_tree/internal/Is_ray_intersection_geomtraits.h>
#include <CGAL/AABB_tree/internal/Primitive_helper.h>
#include <CGAL/Kernel_23/internal/Has_boolean_tags.h>
#include <boost/optional.hpp>
/// \file AABB_traits.h
namespace CGAL {
namespace internal{ namespace AABB_tree {
template <class T>
struct Remove_optional { typedef T type; };
template <class T>
struct Remove_optional< ::boost::optional<T> > { typedef T type; };
//helper controlling whether extra data should be stored in the AABB_tree traits class
template <class Primitive, bool has_shared_data=Has_nested_type_Shared_data<Primitive>::value>
struct AABB_traits_base;
template <class Primitive>
struct AABB_traits_base<Primitive,false>{};
template <class Primitive>
struct AABB_traits_base<Primitive,true>{
typename Primitive::Shared_data m_primitive_data;
template <typename ... T>
void set_shared_data(T&& ... t){
m_primitive_data=Primitive::construct_shared_data(std::forward<T>(t)...);
}
const typename Primitive::Shared_data& shared_data() const {return m_primitive_data;}
};
// AABB_traits_base_2 brings in the Intersection_distance predicate,
// if GeomTraits is a model RayIntersectionGeomTraits.
template <typename GeomTraits, bool ray_intersection_geom_traits=Is_ray_intersection_geomtraits<GeomTraits>::value>
struct AABB_traits_base_2;
template <typename GeomTraits>
struct AABB_traits_base_2<GeomTraits,false>{};
template <typename GeomTraits>
struct AABB_traits_base_2<GeomTraits,true>{
typedef typename GeomTraits::Ray_3 Ray_3;
typedef typename GeomTraits::Point_3 Point_3;
typedef typename GeomTraits::Vector_3 Vector_3;
typedef typename GeomTraits::FT FT;
typedef typename GeomTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3;
typedef typename GeomTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3;
typedef typename GeomTraits::Construct_source_3 Construct_source_3;
typedef typename GeomTraits::Construct_vector_3 Construct_vector_3;
// Defining Bounding_box and other types from the full AABB_traits
// here is might seem strange, but otherwise we would need to use
// CRTP to get access to the derived class, which would bloat the
// code more.
typedef typename CGAL::Bbox_3 Bounding_box;
struct Intersection_distance {
boost::optional<FT> operator()(const Ray_3& ray, const Bounding_box& bbox) const {
FT t_near = -DBL_MAX; // std::numeric_limits<FT>::lowest(); C++1903
FT t_far = DBL_MAX;
const Construct_cartesian_const_iterator_3 construct_cartesian_const_iterator_3
= GeomTraits().construct_cartesian_const_iterator_3_object();
const Construct_source_3 construct_source_3 = GeomTraits().construct_source_3_object();
const Construct_vector_3 construct_vector_3 = GeomTraits().construct_vector_3_object();
const Point_3 source = construct_source_3(ray);
const Vector_3 direction = construct_vector_3(ray);
Cartesian_const_iterator_3 source_iter = construct_cartesian_const_iterator_3(source);
Cartesian_const_iterator_3 direction_iter = construct_cartesian_const_iterator_3(direction);
for(int i = 0; i < 3; ++i, ++source_iter, ++direction_iter) {
if(*direction_iter == 0) {
if((*source_iter < (bbox.min)(i)) || (*source_iter > (bbox.max)(i))) {
return boost::none;
}
} else {
FT t1 = ((bbox.min)(i) - *source_iter) / *direction_iter;
FT t2 = ((bbox.max)(i) - *source_iter) / *direction_iter;
t_near = (std::max)(t_near, (std::min)(t1, t2));
t_far = (std::min)(t_far, (std::max)(t1, t2));
// if(t1 > t2)
// std::swap(t1, t2);
// if(t1 > t_near)
// t_near = t1;
// if(t2 < t_far)
// t_far = t2;
if(t_near > t_far || t_far < FT(0.))
return boost::none;
}
}
if(t_near < FT(0.))
return FT(0.);
else
return t_near;
}
};
Intersection_distance intersection_distance_object() const { return Intersection_distance(); }
};
} } //end of namespace internal::AABB_tree
/// \addtogroup PkgAABBTreeRef
/// @{
// forward declaration
template< typename AABBTraits>
class AABB_tree;
/// This traits class handles any type of 3D geometric
/// primitives provided that the proper intersection tests and
/// constructions are implemented. It handles points, rays, lines and
/// segments as query types for intersection detection and
/// computations, and it handles points as query type for distance
/// queries.
///
/// \cgalModels AABBTraits
/// \cgalModels AABBRayIntersectionTraits
/// \tparam GeomTraits must be a model of the concept \ref AABBGeomTraits,
/// and provide the geometric types as well as the intersection tests and computations.
/// \tparam Primitive provide the type of primitives stored in the AABB_tree.
/// It is a model of the concept `AABBPrimitive` or `AABBPrimitiveWithSharedData`.
///
/// \tparam BboxMap must be a model of `ReadablePropertyMap` that has as key type a primitive id,
/// and as value type a `Bounding_box`.
/// If the type is `Default` the `Datum` must have the
/// member function `bbox()` that returns the bounding box of the primitive.
///
/// If the argument `GeomTraits` is a model of the concept \ref
/// AABBRayIntersectionGeomTraits, this class is also a model of \ref
/// AABBRayIntersectionTraits.
///
/// \sa `AABBTraits`
/// \sa `AABB_tree`
/// \sa `AABBPrimitive`
/// \sa `AABBPrimitiveWithSharedData`
template<typename GeomTraits, typename AABBPrimitive, typename BboxMap = Default>
class AABB_traits
#ifndef DOXYGEN_RUNNING
: public internal::AABB_tree::AABB_traits_base<AABBPrimitive>,
public internal::AABB_tree::AABB_traits_base_2<GeomTraits>
#endif
{
typedef typename CGAL::Object Object;
public:
typedef GeomTraits Geom_traits;
typedef AABB_traits<GeomTraits, AABBPrimitive, BboxMap> AT;
// AABBTraits concept types
typedef typename GeomTraits::FT FT;
typedef AABBPrimitive Primitive;
typedef typename std::pair<Object,typename Primitive::Id> Object_and_primitive_id;
typedef typename std::pair<typename GeomTraits::Point_3, typename Primitive::Id> Point_and_primitive_id;
/// `Intersection_and_primitive_id<Query>::%Type::first_type` is found according to
/// the result type of `GeomTraits::Intersect_3::operator()`. If it is
/// `boost::optional<T>` then it is `T`, and the result type otherwise.
template<typename Query>
struct Intersection_and_primitive_id {
typedef decltype(
std::declval<typename GeomTraits::Intersect_3>()(
std::declval<Query>(),
std::declval<typename Primitive::Datum>())) Intersection_type;
typedef std::pair<
typename internal::AABB_tree::Remove_optional<Intersection_type>::type,
typename Primitive::Id > Type;
};
// types for search tree
/// \name Types
/// @{
/// Point query type.
typedef typename GeomTraits::Point_3 Point_3;
/// additionnal types for the search tree, required by the RangeSearchTraits concept
/// \bug This is not documented for now in the AABBTraits concept.
typedef typename GeomTraits::Iso_cuboid_3 Iso_cuboid_3;
/// Bounding box type.
typedef typename CGAL::Bbox_3 Bounding_box;
/// @}
typedef typename GeomTraits::Sphere_3 Sphere_3;
typedef typename GeomTraits::Cartesian_const_iterator_3 Cartesian_const_iterator_3;
typedef typename GeomTraits::Construct_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3;
typedef typename GeomTraits::Construct_center_3 Construct_center_3;
typedef typename GeomTraits::Compute_squared_radius_3 Compute_squared_radius_3;
typedef typename GeomTraits::Construct_min_vertex_3 Construct_min_vertex_3;
typedef typename GeomTraits::Construct_max_vertex_3 Construct_max_vertex_3;
typedef typename GeomTraits::Construct_iso_cuboid_3 Construct_iso_cuboid_3;
BboxMap bbm;
/// Default constructor.
AABB_traits() { }
AABB_traits(BboxMap bbm)
: bbm(bbm)
{}
typedef typename GeomTraits::Compute_squared_distance_3 Squared_distance;
Squared_distance squared_distance_object() const { return GeomTraits().compute_squared_distance_3_object(); }
typedef typename GeomTraits::Equal_3 Equal_3;
Equal_3 equal_3_object() const { return GeomTraits().equal_3_object(); }
/**
* @internal
* @brief Sorts [first,beyond[
* @param first iterator on first element
* @param beyond iterator on beyond element
* @param bbox the bounding box of [first,beyond[
*
* Sorts the range defined by [first,beyond[. Sort is achieved on bbox longuest
* axis, using the comparison function `<dim>_less_than` (dim in {x,y,z})
*/
class Split_primitives
{
typedef AABB_traits<GeomTraits,AABBPrimitive,BboxMap> Traits;
const Traits& m_traits;
public:
Split_primitives(const AABB_traits<GeomTraits,AABBPrimitive,BboxMap>& traits)
: m_traits(traits) {}
typedef void result_type;
template<typename PrimitiveIterator>
void operator()(PrimitiveIterator first,
PrimitiveIterator beyond,
const typename AT::Bounding_box& bbox) const
{
PrimitiveIterator middle = first + (beyond - first)/2;
switch(Traits::longest_axis(bbox))
{
case AT::CGAL_AXIS_X: // sort along x
std::nth_element(first, middle, beyond, [this](const Primitive& p1, const Primitive& p2){ return Traits::less_x(p1, p2, this->m_traits); });
break;
case AT::CGAL_AXIS_Y: // sort along y
std::nth_element(first, middle, beyond, [this](const Primitive& p1, const Primitive& p2){ return Traits::less_y(p1, p2, this->m_traits); });
break;
case AT::CGAL_AXIS_Z: // sort along z
std::nth_element(first, middle, beyond, [this](const Primitive& p1, const Primitive& p2){ return Traits::less_z(p1, p2, this->m_traits); });
break;
default:
CGAL_error();
}
}
};
Split_primitives split_primitives_object() const {return Split_primitives(*this);}
/*
* Computes the bounding box of a set of primitives
* @param first an iterator on the first primitive
* @param beyond an iterator on the past-the-end primitive
* @return the bounding box of the primitives of the iterator range
*/
class Compute_bbox {
const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& m_traits;
public:
Compute_bbox(const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
:m_traits (traits) {}
template<typename ConstPrimitiveIterator>
typename AT::Bounding_box operator()(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond) const
{
typename AT::Bounding_box bbox = m_traits.compute_bbox(*first,m_traits.bbm);
for(++first; first != beyond; ++first)
{
bbox = bbox + m_traits.compute_bbox(*first,m_traits.bbm);
}
return bbox;
}
};
Compute_bbox compute_bbox_object() const {return Compute_bbox(*this);}
/// \brief Function object using `GeomTraits::Do_intersect`.
/// In the case the query is a `CGAL::AABB_tree`, the `do_intersect()`
/// function of this tree is used.
class Do_intersect {
const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& m_traits;
public:
Do_intersect(const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
:m_traits(traits) {}
template<typename Query>
bool operator()(const Query& q, const Bounding_box& bbox) const
{
return GeomTraits().do_intersect_3_object()(q, bbox);
}
template<typename Query>
bool operator()(const Query& q, const Primitive& pr) const
{
return GeomTraits().do_intersect_3_object()(q, internal::Primitive_helper<AT>::get_datum(pr,m_traits));
}
// intersection with AABB-tree
template<typename AABBTraits>
bool operator()(const CGAL::AABB_tree<AABBTraits>& other_tree, const Primitive& pr) const
{
return other_tree.do_intersect( internal::Primitive_helper<AT>::get_datum(pr,m_traits) );
}
template<typename AABBTraits>
bool operator()(const CGAL::AABB_tree<AABBTraits>& other_tree, const Bounding_box& bbox) const
{
return other_tree.do_intersect(bbox);
}
};
Do_intersect do_intersect_object() const {return Do_intersect(*this);}
class Intersection {
const AABB_traits<GeomTraits,AABBPrimitive,BboxMap>& m_traits;
public:
Intersection(const AABB_traits<GeomTraits,AABBPrimitive,BboxMap>& traits)
:m_traits(traits) {}
template<typename Query>
boost::optional< typename Intersection_and_primitive_id<Query>::Type >
operator()(const Query& query, const typename AT::Primitive& primitive) const {
auto inter_res = GeomTraits().intersect_3_object()(query, internal::Primitive_helper<AT>::get_datum(primitive,m_traits));
if (!inter_res)
return boost::none;
return boost::make_optional( std::make_pair(*inter_res, primitive.id()) );
}
};
Intersection intersection_object() const {return Intersection(*this);}
// This should go down to the GeomTraits, i.e. the kernel
class Closest_point {
typedef typename AT::Point_3 Point;
typedef typename AT::Primitive Primitive;
const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& m_traits;
public:
Closest_point(const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
: m_traits(traits) {}
Point operator()(const Point& p, const Primitive& pr, const Point& bound) const
{
GeomTraits geom_traits;
Point closest_point = geom_traits.construct_projected_point_3_object()(
internal::Primitive_helper<AT>::get_datum(pr,m_traits), p);
return (geom_traits.compare_distance_3_object()(p, closest_point, bound) == LARGER) ?
bound : closest_point;
}
};
// This should go down to the GeomTraits, i.e. the kernel
// and the internal implementation should change its name from
// do_intersect to something like does_contain (this is what we compute,
// this is not the same do_intersect as the spherical kernel)
class Compare_distance {
typedef typename AT::Point_3 Point;
typedef typename AT::FT FT;
typedef typename AT::Primitive Primitive;
public:
CGAL::Comparison_result operator()(const Point& p, const Bounding_box& bb, const Point& bound, Tag_true) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()
(p, GeomTraits().compute_squared_distance_3_object()(p, bound)), bb,true)?
CGAL::SMALLER : CGAL::LARGER;
}
CGAL::Comparison_result operator()(const Point& p, const Bounding_box& bb, const Point& bound, Tag_false) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()
(p, GeomTraits().compute_squared_distance_3_object()(p, bound)), bb)?
CGAL::SMALLER : CGAL::LARGER;
}
CGAL::Comparison_result operator()(const Point& p, const Bounding_box& bb, const Point& bound) const
{
return (*this)(p, bb, bound, Boolean_tag<internal::Has_static_filters<GeomTraits>::value>());
}
// The following functions seem unused...?
template <class Solid>
CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const Point& bound) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()
(p, GeomTraits().compute_squared_distance_3_object()(p, bound)), pr)?
CGAL::SMALLER : CGAL::LARGER;
}
template <class Solid>
CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const FT& sq_distance) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()(p, sq_distance),
pr) ?
CGAL::SMALLER :
CGAL::LARGER;
}
};
Closest_point closest_point_object() const {return Closest_point(*this);}
Compare_distance compare_distance_object() const {return Compare_distance();}
typedef enum { CGAL_AXIS_X = 0,
CGAL_AXIS_Y = 1,
CGAL_AXIS_Z = 2} Axis;
static Axis longest_axis(const Bounding_box& bbox);
private:
/**
* @brief Computes bounding box of one primitive
* @param pr the primitive
* @return the bounding box of the primitive \c pr
*/
template <typename PM>
Bounding_box compute_bbox(const Primitive& pr, const PM&)const
{
return get(bbm, pr.id());
}
Bounding_box compute_bbox(const Primitive& pr, const Default&)const
{
return internal::Primitive_helper<AT>::get_datum(pr,*this).bbox();
}
/// Comparison functions
static bool less_x(const Primitive& pr1, const Primitive& pr2,const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
{
return GeomTraits().less_x_3_object()( internal::Primitive_helper<AT>::get_reference_point(pr1,traits),
internal::Primitive_helper<AT>::get_reference_point(pr2,traits) );
}
static bool less_y(const Primitive& pr1, const Primitive& pr2,const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
{
return GeomTraits().less_y_3_object()( internal::Primitive_helper<AT>::get_reference_point(pr1,traits),
internal::Primitive_helper<AT>::get_reference_point(pr2,traits) );
}
static bool less_z(const Primitive& pr1, const Primitive& pr2,const AABB_traits<GeomTraits,AABBPrimitive, BboxMap>& traits)
{
return GeomTraits().less_z_3_object()( internal::Primitive_helper<AT>::get_reference_point(pr1,traits),
internal::Primitive_helper<AT>::get_reference_point(pr2,traits) );
}
}; // end class AABB_traits
//-------------------------------------------------------
// Private methods
//-------------------------------------------------------
template<typename GT, typename P, typename B>
typename AABB_traits<GT,P,B>::Axis
AABB_traits<GT,P,B>::longest_axis(const Bounding_box& bbox)
{
const double dx = bbox.xmax() - bbox.xmin();
const double dy = bbox.ymax() - bbox.ymin();
const double dz = bbox.zmax() - bbox.zmin();
if(dx>=dy)
{
if(dx>=dz)
{
return CGAL_AXIS_X;
}
else // dz>dx and dx>=dy
{
return CGAL_AXIS_Z;
}
}
else // dy>dx
{
if(dy>=dz)
{
return CGAL_AXIS_Y;
}
else // dz>dy and dy>dx
{
return CGAL_AXIS_Z;
}
}
}
/// @}
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_TRAITS_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,93 @@
// Copyright (c) 2008 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Camille Wormser, Pierre Alliez
#ifndef CGAL_AABB_DRAWING_TRAITS_H
#define CGAL_AABB_DRAWING_TRAITS_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/Bbox_3.h>
#include <vector>
namespace CGAL {
template<typename Primitive, typename Node>
struct AABB_drawing_traits
{
std::vector<float> *v_edges;
double offset[3];
typedef CGAL::Bbox_3 Bbox;
bool go_further() { return true; }
bool intersection(const int&, const Primitive&)
{
return true;
}
bool do_intersect(const int&, // unused
const Node& node)
{
gl_draw(node.bbox());
return true;
}
// draw bbox
void gl_draw(const Bbox& bb)
{
gl_draw_edge(bb.xmin(), bb.ymin(), bb.zmin(),
bb.xmax(), bb.ymin(), bb.zmin());
gl_draw_edge(bb.xmin(), bb.ymin(), bb.zmin(),
bb.xmin(), bb.ymax(), bb.zmin());
gl_draw_edge(bb.xmin(), bb.ymin(), bb.zmin(),
bb.xmin(), bb.ymin(), bb.zmax());
gl_draw_edge(bb.xmax(), bb.ymin(), bb.zmin(),
bb.xmax(), bb.ymax(), bb.zmin());
gl_draw_edge(bb.xmax(), bb.ymin(), bb.zmin(),
bb.xmax(), bb.ymin(), bb.zmax());
gl_draw_edge(bb.xmin(), bb.ymax(), bb.zmin(),
bb.xmax(), bb.ymax(), bb.zmin());
gl_draw_edge(bb.xmin(), bb.ymax(), bb.zmin(),
bb.xmin(), bb.ymax(), bb.zmax());
gl_draw_edge(bb.xmin(), bb.ymin(), bb.zmax(),
bb.xmax(), bb.ymin(), bb.zmax());
gl_draw_edge(bb.xmin(), bb.ymin(), bb.zmax(),
bb.xmin(), bb.ymax(), bb.zmax());
gl_draw_edge(bb.xmax(), bb.ymax(), bb.zmax(),
bb.xmin(), bb.ymax(), bb.zmax());
gl_draw_edge(bb.xmax(), bb.ymax(), bb.zmax(),
bb.xmax(), bb.ymin(), bb.zmax());
gl_draw_edge(bb.xmax(), bb.ymax(), bb.zmax(),
bb.xmax(), bb.ymax(), bb.zmin());
}
void gl_draw_edge(double px, double py, double pz,
double qx, double qy, double qz)
{
v_edges->push_back((float)px+offset[0]);
v_edges->push_back((float)py+offset[1]);
v_edges->push_back((float)pz+offset[2]);
v_edges->push_back((float)qx+offset[0]);
v_edges->push_back((float)qy+offset[1]);
v_edges->push_back((float)qz+offset[2]);
}
}; // AABB_drawing_traits
} // end namespace CGAL
#endif // CGAL_AABB_DRAWING_TRAITS_H
@@ -0,0 +1,321 @@
// Copyright (c) 2008 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Camille Wormser, Pierre Alliez, Stephane Tayeb
#ifndef CGAL_AABB_NODE_H
#define CGAL_AABB_NODE_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/Profile_counter.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/intersections.h>
#include <CGAL/Bbox_3.h>
#include <vector>
namespace CGAL {
/**
* @class AABB_node
*
*
*/
template<typename AABBTraits>
class AABB_node
{
private:
typedef AABB_node<AABBTraits> Self;
public:
typedef typename AABBTraits::Bounding_box Bounding_box;
/// Constructor
AABB_node()
: m_bbox()
, m_p_left_child(nullptr)
, m_p_right_child(nullptr) { };
AABB_node(Self&& node) = default;
// Disabled copy constructor & assignment operator
AABB_node(const Self& src) = delete;
Self& operator=(const Self& src) = delete;
/// Returns the bounding box of the node
const Bounding_box& bbox() const { return m_bbox; }
/**
* @brief General traversal query
* @param query the query
* @param traits the traversal traits that define the traversal behaviour
* @param nb_primitives the number of primitive
*
* General traversal query. The traits class allows using it for the various
* traversal methods we need: listing, counting, detecting intersections,
* drawing the boxes.
*/
template<class Traversal_traits, class Query>
void traversal(const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives) const;
template<class Traversal_traits, class Query>
void traversal_with_priority(const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives) const;
template<class Primitive_vector, class Traversal_traits, class Query>
void traversal_with_priority_and_group_traversal(const Primitive_vector& primitives,
const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives,
std::size_t first_primitive_index,
const std::size_t group_size_bound) const;
private:
typedef AABBTraits AABB_traits;
typedef AABB_node<AABB_traits> Node;
typedef typename AABB_traits::Primitive Primitive;
public:
/// Helper functions
const Node& left_child() const
{ return *static_cast<Node*>(m_p_left_child); }
const Node& right_child() const
{ return *static_cast<Node*>(m_p_right_child); }
const Primitive& left_data() const
{ return *static_cast<Primitive*>(m_p_left_child); }
const Primitive& right_data() const
{ return *static_cast<Primitive*>(m_p_right_child); }
template <class Left, class Right>
void set_children(Left& l, Right& r)
{
m_p_left_child = static_cast<void*>(std::addressof(l));
m_p_right_child = static_cast<void*>(std::addressof(r));
}
void set_bbox(const Bounding_box& bbox)
{
m_bbox = bbox;
}
Node& left_child() { return *static_cast<Node*>(m_p_left_child); }
Node& right_child() { return *static_cast<Node*>(m_p_right_child); }
Primitive& left_data() { return *static_cast<Primitive*>(m_p_left_child); }
Primitive& right_data() { return *static_cast<Primitive*>(m_p_right_child); }
private:
/// node bounding box
Bounding_box m_bbox;
/// children nodes, either pointing towards children (if children are not leaves),
/// or pointing toward input primitives (if children are leaves).
void *m_p_left_child;
void *m_p_right_child;
}; // end class AABB_node
template<typename Tr>
template<class Traversal_traits, class Query>
void
AABB_node<Tr>::traversal(const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives) const
{
// Recursive traversal
switch(nb_primitives)
{
case 2:
traits.intersection(query, left_data());
if( traits.go_further() )
{
traits.intersection(query, right_data());
}
break;
case 3:
traits.intersection(query, left_data());
if( traits.go_further() && traits.do_intersect(query, right_child()) )
{
right_child().traversal(query, traits, 2);
}
break;
default:
if( traits.do_intersect(query, left_child()) )
{
left_child().traversal(query, traits, nb_primitives/2);
if( traits.go_further() && traits.do_intersect(query, right_child()) )
{
right_child().traversal(query, traits, nb_primitives-nb_primitives/2);
}
}
else if( traits.do_intersect(query, right_child()) )
{
right_child().traversal(query, traits, nb_primitives-nb_primitives/2);
}
}
}
template<typename Tr>
template<class Traversal_traits, class Query>
void
AABB_node<Tr>::traversal_with_priority(const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives) const
{
// Recursive traversal
switch(nb_primitives)
{
case 2:
traits.intersection(query, left_data());
if( traits.go_further() )
{
traits.intersection(query, right_data());
}
break;
case 3:
traits.intersection(query, left_data());
if( traits.go_further() && traits.do_intersect(query, right_child()) )
{
right_child().traversal_with_priority(query, traits, 2);
}
break;
default:
bool ileft, iright;
typename Traversal_traits::Priority pleft, pright;
std::tie(ileft, pleft) = traits.do_intersect_with_priority(query, left_child());
std::tie(iright, pright) = traits.do_intersect_with_priority(query, right_child());
CGAL_precondition( (ileft || iright) ? traits.do_intersect(query, *this) : true );
if(ileft)
{
if(iright)
{
// Both children have to be inspected.
if(pleft >= pright)
{
// Inspect the left child first, has higher priority.
left_child().traversal_with_priority(query, traits, nb_primitives/2);
if( traits.go_further() )
right_child().traversal_with_priority(query, traits, nb_primitives-nb_primitives/2);
}
else
{
// Inspect the right child first, has higher priority.
right_child().traversal_with_priority(query, traits, nb_primitives-nb_primitives/2);
if( traits.go_further() )
left_child().traversal_with_priority(query, traits, nb_primitives/2);
}
}
else
{
// Only the left child has to be inspected.
left_child().traversal_with_priority(query, traits, nb_primitives/2);
}
}
else
{
if(iright)
{
// Only the right child has to be inspected.
right_child().traversal_with_priority(query, traits, nb_primitives-nb_primitives/2);
}
}
}
}
// TODO: find a better name
template<typename Tr>
template<class Primitive_vector, class Traversal_traits, class Query>
void
AABB_node<Tr>::traversal_with_priority_and_group_traversal(const Primitive_vector& primitives,
const Query& query,
Traversal_traits& traits,
const std::size_t nb_primitives,
std::size_t first_primitive_index,
const std::size_t group_traversal_bound) const
{
// Group traversal
CGAL_assertion(group_traversal_bound >= 2);
if ( nb_primitives <= group_traversal_bound )
{
if ( !traits.do_intersect(query, *this) ) return;
CGAL_assertion(traits.do_intersect(query, *this));
traits.traverse_group(query, primitives.begin()+first_primitive_index, primitives.begin()+first_primitive_index+nb_primitives);
return;
}
// Recursive traversal
switch(nb_primitives)
{
case 2:
traits.intersection(query, left_data());
if( traits.go_further() )
{
traits.intersection(query, right_data());
}
break;
case 3:
traits.intersection(query, left_data());
if( traits.go_further() && traits.do_intersect(query, right_child()) )
{
right_child().traversal_with_priority_and_group_traversal(primitives, query, traits, 2, first_primitive_index+1, group_traversal_bound);
}
break;
default:
bool ileft, iright;
typename Traversal_traits::Priority pleft, pright;
std::tie(ileft, pleft) = traits.do_intersect_with_priority(query, left_child());
std::tie(iright, pright) = traits.do_intersect_with_priority(query, right_child());
CGAL_precondition( (ileft || iright) ? traits.do_intersect(query, *this) : true );
if(ileft)
{
if(iright)
{
// Both children have to be inspected.
if(pleft >= pright)
{
// Inspect the left child first, has higher priority.
left_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives/2, first_primitive_index, group_traversal_bound);
if( traits.go_further() )
right_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives-nb_primitives/2, first_primitive_index+nb_primitives/2, group_traversal_bound);
}
else
{
// Inspect the right child first, has higher priority.
right_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives-nb_primitives/2, first_primitive_index+nb_primitives/2, group_traversal_bound);
if( traits.go_further() )
left_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives/2, first_primitive_index, group_traversal_bound);
}
}
else
{
// Only the left child has to be inspected.
left_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives/2, first_primitive_index, group_traversal_bound);
}
}
else
{
if(iright)
{
// Only the right child has to be inspected.
right_child().traversal_with_priority_and_group_traversal(primitives, query, traits, nb_primitives-nb_primitives/2, first_primitive_index+nb_primitives/2, group_traversal_bound);
}
}
}
}
} // end namespace CGAL
#endif // CGAL_AABB_NODE_H
@@ -0,0 +1,242 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Philipp Moeller
//
#ifndef CGAL_AABB_RAY_INTERSECTION_H
#define CGAL_AABB_RAY_INTERSECTION_H
#include <CGAL/license/AABB_tree.h>
#include <functional>
#include <boost/optional.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/variant/apply_visitor.hpp>
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4996)
# endif
# include <boost/heap/priority_queue.hpp>
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#include <CGAL/assertions.h>
namespace CGAL {
template<typename AABBTree, typename SkipFunctor>
class AABB_ray_intersection {
typedef typename AABBTree::AABB_traits AABB_traits;
typedef typename AABB_traits::Ray_3 Ray;
typedef typename AABBTree::template Intersection_and_primitive_id<Ray>::Type Ray_intersection_and_primitive_id;
typedef typename Ray_intersection_and_primitive_id::first_type Ray_intersection;
public:
AABB_ray_intersection(const AABBTree& tree) : tree_(tree) {}
boost::optional< Ray_intersection_and_primitive_id >
ray_intersection(const Ray& query, SkipFunctor skip) const {
// We hit the root, now continue on the children. Keep track of
// nb_primitives through a variable in each Node on the stack. In
// BVH_node::traversal this is done through the function parameter
// nb_primitives in the recursion.
typedef
boost::heap::priority_queue< Node_ptr_with_ft, boost::heap::compare< std::greater<Node_ptr_with_ft> > >
Heap_type;
typename AABB_traits::Intersection
intersection_obj = tree_.traits().intersection_object();
// typename AABB_traits::Do_intersect
// do_intersect_obj = tree_.traits().do_intersect_object();
typename AABB_traits::Intersection_distance
intersection_distance_obj = tree_.traits().intersection_distance_object();
as_ray_param_visitor param_visitor = as_ray_param_visitor(&query);
Heap_type pq;
// pq.reserve(tree_.size() / 2);
boost::optional< Ray_intersection_and_primitive_id >
intersection, /* the temporary for calculating the result */
p; /* the current best intersection */
// this is not the right way to do it, but using
// numeric_limits<FT>::{max,infinity} will not work with Epeck.
FT t = (std::numeric_limits<double>::max)();
// Start with the root node.
pq.push(Node_ptr_with_ft(tree_.root_node(), 0, tree_.size()));
while(!pq.empty() && pq.top().value < t) {
Node_ptr_with_ft current = pq.top();
pq.pop();
switch(current.nb_primitives) { // almost copy-paste from BVH_node::traversal
case 2: // Left & right child both leaves
{
//left child
if(!skip(current.node->left_data().id()) /* && do_intersect_obj(query, current.node->left_data()) */) {
intersection = intersection_obj(query, current.node->left_data());
if(intersection) {
FT ray_distance = boost::apply_visitor(param_visitor, intersection->first);
if(ray_distance < t) {
t = ray_distance;
p = intersection;
}
}
}
// right child
if(!skip(current.node->right_data().id()) /* && do_intersect_obj(query, current.node->right_data()) */) {
intersection = intersection_obj(query, current.node->right_data());
if(intersection) {
FT ray_distance = boost::apply_visitor(param_visitor, intersection->first);
if(ray_distance < t) {
t = ray_distance;
p = intersection;
}
}
}
break;
}
case 3: // Left child leaf, right child inner node
{
//left child
if(!skip(current.node->left_data().id()) /* && do_intersect_obj(query, current.node->left_data()) */) {
intersection = intersection_obj(query, current.node->left_data());
if(intersection) {
FT ray_distance = boost::apply_visitor(param_visitor, intersection->first);
if(ray_distance < t) {
t = ray_distance;
p = intersection;
}
}
}
// right child
const Node* child = &(current.node->right_child());
boost::optional< FT > dist = intersection_distance_obj(query, child->bbox());
if(dist)
pq.push(Node_ptr_with_ft(child, *dist, 2));
break;
}
default: // Children both inner nodes
{
const Node* child = &(current.node->left_child());
boost::optional<FT> dist = intersection_distance_obj(query, child->bbox());
if(dist)
pq.push(Node_ptr_with_ft(child, *dist, current.nb_primitives/2));
child = &(current.node->right_child());
dist = intersection_distance_obj(query, child->bbox());
if(dist)
pq.push(Node_ptr_with_ft(child, *dist, current.nb_primitives - current.nb_primitives/2));
break;
}
}
}
return p;
}
private:
const AABBTree& tree_;
typedef typename AABBTree::Point Point;
typedef typename AABBTree::FT FT;
typedef typename AABBTree::Node Node;
typedef typename AABBTree::size_type size_type;
struct Node_ptr_with_ft {
Node_ptr_with_ft(const Node* node, const FT& value, size_type nb_primitives)
: node(node), nb_primitives(nb_primitives), value(value) {}
const Node* node;
size_type nb_primitives;
FT value;
bool operator<(const Node_ptr_with_ft& other) const { return value < other.value; }
bool operator>(const Node_ptr_with_ft& other) const { return value > other.value; }
};
struct as_ray_param_visitor {
typedef FT result_type;
as_ray_param_visitor(const Ray* ray)
: ray(ray), max_i(0)
{
typename AABB_traits::Geom_traits::Vector_3 v = ray->to_vector();
for (int i=1; i<3; ++i)
if( CGAL::abs(v[i]) > CGAL::abs(v[max_i]) )
max_i = i;
}
template<typename T>
FT operator()(const T& s)
{
// intersection is a segment, returns the min relative distance
// of its endpoints
FT r1 = this->operator()(s[0]);
FT r2 = this->operator()(s[1]);
return (std::min)(r1,r2);
}
FT operator()(const Point& point) {
typename AABB_traits::Geom_traits::Vector_3 x(ray->source(), point);
typename AABB_traits::Geom_traits::Vector_3 v = ray->to_vector();
return x[max_i] / v[max_i];
}
const Ray* ray;
int max_i;
};
};
template<typename AABBTraits>
template<typename Ray, typename SkipFunctor>
boost::optional< typename AABB_tree<AABBTraits>::template Intersection_and_primitive_id<Ray>::Type >
AABB_tree<AABBTraits>::first_intersection(const Ray& query,
const SkipFunctor& skip) const {
CGAL_static_assertion_msg((boost::is_same<Ray, typename AABBTraits::Ray_3>::value),
"Ray and Ray_3 must be the same type");
switch(size()) // copy-paste from AABB_tree::traversal
{
case 0: // Tree empty, nothing to intersect
break;
case 1: // Tree has 1 node, intersect directly
return traits().intersection_object()(query, singleton_data());
default: // Tree has >= 2 nodes
if(traits().do_intersect_object()(query, root_node()->bbox())) {
AABB_ray_intersection< AABB_tree<AABBTraits>, SkipFunctor > ri(*this);
return ri.ray_intersection(query, skip);
} else {
// but we don't hit the root
break;
}
}
return boost::none;
}
template<typename AABBTraits>
template<typename Ray, typename SkipFunctor>
boost::optional<typename AABB_tree<AABBTraits>::Primitive_id>
AABB_tree<AABBTraits>::first_intersected_primitive(const Ray& query,
const SkipFunctor& skip) const
{
boost::optional<
typename AABB_tree<AABBTraits>::
template Intersection_and_primitive_id<Ray>::Type > res =
first_intersection(query, skip);
if ( (bool) res )
return boost::make_optional( res->second );
return boost::none;
}
}
#endif /* CGAL_AABB_RAY_INTERSECTION_H */
@@ -0,0 +1,124 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Pierre Alliez, Camille Wormser
#ifndef CGAL_AABB_SEARCH_TREE_H
#define CGAL_AABB_SEARCH_TREE_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/Orthogonal_k_neighbor_search.h>
#include <CGAL/Search_traits_3.h>
namespace CGAL
{
template <class Underlying, class Id>
class Add_decorated_point: public Underlying
{
class Decorated_point: public Underlying::Point_3
{
public:
const Id& id() const { return m_id; }
Decorated_point()
: Underlying::Point_3()
, m_id()
, m_is_id_initialized(false) {}
// Allows the user not to provide the id
// so that we don't break existing code
Decorated_point(const typename Underlying::Point_3& p)
: Underlying::Point_3(p)
, m_id()
, m_is_id_initialized(false) {}
Decorated_point(const typename Underlying::Point_3& p,
const Id& id)
: Underlying::Point_3(p)
, m_id(id)
, m_is_id_initialized(true) {}
Decorated_point(const Decorated_point& rhs)
: Underlying::Point_3(rhs)
, m_id()
, m_is_id_initialized(rhs.m_is_id_initialized)
{
if ( m_is_id_initialized )
m_id = rhs.m_id;
}
Decorated_point& operator=(const Decorated_point&)=default;
private:
Id m_id;
// Needed to avoid exception (depending on Id type)
// "error: attempt to copy-construct an iterator from a singular iterator."
// This exception may appear if we copy-construct an Id
// which has Id() as value (It is done when constructing
// Neighbor_search since we pass the Point only as query)
bool m_is_id_initialized;
};
public:
typedef Decorated_point Point_3;
};
template <class Traits>
class AABB_search_tree
{
public:
typedef typename Traits::FT FT;
typedef typename Traits::Point_3 Point;
typedef typename Traits::Primitive Primitive;
typedef typename Traits::Point_and_primitive_id Point_and_primitive_id;
typedef typename CGAL::Search_traits_3<Add_decorated_point<Traits, typename Traits::Primitive::Id> > TreeTraits;
typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits> Neighbor_search;
typedef typename Neighbor_search::Tree Tree;
private:
Tree m_tree;
Point_and_primitive_id get_p_and_p(const Point_and_primitive_id& p)
{
return p;
}
Point_and_primitive_id get_p_and_p(const Point& p)
{
return Point_and_primitive_id(p, typename Primitive::Id());
}
public:
template <class ConstPointIterator>
AABB_search_tree(ConstPointIterator begin, ConstPointIterator beyond)
: m_tree{}
{
typedef typename Add_decorated_point<Traits,typename Traits::Primitive::Id>::Point_3 Decorated_point;
std::vector<Decorated_point> points;
while(begin != beyond) {
Point_and_primitive_id pp = get_p_and_p(*begin);
points.emplace_back(pp.first, pp.second);
++begin;
}
m_tree.insert(points.begin(), points.end());
m_tree.build();
}
Point_and_primitive_id closest_point(const Point& query) const
{
Neighbor_search search(m_tree, query, 1);
return Point_and_primitive_id(static_cast<Point>(search.begin()->first), search.begin()->first.id());
}
};
}
#endif // CGAL_AABB_SEARCH_TREE_H
@@ -0,0 +1,331 @@
// Copyright (c) 2008-2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Camille Wormser, Pierre Alliez, Stephane Tayeb
#ifndef CGAL_AABB_TRAVERSAL_TRAITS_H
#define CGAL_AABB_TRAVERSAL_TRAITS_H
#include <CGAL/license/AABB_tree.h>
#include <CGAL/AABB_tree/internal/AABB_node.h>
#include <boost/optional.hpp>
namespace CGAL {
namespace internal { namespace AABB_tree {
template <class Value_type, typename Integral_type>
class Counting_output_iterator {
typedef Counting_output_iterator<Value_type,Integral_type> Self;
Integral_type* i;
public:
Counting_output_iterator(Integral_type* i_) : i(i_) {};
struct Proxy {
Proxy& operator=(const Value_type&) { return *this; };
};
Proxy operator*() {
return Proxy();
}
Self& operator++() {
++*i;
return *this;
}
Self& operator++(int) {
++*i;
return *this;
}
};
//-------------------------------------------------------
// Traits classes for traversal computation
//-------------------------------------------------------
/**
* @class First_intersection_traits
*/
template<typename AABBTraits, typename Query>
class First_intersection_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
typedef
boost::optional< typename AABBTraits::template Intersection_and_primitive_id<Query>::Type >
Result;
public:
First_intersection_traits(const AABBTraits& traits)
: m_result(), m_traits(traits)
{}
bool go_further() const {
return !m_result;
}
void intersection(const Query& query, const Primitive& primitive)
{
m_result = m_traits.intersection_object()(query, primitive);
}
bool do_intersect(const Query& query, const Node& node) const
{
return m_traits.do_intersect_object()(query, node.bbox());
}
Result result() const { return m_result; }
bool is_intersection_found() const {
return m_result;
}
private:
Result m_result;
const AABBTraits& m_traits;
};
/**
* @class Listing_intersection_traits
*/
template<typename AABBTraits, typename Query, typename Output_iterator>
class Listing_intersection_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
Listing_intersection_traits(Output_iterator out_it, const AABBTraits& traits)
: m_out_it(out_it), m_traits(traits) {}
bool go_further() const { return true; }
void intersection(const Query& query, const Primitive& primitive)
{
boost::optional< typename AABBTraits::template Intersection_and_primitive_id<Query>::Type >
intersection = m_traits.intersection_object()(query, primitive);
if(intersection)
{
*m_out_it++ = *intersection;
}
}
bool do_intersect(const Query& query, const Node& node) const
{
return m_traits.do_intersect_object()(query, node.bbox());
}
private:
Output_iterator m_out_it;
const AABBTraits& m_traits;
};
/**
* @class Listing_primitive_traits
*/
template<typename AABBTraits, typename Query, typename Output_iterator>
class Listing_primitive_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
Listing_primitive_traits(Output_iterator out_it, const AABBTraits& traits)
: m_out_it(out_it), m_traits(traits) {}
bool go_further() const { return true; }
void intersection(const Query& query, const Primitive& primitive)
{
if( m_traits.do_intersect_object()(query, primitive) )
{
*m_out_it++ = primitive.id();
}
}
bool do_intersect(const Query& query, const Node& node) const
{
return m_traits.do_intersect_object()(query, node.bbox());
}
private:
Output_iterator m_out_it;
const AABBTraits& m_traits;
};
/**
* @class First_primitive_traits
*/
template<typename AABBTraits, typename Query>
class First_primitive_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
First_primitive_traits(const AABBTraits& traits)
: m_is_found(false)
, m_result()
, m_traits(traits) {}
bool go_further() const { return !m_is_found; }
void intersection(const Query& query, const Primitive& primitive)
{
if( m_traits.do_intersect_object()(query, primitive) )
{
m_result = boost::optional<typename Primitive::Id>(primitive.id());
m_is_found = true;
}
}
bool do_intersect(const Query& query, const Node& node) const
{
return m_traits.do_intersect_object()(query, node.bbox());
}
boost::optional<typename Primitive::Id> result() const { return m_result; }
bool is_intersection_found() const { return m_is_found; }
private:
bool m_is_found;
boost::optional<typename Primitive::Id> m_result;
const AABBTraits& m_traits;
};
/**
* @class Do_intersect_traits
*/
template<typename AABBTraits, typename Query>
class Do_intersect_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
Do_intersect_traits(const AABBTraits& traits)
: m_is_found(false), m_traits(traits)
{}
bool go_further() const { return !m_is_found; }
void intersection(const Query& query, const Primitive& primitive)
{
if( m_traits.do_intersect_object()(query, primitive) )
m_is_found = true;
}
bool do_intersect(const Query& query, const Node& node) const
{
return m_traits.do_intersect_object()(query, node.bbox());
}
bool is_intersection_found() const { return m_is_found; }
private:
bool m_is_found;
const AABBTraits& m_traits;
};
/**
* @class Projection_traits
*/
template <typename AABBTraits>
class Projection_traits
{
typedef typename AABBTraits::FT FT;
typedef typename AABBTraits::Point_3 Point;
typedef typename AABBTraits::Primitive Primitive;
typedef typename AABBTraits::Bounding_box Bounding_box;
typedef typename AABBTraits::Primitive::Id Primitive_id;
typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
typedef ::CGAL::AABB_node<AABBTraits> Node;
public:
Projection_traits(const Point& hint,
const typename Primitive::Id& hint_primitive,
const AABBTraits& traits)
: m_closest_point(hint),
m_closest_primitive(hint_primitive),
m_traits(traits)
{}
bool go_further() const { return true; }
void intersection(const Point& query, const Primitive& primitive)
{
Point new_closest_point = m_traits.closest_point_object()
(query, primitive, m_closest_point);
if( !m_traits.equal_3_object()(new_closest_point, m_closest_point) )
{
m_closest_primitive = primitive.id();
m_closest_point = new_closest_point; // this effectively shrinks the sphere
}
}
bool do_intersect(const Point& query, const Node& node) const
{
return m_traits.compare_distance_object()
(query, node.bbox(), m_closest_point) == CGAL::SMALLER;
}
Point closest_point() const { return m_closest_point; }
Point_and_primitive_id closest_point_and_primitive() const
{
return Point_and_primitive_id(m_closest_point, m_closest_primitive);
}
private:
Point m_closest_point;
typename Primitive::Id m_closest_primitive;
const AABBTraits& m_traits;
};
}}} // end namespace CGAL::internal::AABB_tree
#endif // CGAL_AABB_TRAVERSAL_TRAITS_H
@@ -0,0 +1,72 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
//******************************************************************************
// File Description :
//
//******************************************************************************
#ifndef CGAL_INTERNAL_AABB_TREE_HAS_NESTED_TYPE_SHARED_DATA_H
#define CGAL_INTERNAL_AABB_TREE_HAS_NESTED_TYPE_SHARED_DATA_H
#include <CGAL/license/AABB_tree.h>
#include <boost/mpl/has_xxx.hpp>
#include <CGAL/tags.h>
namespace CGAL{
namespace internal{
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_Shared_data,Shared_data,false)
// Utility class used by AABB_face_graph_triangle_primitive and AABB_halfedge_graph_segment_primitive
// to implement the Construct_shared_data static function.
template<class Graph, class Base, class ObjectPropertyMap, class PointPropertyMap, class HasSharedDataTag>
struct Cstr_shared_data;
template<class Graph, class Base, class ObjectPropertyMap, class PointPropertyMap>
struct Cstr_shared_data<Graph, Base, ObjectPropertyMap, PointPropertyMap, ::CGAL::Tag_true>
{
typedef typename Base::Shared_data Shared_data;
static Shared_data construct_shared_data(Graph& graph)
{
return Base::construct_shared_data(ObjectPropertyMap(&graph), PointPropertyMap(&graph));
}
template <class VertexPmap>
static Shared_data construct_shared_data(Graph& graph, const VertexPmap& vpm)
{
return Base::construct_shared_data(ObjectPropertyMap(&graph, vpm), PointPropertyMap(&graph, vpm));
}
};
template<class Graph, class Base, class ObjectPropertyMap, class PointPropertyMap>
struct Cstr_shared_data<Graph, Base, ObjectPropertyMap, PointPropertyMap, ::CGAL::Tag_false>
{
typedef void* Shared_data;
static Shared_data construct_shared_data(Graph&)
{
return nullptr;
}
template <class VertexPmap>
static Shared_data construct_shared_data(Graph&, VertexPmap)
{
return nullptr;
}
};
} } //namespace CGAL
#endif //CGAL_INTERNAL_AABB_TREE_HAS_NESTED_TYPE_SHARED_DATA_H
@@ -0,0 +1,47 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Philipp Moeller
//
#ifndef CGAL_IS_RAY_INTERSECTION_GEOMTRAITS_H
#define CGAL_IS_RAY_INTERSECTION_GEOMTRAITS_H
#include <CGAL/license/AABB_tree.h>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/and.hpp>
namespace CGAL {
namespace internal {
namespace AABB_tree {
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_ray_3,Ray_3,false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_construct_source_3,Construct_source_3,false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_vector_3,Construct_vector_3,false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_construct_cartesian_const_iterator_3,Construct_cartesian_const_iterator_3,false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_cartesian_const_iterator_3,Cartesian_const_iterator_3,false)
template<typename GeomTraits>
struct Is_ray_intersection_geomtraits
: boost::mpl::and_< Has_ray_3<GeomTraits>,
Has_construct_source_3<GeomTraits>,
Has_vector_3<GeomTraits>,
Has_construct_cartesian_const_iterator_3<GeomTraits>,
Has_cartesian_const_iterator_3<GeomTraits> >::type
{};
} // AABB_tree
} // internal
} // CGAL
#endif /* CGAL_IS_RAY_INTERSECTION_GEOMTRAITS_H */
@@ -0,0 +1,66 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_AABB_TREE_PRIMITIVE_HELPER
#define CGAL_INTERNAL_AABB_TREE_PRIMITIVE_HELPER
#include <CGAL/license/AABB_tree.h>
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
#include <boost/mpl/has_xxx.hpp>
namespace CGAL{
namespace internal{
//for backward compatibility: if Datum_reference and Point_reference are not defined in the primitive
//(using auto would solve the pb)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_Datum_reference,Datum_reference,false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_Point_reference,Point_reference,false)
template<class Primitive,bool has_nested_type=Has_nested_type_Datum_reference<Primitive>::value>
struct Datum_result_type{ typedef typename Primitive::Datum_reference type; };
template<class Primitive>
struct Datum_result_type<Primitive,false>{ typedef typename Primitive::Datum type; };
template<class Primitive,bool has_nested_type=Has_nested_type_Point_reference<Primitive>::value>
struct Point_result_type{ typedef typename Primitive::Point_reference type; };
template<class Primitive>
struct Point_result_type<Primitive,false>{ typedef typename Primitive::Point type; };
//helper controlling whether extra data should be stored in the AABB_tree traits class
template <class AABBTraits, bool has_shared_data=Has_nested_type_Shared_data<typename AABBTraits::Primitive>::value>
struct Primitive_helper;
template <class AABBTraits>
struct Primitive_helper<AABBTraits,true>{
typedef typename Datum_result_type<typename AABBTraits::Primitive>::type Datum_type;
static Datum_type get_datum(const typename AABBTraits::Primitive& p,const AABBTraits& traits)
{
return p.datum(traits.shared_data());
}
typedef typename Point_result_type<typename AABBTraits::Primitive>::type Reference_point_type;
static Reference_point_type get_reference_point(const typename AABBTraits::Primitive& p,const AABBTraits& traits) {
return p.reference_point(traits.shared_data());
}
};
template <class AABBTraits>
struct Primitive_helper<AABBTraits,false>{
typedef typename Datum_result_type<typename AABBTraits::Primitive>::type Datum_type;
static Datum_type get_datum(const typename AABBTraits::Primitive& p,const AABBTraits&) {return p.datum();}
typedef typename Point_result_type<typename AABBTraits::Primitive>::type Reference_point_type;
static Reference_point_type get_reference_point(const typename AABBTraits::Primitive& p,const AABBTraits&) {return p.reference_point();}
};
} } //namespace CGAL::internal
#endif //CGAL_INTERNAL_AABB_TREE_PRIMITIVE_HELPER
@@ -0,0 +1,102 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_AABB_TRIANGLE_PRIMITIVE_H_
#define CGAL_AABB_TRIANGLE_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <CGAL/AABB_primitive.h>
#include <iterator>
namespace CGAL {
namespace internal {
template <class GeomTraits, class Iterator>
struct Point_from_triangle_3_iterator_property_map{
//classical typedefs
typedef Iterator key_type;
typedef typename GeomTraits::Point_3 value_type;
// typedef decltype(
// std::declval<typename GeomTraits::Construct_vertex_3>()(
// std::declval<typename GeomTraits::Triangle_3>(),
// std::declval<int>())) reference;
typedef decltype(
typename GeomTraits::Construct_vertex_3()(
*std::declval<key_type&>(), 0)) reference;
typedef boost::readable_property_map_tag category;
typedef Point_from_triangle_3_iterator_property_map<GeomTraits, Iterator> Self;
inline friend reference
get(Self, key_type it)
{
return typename GeomTraits::Construct_vertex_3()( *it, 0 );
}
};
}//namespace internal
/*!
* \ingroup PkgAABBTreeRef
* Primitive type that uses as identifier an iterator with a 3D triangle as `value_type`.
* The iterator from which the primitive is built should not be invalided
* while the AABB tree holding the primitive is in use.
*
* \cgalModels `AABBPrimitive`
*
* \tparam GeomTraits is a traits class providing the nested type `Point_3` and `Triangle_3`.
* It also provides the functor `Construct_vertex_3` that has an operator taking a `Triangle_3`
* and an integer as parameters and returning a triangle point as a type convertible to `Point_3`.
* \tparam Iterator is a model of `ForwardIterator` with its value type convertible to `GeomTraits::Triangle_3`
* \tparam CacheDatum is either `CGAL::Tag_true` or `CGAL::Tag_false`. In the former case,
* the datum is stored in the primitive, while in the latter it is
* constructed on the fly to reduce the memory footprint.
* The default is `CGAL::Tag_false` (datum is not stored).
*
* \sa `AABBPrimitive`
* \sa `AABB_primitive<Id,ObjectPropertyMap,PointPropertyMapPolyhedron,ExternalPropertyMaps,CacheDatum>`
* \sa `AABB_segment_primitive<Iterator,CacheDatum>`
* \sa `AABB_halfedge_graph_segment_primitive<HalfedgeGraph,OneHalfedgeGraphPerTree,CacheDatum>`
* \sa `AABB_face_graph_triangle_primitive<FaceGraph,OneFaceGraphPerTree,CacheDatum>`
*/
template < class GeomTraits,
class Iterator,
class CacheDatum=Tag_false>
class AABB_triangle_primitive
#ifndef DOXYGEN_RUNNING
: public AABB_primitive< Iterator,
Input_iterator_property_map<Iterator>,
internal::Point_from_triangle_3_iterator_property_map<GeomTraits, Iterator>,
Tag_false,
CacheDatum >
#endif
{
typedef AABB_primitive< Iterator,
Input_iterator_property_map<Iterator>,
internal::Point_from_triangle_3_iterator_property_map<GeomTraits, Iterator>,
Tag_false,
CacheDatum > Base;
public:
///constructor from an iterator
AABB_triangle_primitive(Iterator it) : Base(it){}
};
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_AABB_TRIANGLE_PRIMITIVE_H_
@@ -0,0 +1,99 @@
// Copyright (c) 2017 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author : Jane Tournois
//
#ifndef CGAL_AABB_TRIANGULATION_3_CELL_PRIMITIVE_H_
#define CGAL_AABB_TRIANGULATION_3_CELL_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/AABB_primitive.h>
#include <iterator>
namespace CGAL
{
namespace internal
{
template <class GeomTraits, class Iterator>
struct Point_from_cell_iterator_proprety_map
{
//classical typedefs
typedef Iterator key_type;
typedef typename GeomTraits::Point_3 value_type;
typedef decltype(
std::declval<typename GeomTraits::Construct_vertex_3>()(
std::declval<typename GeomTraits::Tetrahedron_3>(),
std::declval<int>())) reference;
// typedef decltype(
// typename GeomTraits::Construct_vertex_3()(
// *std::declval<key_type&>(), 0)) reference; // fails polyhedron demo!
typedef boost::readable_property_map_tag category;
typedef Point_from_cell_iterator_proprety_map<GeomTraits, Iterator> Self;
inline friend reference
get(Self, key_type it)
{
typename GeomTraits::Construct_point_3 point;
return point(it->vertex(1)->point());
}
};
template <class GeomTraits, class Iterator>
struct Tet_from_cell_iterator_proprety_map
{
//classical typedefs
typedef Iterator key_type;
typedef typename GeomTraits::Tetrahedron_3 value_type;
typedef value_type reference;
typedef boost::readable_property_map_tag category;
inline friend
value_type
get(Tet_from_cell_iterator_proprety_map<GeomTraits, Iterator>, key_type it)
{
typename GeomTraits::Construct_point_3 point;
return value_type(point(it->vertex(0)->point()),
point(it->vertex(1)->point()),
point(it->vertex(2)->point()),
point(it->vertex(3)->point()));
}
};
}//namespace internal
template < class GeomTraits,
class Tr,
class CacheDatum = Tag_false,
class Handle = typename Tr::Cell_handle>
class AABB_triangulation_3_cell_primitive
#ifndef DOXYGEN_RUNNING
: public AABB_primitive< Handle,
internal::Tet_from_cell_iterator_proprety_map<GeomTraits, Handle>,
internal::Point_from_cell_iterator_proprety_map<GeomTraits, Handle>,
Tag_false,
CacheDatum >
#endif
{
typedef AABB_primitive< Handle,
internal::Tet_from_cell_iterator_proprety_map<GeomTraits, Handle>,
internal::Point_from_cell_iterator_proprety_map<GeomTraits, Handle>,
Tag_false,
CacheDatum > Base;
public:
AABB_triangulation_3_cell_primitive(Handle h) : Base(h){} };
} // end namespace CGAL
#endif // CGAL_AABB_TRIANGULATION_3_CELL_PRIMITIVE_H_
@@ -0,0 +1,116 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Stéphane Tayeb, Pierre Alliez
//
#ifndef AABB_TRIANGULATION_3_TRIANGLE_PRIMITIVE_H_
#define AABB_TRIANGULATION_3_TRIANGLE_PRIMITIVE_H_
#include <CGAL/license/AABB_tree.h>
#include <CGAL/disable_warnings.h>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
namespace CGAL {
// \ingroup PkgAABBTreeRef
// Primitive type that wraps a facet handle of a CGAL::Triangulation_3,
// which is used as id, and allows the construction of the datum on
// the fly. Since only the facet handle is stored in this primitive,
// the TriangleMesh from which the AABB tree is built should not be
// deleted while the AABB tree is in use.
//
// \cgalModels `AABBPrimitive`
// \tparam GeomTraits must provides a \c %Point_3
// type, used as \c Point, and a \c %Triangle_3 type, used as \c
// Datum and constructible from three arguments of type \c
// Point.
// \tparam Tr must be a
// \c CGAL::Triangulation_3 whose points have type \c Point.
//
// \sa `AABBPrimitive`
template<typename GeomTraits, typename Tr>
class AABB_triangulation_3_triangle_primitive
{
public:
typedef typename GeomTraits::Point_3 Point;
// \name Types
// @{
// Id type.
typedef typename Tr::Facet Id;
// Geometric data type.
typedef typename GeomTraits::Triangle_3 Datum;
// @}
// Self
typedef AABB_triangulation_3_triangle_primitive<GeomTraits, Tr> Self;
// Constructors
AABB_triangulation_3_triangle_primitive() {}
AABB_triangulation_3_triangle_primitive(const AABB_triangulation_3_triangle_primitive& primitive)
{
m_facet = primitive.id();
}
AABB_triangulation_3_triangle_primitive(const Id& handle)
: m_facet(handle) { }
AABB_triangulation_3_triangle_primitive(const Id* ptr)
: m_facet(*ptr) { }
template <class Iterator>
AABB_triangulation_3_triangle_primitive( Iterator it,
typename boost::enable_if<
boost::is_same<Id,typename Iterator::value_type>
>::type* =0
) : m_facet(*it) { }
// Default destructor, copy constructor and assignment operator are ok
// Returns by constructing on the fly the geometric datum wrapped by the primitive
Datum datum() const
{
typename GeomTraits::Construct_point_3 cp =
GeomTraits().construct_point_3_object();
int i = m_facet.second;
const Point& a = cp(m_facet.first->vertex((i+1) &3)->point());
const Point& b = cp(m_facet.first->vertex((i+2) &3)->point());
const Point& c = cp(m_facet.first->vertex((i+3) &3)->point());
return Datum(a,b,c);
}
// Returns a point on the primitive
Point reference_point() const
{
typename GeomTraits::Construct_point_3 cp =
GeomTraits().construct_point_3_object();
return cp(m_facet.first->vertex((m_facet.second +1) &3)->point());
}
// Returns the identifier
const Id& id() const { return m_facet; }
Id& id() { return m_facet; }
private:
// The id, here a Tr::Facet
Id m_facet;
}; // end class AABB_triangulation_3_triangle_primitive
} // end namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // AABB_TRIANGULATION_3_TRIANGLE_PRIMITIVE_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_AFSR_SURFACE_FACE_BASE_2_H
#define CGAL_AFSR_SURFACE_FACE_BASE_2_H
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
// This face class stores a facet in the tetrahedrization
// When it gets reoriented by the TDS, it also changes the facet
namespace CGAL {
namespace AFSR {
template < typename GT,
typename F3,
typename Fb = CGAL::Triangulation_ds_face_base_2<> >
class Surface_face_base_2
: public Fb
{
typedef typename Fb::Triangulation_data_structure Tds;
public:
typedef typename Tds::Face_handle Face_handle;
typedef typename Tds::Vertex_handle Vertex_handle;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
typedef Surface_face_base_2<GT, F3, Fb2> Other;
};
private:
F3 _facet;
bool _is_on_surface;
public:
Surface_face_base_2()
: Fb(), _is_on_surface(true)
{}
Surface_face_base_2(Vertex_handle v0,
Vertex_handle v1,
Vertex_handle v2)
: Fb(v0, v1, v2), _is_on_surface(true)
{}
Surface_face_base_2(Vertex_handle v0,
Vertex_handle v1,
Vertex_handle v2,
Face_handle n0,
Face_handle n1,
Face_handle n2)
: Fb(v0, v1, v2, n0, n1, n2), _is_on_surface(true)
{}
void set_facet(const F3& facet)
{
_facet = facet;
}
const F3& facet() const
{
return _facet;
}
void set_is_on_surface(bool is_on_surface)
{
_is_on_surface = is_on_surface;
}
bool is_on_surface() const
{
return _is_on_surface;
}
void reorient()
{
Fb::reorient();
if( is_on_surface()){
_facet = std::make_pair(_facet.first->neighbor(_facet.second),
_facet.first->neighbor(_facet.second)->index(_facet.first));
}
}
};
} // namespace AFSR
} // namespace CGAL
#endif // CGAL_AFSR_SURFACE_FACE_BASE_2_H
@@ -0,0 +1,73 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_AFSR_SURFACE_VERTEX_BASE_2_H
#define CGAL_AFSR_SURFACE_VERTEX_BASE_2_H
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
#include <CGAL/basic.h>
#include <CGAL/Triangulation_ds_vertex_base_2.h>
namespace CGAL {
namespace AFSR {
template < typename GT,
typename V3,
typename Vb = CGAL::Triangulation_ds_vertex_base_2<> >
class Surface_vertex_base_2
: public Vb
{
typedef typename Vb::Triangulation_data_structure Tds;
public:
typedef GT Geom_traits;
typedef typename GT::Point_3 Point;
typedef Tds Triangulation_data_structure;
typedef typename Tds::Face_handle Face_handle;
typedef typename Tds::Vertex_handle Vertex_handle;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
typedef Surface_vertex_base_2<GT,V3, Vb2> Other;
};
private:
V3 _vertex;
public:
Surface_vertex_base_2() : Vb() {}
Surface_vertex_base_2(Face_handle f) : Vb(f) {}
void set_vertex(const V3& v)
{
_vertex = v;
}
V3 vertex_3() const
{
return _vertex;
}
const Point& point() const { return _vertex->point(); }
};
} // namespace AFSR
} // namespace CGAL
#endif //CGAL::AFSR_SURFACE_VERTEX_BASE_2_H
@@ -0,0 +1,85 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
#define CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
namespace CGAL {
template <class Triangulation, class Filter>
class Advancing_front_polyhedron_reconstruction;
namespace AFSR {
template <class HDS, class Surface>
class Construct_polyhedron: public CGAL::Modifier_base<HDS> {
const Surface& s;
public:
Construct_polyhedron(Surface& s)
: s(s)
{}
void operator()( HDS& hds)
{
CGAL::Polyhedron_incremental_builder_3<HDS> B( hds, true);
B.begin_surface( s.number_of_vertices(), s.number_of_facets(), 6* s.number_of_facets());
typedef typename Surface::TDS_2 TDS_2;
typedef typename TDS_2::Face_iterator Face_iterator;
typedef typename TDS_2::Vertex_iterator Vertex_iterator;
const TDS_2& tds = s.triangulation_data_structure_2();
std::size_t index = 0;
Vertex_iterator end = tds.vertices_end();
for(Vertex_iterator vit = tds.vertices_begin(); vit != end; ++vit){
if(vit->vertex_3() != s.triangulation_3().infinite_vertex()){
B.add_vertex(vit->point());
vit->vertex_3()->id() = index++;
}
}
for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){
if(fit->is_on_surface()){
B.begin_facet();
for(int i=0; i < 3; i++){
B.add_vertex_to_facet(fit->vertex(i)->vertex_3()->id());
}
B.end_facet();
}
}
B.end_surface();
}
};
template <class Polyhedron, class Surface>
void
construct_polyhedron(Polyhedron& P, Surface& surface)
{
typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
Construct_polyhedron<HalfedgeDS, Surface> builder(surface);
P.delegate(builder);
}
} // namespace AFSR
} // namespace CGAL
#endif // CGAL_AFSR_CONSTRUCT_POLYHEDRON_2
@@ -0,0 +1,142 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_AFSR_CONSTRUCT_SURFACE_2
#define CGAL_AFSR_CONSTRUCT_SURFACE_2
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
namespace CGAL {
template <class Triangulation, class Filter>
class Advancing_front_surface_reconstruction;
namespace AFSR {
template <class Tr, class TDS, class Filter>
typename TDS::Vertex_handle
construct_surface(TDS& tds, const Advancing_front_surface_reconstruction<Tr,Filter>& surface)
{
typedef typename TDS::Vertex_handle Vertex_handle;
typedef std::pair<Vertex_handle,Vertex_handle> Vh_pair;
typedef typename TDS::Face_handle Face_handle;
typedef typename TDS::Edge Edge;
typedef typename Advancing_front_surface_reconstruction<Tr,Filter>::Triangulation_3 Triangulation;
Triangulation& T = surface.triangulation_3();
// create an infinite-vertex and infinite faces with the
// boundary edges if any.
// return the infinite vertex if created
Vertex_handle vinf;
std::vector<Vertex_handle > vvh;
if(tds.number_of_vertices() != 0){
tds.clear();
}
int dim = 2;
tds.set_dimension(dim);
CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int> vertex_index_map(-1, T.number_of_vertices());
int i=0;
for (typename Triangulation::Finite_vertices_iterator v_it = T.finite_vertices_begin();
v_it != T.finite_vertices_end();
v_it++){
typename CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int>::Data& d = vertex_index_map[v_it];
if ((!v_it->is_exterior()) && d == -1){
d = i;
Vertex_handle vh = tds.create_vertex();
vvh.push_back(vh);
vh->set_vertex(typename Triangulation::Vertex_handle(v_it));
i++;
}
}
std::map<Vh_pair, Edge> edge_map;
for(typename Triangulation::Finite_facets_iterator f_it = T.finite_facets_begin();
f_it != T.finite_facets_end();
f_it++)
{
typename Triangulation::Cell_handle n, c = (*f_it).first;
int ni, ci = (*f_it).second;
n = c->neighbor(ci);
ni = n->index(c);
int i1, i2 ,i3;
if (c->is_selected_facet(ci))
{
i1 = (ci+1) & 3;
i2 = (ci+2) & 3;
i3 = (ci+3) & 3;
Face_handle fh = tds.create_face(vvh[vertex_index_map[c->vertex(i1)]],
vvh[vertex_index_map[c->vertex(i2)]],
vvh[vertex_index_map[c->vertex(i3)]]);
fh->set_facet(*f_it);
vvh[vertex_index_map[c->vertex(i1)]]->set_face(fh);
vvh[vertex_index_map[c->vertex(i2)]]->set_face(fh);
vvh[vertex_index_map[c->vertex(i3)]]->set_face(fh);
for (int ih = 0; ih < 3; ++ih) {
tds.set_adjacency(fh, ih, edge_map);
}
}
if (n->is_selected_facet(ni))
{
i1 = (ni+1) & 3;
i2 = (ni+2) & 3;
i3 = (ni+3) & 3;
Face_handle fh = tds.create_face(vvh[vertex_index_map[n->vertex(i1)]],
vvh[vertex_index_map[n->vertex(i2)]],
vvh[vertex_index_map[n->vertex(i3)]]);
fh->set_facet(std::make_pair(n, ni));
vvh[vertex_index_map[n->vertex(i1)]]->set_face(fh);
vvh[vertex_index_map[n->vertex(i2)]]->set_face(fh);
vvh[vertex_index_map[n->vertex(i3)]]->set_face(fh);
for (int ih = 0; ih < 3; ++ih) {
tds.set_adjacency(fh, ih, edge_map);
}
}
}
if ( !edge_map.empty()) {
vinf = tds.create_vertex();
vinf->set_vertex(T.infinite_vertex());
std::map<Vh_pair, Edge> inf_edge_map;
while (!edge_map.empty()) {
Face_handle fh = edge_map.begin()->second.first;
int ih = edge_map.begin()->second.second;
Face_handle fn = tds.create_face( vinf,
fh->vertex(TDS::cw(ih)),
fh->vertex(TDS::ccw(ih)));
fn->set_facet(std::make_pair( typename Triangulation::Cell_handle(),0));
fn->set_is_on_surface(false);
vinf->set_face(fn);
tds.set_adjacency(fn, 0, fh, ih);
tds.set_adjacency(fn, 1, inf_edge_map);
tds.set_adjacency(fn, 2, inf_edge_map);
edge_map.erase(edge_map.begin());
}
CGAL_assertion(inf_edge_map.empty());
}
tds.reorient_faces();
return vinf;
}
} // namespace AFSR
} // namespace CGAL
#endif // CGAL_AFSR_CONSTRUCT_SURFACE_2
@@ -0,0 +1,55 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_AFSR_WRITE_TRIPLE_INDICES_H
#define CGAL_AFSR_WRITE_TRIPLE_INDICES_H
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
#include <CGAL/array.h>
namespace CGAL {
template <class Triangulation, class Filter>
class Advancing_front_surface_reconstruction;
template <class OutputIterator, class Triangulation, class Filter>
OutputIterator
write_triple_indices(OutputIterator out, const Advancing_front_surface_reconstruction<Triangulation,Filter>& S)
{
typedef Advancing_front_surface_reconstruction<Triangulation,Filter> Surface;
typedef typename Surface::TDS_2 TDS_2;
typedef typename TDS_2::Face_iterator Face_iterator;
if(S.triangulation_3().dimension() < 3){
std::cerr << "not 3D\n";
return out;
}
const TDS_2& tds = S.triangulation_data_structure_2();
for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){
if(fit->is_on_surface()){
*out++ = CGAL::make_array(fit->vertex(0)->vertex_3()->id(),
fit->vertex(1)->vertex_3()->id(),
fit->vertex(2)->vertex_3()->id());
}
}
return out;
}
}
#endif
@@ -0,0 +1,247 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
#define CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
namespace CGAL {
/*!
\ingroup PkgAdvancingFrontSurfaceReconstructionRef
The class `Advancing_front_surface_reconstruction_cell_base_3` is the default
cell type for the class `Advancing_front_surface_reconstruction`.
\tparam Traits has to be a model of `DelaunayTriangulationTraits_3`.
\tparam Cb has to be a model of `DelaunayTriangulationCellBase_3`.
*/
template < typename Traits, typename Cb = Delaunay_triangulation_cell_base_3<Traits> >
class Advancing_front_surface_reconstruction_cell_base_3 : public Cb
{
public:
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Cb::template Rebind_TDS<TDS2>::Other Cb2;
typedef Advancing_front_surface_reconstruction_cell_base_3<Traits,Cb2> Other;
};
typedef typename Cb::Vertex_handle Vertex_handle;
typedef typename Cb::Cell_handle Cell_handle;
private:
#ifdef AFSR_FACET_NUMBER
int _facet_number[4];
#endif
typedef double coord_type;
#ifdef AFSR_LAZY
typedef typename CGAL::Simple_cartesian<coord_type>::Point_3 D_Point;
#endif
//-------------------- DATA MEMBERS ---------------------------------
coord_type* _smallest_radius_facet_tab;
unsigned char selected_facet;
#ifdef AFSR_LAZY
D_Point* _circumcenter;
coord_type* _squared_radius;
#endif
//-------------------- CONSTRUCTORS ----------------------------------
public:
Advancing_front_surface_reconstruction_cell_base_3()
: Cb(),
_smallest_radius_facet_tab(nullptr), selected_facet(0)
#ifdef AFSR_LAZY
, _circumcenter(nullptr), _squared_radius(nullptr)
#endif
{
#ifdef AFSR_FACET_NUMBER
for(int i = 0; i < 4; i++){
_facet_number[i] = -1;
}
#endif
}
Advancing_front_surface_reconstruction_cell_base_3(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3)
: Cb( v0, v1, v2, v3),
_smallest_radius_facet_tab(nullptr), selected_facet(0)
#ifdef AFSR_LAZY
, _circumcenter(nullptr), _squared_radius(nullptr)
#endif
{
#ifdef FACET_NUMBER
for(int i = 0; i < 4; i++){
_facet_number[i] = -1;
}
#endif
}
Advancing_front_surface_reconstruction_cell_base_3(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3,
Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3)
: Cb(v0, v1, v2, v3,
n0, n1, n2, n3),
_smallest_radius_facet_tab(nullptr), selected_facet(0)
#ifdef AFSR_LAZY
, _circumcenter(nullptr), _squared_radius(nullptr)
#endif
{
#ifdef AFSR_FACET_NUMBER
for(int i = 0; i < 4; i++){
_facet_number[i] = -1;
}
#endif
}
//-------------------- DESTRUCTOR -----------------------------------
inline ~Advancing_front_surface_reconstruction_cell_base_3()
{
if (_smallest_radius_facet_tab != nullptr)
delete[] _smallest_radius_facet_tab;
#ifdef AFSR_LAZY
if (_circumcenter != nullptr)
delete _circumcenter;
if (_squared_radius != nullptr)
delete _squared_radius;
#endif
}
//-------------------- MEMBER FUNCTIONS ----------------------------
public:
inline void clear()
{
if (_smallest_radius_facet_tab != nullptr)
delete[] _smallest_radius_facet_tab;
_smallest_radius_facet_tab = nullptr;
selected_facet = 0;
#ifdef AFSR_LAZY
if (_circumcenter != nullptr)
delete _circumcenter;
_circumcenter = nullptr;
if (_squared_radius != nullptr)
delete _squared_radius;
_squared_radius = nullptr;
#endif
}
//-------------------------------------------------------------------
inline coord_type smallest_radius(const int& i)
{
if (_smallest_radius_facet_tab == nullptr)
return -1;
return _smallest_radius_facet_tab[i];
}
inline void set_smallest_radius(const int& i, const coord_type& c)
{
if (_smallest_radius_facet_tab == nullptr)
{
_smallest_radius_facet_tab = new coord_type[4];
for(int i = 0; i < 4; i++)
_smallest_radius_facet_tab[i] = -1;
}
_smallest_radius_facet_tab[i] = c;
}
// pour un controle de l'allocation memoire... utile???
inline bool alloc_smallest_radius_tab(coord_type* ptr)
{
if (_smallest_radius_facet_tab==nullptr)
{
_smallest_radius_facet_tab = ptr;
return true;
}
return false;
}
//-------------------------------------------------------------------
#ifdef FACET_NUMBER
void set_facet_number(int i, int n){}
{
_facet_number[i] = n;
}
int facet_number(int i)
{
return _facet_number[i];
}
#else
void set_facet_number(int, int){}
int facet_number(int){return 0;}
#endif
//-------------------------------------------------------------------
inline void select_facet(const int& i)
{
selected_facet |= (1 << i);
}
inline void unselect_facet(const int& i)
{
selected_facet &= (15 - (1 << i));
}
inline bool is_selected_facet(const int& i)
{
return (selected_facet & (1 << i)) != 0;
}
inline bool has_facet_on_surface(const int& i)
{
return (selected_facet & (1 << i)) != 0;
}
#ifdef AFSR_LAZY
//-------------------------------------------------------------------
inline D_Point* lazy_circumcenter()
{
return _circumcenter;
}
inline void set_lazy_circumcenter(const D_Point& p)
{
_circumcenter = new D_Point(p);
}
//-------------------------------------------------------------------
inline coord_type* lazy_squared_radius()
{
return _squared_radius;
}
inline void set_lazy_squared_radius(const coord_type& sr)
{
_squared_radius = new coord_type(sr);
}
#endif //AFSR_LAZY
};
} // namespace CGAL
#endif // CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_CELL_BASE_3_H
@@ -0,0 +1,281 @@
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
#ifndef CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_WITH_ID_3_H
#define CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_WITH_ID_3_H
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
#include <CGAL/Triangulation_vertex_base_3.h>
#include <CGAL/utility.h>
#include <utility>
#include <list>
namespace CGAL {
template <class B, class C> class Advancing_front_surface_reconstruction;
/*!
\ingroup PkgAdvancingFrontSurfaceReconstructionRef
The class `Advancing_front_surface_reconstruction_vertex_base_3` is the default
vertex type for the class `Advancing_front_surface_reconstruction`.
\tparam Traits has to be a model of `DelaunayTriangulationTraits_3`.
\tparam Vb has to be a model of `TriangulationVertexBase_3`.
*/
template <typename Traits, typename Vb = Triangulation_vertex_base_3<Traits> >
class Advancing_front_surface_reconstruction_vertex_base_3 : public Vb
{
public:
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
typedef Advancing_front_surface_reconstruction_vertex_base_3<Traits,Vb2> Other;
};
template <class B,class C> friend class Advancing_front_surface_reconstruction;
typedef Vb Base;
typedef typename Base::Vertex_handle Vertex_handle;
typedef typename Base::Cell_handle Cell_handle;
typedef typename Vb::Point Point;
typedef double coord_type;
typedef Triple< Cell_handle, int, int > Edge;
typedef std::pair< Edge, int > Edge_incident_facet;
typedef std::pair< Edge_incident_facet, Edge_incident_facet > IO_edge_type;
typedef coord_type criteria;
typedef std::pair< criteria, IO_edge_type > Radius_edge_type;
typedef std::pair< Radius_edge_type, int > Border_elt;
typedef std::pair< Vertex_handle, Border_elt > Next_border_elt;
//par convention je remplis d'abord first et si necessaire second...
typedef std::pair< Next_border_elt*, Next_border_elt*> Intern_successors_type;
public:
typedef std::pair< criteria, IO_edge_type* > Radius_ptr_type;
typedef std::pair< Vertex_handle, Vertex_handle > Edge_like;
typedef std::pair< criteria, Edge_like > Incidence_request_elt;
typedef std::list< Incidence_request_elt > Incidence_request_type;
typedef typename Incidence_request_type::iterator Incidence_request_iterator;
//-------------------- DATA MEMBERS ---------------------------------
typedef std::size_t Info; // so that we are a model of TriangulationVertexBaseWithInfo_3
private:
std::size_t m_id;
int m_mark;
int m_post_mark;
Intern_successors_type* m_incident_border;
// Instead of having a set per vertex, there is a global list
// in the surface reconstruction class
// and two iterators per vertex in this list
// Note that m_ie_last is not past the end
// m_ie_first == m_ie_last == interior_edge.end() iff the set is empty
typename std::list<Vertex_handle>::iterator m_ie_first, m_ie_last;
// We do the same for the incidence requests
typename std::list< Incidence_request_elt >::iterator m_ir_first, m_ir_last;
//-------------------- CONSTRUCTORS ---------------------------------
public:
Advancing_front_surface_reconstruction_vertex_base_3()
: Vb(), m_mark(-1),
m_post_mark(-1)
{}
Advancing_front_surface_reconstruction_vertex_base_3(const Point & p)
: Vb(p), m_mark(-1),
m_post_mark(-1)
{}
Advancing_front_surface_reconstruction_vertex_base_3(const Point & p, Cell_handle f)
: Vb(p, f), m_mark(-1),
m_post_mark(-1)
{}
Advancing_front_surface_reconstruction_vertex_base_3(Cell_handle f)
: Vb(f), m_mark(-1),
m_post_mark(-1)
{}
Advancing_front_surface_reconstruction_vertex_base_3(const Advancing_front_surface_reconstruction_vertex_base_3& other)
: Vb(other), m_mark(-1),
m_post_mark(-1)
{}
//-------------------- MEMBER FUNCTIONS -----------------------------
public:
std::size_t& id()
{
return m_id;
}
const std::size_t& id() const
{
return m_id;
}
std::size_t& info()
{
return m_id;
}
const std::size_t& info() const
{
return m_id;
}
//-------------------------------------------------------------------
private:
void delete_border()
{
m_incident_border = nullptr;
}
inline Next_border_elt* next_on_border(const int& i) const
{
if (m_incident_border == nullptr) return nullptr; //vh is interior
if (m_incident_border->first->first != nullptr)
if (m_incident_border->first->second.second == i)
return m_incident_border->first;
if (m_incident_border->second->first != nullptr)
if (m_incident_border->second->second.second == i)
return m_incident_border->second;
return nullptr;
}
inline bool is_border_edge(Vertex_handle v) const
{
if (m_incident_border == nullptr) return false;
return ((m_incident_border->first->first == v)||
(m_incident_border->second->first == v));
}
inline Next_border_elt* border_elt(Vertex_handle v) const
{
if (m_incident_border == nullptr) return nullptr;
if (m_incident_border->first->first == v) return m_incident_border->first;
if (m_incident_border->second->first == v) return m_incident_border->second;
return nullptr;
}
public:
inline Next_border_elt* first_incident() const
{
if (m_incident_border == nullptr) return nullptr;
return m_incident_border->first;
}
private:
inline Next_border_elt* second_incident() const
{
if (m_incident_border == nullptr) return nullptr;
return m_incident_border->second;
}
inline void set_next_border_elt(const Next_border_elt& elt)
{
if (m_incident_border->first->first == nullptr)
*m_incident_border->first = elt;
else
{
if (m_incident_border->second->first != nullptr)
std::cerr << "+++probleme de MAJ du bord <Vertex_base>" << std::endl;
*m_incident_border->second = elt;
}
}
//-------------------------------------------------------------------
public:
inline bool is_on_border() const
{
return (m_mark > 0);
}
inline bool not_interior() const
{
return (m_mark != 0);
}
inline int number_of_incident_border() const
{
return m_mark;
}
inline bool is_exterior() const
{
return (m_mark < 0);
}
//-------------------------------------------------------------------
private:
inline void inc_mark()
{
if (m_mark==-1)
m_mark=1;
else
m_mark++;
}
//-------------------------------------------------------------------
public:
inline void set_post_mark(const int& i)
{
m_post_mark = i;
}
inline bool is_post_marked(const int& i)
{
return (m_post_mark == i);
}
};
} // namespace CGAL
#endif // CGAL_ADVANCING_FRONT_SURFACE_RECONSTRUCTION_VERTEX_BASE_3_H
@@ -0,0 +1,125 @@
// Copyright (c) 1999
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Andreas Fabri, Stefan Schirra
#ifndef CGAL_AFF_TRANSFORMATION_2_H
#define CGAL_AFF_TRANSFORMATION_2_H
#include <CGAL/config.h>
#include <CGAL/Dimension.h>
#include <CGAL/aff_transformation_tags.h>
namespace CGAL {
template <class R_>
class Aff_transformation_2 : public R_::Kernel_base::Aff_transformation_2
{
typedef typename R_::RT RT;
typedef typename R_::FT FT;
typedef typename R_::Line_2 Line_2;
typedef typename R_::Direction_2 Direction_2;
typedef typename R_::Vector_2 Vector_2;
typedef typename R_::Kernel_base::Aff_transformation_2 RAff_transformation_2;
public:
typedef CGAL::Dimension_tag<2> Ambient_dimension;
typedef R_ R;
Aff_transformation_2() {}
Aff_transformation_2(const RAff_transformation_2& t)
: RAff_transformation_2(t)
{}
Aff_transformation_2(const Identity_transformation tag)
: RAff_transformation_2(tag)
{}
Aff_transformation_2(const Translation tag, const Vector_2 &v)
: RAff_transformation_2(tag, v)
{}
// Rational Rotation:
Aff_transformation_2(const Rotation tag,
const Direction_2 &d,
const RT &num,
const RT &den = RT(1))
: RAff_transformation_2(tag, d, num, den)
{}
Aff_transformation_2(const Rotation tag,
const RT &sin,
const RT &cos,
const RT &den = RT(1))
: RAff_transformation_2(tag, sin, cos, den)
{}
Aff_transformation_2(const Reflection tag, const Line_2& l )
: RAff_transformation_2(tag, l)
{}
Aff_transformation_2(const Scaling tag,
const RT &s,
const RT &w= RT(1))
: RAff_transformation_2(tag, s, w)
{}
// The general case:
Aff_transformation_2(const RT & m11,
const RT & m12,
const RT & m13,
const RT & m21,
const RT & m22,
const RT & m23,
const RT &w= RT(1))
: RAff_transformation_2(m11, m12, m13,
m21, m22, m23,
w)
{}
Aff_transformation_2(const RT & m11, const RT & m12,
const RT & m21, const RT & m22,
const RT &w = RT(1))
: RAff_transformation_2(m11, m12,
m21, m22,
w)
{}
};
#ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATION_2
template < class R >
std::ostream &
operator<<(std::ostream &os, const CGAL::Aff_transformation_2<R> &t)
{
typedef typename R::Kernel_base::Aff_transformation_2 RAff_transformation_2;
return os << static_cast<const RAff_transformation_2&>(t);
}
#endif // CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATION_2
#ifndef CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATION_2
template < class R >
std::istream &
operator>>(std::istream &is, CGAL::Aff_transformation_2<R> &t)
{
typedef typename R::Kernel_base::Aff_transformation_2 RAff_transformation_2;
return is >> static_cast<RAff_transformation_2&>(t);
}
#endif // CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATION_2
} //namespace CGAL
#endif // CGAL_AFF_TRANSFORMATION_2_H
@@ -0,0 +1,103 @@
// Copyright (c) 1999
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Andreas Fabri, Stefan Schirra
#ifndef CGAL_AFF_TRANSFORMATION_3_H
#define CGAL_AFF_TRANSFORMATION_3_H
#include <CGAL/Dimension.h>
#include <CGAL/aff_transformation_tags.h>
#ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATION_3
#include <ostream>
#endif
#ifndef CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATION_3
#include <istream>
#endif
namespace CGAL {
template <class R_>
class Aff_transformation_3 : public R_::Kernel_base::Aff_transformation_3
{
typedef typename R_::RT RT;
typedef typename R_::Vector_3 Vector_3;
typedef typename R_::Kernel_base::Aff_transformation_3 RAff_transformation_3;
public:
typedef CGAL::Dimension_tag<3> Ambient_dimension;
typedef R_ R;
Aff_transformation_3() {}
Aff_transformation_3(const RAff_transformation_3& t)
: RAff_transformation_3(t) {}
Aff_transformation_3(const Identity_transformation& tag)
: RAff_transformation_3(tag) {}
Aff_transformation_3(const Translation tag,
const Vector_3& v)
: RAff_transformation_3(tag, v) {}
Aff_transformation_3(const Scaling tag,
const RT& s,
const RT& w= RT(1) )
: RAff_transformation_3(tag, s, w) {}
// the general case:
Aff_transformation_3(
const RT& m11, const RT& m12, const RT& m13, const RT& m14,
const RT& m21, const RT& m22, const RT& m23, const RT& m24,
const RT& m31, const RT& m32, const RT& m33, const RT& m34,
const RT& w= RT(1) )
: RAff_transformation_3(m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
w) {}
Aff_transformation_3(
const RT& m11, const RT& m12, const RT& m13,
const RT& m21, const RT& m22, const RT& m23,
const RT& m31, const RT& m32, const RT& m33,
const RT& w = RT(1) )
: RAff_transformation_3(m11, m12, m13,
m21, m22, m23,
m31, m32, m33,
w) {}
};
#ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATION_3
template < class R >
std::ostream&
operator<<(std::ostream& os, const CGAL::Aff_transformation_3<R>& t)
{
typedef typename R::Kernel_base::Aff_transformation_3 RAff_transformation_3;
return os << static_cast<const RAff_transformation_3&>(t);
}
#endif // CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATION_3
#ifndef CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATION_3
template < class R >
std::istream&
operator>>(std::istream& is, CGAL::Aff_transformation_3<R>& t)
{
typedef typename R::Kernel_base::Aff_transformation_3 RAff_transformation_3;
return is >> static_cast<const RAff_transformation_3&>(t);
}
#endif // CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATION_3
} //namespace CGAL
#endif // CGAL_AFF_TRANSFORMATION_3_H
@@ -0,0 +1,79 @@
// Copyright (c) 2006-2007 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// =============================================================================
/*! \file CGAL/Algebraic_extension_traits.h
* \brief defines traits class CGAL::Algebraic_extension_traits.
*/
#ifndef CGAL_ALGEBRAIC_NUMBER_TRAITS_H
#define CGAL_ALGEBRAIC_NUMBER_TRAITS_H 1
#include <numeric> // for std::accumulate
#include <CGAL/tags.h>
#include <CGAL/Algebraic_structure_traits.h>
namespace CGAL {
template< class T >
class Algebraic_extension_traits {
public:
//! \name Typedefs
//! the number type for which this instance has been instantiated
typedef T Type;
//! standard number types are not extended
typedef CGAL::Tag_false Is_extended;
//! computes the factor which normalizes a number to be integral after
// multiplication
class Normalization_factor
: public CGAL::cpp98::unary_function<Type,Type> {
private:
static Type
normalization_factor(const Type&,Integral_domain_without_division_tag){
return Type(1);
}
static Type
normalization_factor(const Type& a, Field_tag){
return Type(1)/a;
}
public:
//! determine normalization factor
Type operator () (const Type& a) {
CGAL_precondition(a != Type(0));
typedef typename Algebraic_structure_traits<Type>::Algebraic_category
Tag;
return normalization_factor(a, Tag());
}
};
class Denominator_for_algebraic_integers
: public CGAL::cpp98::unary_function<Type,Type> {
public:
//! determine normalization factor
Type operator () (const Type&) {
return Type(1);
}
template <class InputIterator>
Type operator () (InputIterator, InputIterator) {
return Type(1);
}
};
};
} //namespace CGAL
#endif // NiX_ALGEBRAIC_NUMBER_TRAITS_H
// EOF
@@ -0,0 +1,62 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion, Constantinos Tsirogiannis
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_CONVERTER_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_CONVERTER_H
#include <CGAL/license/Circular_kernel_2.h>
#include <CGAL/NT_converter.h>
namespace CGAL {
// TODO :
// - FT converter ?
template < class Al_K1, class Al_K2,
class RT_converter = NT_converter<typename Al_K1::RT,
typename Al_K2::RT>,
class Root_of_converter = NT_converter<typename Al_K1::Root_of_2,
typename Al_K2::Root_of_2 > >
class Algebraic_kernel_converter {
public:
typedef typename Al_K1::RT RT_1;
typedef typename Al_K2::RT RT_2;
typedef RT_converter RT_type_converter;
typedef Root_of_converter Root_of_type_converter;
typename Al_K2::Polynomial_1_2 operator () (const typename Al_K1::Polynomial_1_2 &p) const
{
return typename Al_K2::Polynomial_1_2(RT_converter()(p.a()),
RT_converter()(p.b()),
RT_converter()(p.c()));
}
typename Al_K2::Polynomial_for_circles_2_2 operator ()
(const typename Al_K1::Polynomial_for_circles_2_2 &p) const
{
return typename Al_K2::Polynomial_for_circles_2_2(RT_converter()(p.a()),
RT_converter()(p.b()),
RT_converter()(p.r_sq()));
}
};
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_CONVERTER_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,598 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// The comments are all original EXACUS comments and aren't adapted.
#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H
#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H
#include <CGAL/basic.h>
#include <CGAL/tags.h>
#include <CGAL/Polynomial_type_generator.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_real_rep.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/tss.h>
#include <iterator>
#include <list>
#include <vector>
#include <queue>
namespace CGAL {
namespace internal {
template <class Coefficient_, class Rational_, class HandlePolicy , class AlgebraicRealRep_d_1 >
class Algebraic_real_d_1;
}
template <
class Coefficient_, class Rational_, class HandlePolicy, class AlgebraicRealRep_d_1 >
typename Get_arithmetic_kernel<Coefficient_>::Arithmetic_kernel::Bigfloat_interval
inline convert_to_bfi(
const internal::Algebraic_real_d_1< Coefficient_, Rational_, HandlePolicy, AlgebraicRealRep_d_1 >& x);
namespace internal {
/*! \ingroup NiX_Algebraic_real
\brief An Algebraic_real_d_1 \a x is represented by a polynomial and an
isolating interval. It is guaranteed that the polynomial is square free.
The isolating interval is an open interval and it is guaranteed that the
polynomial is non-zero at the endpoints of the interval.
The algebraic real are reference counted by default.
The template parameters are:
- \b Coefficient_: a model of the \c IntegralDomain concept.
- \b Rational_: a model of the \c Field concept.
Must be assignable to \c Field_with_sqrt_.
- \b HandlePolicy: a model of the \c HandlePolicy concept or the
\c Handle_policy_in_place class template that selects a specialized
implementation without reference counting. Has the
default \c Handle_policy_union.
THIS CLASS IS CONSIDERED AS EXPERIMENTAL !
*/
template < class Coefficient_,
class Rational_,
class HandlePolicy = ::CGAL::Handle_policy_no_union,
class AlgebraicRealRep_d_1 = internal::Algebraic_real_rep< Coefficient_, Rational_ > >
class Algebraic_real_d_1 :
public ::CGAL::Handle_with_policy< AlgebraicRealRep_d_1, HandlePolicy > {
// currently Rational is the only supported Bound type.
CGAL_static_assertion(
( ::boost::is_same <Rational_,
typename Get_arithmetic_kernel<Coefficient_>::Arithmetic_kernel::Rational>::value));
public :
typedef ::CGAL::Handle_with_policy<AlgebraicRealRep_d_1,HandlePolicy> Base;
typedef Algebraic_real_d_1<Coefficient_,Rational_, HandlePolicy, AlgebraicRealRep_d_1> Self;
typedef Coefficient_ Coefficient;
typedef Rational_ Bound;
typedef HandlePolicy Handle_policy;
typedef AlgebraicRealRep_d_1 Algebraic_real_rep_d_1;
typedef typename Algebraic_real_rep_d_1::Polynomial_1 Polynomial_1;
// These public typedefs should be removed in the long run
// typedef typename Algebraic_real_rep_d_1::Polynomial_1 Polynomial;
typedef Rational_ Rational;
private:
typedef CGAL::Fraction_traits<Rational> FT_rational;
typedef typename FT_rational::Numerator_type Integer;
private:
static inline Self& get_default_instance(){
CGAL_STATIC_THREAD_LOCAL_VARIABLE(Self, x,0);
return x;
}
public:
//! Default constructor
Algebraic_real_d_1() : Base(static_cast<const Base&>(get_default_instance())) {}
//! creates the algebraic real from \a i.
Algebraic_real_d_1(int i ) : Base(Algebraic_real_rep_d_1(i)) { }
//! creates the algebraic real from \a x.
explicit Algebraic_real_d_1(const Rational& x) : Base(Algebraic_real_rep_d_1(x)) { }
/*! \brief creates the algebraic real as the unique root of \a P
* in the open interval <var>]low,high[</var>.
* \pre P is square free.
* \pre P is not zero at low
* \pre P is not zero at high
*/
Algebraic_real_d_1(const Polynomial_1& P, Rational low, Rational high)
: Base (Algebraic_real_rep_d_1(P,low,high)) {}
//! returns the polynomial defining \a x
const Polynomial_1& polynomial() const { return this->ptr()->polynomial(); }
/*! \brief returns the degree of the polynomial defining \a x
* This is not necessarily the algebraic degree of \a x, since
* the polynomial may be reducible.
*/
int degree() const {
return CGAL::degree(this->ptr()->polynomial());
}
//! returns the lower endpoint of the isolating interval
Rational low() const { return this->ptr()->low(); }
Rational lower() const { return this->ptr()->low(); }
//! returns the upper endpoint of the isolating interval
Rational high() const { return this->ptr()->high(); }
Rational upper() const { return this->ptr()->high(); }
/*! \brief returns the sign of the defining polynomial
* at the lower endpoint of the isolating interval
*/
int sign_at_low() const { return this->ptr()->sign_at_low(); }
/*! \brief returns whether a rational representation
* (as Rational) is known.
*/
bool is_rational() const { return this->ptr()->is_rational(); }
//! returns a rational representation of \a x
/*! \pre: type() == NiX::IS_Rational_IONAL */
Rational rational() const {
CGAL_precondition(is_rational());
return this->ptr()->rational();
}
//! compute a \c double approximation (without guarantees)
double to_double() const {
return (to_interval().first +to_interval().second)/2;
}
/*! \brief returns a double Interval approximation,
* it is guaranteed that \a x is contained in the Interval.
*
* This is not the isolating interval.
*/
std::pair<double, double> to_interval() const {
if( this->ptr()->interval_option ) {
return *(this->ptr()->interval_option);
} else {
typedef typename Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Bigfloat_interval BFI;
long old_precision = get_precision( BFI() );
set_precision( BFI(), 53 );
std::pair<double, double> interval = CGAL::to_interval( convert_to_bfi( (*this)));
this->ptr()->interval_option = boost::optional< std::pair<double, double> >(interval);
set_precision( BFI(), old_precision );
return *(this->ptr()->interval_option);
}
}
/*! \brief refines the isolating interval. */
void refine() const{ this->ptr()->refine(); }
/*! \brief Bisects the isolating interval. */
void bisect() const{ this->ptr()->bisect(); }
/*! \brief refines the isolating interval until \a m is outside
* the \c closed interval
*/
template < class NTX >
void strong_refine(const NTX& m) const{ compare(m); }
/*! \brief compares \a x with respect to \a y
* It returns CGAL::SMALLER if \a x is smaller than <var>y</var>,
* CGAL::EQUAL if they are equal and CGAL::LARGER otherwise.
*/
template < class NTX >
CGAL::Comparison_result
compare(const NTX& y) const { return intern_compare(y,false); }
/*! \brief compares \a x with respect to \a y
* \pre \a x != \a y
*/
template < class NTX >
CGAL::Comparison_result
compare_distinct(const NTX& y) const { return intern_compare(y,true); }
template <class Algebraic_real_iterator>
static void conjugate(Algebraic_real_iterator begin,
Algebraic_real_iterator end){
if(begin == end) return;
CGAL_precondition(begin->ptr()->next==begin->ptr());
CGAL_precondition(begin->ptr()->prev==begin->ptr());
for(Algebraic_real_iterator it = begin; it != end; ++it){
CGAL_precondition(it->ptr()->next==it->ptr());
CGAL_precondition(it->ptr()->prev==it->ptr());
CGAL_precondition(it->polynomial()==begin->polynomial());
it->ptr()->next =begin->ptr();
it->ptr()->prev =begin->ptr()->prev;
begin->ptr()->prev->next=it->ptr();
begin->ptr()->prev =it->ptr();
}
}
private:
CGAL::Comparison_result
intern_compare(const Self& y, bool distinct) const {
if(distinct)
CGAL_precondition(this->ptr()!=y.ptr());
else if(this->ptr()==y.ptr()) {
return CGAL::EQUAL;
}
CGAL::Comparison_result result =
this->ptr()->compare(*(y.ptr()), distinct);
if (result == CGAL::EQUAL) {
this->unify(y);
}
return result;
}
CGAL::Comparison_result
intern_compare(const Rational& y, bool distinct) const {
return this->ptr()->compare(y,distinct);
}
template < class NTX >
CGAL::Comparison_result
intern_compare(const NTX& y, bool distinct) const {
if(y < NTX(low())) return CGAL::LARGER;
if(NTX(high()) < y ) return CGAL::SMALLER;
if(!distinct){
typename Real_embeddable_traits<NTX>::To_interval to_interval;
if( CGAL::Interval_nt<true>( this->to_interval() ).do_overlap(
CGAL::Interval_nt<true>(to_interval(y)) ) ) {
if(polynomial().sign_at(y)==CGAL::ZERO)
return CGAL::EQUAL;
}
}
while(NTX(low()) <= y && y <= NTX(high())) {
refine();
}
if(y < NTX(low())) return CGAL::LARGER;
CGAL_assertion(NTX(high()) < y); return CGAL::SMALLER;
}
public:
//! returns if y is contained in the \c closed isolating interval
template < class NTX >
bool contains(const NTX& y) const {
return ((NTX(low()) <= y) && (y <= NTX(high())));
}
//! return if \a x is a root of Q
bool is_root_of(const Polynomial_1& Q) const {return this->ptr()->is_root_of(Q); }
/*! \brief returns a rational (Rational) between this number and \c y.
* \pre x != y
*/
Rational rational_between (const Self& y) const{
CGAL::Comparison_result s = compare(y);
CGAL_precondition(s != CGAL::EQUAL);
if(s == CGAL::SMALLER){
Rational r((high()+y.low())/Rational(2));
CGAL::simplify(r);
return r;
}else{
Rational r((y.high()+low())/Rational(2));
CGAL::simplify(r);
return r;
}
}
public:
/*! \brief refines the isolating interval to ]<var>lo</var>,
* <var>hi</var>[.
*
* This function can be used to inform an Algebraic_real_d_1 \a x of an
* externally refined isolating interval. Its arguments must be
* the boundaries of an isolating interval that contains \a x in its
* interior. (Use other functions like \c .strong_refine() in case you
* want to communicate an explicit value.)
*/
void refine_to(const Rational& lo, const Rational& hi) const {
// test whether lo < x < hi
// and refines isolating interval until in ]lo,hi[
CGAL_assertion_code(CGAL::Comparison_result s =) compare_distinct(lo);
CGAL_assertion(CGAL::LARGER == s);
CGAL_assertion_code(s =) compare_distinct(hi);
CGAL_assertion(CGAL::SMALLER == s);
}
public:
template <class NTX>
bool operator==( const NTX& y) const {return compare(y)==CGAL::EQUAL;}
template <class NTX>
bool operator!=( const NTX& y) const {return compare(y)!=CGAL::EQUAL;}
template <class NTX>
bool operator< ( const NTX& y) const {return compare(y)==CGAL::SMALLER;}
template <class NTX>
bool operator> ( const NTX& y) const {return compare(y)==CGAL::LARGER;}
template <class NTX>
bool operator<=( const NTX& y) const {return compare(y)!=CGAL::LARGER;}
template <class NTX>
bool operator>=( const NTX& y) const {return compare(y)!=CGAL::SMALLER;}
//! unary operator +
const Self& operator+() const { return *this; }
//! unary operator -
Self operator-() const {
Polynomial_1 P(polynomial());
P.scale_up(Coefficient(-1));
Rational high_(-low());
Rational low_ (-high());
return Self(P,low_,high_);
}
//! Simplifies the algebraic number
void simplify() const {
this->ptr()->simplify();
}
}; // class Algebraic_real_d_1
} // namespace internal
//----------------------------------------------------------
/*! \ingroup NiX_Algebraic_real_d_1
* \ingroup NiX_NT_traits_spec
* \brief NT_traits class for NiX::Algebraic_real_d_1, which is a model of the
* RealComparable concept.
*
* NiX::Algebraic_real_d_1 does not support any arithmetic operations, thus they
* are not even a model of the IntegralDomainWithoutDiv concept. \see NiX_NT_Concepts
*/
template< class Coefficient, class Rational, class HandlePolicy, class RepClass >
class Real_embeddable_traits< internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > >
: public INTERN_RET::Real_embeddable_traits_base< internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > , CGAL::Tag_true > {
public:
typedef internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > Type;
class Compare
: public CGAL::cpp98::binary_function< Type, Type, CGAL::Comparison_result > {
public:
CGAL::Comparison_result operator()( const Type& a, const Type& b ) const
{ return a.compare( b ); }
CGAL::Comparison_result operator()( int a, const Type& b ) const
{ return - b.compare( Rational(a) ); }
CGAL::Comparison_result operator()( const Type& a, int b ) const
{ return a.compare( Rational(b) ); }
CGAL::Comparison_result operator()( const Rational& a, const Type& b ) const
{ return - b.compare( a ); }
CGAL::Comparison_result operator()( const Type& a, const Rational& b ) const
{ return a.compare( b ); }
CGAL::Comparison_result operator()(
const typename First_if_different<Coefficient,Rational>::Type& a,
const Type& b ) const
{
typename Coercion_traits<Coefficient,Type>::Cast cast;
return cast(a).compare(b);
}
CGAL::Comparison_result operator()(
const Type& a,
const typename First_if_different<Coefficient,Rational>::Type& b ) const
{
typename Coercion_traits<Coefficient,Type>::Cast cast;
return a.compare(cast(b));
}
};
class Sgn
: public CGAL::cpp98::unary_function< Type, CGAL::Sign > {
public:
CGAL::Sign operator()( const Type& a ) const {
return a.compare( Rational(0) );
}
};
class To_double
: public CGAL::cpp98::unary_function< Type, double > {
public:
double operator()(const Type& a) const {
return a.to_double();
}
};
class To_interval
: public CGAL::cpp98::unary_function< Type, std::pair<double, double> > {
public:
typename std::pair<double, double> operator()(const Type& a) const {
return a.to_interval();
}
};
};
/*! \relates NiX::Algebraic_real_d_1
* \brief outputs \c x to \c os
*/
template<class Coefficient, class Rational, class HandlePolicy, class RepClass >
std::ostream&
operator << (std::ostream& os,
const CGAL::internal::Algebraic_real_d_1<Coefficient, Rational, HandlePolicy, RepClass >& x){
os << "[" << x.polynomial()
<< ",[" << IO::oformat(x.low())
<< " , " << IO::oformat(x.high()) << " ]]";
return os;
}
/*! \relates NiX::Algebraic_real_d_1
* \brief read an NiX::Algebraic_real_d_1 from \c is into \c x.
*/
template<class Coefficient, class Rational, class HandlePolicy, class RepClass>
std::istream&
operator >> (std::istream& is,
CGAL::internal::Algebraic_real_d_1<Coefficient, Rational, HandlePolicy, RepClass>& x){
typedef CGAL::internal::Algebraic_real_d_1<Coefficient, Rational, HandlePolicy, RepClass > ALGNUM;
Rational low, high;
typename CGAL::Polynomial_type_generator<Coefficient,1>::Type poly;
swallow(is, '[');// read the "["
is >> poly;
swallow(is, ',');// read the ","
swallow(is, '[');// read the ","
is >> IO::iformat(low);
swallow(is, ',');// read the ","
is >> IO::iformat(high);
swallow(is, ']');// read the "]"
swallow(is, ']');// read the "]"
x = ALGNUM(poly, low, high);
return is;
}
template <class Coefficient_, class Rational_, class HandlePolicy, class AlgebraicRealRep_d_1 >
typename Get_arithmetic_kernel<Coefficient_>::Arithmetic_kernel::Bigfloat_interval
inline
convert_to_bfi(const internal::Algebraic_real_d_1< Coefficient_, Rational_, HandlePolicy, AlgebraicRealRep_d_1 >& x){
typedef typename Get_arithmetic_kernel<Coefficient_>::Arithmetic_kernel AT;
typedef typename AT::Bigfloat_interval BFI;
if (x.is_rational()) return convert_to_bfi(x.rational());
if(CGAL::sign(x) == CGAL::ZERO) return (BFI(0));
CGAL_postcondition(CGAL::sign(x.low()) == CGAL::sign(x.high()));
long final_prec = set_precision( BFI(),get_precision( BFI())+4);
BFI bfi = CGAL::hull(convert_to_bfi(x.low()), convert_to_bfi(x.high()));
while( !singleton(bfi) && get_significant_bits(bfi) < final_prec ){
x.refine();
bfi = CGAL::hull(
convert_to_bfi(x.low()),
convert_to_bfi(x.high()));
}
set_precision(BFI(),final_prec);
return bfi;
}
template <class Coefficient,class Rational,class Handle_policy,class Rep_class>
struct Get_arithmetic_kernel<CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> >{
typedef typename Get_arithmetic_kernel<Coefficient>::Arithmetic_kernel
Arithmetic_kernel;
};
template <class Coefficient,class Rational,class Handle_policy,class Rep_class>
inline CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>
min BOOST_PREVENT_MACRO_SUBSTITUTION(
const CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>& x,
const CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>& y){
return (x<=y)?x:y;
}
template <class Coefficient,class Rational,class Handle_policy,class Rep_class>
inline CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>
max BOOST_PREVENT_MACRO_SUBSTITUTION(
const CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>& x,
const CGAL::internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class>& y){
return (x>=y)?x:y;
}
template <class Coefficient, class Rational, class Handle_policy, class Rep_class>
struct Coercion_traits<int, internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> >{
typedef internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> Type;
typedef Tag_true Are_explicit_interoperable;
typedef Tag_false Are_implicit_interoperable;
struct Cast{
typedef Type result_type;
Type operator()(const Type& x) const { return x; }
Type operator()(const int& x) const { return Type(x); }
};
};
template <class A, class B, class C, class D>
struct Coercion_traits<internal::Algebraic_real_d_1<A,B,C,D>,int >
:public Coercion_traits<int,internal::Algebraic_real_d_1<A,B,C,D> >{};
template <class Coefficient, class Rational, class Handle_policy, class Rep_class>
struct Coercion_traits<Rational, internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> >{
typedef internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> Type;
typedef Tag_true Are_explicit_interoperable;
typedef Tag_false Are_implicit_interoperable;
struct Cast{
typedef Type result_type;
Type operator()(const Type& x) const { return x; }
Type operator()(const Rational& x) const { return Type(x); }
};
};
template <class A, class Rational, class C, class D>
struct Coercion_traits<internal::Algebraic_real_d_1<A,Rational,C,D>, Rational >
:public Coercion_traits<Rational,internal::Algebraic_real_d_1<A,Rational,C,D> >{};
template <class Coefficient, class Rational, class Handle_policy, class Rep_class>
struct Coercion_traits<
typename First_if_different<Coefficient,Rational>::Type,
internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> >
{
typedef internal::Algebraic_real_d_1<Coefficient,Rational,Handle_policy,Rep_class> Type;
typedef Tag_true Are_explicit_interoperable;
typedef Tag_false Are_implicit_interoperable;
typedef Coercion_traits<Coefficient,Rational> CTCR;
struct Cast{
private:
Type operator()(const Coefficient& a, Tag_true) const {
return Type(typename CTCR::Cast()(a));
}
Type operator()(const Coefficient& a, Tag_false) const {
typedef typename Type::Polynomial_1 Poly;
typedef CGAL::Polynomial_traits_d<Poly> PT;
Poly p = typename PT::Shift()(Poly(1),1) - a ; // (x-a)
Rational b(2);
Coefficient aa = CGAL::abs(a);
while( CGAL::compare(b,aa) != LARGER ){b*=2;};
return Type(p,-b,b);
}
public:
typedef Type result_type;
Type operator()(const Type& a) const { return a; }
Type operator()(const Coefficient& a) const {
static const bool b = boost::is_same<Rational,typename CTCR::Type>::value;
return (*this)(a,Boolean_tag<b>());
}
};
};
template <class Coefficient, class Rational, class C, class D>
struct Coercion_traits<
internal::Algebraic_real_d_1<Coefficient,Rational,C,D>,
typename First_if_different<Coefficient,Rational>::Type>
:public Coercion_traits<Coefficient,internal::Algebraic_real_d_1<Coefficient,Rational,C,D> >{};
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H
// EOF
@@ -0,0 +1,503 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
// Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
#ifndef CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_BFI_H
#define CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_BFI_H
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_real_rep.h>
#include <CGAL/Algebraic_kernel_d/Float_traits.h>
#include <CGAL/Algebraic_kernel_d/Real_embeddable_extension.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/Arithmetic_kernel.h>
#include <boost/none.hpp>
#include <CGAL/Polynomial_type_generator.h>
namespace CGAL {
namespace internal {
// definition of the Algebraic_real_rep x:
//For details about the method, see
/*
* @Unpublished{abbott-quadratic,
* author = {John Abbott},
* title = {Quadratic Interval Refinement for Real Roots},
* url = {http://www.dima.unige.it/~abbott/},
* note = {Poster presented at the 2006 Internat. Sympos. on Symbolic
and Algebraic Computation (ISSAC 2006)}
* }
*/
template< class Coefficient_, class Field_>
class Algebraic_real_quadratic_refinement_rep_bfi
: public Algebraic_real_rep<Coefficient_, Field_> {
typedef Coefficient_ Coefficient;
typedef Field_ Field;
typedef typename
CGAL::Get_arithmetic_kernel<Field>::Arithmetic_kernel::
Bigfloat_interval BFI;
typedef typename CGAL::Bigfloat_interval_traits<BFI>::Bound BF;
// This is a implicit restriction - Field must be some type
// modelling rational numbers to get an integer type
typedef typename CGAL::Fraction_traits<Field>::Numerator_type Integer;
typedef typename
CGAL::Polynomial_type_generator<Coefficient,1>::Type Poly;
typedef Algebraic_real_rep <Coefficient,Field> Base;
typedef Algebraic_real_quadratic_refinement_rep_bfi<Coefficient,Field>
Self;
typedef typename CGAL::Coercion_traits<Coefficient,Field>::Type
Eval_result_type;
private:
mutable long prec_;
typedef typename
CGAL::Polynomial_traits_d<Poly>::template Rebind<BFI,1>
::Other::Type BFI_polynomial;
mutable boost::optional
< BFI_polynomial > f_bfi_;
mutable boost::optional<BFI> low_bfi_, f_low_bfi_,
high_bfi_, f_high_bfi_;
mutable long N;
// TODO: replace by call of Coercion_traits<Poly,BFI>::Cast()
BFI_polynomial _convert_polynomial_to_bfi(const Poly& f) const {
std::vector<BFI> coeffs;
for(int i = 0; i <= CGAL::degree(f); i++) {
coeffs.push_back(CGAL::convert_to_bfi(f[i]));
}
return BFI_polynomial(coeffs.begin(), coeffs.end());
}
void _set_prec(long new_prec) const {
prec_ = new_prec;
CGAL::set_precision(BFI(), prec_);
f_bfi_ = _convert_polynomial_to_bfi(this->polynomial());
low_bfi_ = CGAL::convert_to_bfi(this->low());
high_bfi_ = CGAL::convert_to_bfi(this->high());
f_low_bfi_ = f_bfi_.get().evaluate(low_bfi_.get());
f_high_bfi_ = f_bfi_.get().evaluate(high_bfi_.get());
}
CGAL::Sign _sign_at(Field m, BFI& m_bfi, BFI& f_m_bfi) const {
if(! f_bfi_) {
f_bfi_ = _convert_polynomial_to_bfi(this->polynomial());
}
m_bfi = CGAL::convert_to_bfi(m);
f_m_bfi = f_bfi_.get().evaluate(m_bfi);
if(CGAL::zero_in(f_m_bfi)) {
// Okay, compute exactly
return CGAL::sign(this->polynomial().evaluate(m));
}
// If we are here, then the interval is away from zero
return CGAL::sign(CGAL::upper(f_m_bfi));
}
private:
// Stores whether the last bisection has taken the upper or lower part
mutable bool last_bisect_lower;
public:
//! creates the algebraic real from int \a i.
explicit Algebraic_real_quadratic_refinement_rep_bfi(int i = 0)
: Base(i),N(2){
}
//! creates the algebraic real from Field \a m.
explicit Algebraic_real_quadratic_refinement_rep_bfi(const Field& m)
: Base(m),N(2) {
}
/*! \brief creates the algebraic real as the unique root of \a P
in the open interval <var>]low,high[</var>.
\pre the polynomial \a P is square free
\pre P(low)!=0
\pre P(high)<0
\pre x is the one and only root in the open interval of \a P.
*/
Algebraic_real_quadratic_refinement_rep_bfi(const Poly& P,
Field LOW,
Field HIGH)
: Base(P,LOW,HIGH),
N(2)
{
_set_prec(16);
}
//! copy constructor
Algebraic_real_quadratic_refinement_rep_bfi(const Self& y)
: Base(y), prec_(y.prec_), f_bfi_(y.f_bfi_), low_bfi_(y.low_bfi_),
f_low_bfi_(y.f_low_bfi_), high_bfi_(y.high_bfi_),
f_high_bfi_(y.f_high_bfi_), N(y.N)
{
}
// assignment
Algebraic_real_quadratic_refinement_rep_bfi& operator=(const Self& y) {
Base::operator=(y);
f_low_bfi_=y.f_low_bfi_;
f_high_bfi_=y.f_high_bfi_;
low_bfi_=y.low_bfi_;
high_bfi_=y.high_bfi_;
f_bfi_=y.f_bfi_;
N=y.N;
return *this;
}
public:
virtual void bisect() const{
if(this->is_rational()) return;
Field m = (this->low_+this->high_)/Field(2);
CGAL::simplify(m);
BFI m_bfi, f_m_bfi;
CGAL::Sign s = _sign_at(m,m_bfi,f_m_bfi);
if (s == ::CGAL::ZERO ) {
this->learn_from(m);
}
else {
if ( s == this->sign_at_low() ) {
this->low_ = m;
low_bfi_ = m_bfi;
f_low_bfi_ = f_m_bfi;
last_bisect_lower=false;
} else {
this->high_ = m;
high_bfi_ = m_bfi;
f_high_bfi_ = f_m_bfi;
last_bisect_lower=true;
}
}
}
protected:
virtual void set_implicit_rep(const Poly & P,
const Field& LOW,
const Field& HIGH,
bool dummy_bool=false) const {
bool poly_changed = (P!=this->polynomial());
if(poly_changed) {
f_bfi_ = boost::none;
}
if(poly_changed || LOW != this->low()) {
f_low_bfi_ = low_bfi_ = boost::none;
}
if(poly_changed || HIGH != this->high()) {
f_high_bfi_ = high_bfi_ = boost::none;
}
Base::set_implicit_rep(P,LOW,HIGH,dummy_bool);
}
virtual void set_explicit_rep(const Field& m) const {
f_bfi_ = boost::none;
f_low_bfi_ = low_bfi_ = boost::none;
f_high_bfi_ = high_bfi_ = boost::none;
Base::set_explicit_rep(m);
}
public:
virtual void refine_at(const Field& m) const{
Field old_low_=this->low_, old_high_=this->high_;
Poly old_pol = this->polynomial();
Base::refine_at(m);
if(this->is_rational()) return;
if(old_low_!=this->low_) {
f_low_bfi_ = low_bfi_ = boost::none;
}
if(old_high_!=this->high_) {
f_high_bfi_ = high_bfi_ = boost::none;
}
if(old_pol != this->polynomial()) {
f_bfi_ = boost::none;
}
}
// Abbott's refinement method
virtual void refine() const {
if(this->is_rational()) {
return;
}
CGAL_assertion(this->low() != this->high());
long old_prec = CGAL::get_precision(BFI());
CGAL::set_precision(BFI(),prec_);
CGAL_assertion(CGAL::sign(this->polynomial().evaluate(this->low()))
==this->sign_at_low_);
CGAL_assertion( this->sign_at_low_ !=
CGAL::sign(this->polynomial().evaluate(this->high())) );
CGAL_assertion(this->low() != this->high());
Integer i = find_interval();
while(N!=1 && !refine_by_factor(i)) {
N/=2;
i = find_interval();
}
N*=2;
CGAL::set_precision(BFI(),old_prec);
}
private:
std::pair<Integer,Integer> _to_integer_interval(BFI z, long N) const {
Integer i_low, i_high;
//typename CGAL::internal::Real_embeddable_extension<BF>::Floor floor;
//typename CGAL::internal::Real_embeddable_extension<BF>::Ceil ceil;
typename CGAL::internal::Float_traits<BF>::Mul_by_pow_of_2 mul_2;
BF z_low=CGAL::lower(z), z_high = CGAL::upper(z);
i_low = CGAL::internal::floor(mul_2(CGAL::lower(z),N));
i_high = CGAL::internal::ceil(mul_2(CGAL::upper(z),N));
return std::make_pair(i_low,i_high);
}
Integer find_interval() const {
if(! f_bfi_) {
f_bfi_ = _convert_polynomial_to_bfi(this->polynomial());
}
if(! low_bfi_) {
low_bfi_ = CGAL::convert_to_bfi(this->low());
}
if(! f_low_bfi_) {
f_low_bfi_ = f_bfi_.get().evaluate(low_bfi_.get());
}
if(! high_bfi_) {
high_bfi_ = CGAL::convert_to_bfi(this->high());
}
if(! f_high_bfi_) {
f_high_bfi_ = f_bfi_.get().evaluate(high_bfi_.get());
}
Integer i;
while(true) {
if(CGAL::zero_in(f_low_bfi_.get() - f_high_bfi_.get())) {
_set_prec(2*prec_);
continue;
}
BFI denom = f_low_bfi_.get()-f_high_bfi_.get();
BFI z = f_low_bfi_.get() / denom;
std::pair<Integer, Integer> int_pair = _to_integer_interval(z,N);
Integer i_low = int_pair.first;
Integer i_high = int_pair.second;
if(CGAL::abs(i_high-i_low) <= 2) {
i = CGAL::abs((i_high+i_low))/2;
break;
}
_set_prec(2*prec_);
}
CGAL_postcondition(i>=0 &&
i <= CGAL::ipower(Integer(2),N));
return i;
}
bool refine_by_factor(Integer i) const {
if(N==2) {
bool refined = refine_by_factor_4(i);
return refined;
}
bool refined = refine_by_factor_greater_4(i);
return refined;
}
bool refine_by_factor_4(Integer i) const {
Integer actual_i;
bisect();
actual_i=last_bisect_lower ? 0 : 2;
bisect();
if(! last_bisect_lower) {
actual_i = actual_i+1;
}
return this->is_rational() || actual_i==i;
}
bool refine_by_factor_greater_4(Integer i) const {
Integer intervals = CGAL::ipower(Integer(2),N);
Field step = (this->high_-this->low_)/Field(intervals);
CGAL::simplify(step);
Field m
= this->low_ + step*Field(i);
CGAL::simplify(m);
BFI m_bfi, f_m_bfi;
CGAL::Sign s_m = _sign_at(m,m_bfi,f_m_bfi);
if(s_m==CGAL::ZERO) {
this->learn_from(m);
return true;
}
Field new_left, new_right;
BFI new_left_bfi, new_right_bfi, f_new_left_bfi, f_new_right_bfi;
CGAL::Sign s_new_left, s_new_right;
if(s_m == this->sign_at_low_) {
// Go to the right
new_left=m;
new_left_bfi = m_bfi;
f_new_left_bfi = f_m_bfi;
s_new_left = s_m;
new_right = m+step;
CGAL::simplify(new_right);
s_new_right = _sign_at(new_right,new_right_bfi,f_new_right_bfi);
if(s_new_right==CGAL::ZERO) {
this->learn_from(new_right);
return true;
}
} else {
// Go to the left
new_right=m;
new_right_bfi = m_bfi;
f_new_right_bfi = f_m_bfi;
s_new_right=s_m;
new_left = m-step;
CGAL::simplify(new_left);
s_new_left = _sign_at(new_left,new_left_bfi,f_new_left_bfi);
if(s_new_left==CGAL::ZERO) {
this->learn_from(new_left);
return true;
}
}
if(s_new_left != s_new_right) {
this->low_=new_left;
this->high_=new_right;
low_bfi_ = new_left_bfi;
high_bfi_ = new_right_bfi;
f_low_bfi_ = f_new_left_bfi;
f_high_bfi_ = f_new_right_bfi;
this->sign_at_low_=s_new_left;
return true;
}
else {
return false;
}
}
protected:
virtual CGAL::Sign sign_of_polynomial_at( const Field& f ) const {
//return polynomial().sign_at( f );
Field m = f;
CGAL::simplify(m);
if(! f_bfi_) {
f_bfi_ = _convert_polynomial_to_bfi(this->polynomial());
}
BFI eval = f_bfi_.get().evaluate(convert_to_bfi(m));
CGAL::Sign s = CGAL::sign(CGAL::lower(eval));
// correct sign if needed
if( s*CGAL::sign(CGAL::upper(eval) ) != CGAL::POSITIVE ){
//std::cout << "APPROX FAILED-------------------------------"<<std::endl;
s = this->polynomial().sign_at(m);
if ( s != CGAL::ZERO ) {
_set_prec(2*prec_);
}
}
CGAL_postcondition(s == this->polynomial_.sign_at(m));
if ( s == CGAL::ZERO ) {
this->learn_from(m);
}else{
if ( s == this->sign_at_low() ) this->low_ = m;
else this->high_ = m;
}
return s;
}
public:
virtual void simplify() const {
Poly f_old = this->polynomial();
Base::simplify();
if(f_old != this->polynomial()) {
f_bfi_ = boost::none;
}
}
};
} // namepace internal
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif //CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_H
@@ -0,0 +1,522 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H
#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Polynomial_type_generator.h>
#include <CGAL/Polynomial_traits_d.h>
#include <boost/optional.hpp>
namespace CGAL {
namespace internal {
// definition of the Algebraic_real_rep x:
//IS_GENERAL:
// low_ lower bound of x
// high_ upper bound of x
// polynomial_ a square free polynomial
// sign_at_low_ = polynomial_.evaluate(low_)
// x is the only root of polynomial_ in the open interval ]low_,high_[
// low_ != x != high
// ******************* EXEPTION *******************
// x is rational: in this case low=high=x
template< class Coefficient_, class Rational_>
class Algebraic_real_rep{
public:
typedef Coefficient_ Coefficient;
typedef Rational_ Bound;
typedef typename CGAL::Polynomial_type_generator<Coefficient,1>::Type Polynomial_1;
private:
typedef Rational_ Rational;
typedef typename CGAL::Polynomial_type_generator<Coefficient,1>::Type Poly;
typedef CGAL::Sign TRI_BOOL;
typedef Algebraic_real_rep <Coefficient,Rational> Self;
public:
typedef boost::optional< std::pair<double, double> > Interval_option;
mutable Poly polynomial_; //!< square free polynomial
mutable Rational low_; //!< lower endpoint of interval
mutable Rational high_; //!< upper endpoint of interval
mutable CGAL::Sign sign_at_low_; //!< sign of polynomial a \a low_
mutable Interval_option interval_option;
mutable bool is_rational_;
mutable const Self *next;
mutable const Self *prev;
private:
void copy_all_members(const Algebraic_real_rep& y) const {
polynomial_ = y.polynomial_;
low_ = y.low_;
high_ = y.high_;
sign_at_low_ = y.sign_at_low_;
interval_option = y.interval_option;
is_rational_ = y.is_rational_;
}
protected:
virtual CGAL::Sign sign_of_polynomial_at( const Rational& f ) const {
return polynomial().sign_at( f );
}
protected:
// joins the two lists of related algebraic reals
void introduce(const Algebraic_real_rep& y) const{
y.prev->next=next;
next->prev=y.prev;
next=&y;
y.prev=this;
}
protected:
// x leaves the list of related algebraic reals
void erase_from_list() const {
next->prev=prev;
prev->next=next;
next=prev=this;
}
protected:
virtual void set_explicit_rep(const Rational& m) const {
typename Fraction_traits<Rational>::Decompose decomp;
typename Fraction_traits<Rational>::Numerator_type num;
typename Fraction_traits<Rational>::Denominator_type den;
decomp(m, num, den);
polynomial_ = Poly(-Coefficient(num),Coefficient(den));
is_rational_ = true;
low_ = m;
high_ = m;
sign_at_low_= CGAL::ZERO;
interval_option = Interval_option(CGAL::to_interval(m));
}
protected:
virtual void set_implicit_rep(const Poly & P,
const Rational& LOW,
const Rational& HIGH,
bool use_expensive_sign = false ) const {
CGAL_precondition(LOW < HIGH);
CGAL_precondition(P.sign_at(LOW) != CGAL::ZERO);
CGAL_precondition(P.sign_at(HIGH) != CGAL::ZERO);
CGAL_precondition(P.sign_at(HIGH) != P.sign_at(LOW));
CGAL_precondition_msg(typename CGAL::Polynomial_traits_d< Poly >::Is_square_free()(P), "Polynomial not square-free.");
polynomial_ = P;
low_=LOW;
high_=HIGH;
sign_at_low_=(use_expensive_sign ? P.sign_at(LOW) : sign_of_polynomial_at(LOW) );
is_rational_=false;
// interval_option left out
// trys to set rational if degree is 1
typedef typename CGAL::Coercion_traits< Coefficient, Rational >::Type RET;
set_rational(RET());
}
private:
template < class NTX >
void set_rational(NTX) const {
}
void set_rational(Rational) const {
if (CGAL::degree(polynomial()) == 1) {
low_ = high_ = -Rational(polynomial()[0])/Rational(polynomial()[1]);
is_rational_ = true;
interval_option = Interval_option(CGAL::to_interval(rational()));
}
}
public:
//! creates the algebraic real from int \a i.
explicit Algebraic_real_rep(int i = 0){
next=prev=this;
set_explicit_rep(i);
}
//! creates the algebraic real from Rational \a m.
explicit Algebraic_real_rep(const Rational& m){
next=prev=this;
set_explicit_rep(m);
}
/*! \brief creates the algebraic real as the unique root of \a P
in the open interval <var>]low,high[</var>.
\pre the polynomial \a P is square free
\pre P(low)!=0
\pre P(high)<0
\pre x is the one and only root in the open interval of \a P.
*/
Algebraic_real_rep(const Poly& P, Rational LOW, Rational HIGH) {
if (LOW == HIGH) {
CGAL_precondition(P.sign_at(LOW) == CGAL::ZERO);
set_explicit_rep(LOW);
} else {
CGAL_precondition(LOW < HIGH);
CGAL_precondition(P.sign_at(LOW) != CGAL::ZERO);
CGAL_precondition(P.sign_at(HIGH) != CGAL::ZERO);
CGAL_precondition(P.sign_at(HIGH) != P.sign_at(LOW));
CGAL_precondition_msg(typename CGAL::Polynomial_traits_d<Poly>::Is_square_free()(P), "Polynomial not square-free.");
set_implicit_rep(P,LOW,HIGH);
}
next=prev=this;
}
//! copy constructor
Algebraic_real_rep(const Self& y){
next=prev=this;
copy_all_members(y);
introduce(y);
}
//! destructor
virtual ~Algebraic_real_rep(){
erase_from_list();
}
// assignment
Algebraic_real_rep& operator=(const Self& y) {
if ( this != & y) {
erase_from_list();
copy_all_members(y);
introduce(y);
}
CGAL_expensive_postcondition(self_test());
return *this;
}
public:
const Rational& low() const {return low_;}
const Rational& high() const {return high_;}
const Poly& polynomial() const {return polynomial_;}
const TRI_BOOL& sign_at_low() const {return sign_at_low_;}
/*const std::pair< double, double>& interval() const {
if( interval_option ) {
return *interval_option;
} else {
typedef typename Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Bigfloat BF;
//typedef typename LEDA_arithmetic_kernel::Bigfloat BF;
long old_precision = get_precision( BF() );
set_precision( BF(), 53 );
interval_option = Interval_option( internal::to_interval( convert_to_bfi( (*this) ) ) );
set_precision( BF(), old_precision );
return *interval_option;
}
}*/
/*const std::pair<double, double>& interval() const {
if(interval_option){
return *interval_option;
}else{
interval_option = Interval_option(
compute_interval_approximation(polynomial(),low(),high()));
return *interval_option;
}
}*/
bool is_rational() const {return is_rational_;}
const Rational& rational() const {
CGAL_precondition(is_rational());
CGAL_precondition(low()==high());
CGAL_precondition(polynomial().sign_at(low())==CGAL::ZERO);
return low_;
}
/*! \brief convert algebraic real to type double */
/*double to_double() const {
return (to_interval().first +to_interval().second)/2;
}*/
/*! \brief convert algebraic real to type Interval */
/*std::pair<double, double> to_interval() const {
CGAL_precondition(compare(Rational(interval().first)) != CGAL::SMALLER);
CGAL_precondition(compare(Rational(interval().second)) != CGAL::LARGER);
return interval();
}*/
private:
bool self_test() const{
if(!is_rational()){
CGAL_precondition(low()<high());
CGAL_precondition(sign_at_low() != CGAL::ZERO);
CGAL_precondition(polynomial().sign_at(low() )== sign_at_low());
CGAL_precondition(polynomial().sign_at(high())==-sign_at_low());
}else{
CGAL_precondition(low()==high());
CGAL_precondition(polynomial().sign_at(low() )==CGAL::ZERO);
}
return true;
}
public:
virtual void bisect() const {
if(is_rational()) return;
Rational m = (low()+high())/Rational(2);
CGAL::simplify(m);
CGAL::Sign s = sign_of_polynomial_at(m);
if ( s == CGAL::ZERO ) learn_from(m);
else
if ( s == sign_at_low() ) low_ = m;
else high_ = m;
}
virtual void refine() const{
bisect();
}
public:
template <class NTX>
void strong_refine(const NTX& m) const{
if(is_rational()) return;
if( NTX(low()) <= m && m <= NTX(high()) ){
CGAL_precondition(polynomial().sign_at(m)!=CGAL::ZERO);
refine();
while( NTX(low()) <= m && m <= NTX(high())) refine();
}
}
public:
virtual void refine_at(const Rational& m) const{
if(is_rational()) return;
if( m <= low() || high() <= m ) return;
// now: low < m < high
CGAL::Sign s = sign_of_polynomial_at(m);
if(s == CGAL::ZERO) learn_from(m);
else (s == sign_at_low())? low_ = m : high_=m;
}
public:
CGAL::Comparison_result
compare(const Rational& y, bool are_distinct = false) const {
if(is_rational()) return CGAL::compare(rational(),y);
if(y <= low()) {
strong_refine(y);
return CGAL::LARGER;
}
if(high() <= y) {
strong_refine(y);
return CGAL::SMALLER;
}
// now: low < y < high
if(!are_distinct){
if(sign_of_polynomial_at(y)==CGAL::ZERO){
learn_from(y);
return CGAL::EQUAL ;
}
}else{
CGAL_precondition(polynomial().sign_at(y)!=CGAL::ZERO);
}
strong_refine(y);
CGAL_postcondition(y < low() || high() < y );
if(y < low()) return CGAL::LARGER;
else return CGAL::SMALLER;
}
CGAL::Comparison_result
compare (const Algebraic_real_rep& y, bool are_distinct = false) const{
if( is_rational()) return -y.compare( rational());
if(y.is_rational()) return compare(y.rational());
// type of both x and y IS_GENERAL
if ( high() <= y.low() ) return CGAL::SMALLER;
if ( low() >= y.high()) return CGAL::LARGER;
// intersection isolating intervals is ]L,R[
Rational L = (low() > y.low() ) ? low() : y.low() ;
Rational R = (high() < y.high()) ? high() : y.high() ;
// refine to smaller intervals at intersection interval boundaries
// this can change type() only to IS_RATIONAL
refine_at(L);
refine_at(R);
y.refine_at(L);
y.refine_at(R);
if ( is_rational()) return -y.compare( rational());
if (y.is_rational()) return compare(y.rational());
// type of both x and y still IS_GENERAL
if ( high() <= y.low() ) return CGAL::SMALLER;
if ( y.high() <= low() ) return CGAL::LARGER;
// filter 2: probabilistically check coprimality
if (!are_distinct) {
are_distinct = !(may_have_common_factor(polynomial(),
y.polynomial()));
}
if (!are_distinct) {
// OK, filters failed. So we have to do the actual work
// and compute the gcd of the defining polynomials.
// we have ]low(), high()[ == ]y.low(),y.high()[ == ]L,R[
// and let both numbers decide for the gcd or its complement
Poly F1,F2,G;
G = CGAL::gcd_up_to_constant_factor(polynomial(),y.polynomial());
F1 = integral_division_up_to_constant_factor(polynomial(),G);
CGAL_postcondition(CGAL::degree(F1)==
CGAL::degree(polynomial())-CGAL::degree(G));
F2 = integral_division_up_to_constant_factor(y.polynomial(),G);
CGAL_postcondition(CGAL::degree(F2)==
CGAL::degree(y.polynomial())-CGAL::degree(G));
learn_from(G,F1);
y.learn_from(G,F2);
// this may simplify them due to degree loss
if (y.is_rational()) return compare(y.rational());
if ( is_rational()) return -y.compare( rational());
// type of x and y is still IS_GENERAL
// check for equality
if (G.sign_at(L)!=G.sign_at(R)){
introduce(y);
return CGAL::EQUAL;
}
}
// if we are here, we know the numbers to be distinct
// refine to disjointness
for (;;) {
y.refine();
refine();
if (y.is_rational()) return compare(y.rational());
if ( is_rational()) return -y.compare( rational());
if ( high() <= y.low()) return CGAL::SMALLER;
if (y.high() <= low()) return CGAL::LARGER;
}
}
protected:
void learn_from(const Rational& m) const {
if(is_rational()){
CGAL_precondition(rational()==m);
return;
}
CGAL_precondition(polynomial().sign_at(m)==CGAL::ZERO);
typename Fraction_traits<Rational>::Decompose decomp;
typename Fraction_traits<Rational>::Numerator_type num;
typename Fraction_traits<Rational>::Denominator_type den;
decomp(m, num, den);
Poly G = Poly(-Coefficient(num),Coefficient(den));
Poly F1= integral_division_up_to_constant_factor(polynomial(),G);
CGAL_postcondition(CGAL::degree(F1)==
CGAL::degree(polynomial())-CGAL::degree(G));
learn_from(G,F1);
if(!is_rational()) set_explicit_rep(m);
}
// splits the list of related algebraic reals according to the two
// factors of the polynomial
void learn_from(const Poly& pfactor1,
const Poly& pfactor2) const {
if(CGAL::degree(pfactor1)==0) return;
if(CGAL::degree(pfactor2)==0) return;
CGAL_precondition(may_have_common_factor(polynomial(),pfactor1));
CGAL_precondition(may_have_common_factor(polynomial(),pfactor2));
CGAL_precondition(CGAL::degree(pfactor1)+CGAL::degree(pfactor2)
== CGAL::degree(polynomial()));
Self dummy1, dummy2;
Self const *last=prev;
Self const *current=this;
Self const *next;
while(true){
next=current->next;
if(pfactor1.sign_at(current->low())!=
pfactor1.sign_at(current->high())){
current->next=&dummy1;
current->prev=dummy1.prev;
dummy1.prev->next=current;
dummy1.prev=current;
current->set_implicit_rep(pfactor1,
current->low(),
current->high(), true );
}else{
current->next=&dummy2;
current->prev=dummy2.prev;
dummy2.prev->next=current;
dummy2.prev=current;
current->set_implicit_rep(pfactor2,
current->low(),
current->high(), true );
}
if(current==last) break;
current=next;
}
}
public:
bool is_root_of(const Poly& Q) const {
if (CGAL::degree(Q) == 0) return Q.is_zero();
if (is_rational() ) return CGAL::ZERO == Q.sign_at(rational());
if ( may_have_common_factor(polynomial(), Q) ) {
Poly G = CGAL::gcd_up_to_constant_factor(polynomial(),Q);
if(CGAL::degree(G)!=0){
Poly F1 = integral_division_up_to_constant_factor(
polynomial(),G
);
CGAL_postcondition(CGAL::degree(F1)==
CGAL::degree(polynomial())-CGAL::degree(G));
learn_from(G,F1);
return (G.sign_at(low()) != G.sign_at(high()));
}
}
return false;
}
public:
virtual void simplify() const{
if(is_rational()){
}else{
CGAL::simplify(low_);
CGAL::simplify(high_);
polynomial_ = typename Polynomial_traits_d<Poly>::Canonicalize()(polynomial_);
}
}
};
} // namespace internal
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H
@@ -0,0 +1,417 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
// This is code is expreimental !
/*! \file NiX/Algebraic_real_rep_bfi.h
\brief Algebraic_real_rep with refinement via interval rep
*/
#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H
#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H
#include <CGAL/basic.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Polynomial_type_generator.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_real_rep.h>
#include <CGAL/Interval_traits.h>
#include <CGAL/Bigfloat_interval_traits.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/Sqrt_extension_fwd.h>
#include <CGAL/Get_arithmetic_kernel.h>
namespace CGAL {
// it would be nice to remove the explicit use of Sqrt_extension
// in this file. However, it is much more efficient to convert the root
// only once. see convert_to_bfi
//template <class COEFF, class ROOT> class Sqrt_extension; //use forward declaration instead
namespace internal {
// definition of the Algebraic_real_rep_bfi x:
//IS_GENERAL:
// low_ lower bound of x
// high_ upper bound of x
// polynomial_ a square free polynomial
// sign_at_low_ = polynomial_.evaluate(low_)
// x is the only root of polynomial_ in the open interval ]low_,high_[
// low_ != x != high
// ******************* EXEPTION *******************
// x is rational: in this case low=high=x
template< class Coefficient_, class Field_>
class Algebraic_real_rep_bfi
: public Algebraic_real_rep<Coefficient_,Field_> {
typedef Algebraic_real_rep<Coefficient_,Field_> Base;
typedef Coefficient_ Coefficient;
typedef Field_ Field;
typedef typename CGAL::Get_arithmetic_kernel<Coefficient>::Arithmetic_kernel AT;
typedef typename AT::Bigfloat BF;
typedef typename AT::Bigfloat_interval BFI;
typedef typename AT::Field_with_sqrt FWS;
typedef typename CGAL::Polynomial_type_generator<Coefficient,1>::Type Poly;
typedef typename Poly::const_iterator PIterator;
typedef Algebraic_real_rep_bfi <Coefficient,Field> Self;
mutable std::vector<BFI> polynomial_approx;
mutable long current_prec;
private:
template <class Polynomial_1, class OI>
inline
void convert_coeffs(const Polynomial_1& poly, OI it) const {
typename CGAL::Polynomial_traits_d<Polynomial_1>::Get_coefficient
coeff;
for(int i = 0; i <= CGAL::degree(poly); i++){
*it++ = convert_to_bfi(coeff(poly,i));
}
}
template <class COEFF, class ROOT, class ACDE_TAG, class FP_TAG, class OI >
inline
void
convert_coeffs(
const CGAL::Polynomial< CGAL::Sqrt_extension<COEFF,ROOT,ACDE_TAG,FP_TAG> >& poly,
OI it ) const {
BFI root(0);
for(int i = 0; i <= CGAL::degree(poly); i++){
if(poly[i].is_extended()){
// typename Coercion_traits<FWS,ROOT >::Cast cast_root;
// root = convert_to_bfi(NiX::sqrt(cast_root(poly[i].root())));
root = CGAL::sqrt(convert_to_bfi(poly[i].root()));
break;
}
}
for(int i = 0; i <= CGAL::degree(poly); i++){
if(poly[i].is_extended()){
*it++ =
convert_to_bfi(poly[i].a0()) +
convert_to_bfi(poly[i].a1()) * root ;
}else{
*it++ = convert_to_bfi(poly[i].a0());
}
}
}
typedef CGAL::Sign TRI_BOOL;
public:
const Field& low() const {return this->low_;}
const Field& high() const {return this->high_;}
const Poly& polynomial() const {return this->polynomial_;}
const TRI_BOOL& sign_at_low() const {return this->sign_at_low_;}
template <class NTX>
void strong_refine(const NTX& m) const{
if(is_rational()) return;
if( NTX(low()) <= m && m <= NTX(high()) ){
CGAL_precondition(polynomial().sign_at(m)!=CGAL::ZERO);
refine();
while( NTX(low()) <= m && m <= NTX(high())) refine();
}
}
bool is_rational() const {return this->is_rational_;}
const Field& rational() const {
CGAL_precondition(is_rational());
CGAL_precondition(low()==high());
CGAL_precondition(polynomial().sign_at(low())==CGAL::ZERO);
return this->low_;
}
CGAL::Comparison_result
compare(const Field& y, bool are_distinct = false) const {
if(is_rational()) return CGAL::compare(rational(),y);
if(y <= low()) {
strong_refine(y);
return CGAL::LARGER;
}
if(high() <= y) {
strong_refine(y);
return CGAL::SMALLER;
}
// now: low < y < high
if(!are_distinct){
if(sign_of_polynomial_at(y)==CGAL::ZERO){
this->learn_from(y);
return CGAL::EQUAL ;
}
}else{
CGAL_precondition(polynomial().sign_at(y)!=CGAL::ZERO);
}
strong_refine(y);
CGAL_postcondition(y < low() || high() < y );
if(y < low()) return CGAL::LARGER;
else return CGAL::SMALLER;
}
CGAL::Comparison_result
compare (const Algebraic_real_rep_bfi& y, bool are_distinct = false) const{
if( is_rational()) return -y.compare( rational());
if(y.is_rational()) return compare(y.rational());
// type of both x and y IS_GENERAL
if ( high() <= y.low() ) return CGAL::SMALLER;
if ( low() >= y.high()) return CGAL::LARGER;
// intersection isolating intervals is ]L,R[
Field L = (low() > y.low() ) ? low() : y.low() ;
Field R = (high() < y.high()) ? high() : y.high() ;
// refine to smaller intervals at intersection interval boundaries
// this can change type() only to IS_RATIONAL
this->refine_at(L);
this->refine_at(R);
y.refine_at(L);
y.refine_at(R);
if ( is_rational()) return -y.compare( rational());
if (y.is_rational()) return compare(y.rational());
// type of both x and y still IS_GENERAL
if ( high() <= y.low() ) return CGAL::SMALLER;
if ( y.high() <= low() ) return CGAL::LARGER;
// filter 1 (optional): determine distinctness by refining intervals
#if NiX_REFINEMENTS_BEFORE_GCD > 0
if (!are_distinct) {
// we may want to refine a bit and hope for the best
// because computing the gcd is expensive
for (int ntries=0; ntries < NiX_REFINEMENTS_BEFORE_GCD; ntries++) {
y.refine();
refine();
if (y.is_rational()) return compare(y.rational());
if ( is_rational()) return -y.compare( rational());
if ( high() <= y.low()) return CGAL::SMALLER;
if (y.high() <= low()) return CGAL::LARGER;
}
}
#endif
// filter 2: probabilistically check coprimality
if (!are_distinct) {
are_distinct = !(may_have_common_factor(polynomial(),
y.polynomial()));
}
if (!are_distinct) {
// OK, filters failed. So we have to do the actual work
// and compute the gcd of the defining polynomials.
// we have ]low(), high()[ == ]y.low(),y.high()[ == ]L,R[
// and let both numbers decide for the gcd or its complement
Poly F1,F2,G;
G = CGAL::gcd_up_to_constant_factor(polynomial(),y.polynomial());
F1 = CGAL::integral_division_up_to_constant_factor(polynomial(),G);
CGAL_postcondition(CGAL::degree(F1)==
CGAL::degree(polynomial())-CGAL::degree(G));
F2 = CGAL::integral_division_up_to_constant_factor(y.polynomial(),G);
CGAL_postcondition(CGAL::degree(F2)==
CGAL::degree(y.polynomial())-CGAL::degree(G));
this->learn_from(G,F1);
y.learn_from(G,F2);
// this may simplify them due to degree loss
if (y.is_rational()) return compare(y.rational());
if ( is_rational()) return -y.compare( rational());
// type of x and y is still IS_GENERAL
// check for equality
if (G.sign_at(L)!=G.sign_at(R)){
this->introduce(y);
return CGAL::EQUAL;
}
}
// if we are here, we know the numbers to be distinct
// refine to disjointness
for (;;) {
y.refine();
refine();
if (y.is_rational()) return compare(y.rational());
if ( is_rational()) return -y.compare( rational());
if ( high() <= y.low()) return CGAL::SMALLER;
if (y.high() <= low()) return CGAL::LARGER;
}
}
//! creates the algebraic real from int \a i.
explicit Algebraic_real_rep_bfi(int i = 0)
:Base(i){}
//! creates the algebraic real from Field \a m.
explicit Algebraic_real_rep_bfi(const Field& m)
:Base(m), current_prec(53) {}
/*! \brief creates the algebraic real as the unique root of \a P
in the open interval <var>]low,high[</var>.
\pre the polynomial \a P is square free
\pre P(low)!=0
\pre P(high)<0
\pre x is the one and only root in the open interval of \a P.
*/
Algebraic_real_rep_bfi(const Poly& P, Field LOW, Field HIGH):
Base(P,LOW,HIGH), current_prec(53){};
//! copy constructor
Algebraic_real_rep_bfi(const Self& y)
: Base(y), current_prec(53){}
// assignment
Algebraic_real_rep_bfi& operator=(const Self& y) {
if ( this != & y) {
this->erase_from_list();
this->copy_all_members(y);
this->introduce(y);
current_prec = y->current_prec;
}
NiX_expensive_postcond(this->self_test());
return *this;
}
BFI evaluate_polynomial_approx(const BFI& x) const {
// std::cout << "eval approx begin"<< std::endl;
typedef std::vector<BFI> BFI_VEC;
typedef typename BFI_VEC::reverse_iterator RIT;
BFI result(0);
for(RIT rit = polynomial_approx.rbegin();
rit != polynomial_approx.rend();
rit++){
result = result * x + (*rit);
}
// std::cout << "eval approx end"<< std::endl;
return result;
}
void refine_poly_approximation() const {
CGAL_precondition(current_prec > 1);
current_prec *= 2;
// std::cout <<"ALGREAL: refine approx: "<< current_prec<<std::endl;
set_precision(BFI(),current_prec);
polynomial_approx.clear();
convert_coeffs(
this->polynomial(),
std::back_inserter(polynomial_approx));
Self const *next = static_cast<const Self *>(this->next);
while(this != next){
// std::cout << this << " " << next << std::endl;
next->polynomial_approx = polynomial_approx;
next->current_prec = current_prec;
next = static_cast<const Self *>(next->next);
}
};
void update_poly_approximation() const {
long old_prec = set_precision( BFI(), current_prec );
polynomial_approx.clear();
convert_coeffs( this->polynomial(), std::back_inserter( polynomial_approx ) );
set_precision( BFI(), old_prec );
// TODO: Problems if the next block gets executed
// Self const *next = static_cast<const Self *>(this->next);
// while(this != next){
// // std::cout << this << " " << next << std::endl;
// next->polynomial_approx = polynomial_approx;
// next->current_prec = current_prec;
// next = static_cast<const Self *>(next->next);
// }
}
void refine() const{
if(this->is_rational()) return;
// std::cout << "refine begin ------- "<< std::endl;
Field m = (this->low()+this->high())/Field(2);
// Currently, sign_of_polynomial_at performs exactly the needed
// refinement.
// TODO: But what if this changes?
sign_of_polynomial_at( m );
//std::cout << "refine end ----------------- "<<current_prec<< std::endl;
}
protected:
virtual CGAL::Sign sign_of_polynomial_at( const Field& f ) const {
//return polynomial().sign_at( f );
long old_prec = set_precision(BFI(),current_prec);
Field m = f;
CGAL::simplify(m);
// if polynomial has changed, the approximated polynomial gets
// updated
if ( (int) polynomial_approx.size() !=
CGAL::degree(this->polynomial_)+1) {
update_poly_approximation();
}
CGAL_postcondition(polynomial_approx.size() > 0);
BFI eval = evaluate_polynomial_approx(convert_to_bfi(m));
CGAL::Sign s = CGAL::sign(CGAL::lower(eval));
// correct sign if needed
if( s*CGAL::sign(CGAL::upper(eval) ) != CGAL::POSITIVE ){
//std::cout << "APPROX FAILED-------------------------------"<<std::endl;
s = this->polynomial().sign_at(m);
if ( s != CGAL::ZERO ) {
refine_poly_approximation();
}
}
CGAL_postcondition(s == this->polynomial_.sign_at(m));
if ( s == CGAL::ZERO ) {
this->learn_from(m);
}else{
if ( s == this->sign_at_low() ) this->low_ = m;
else this->high_ = m;
}
set_precision(BFI(),old_prec);
return s;
}
};
}//namespace internal
} //namespace CGAL
#endif //CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H
@@ -0,0 +1,63 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ==========================================================================
#ifndef CGAL_BITSTREAM_COEFFICIENT_KERNEL_H
#define CGAL_BITSTREAM_COEFFICIENT_KERNEL_H 1
#include <CGAL/Algebraic_structure_traits.h>
#include <CGAL/convert_to_bfi.h>
namespace CGAL {
namespace internal {
template <typename Coefficient_> struct Bitstream_coefficient_kernel {
typedef Coefficient_ Coefficient;
typedef typename
CGAL::Get_arithmetic_kernel<Coefficient_>::Arithmetic_kernel
Arithmetic_kernel;
typedef typename Arithmetic_kernel::Bigfloat_interval Bigfloat_interval;
typedef typename Arithmetic_kernel::Integer Integer;
typedef typename Arithmetic_kernel::Rational Bound;
typedef typename CGAL::Algebraic_structure_traits<Coefficient>
::Is_zero Is_zero;
Is_zero is_zero_object() const {
return Is_zero();
}
struct Convert_to_bfi : public CGAL::cpp98::unary_function
<Coefficient,Bigfloat_interval> {
Bigfloat_interval operator() (Coefficient c) const {
return CGAL::convert_to_bfi(c);
}
};
Convert_to_bfi convert_to_bfi_object() const {
return Convert_to_bfi();
}
}; // of class Bitstream_coefficient_kernel
} // namespace internal
} //namespace CGAL
#endif // CGAL_BITSTREAM_COEFFICIENT_KERNEL_H
@@ -0,0 +1,226 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H
#define CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H 1
namespace CGAL {
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/convert_to_bfi.h>
namespace internal {
template < typename AlgebraicKernel_1 >
class Bitstream_coefficient_kernel_at_alpha;
template < typename AlgebraicKernel_1 >
class Bitstream_coefficient_kernel_at_alpha_rep {
public:
typedef AlgebraicKernel_1 Algebraic_kernel_d_1;
typedef typename Algebraic_kernel_d_1::Polynomial_1 Polynomial_1;
typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1;
Bitstream_coefficient_kernel_at_alpha_rep() : _m_kernel(nullptr) {}
Bitstream_coefficient_kernel_at_alpha_rep(Algebraic_kernel_d_1* kernel,
Algebraic_real_1 alpha)
: _m_kernel(kernel), _m_alpha(alpha) {}
friend class Bitstream_coefficient_kernel_at_alpha
<Algebraic_kernel_d_1>;
private:
Algebraic_kernel_d_1* _m_kernel;
Algebraic_real_1 _m_alpha;
};
template < typename AlgebraicKernel_1 >
class Bitstream_coefficient_kernel_at_alpha
: public CGAL::Handle_with_policy
< CGAL::internal::Bitstream_coefficient_kernel_at_alpha_rep
<AlgebraicKernel_1 >
>
{
public:
//! \name typedefs
//! @{
typedef AlgebraicKernel_1 Algebraic_kernel_d_1;
typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1;
typedef typename Algebraic_kernel_d_1::Polynomial_1 Polynomial_1;
typedef Polynomial_1 Coefficient;
typedef typename
CGAL::Get_arithmetic_kernel<typename Coefficient::NT>::Arithmetic_kernel
Arithmetic_kernel;
typedef typename Arithmetic_kernel::Integer Integer;
typedef typename Algebraic_kernel_d_1::Bound Bound;
typedef typename Arithmetic_kernel::Bigfloat_interval Bigfloat_interval;
typedef CGAL::internal::Bitstream_coefficient_kernel_at_alpha_rep
<Algebraic_kernel_d_1> Rep;
typedef CGAL::Handle_with_policy<Rep> Base;
typedef Bitstream_coefficient_kernel_at_alpha<Algebraic_kernel_d_1> Self;
//! @}
public:
//! \name Constructors
// !@{
Bitstream_coefficient_kernel_at_alpha() : Base(Rep()) {}
#ifdef DOXYGEN_RUNNING
Bitstream_coefficient_kernel_at_alpha(const Self& traits)
: Base(static_cast<const Base&>(traits)) {}
#endif
Bitstream_coefficient_kernel_at_alpha(Algebraic_kernel_d_1* kernel,
Algebraic_real_1 alpha)
: Base(kernel,alpha) {}
//@}
//! \name Functors
//! @{
struct Is_zero : public CGAL::cpp98::unary_function<Coefficient,bool> {
Is_zero(Algebraic_kernel_d_1* kernel,Algebraic_real_1 alpha)
: _m_kernel(kernel),_m_alpha(alpha) {}
bool operator() (Coefficient f) const {
return _m_kernel->is_zero_at_1_object() (f,_m_alpha);
}
private:
Algebraic_kernel_d_1* _m_kernel;
Algebraic_real_1 _m_alpha;
};
Is_zero is_zero_object() const {
return Is_zero(this->ptr()->_m_kernel,this->ptr()->_m_alpha);
}
struct Convert_to_bfi
: public CGAL::cpp98::unary_function<Coefficient,Bigfloat_interval> {
Convert_to_bfi(Algebraic_kernel_d_1* kernel,
Algebraic_real_1 alpha)
: _m_kernel(kernel), _m_alpha(alpha) {}
Bigfloat_interval operator() (Coefficient f) const {
typename CGAL::Polynomial_traits_d<Coefficient>
::template Rebind<Bigfloat_interval,1>::Other::Type f_bfi;
typename Algebraic_kernel_d_1::Approximate_relative_1 approx_alpha
=_m_kernel->approximate_relative_1_object();
typedef typename Algebraic_kernel_d_1::Bound Bound;
Bigfloat_interval alpha_bfi, f_alpha_bfi;
long p = CGAL::get_precision(Bigfloat_interval());
long prec = 16;
long wbit = 0;
while(true) {
CGAL::set_precision(Bigfloat_interval(),prec);
f_bfi = this->_convert_polynomial_to_bfi(f);
std::pair<Bound,Bound> alpha_bounds
= approx_alpha(_m_alpha,prec);
alpha_bfi = CGAL::hull
(CGAL::convert_to_bfi(alpha_bounds.first),
CGAL::convert_to_bfi(alpha_bounds.second));
f_alpha_bfi = f_bfi.evaluate(alpha_bfi);
if(!CGAL::singleton(f_alpha_bfi)) {
long ceil = CGAL::internal::ceil_log2_abs(f_alpha_bfi);
long signi = CGAL::get_significant_bits(f_alpha_bfi);
wbit = ceil - signi + p;
}
if(wbit<-5 || CGAL::singleton(f_alpha_bfi)) {
break;
} else {
prec*=2;
}
}
CGAL::set_precision(Bigfloat_interval(),p);
return f_alpha_bfi;
}
private:
typename CGAL::Polynomial_traits_d<Coefficient>
::template Rebind<Bigfloat_interval,1>::Other::Type
_convert_polynomial_to_bfi(Coefficient f) const {
typename
CGAL::Polynomial_traits_d<Coefficient>::Get_coefficient coeff;
std::vector<Bigfloat_interval> coeffs(CGAL::degree(f)+1);
const int d = CGAL::degree(f);
for(int i = 0; i <= d; i++) {
coeffs[i] = CGAL::convert_to_bfi(coeff(f,i));
}
return typename CGAL::Polynomial_traits_d<Coefficient>
::template Rebind<Bigfloat_interval,1>::Other
::Construct_polynomial()(coeffs.begin(),coeffs.end());
}
Algebraic_kernel_d_1* _m_kernel;
Algebraic_real_1 _m_alpha;
};
Convert_to_bfi convert_to_bfi_object() const {
return Convert_to_bfi(this->ptr()->_m_kernel,this->ptr()->_m_alpha);
}
// @}
};
} // namespace internal
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,440 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H
#define CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Algebraic_kernel_d/Real_embeddable_extension.h>
#include <CGAL/Bigfloat_interval_traits.h>
#include <CGAL/Algebraic_kernel_d/Float_traits.h>
#include <CGAL/Polynomial_type_generator.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/tss.h>
#include <vector>
#if CGAL_USE_CORE
namespace CORE { class BigInt; }
#endif
namespace CGAL {
namespace internal {
#if CGAL_USE_CORE
// bugfix for CORE by Michael Kerber
// why is there a specialized function for CORE?
inline CORE::BigInt shift_integer_by(CORE::BigInt x, long shift){
if( shift > 0 ){
while(shift>63) {
x = (x >> 63);
shift-=63;
}
x = (x >> shift);
}else{
// add 0 bits
x = (x << -shift);
}
return x;
}
#endif
template <class Shiftable>
Shiftable shift_integer_by(Shiftable x, long shift){
if( shift > 0 ){
x >>= shift;
}else{
x <<= -shift; // adds 0 bits
}
return x;
}
// forward
template <typename BitstreamCoefficientKernel>
class Bitstream_descartes_rndl_tree_traits;
template <class BitstreamCoefficientKernel>
class Bitstream_descartes_rndl_tree_traits_rep {
public:
typedef BitstreamCoefficientKernel Bitstream_coefficient_kernel;
Bitstream_descartes_rndl_tree_traits_rep
(Bitstream_coefficient_kernel kernel)
: _m_kernel(kernel)
{
}
Bitstream_descartes_rndl_tree_traits_rep() {}
private:
Bitstream_coefficient_kernel _m_kernel;
friend class Bitstream_descartes_rndl_tree_traits
<Bitstream_coefficient_kernel>;
}; // end of class Bitstream_descartes_rndl_tree_traits_rep
// A version that relies on a Bitstream_coefficient_kernel model
template <typename BitstreamCoefficientKernel>
class Bitstream_descartes_rndl_tree_traits
: CGAL::Handle_with_policy
<CGAL::internal::Bitstream_descartes_rndl_tree_traits_rep
<BitstreamCoefficientKernel> >
{
public:
//! typedefs
//! @{
typedef BitstreamCoefficientKernel Bitstream_coefficient_kernel;
typedef typename Bitstream_coefficient_kernel::Coefficient Coefficient;
typedef typename Bitstream_coefficient_kernel::Bigfloat_interval BFI;
typedef typename CGAL::Bigfloat_interval_traits<BFI>::Bound BF;
typedef typename
CGAL::Polynomial_type_generator<Coefficient,1>::Type POLY;
typedef Bitstream_descartes_rndl_tree_traits
< Bitstream_coefficient_kernel > Self;
typedef CGAL::Handle_with_policy
<CGAL::internal::Bitstream_descartes_rndl_tree_traits_rep
<Bitstream_coefficient_kernel> >
Base;
typedef typename Bitstream_coefficient_kernel::Integer Integer;
typedef typename Bitstream_coefficient_kernel::Bound Bound;
//! @}
private:
static const Self& get_default_instance(){
Bitstream_coefficient_kernel kernel;
CGAL_STATIC_THREAD_LOCAL_VARIABLE(Self, x,kernel);
return x;
}
public:
//! \name Constructors
//! @{
Bitstream_descartes_rndl_tree_traits(const Bitstream_coefficient_kernel& kernel)
: Base(kernel){}
Bitstream_descartes_rndl_tree_traits()
: Base(static_cast<const Base&>(get_default_instance())){}
// explicit copy-constructor, required by VC9
#ifdef DOXYGEN_RUNNING
Bitstream_descartes_rndl_tree_traits(const Self& traits)
: Base(static_cast<const Base&>(traits)){}
#endif
//! @}
class Approximator {
private:
Bitstream_coefficient_kernel _m_kernel;
public:
Approximator
(const Bitstream_coefficient_kernel& kernel)
: _m_kernel(kernel) {};
Approximator() {};
Integer operator() (Coefficient f, long p) {
//std::cout << "Called approximator with f=" << f
// << " and p=" << p << std::endl;
typename CGAL::internal::Float_traits<BF>::Get_exponent get_exp;
typename CGAL::internal::Float_traits<BF>::Get_mantissa get_m;
long old_prec = CGAL::get_precision(BFI());
long prec = 4;
BFI f_alpha_bfi;
while(true) {
CGAL::set_precision(BFI(),prec);
f_alpha_bfi = _m_kernel.convert_to_bfi_object()(f);
if(CGAL::singleton(f_alpha_bfi)) {
break;
}
if(CGAL::internal::ceil_log2_abs(CGAL::upper(f_alpha_bfi)-
CGAL::lower(f_alpha_bfi)) <=-p) {
break;
} else {
prec*=2;
}
}
BF lower = CGAL::lower(f_alpha_bfi);
long shift = - (p + get_exp(lower));
Integer bfi_m(get_m(lower));
bfi_m = shift_integer_by(bfi_m,shift);
// if( shift > 0 ){
// while(shift>63) { // this is a bug fix HACK for CORE::BigInt
// bfi_m = (bfi_m >> 63);
// shift-=63;
// }
// bfi_m = (bfi_m >> shift);
// }else{
// // add 0 bits
// bfi_m = (bfi_m << -shift);
// }
CGAL::set_precision(BFI(),old_prec);
//std::cout << "returns " << bfi_m << std::endl;
return bfi_m;
}
};
Approximator approximator_object() const {
return Approximator(this->ptr()->_m_kernel);
}
class Lower_bound_log2_abs {
private:
Bitstream_coefficient_kernel _m_kernel;
public:
Lower_bound_log2_abs
(const Bitstream_coefficient_kernel& kernel)
: _m_kernel(kernel) {}
Lower_bound_log2_abs() {};
long operator() (Coefficient f) {
//std::cout << "Called lower_bound_log2_abs with "
// << f << std::flush;
CGAL_assertion(! _m_kernel.is_zero_object()(f));
long old_prec = CGAL::get_precision(BFI());
long prec = 4;
BFI f_alpha_iv;
long result;
while(true) {
CGAL::set_precision(BFI(),prec);
f_alpha_iv = _m_kernel.convert_to_bfi_object()(f);
CGAL::Sign lower_sign = CGAL::sign(CGAL::lower(f_alpha_iv));
if(CGAL::sign(CGAL::upper(f_alpha_iv))==lower_sign) {
BF abs_lower, abs_upper;
if(lower_sign==CGAL::POSITIVE) {
abs_lower=CGAL::lower(f_alpha_iv);
abs_upper=CGAL::upper(f_alpha_iv);
}
else {
abs_lower=CGAL::abs(CGAL::upper(f_alpha_iv));
abs_upper=CGAL::abs(CGAL::upper(f_alpha_iv));
}
long lower_bound = CGAL::internal::floor_log2_abs(abs_lower),
upper_bound = CGAL::internal::ceil_log2_abs(abs_upper);
CGAL_assertion(upper_bound>=lower_bound);
if(upper_bound-lower_bound <=2) {
result = lower_bound;
break;
}
}
prec*=2;
}
//std::cout << "returning " << result << std::endl;
CGAL::set_precision(BFI(),old_prec);
return result;
}
};
Lower_bound_log2_abs lower_bound_log2_abs_object() const {
return Lower_bound_log2_abs(this->ptr()->_m_kernel);
}
class Upper_bound_log2_abs_approximator {
private:
Bitstream_coefficient_kernel _m_kernel;
// Stores id of polynomials which are known to vanish (or not to
// vanish) at alpha
std::vector<Coefficient> zeroes,non_zeroes;
std::vector<Coefficient> coeffs_for_alpha;
// Stores the last known approximation to ensure an improvement
long prec;
public:
Upper_bound_log2_abs_approximator
(const Bitstream_coefficient_kernel& kernel)
: _m_kernel(kernel), prec(4)
{}
Upper_bound_log2_abs_approximator() : prec(4) {};
bool initial_upper_bound
(Coefficient f, long& ub_log2_abs,bool& is_certainly_zero) {
return improve_upper_bound(f,ub_log2_abs,is_certainly_zero);
}
bool improve_upper_bound
(const Coefficient f, long& ub_log2_abs,bool& is_certainly_zero) {
//std::cout << "improve upper bound.."
// << f << std::endl;
long old_prec = CGAL::get_precision(BFI());
if(std::find(zeroes.begin(),
zeroes.end(),
f)!=zeroes.end()) {
//std::cout << "ZERO FROM CACHE" << std::endl;
is_certainly_zero=true;
return true;
}
else if(std::find(non_zeroes.begin(),
non_zeroes.end(),
f)!=non_zeroes.end()) {
//std::cout << "NON-ZERO FROM CACHE" << std::endl;
is_certainly_zero=false;
}
else {
bool zero = _m_kernel.is_zero_object()(f);
if(zero) {
//std::cout << "THAT IS ZERO!" << std::endl;
zeroes.push_back(f);
is_certainly_zero=true;
return true;
}
else {
//std::cout << "THAT IS NOT ZERO!" << std::endl;
non_zeroes.push_back(f);
is_certainly_zero=false;
}
}
if(std::find(coeffs_for_alpha.begin(),
coeffs_for_alpha.end(),f)!=
coeffs_for_alpha.end()) {
prec*=2;
coeffs_for_alpha.clear();
}
coeffs_for_alpha.push_back(f);
BFI f_alpha_iv = _m_kernel.convert_to_bfi_object()(f);
BF abs_upper = (std::max)(CGAL::abs(CGAL::lower(f_alpha_iv)),
CGAL::abs(CGAL::upper(f_alpha_iv)));
if(CGAL::sign(abs_upper)==CGAL::ZERO) {
is_certainly_zero=true;
CGAL::set_precision(BFI(),old_prec);
return true;
}
ub_log2_abs = CGAL::internal::ceil_log2_abs(abs_upper);
if(! CGAL::zero_in(f_alpha_iv) ) {
BF abs_lower = (std::min)(CGAL::abs(CGAL::lower(f_alpha_iv)),
CGAL::abs(CGAL::upper(f_alpha_iv)));
long lb_log2_abs
= CGAL::internal::floor_log2_abs
(CGAL::convert_to_bfi(abs_lower));
CGAL_assertion(ub_log2_abs >= lb_log2_abs);
CGAL::set_precision(BFI(),old_prec);
return ((ub_log2_abs - lb_log2_abs) <= 2);
}
else {
//std::cout << "Upper: " << ub_log2_abs << std::endl;
CGAL::set_precision(BFI(),old_prec);
return false;
}
}
};
Upper_bound_log2_abs_approximator
upper_bound_log2_abs_approximator_object() const {
return Upper_bound_log2_abs_approximator(this->ptr()->_m_kernel);
}
// TODO: Look whether this is best possible
class Bound_creator {
public:
Bound_creator() {}
Bound operator() (Integer x,long p) {
Integer num=x, denom,two(2),q,r;
if(p < 0) {
CGAL::div_mod(num,two,q,r);
while(r==Integer(0) && p<0) {
num=q;
p++;
CGAL::div_mod(num,two,q,r);
}
denom = CGAL::ipower(Integer(2),-p);
}
else {
num*=CGAL::ipower(Integer(2),p);
denom=1;
}
Bound b(num);
b /= Bound(denom);
CGAL::simplify(b);
return b;
}
};
typedef typename CGAL::Real_embeddable_traits<Integer>::Sgn Sign;
typedef typename CGAL::internal::Real_embeddable_extension<Integer>
::Ceil_log2_abs Ceil_log2_abs_Integer;
typedef typename CGAL::internal::Real_embeddable_extension<long>
::Ceil_log2_abs Ceil_log2_abs_long;
}; // end of class Bitstream_descartes_rndl_tree_traits
} // namespace internal
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,464 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
/*! \file NiX/Descartes.h
\brief defines class NiX::Descartes.
Isolate real roots of polynomials.
This file provides a class to isolate real roots of polynomials,
using the algorithm based on the method of Descartes.
The polynomial has to be a univariat polynomial over any number
type which is contained in the real numbers.
*/
#ifndef CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H
#define CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H
#include <CGAL/basic.h>
#include <CGAL/Polynomial.h>
#include <CGAL/Algebraic_kernel_d/univariate_polynomial_utils.h>
#include <CGAL/Algebraic_kernel_d/construct_binary.h>
#define POLYNOMIAL_REBIND( coeff ) \
typename CGAL::Polynomial_traits_d<Polynomial>::template \
Rebind<coeff,1>::Other::Type
namespace CGAL {
namespace internal {
/*! \ingroup NiX_Algebraic_real
* \brief A model of concept RealRootIsolator.
*/
template <class Polynomial_, class Rational_>
class Descartes {
typedef CGAL::Fraction_traits<Polynomial_> FT_poly;
typedef Fraction_traits<Rational_> FT_rat;
public:
//! First template parameter
typedef Polynomial_ Polynomial;
//! Second template parameter
typedef Rational_ Rational;
//! Bound type of the isolating intervals
typedef Rational_ Bound;
// Integer or Numerator/Denominator type of bound.
typedef typename CGAL::Fraction_traits<Rational>::Numerator_type Integer;
private:
typedef typename Polynomial::NT Coeff;
typedef Integer IT;
Polynomial poly_;
int number_of_real_roots_;
IT* numerator;
IT* denominator_exponent;
bool* is_exact;
IT LEFT,SCALE,DENOM;
bool is_strong_;
int k;
bool interval_given;
public:
/*! \brief Constructor from univariate square free polynomial.
The RealRootIsolator provides isolating intervals for the real
roots of the polynomial.
\pre the polynomial is square free
*/
Descartes(const Polynomial& P = Polynomial(Coeff(0)),
bool is_strong = false,
int kk = 2)
: poly_(P) ,
is_strong_(is_strong),
k(kk),
interval_given(false) {
numerator = new IT[CGAL::degree(P)];
denominator_exponent = new IT[CGAL::degree(P)];
is_exact = new bool[CGAL::degree(P)];
number_of_real_roots_ = 0;
if(CGAL::degree(P) == 0)
{
if(P.is_zero()) number_of_real_roots_ = -1;
return;
}
intern_decompose(poly_,typename FT_poly::Is_fraction());
}
// constructor for coefficient types \c Coeff with given interval
// (experimental)
Descartes(const Polynomial& P,
const Rational& left,
const Rational& right,
bool is_strong = false,
int kk = 2)
: poly_(P) ,
is_strong_(is_strong),
k(kk),
interval_given(true) {
numerator = new IT[CGAL::degree(P)];
denominator_exponent = new IT[CGAL::degree(P)];
is_exact = new bool[CGAL::degree(P)];
number_of_real_roots_ = 0;
if(CGAL::degree(P) == 0)
{
if(P.is_zero()) number_of_real_roots_ = -1;
return;
}
typename FT_rat::Decompose decompose;
typedef typename FT_rat::Numerator Numerator;
typedef typename FT_rat::Denominator Denominator;
Numerator numleft, numright;
Denominator denleft, denright;
decompose(left,numleft,denleft);
decompose(right,numright,denright);
LEFT = numleft * denright;
SCALE = numright * denleft - LEFT;
DENOM = denleft * denright;
poly_.scale_down(denleft*denright);
intern_decompose(poly_,typename FT_poly::Is_decomposable());
}
//! copy constructor
Descartes(const Descartes& D)
: poly_(D.poly_),
number_of_real_roots_(D.number_of_real_roots_),
LEFT(D.LEFT),
SCALE(D.SCALE),
DENOM(D.DENOM),
is_strong_(D.is_strong_),
k(D.k),
interval_given(D.interval_given) {
numerator = new IT[CGAL::degree(poly_)];
denominator_exponent = new IT[CGAL::degree(poly_)];
is_exact = new bool[CGAL::degree(poly_)];
for(int i=0; i<number_of_real_roots(); i++)
{
numerator[i] = D.numerator[i];
denominator_exponent[i] = D.denominator_exponent[i];
is_exact[i] = D.is_exact[i];
}
}
// destructor
~Descartes() {
delete[] numerator;
delete[] denominator_exponent;
delete[] is_exact;
}
public: // functions
/*! \brief returns the defining polynomial*/
Polynomial polynomial() const { return poly_; }
//! returns the number of real roots
int number_of_real_roots() const { return number_of_real_roots_; }
/*! \brief returns true if the isolating interval is degenerated to a
single point.
If is_exact_root(i) is true,
then left_bound(int i) equals \f$root_i\f$. \n
If is_exact_root(i) is true,
then right_bound(int i) equals \f$root_i\f$. \n
*/
bool is_exact_root(int i) const { return is_exact[i]; }
public:
void left_bound(int i, IT& numerator_, IT& denominator_) const {
CGAL_assertion(i >= 0 && i < number_of_real_roots_);
construct_binary(denominator_exponent[i], denominator_);
numerator_= SCALE * numerator[i] + LEFT * denominator_;
denominator_ = denominator_ * DENOM;
}
void right_bound(int i,IT& numerator_, IT& denominator_) const {
CGAL_assertion(i >= 0 && i < number_of_real_roots_);
if(is_exact[i]){
return left_bound(i,numerator_,denominator_);
}
else{
construct_binary(denominator_exponent[i],denominator_);
numerator_= SCALE * (numerator[i]+1) + LEFT * denominator_;
denominator_ = denominator_ * DENOM;
}
}
public:
/*! \brief returns \f${l_i}\f$ the left bound of the isolating interval
for root \f$root_{i}\f$.
In case is_exact_root(i) is true, \f$l_i = root_{i}\f$,\n
otherwise: \f$l_i < root_{i}\f$.
If \f$i-1>=0\f$, then \f$l_i > root_{i-1}\f$. \n
If \f$i-1>=0\f$, then \f$l_i >= r_{i-1}\f$,
the right bound of \f$root_{i-1}\f$\n
\pre 0 <= i < number_of_real_roots()
*/
Rational left_bound(int i) const {
IT numerator_, denominator_;
left_bound(i,numerator_,denominator_);
return Rational(numerator_) / Rational(denominator_);
}
/*! \brief returns \f${r_i}\f$ the right bound of the isolating interval
for root \f$root_{i}\f$.
In case is_exact_root(i) is true, \f$r_i = root_{i}\f$,\n
otherwise: \f$r_i > root_{i}\f$.
If \f$i+1< n \f$, then \f$r_i < root_{i+1}\f$,
where \f$n\f$ is number of real roots.\n
If \f$i+1< n \f$, then \f$r_i <= l_{i+1}\f$,
the left bound of \f$root_{i+1}\f$\n
\pre 0 <= i < number_of_real_roots()
*/
Rational right_bound(int i) const {
IT numerator_, denominator_;
right_bound(i,numerator_,denominator_);
return Rational(numerator_) / Rational(denominator_);
}
private:
void intern_decompose( Polynomial P_, ::CGAL::Tag_true){
typename FT_poly::Decompose decompose;
typename FT_poly::Numerator_type NumP;
typename FT_poly::Denominator_type dummy;
decompose(P_,NumP,dummy);
init_with(NumP);
}
void intern_decompose( Polynomial P, ::CGAL::Tag_false){
init_with(P);
}
template<class Polynomial__>
void init_with(const Polynomial__& P){
typedef typename Polynomial__::NT Coeff;
if(!interval_given)
{
LEFT = -weak_upper_root_bound<Coeff>(P);
SCALE = - LEFT * IT(2);
DENOM = IT(1);
}
Polynomial__ R = ::CGAL::translate(P,Coeff(LEFT));
Polynomial__ Q = ::CGAL::scale_up(R,Coeff(SCALE));
zero_one_descartes<Coeff>(Q,0,0);
}
//! returns the polynomial $(1 + x)^n P(1/(1 + x))$.
template <class Coeff__>
/*
typename
CGAL::Polynomial_traits_d<Polynomial>
::template Rebind<Coeff__,1>::Other::Type
*/
POLYNOMIAL_REBIND(Coeff__)
variation_transformation(const POLYNOMIAL_REBIND(Coeff__)& P) {
POLYNOMIAL_REBIND(Coeff__) R = reversal(P);
return translate_by_one(R);
}
//! Returns an upper bound on the absolute value of all roots of $P$.
/*! The upper bound is a power of two. Only works for univariate
* polynomials.
*/
template <class Coeff__>
IT weak_upper_root_bound(const POLYNOMIAL_REBIND(Coeff__)& P) {
typename Real_embeddable_traits<Coeff__>::Abs abs;
const int n = CGAL::degree(P);
IT r(1); // return value
Coeff__ x(1); // needed to "evaluate" the polynomial
Coeff__ val;
for (;;) {
val = -abs(P[n]);
for (int i = n-1; i >= 0; i--) {
val = val*x + abs(P[i]);
}
if (val < Coeff__(0)) return r;
r *= IT(2);
x = Coeff__(r);
}
}
//! tests if the polynomial has no root in the interval.
template <class Coeff__>
bool not_zero_in_interval(const POLYNOMIAL_REBIND(Coeff__)& P)
{
if(CGAL::degree(P) == 0) return true;
if(internal::sign_variations(variation_transformation<Coeff__>(P)) != 0)
return false;
return (P[0] != Coeff__(0) && P.evaluate(Coeff__(1)) != Coeff__(0));
}
//! Descartes algoritm to determine isolating intervals for the roots
//! lying in the interval (0,1).
// The parameters $(i,D)$ describe the interval $(i/2^D, (i+1)/2^D)$.
// Here $0\leq i < 2^D$.
template <class Coeff__>
void zero_one_descartes(const POLYNOMIAL_REBIND(Coeff__)& P,
IT i, IT D) {
// Determine the number of sign variations of the transformed
// polynomial $(1+x)^nP(1/(1+x))$. This gives the number of
// roots of $P$ in $(0,1)$.
POLYNOMIAL_REBIND(Coeff__) R = variation_transformation<Coeff__>(P);
int descarte = sign_variations(R);
// no root
if ( descarte == 0 ) return;
// exactly one root
// Note the termination criterion $P(0)\neq 0$ and $P(1)\neq 0$.
// This ensures that the given interval is an isolating interval.
if ( descarte == 1
&& P[0] != Coeff__(0)
&& P.evaluate(Coeff__(1)) != Coeff__(0) ) {
if(is_strong_) {
strong_zero_one_descartes<Coeff__>(P,i,D);
return;
}
else {
numerator[number_of_real_roots_] = i;
denominator_exponent[number_of_real_roots_] = D;
is_exact[number_of_real_roots_] = false;
number_of_real_roots_++;
return;
}
}
// more than one root
// Refine the interval.
i = 2*i; D = D+1;
// Transform the polynomial such that the first half of the interval
// is mapped to the unit interval.
POLYNOMIAL_REBIND(Coeff__) Q = scale_down(P,Coeff__(2));
// Consider the first half of the interval.
zero_one_descartes<Coeff__>(Q,i,D);
// Test if the polynomial is zero at the midpoint of the interval
POLYNOMIAL_REBIND(Coeff__) S = translate_by_one(Q);
if ( S[0] == Coeff__(0) ) {
numerator[number_of_real_roots_] = i + 1;
denominator_exponent[number_of_real_roots_] = D;
is_exact[number_of_real_roots_] = true;
number_of_real_roots_++;
}
// Consider the second half of the interval.
zero_one_descartes<Coeff__>(S,i+1,D);
}
//! Strong Descartes algoritm to determine isolating intervals for the
//! roots lying in the interval (0,1), where the first
//! derivative have no sign change. \pre $P$ has only one root in the
//! interval given by $(i,D)$.
// The parameters $(i,D)$ describe the interval $(i/2^D, (i+1)/2^D)$.
// Here $0\leq i < D$.
template <class Coeff__>
void strong_zero_one_descartes(const POLYNOMIAL_REBIND(Coeff__)& P,
IT i, IT D) {
// Test if the polynomial P' has no roots in the
// interval. For further use in Newton, the interval should be not
// too large.
// test if isolating interval is smaller than epsilon
// [l,r] -> r-l < epsilon
// l = (r-l) * i/2^D + l
// r = (r-l) * (i+1)/2^D + l
// r-l = (r-l) * 1/2^D
// r-l < epsilon = 2^(-k)
// <=> (r-l) * 1/2^D < 2^(-k)
// <=> 2^D > (r-l) / 2^(-k)
// <=> 2^D > (r-l) * 2^k
POLYNOMIAL_REBIND(Coeff__) PP = CGAL::differentiate(P);
if(not_zero_in_interval<Coeff__>(PP)) { // P'
IT tmp;
construct_binary(D-k, tmp); // tmp = 2^{D-k}
if(tmp * DENOM > SCALE ) {
numerator[number_of_real_roots_] = i;
denominator_exponent[number_of_real_roots_] = D;
is_exact[number_of_real_roots_] = false;
number_of_real_roots_++;
return;
}
}
// either $P'$ fails the test,
// or the interval is too large
// Refine the interval.
i = 2*i; D = D+1;
// Transform the polynomial such that the first half of the interval
// is mapped to the unit interval.
POLYNOMIAL_REBIND(Coeff__) Q = scale_down(P,Coeff__(2));
// Test if the polynomial is zero at the midpoint of the interval
POLYNOMIAL_REBIND(Coeff__) S = translate_by_one(Q);
if ( S[0] == Coeff__(0) ) {
numerator[number_of_real_roots_] = i + 1;
denominator_exponent[number_of_real_roots_] = D;
is_exact[number_of_real_roots_] = true;
number_of_real_roots_++;
return;
}
// Consider the first half of the interval.
if(sign_variations(variation_transformation<Coeff__>(Q)) == 1) {
strong_zero_one_descartes<Coeff__>(Q,i,D);
return;
}
// Consider the second half of the interval.
strong_zero_one_descartes<Coeff__>(S,i+1,D);
return;
}
};
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H
@@ -0,0 +1,739 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_EVENT_LINE_BUILDER
#define CGAL_ACK_EVENT_LINE_BUILDER 1
#include <CGAL/basic.h>
#include <CGAL/Algebraic_structure_traits.h>
#include <CGAL/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_descartes.h>
#include <CGAL/Algebraic_kernel_d/exceptions.h>
#include <boost/numeric/interval.hpp>
#include <vector>
#include <algorithm>
#include <utility>
// Constant for the interval test in \c compute_mk
#define CGAL_ACK_COMPUTE_MK_PRECISION 64
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4290)
#endif
namespace CGAL {
namespace internal {
/*!
* \brief Constructs Vert_line-objects for an algebraic curve.
*
*
* The method \ref create_event_line builds such a vert-line
* for critical x-values. See the
* documentation of this routines for further information.
*
*/
template<typename AlgebraicKernelWithAnalysis_2>
class Event_line_builder {
public:
typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2;
// \brief The curve class.
typedef typename Algebraic_kernel_with_analysis_2::Curve_analysis_2 Curve_analysis_2;
// \brief Type of the coefficients of the input polynomial
typedef typename Algebraic_kernel_with_analysis_2::Coefficient Coefficient;
// \brief The type for rational x-coordinates and for interval boundaries
typedef typename Algebraic_kernel_with_analysis_2::Bound Bound;
// \brief Univariate polynomials
typedef typename Algebraic_kernel_with_analysis_2::Polynomial_1
Polynomial_1;
// \brief Bivariate polynomials
typedef typename Algebraic_kernel_with_analysis_2::Polynomial_2
Polynomial_2;
// \brief Rational polynomials
typedef typename
CGAL::Polynomial_traits_d<Polynomial_2>
::template Rebind<Bound,1>::Other::Type Poly_rat_1;
// \brief Type for x-values
typedef typename Curve_analysis_2::Algebraic_real_1 Algebraic_real_1;
//! \brief \c Vert_line specification for critical x-values
typedef typename Curve_analysis_2::Status_line_1 Status_line_1;
// \brief Type for Polynomial traits
typedef CGAL::Polynomial_traits_d<Polynomial_2> Polynomial_traits_2;
//! Default Constructor
Event_line_builder() {}
/*!
* \brief Constructs the builder for the \c curve object.
*
* Apart from the curve itself a polynomial is passed which is expected
* to be the primitive part of the curve.
* If the flag \c compute_sturm_habicht is set, the principal and
* coprincipal Sturm-Habicht coefficients of \c polynomial are computed.
* These coefficients provide information about properties of the curve
* at certain <tt>x</tt>-coordinates. Some methods of this class are only
* possible if they are computed.
*
* See \c NiX_resultant_matrix for
* more details about Sturm-Habicht sequences.
*/
Event_line_builder(Algebraic_kernel_with_analysis_2* kernel,
Curve_analysis_2 curve,
Polynomial_2 polynomial)
: _m_kernel(kernel), curve(curve), polynomial(polynomial)
{}
/*!
* \brief creates an event line at position \c alpha for the specified
* curve.
*
* Additionally, the \c id of the event line to be created has to be
* specfied, and
* the number of arcs that are entering from the left and leaving to the
* right are needed. Furthermore, the flag \c root_of_resultant tells
* whether \c alpha is a root of the resultant of the specified curve, and
* \c root_of_content indicates whether \c alpha is a root of the content,
* which is equivalent to the existence of a vertical line component.
*
* The function tries to apply the Bitstream Descartes method to isolate
* the real roots and create the Vert_line accordingly. For that purpose,
* symbolic precomputations are mostly necessary, using the Sturm-Habicht
* coefficients. It is necessary that they were computed beforehand.
* However, such symbolic computations need not be done if alpha is a
* simple root of the resultant, so if \c mult equals 1.
*
* The method will succeed, if the curve has only one multiple root
* at \c alpha over the complex numbers. It will never succeed, if there is
* more than one real root at \c alpha. In other cases, the outcome is not
* clear. In cases where the functions fails, a
* CGAL::internal::Non_generic_position_exception is thrown, otherwise, a
* fixed AcX::Vert_line object is returned.
*/
Status_line_1
create_event_line(int id,Algebraic_real_1 alpha,int arcs_left,int arcs_right,
bool root_of_resultant, bool root_of_content,int mult)
{
try {
int k;
Bitstream_descartes bit_des
= construct_bitstream_descartes(alpha,k,root_of_resultant,mult,
arcs_left,arcs_right);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "bitstream descartes constructed"
<< std::endl;
#endif
*/
int n = bit_des.number_of_real_roots();
int c = this->get_index_of_multiple_root(bit_des);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "n and c: " << n << " " << c << std::endl;
#endif
*/
int arcs_to_candidate_left=arcs_left-n+1;
int arcs_to_candidate_right=arcs_right-n+1;
//flag seems to be not used for now, but caused warnings (M.Hemmer)
//bool event_flag;
//if(false) {
if(arcs_to_candidate_left!=1 || arcs_to_candidate_right!= 1) {
//event_flag=true;
}
else {
// Need this flag to decide the event flag correctly,
// we don't care about it for now!
#if !CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY
//event_flag=false;
#else
Polynomial_2& f = polynomial;
if(c==-1 || k==0) {
//event_flag=false;
} else {
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Ev check..." << std::flush;
#endif
typename Polynomial_traits_2::Differentiate diff;
Polynomial_2 fx diff(f,0);
Polynomial_2 fy diff(f,1);
//event_flag=
event_point_checker(bit_des,f,alpha,k,fx,fy);
}
#endif
}
int root_number=bit_des.number_of_real_roots();
typename Status_line_1::Arc_container arc_container;
for(int i=0;i<root_number;i++) {
if(i != c ) {
arc_container.push_back(std::make_pair(1,1));
}
else {
arc_container.push_back
(std::make_pair(arcs_to_candidate_left,
arcs_to_candidate_right));
}
}
Status_line_1 vl(alpha, id, curve, arcs_left, arcs_right,
arc_container);
vl.set_isolator(bit_des);
vl._set_number_of_branches_approaching_infinity
(std::make_pair(0,0),std::make_pair(0,0));
#if !CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES
if(kernel()->is_zero_at_1_object()
(CGAL::leading_coefficient(polynomial),alpha)) {
int n = CGAL::degree(polynomial,1);
CGAL_assertion(! kernel()->is_zero_at_1_object()
(CGAL::get_coefficient(polynomial,n-1),
alpha));
CGAL::Sign asym_sign
= kernel()->sign_at_1_object()
(CGAL::get_coefficient(polynomial,n-1),alpha)
* kernel()->sign_at_1_object()
(CGAL::differentiate
(CGAL::get_coefficient(polynomial,n)),alpha);
CGAL_assertion(asym_sign!=CGAL::ZERO);
if(asym_sign==CGAL::SMALLER) {
vl._set_number_of_branches_approaching_infinity
(std::make_pair(1,0),std::make_pair(0,1));
} else {
vl._set_number_of_branches_approaching_infinity
(std::make_pair(0,1),std::make_pair(1,0));
}
}
#endif
if(root_of_content) {
vl._set_v_line();
}
return vl;
}
catch(CGAL::internal::Non_generic_position_exception /* err */) {
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Detected non-generic position for alpha="
<< CGAL::to_double(alpha) << std::endl;
#endif
throw CGAL::internal::Non_generic_position_exception();
}
}
protected:
Algebraic_kernel_with_analysis_2* kernel() const {
return this->_m_kernel;
}
/*!
* Typedef for the Interval type
*/
typedef boost::numeric::interval<Bound> Interval;
// \brief Refinement type from the curve class.
typedef typename Curve_analysis_2::Bitstream_descartes
Bitstream_descartes;
typedef typename Curve_analysis_2::Bitstream_coefficient_kernel
Bitstream_coefficient_kernel;
typedef typename Curve_analysis_2::Bitstream_traits
Bitstream_traits;
Algebraic_kernel_with_analysis_2* _m_kernel;
//! The curve whose Status_line_1s are built.
Curve_analysis_2 curve;
//! The content free part of the curve's polynomial
Polynomial_2 polynomial;
/*!
* \brief Exact information about <tt>f<sub>x=alpha</sub></tt>.
*
* Returns a pair <tt>(m,k)</tt> with the following meaning. Let
* \c seq be a sequence <tt>g<sub>0</sub>,...,g<sub>n</sub></tt>.
* Then, \c k is the first index for which <tt>g<sub>i</sub>(alpha)</tt>
* is not zero. The number <tt>m</tt> is the result of the function
* <tt>C (g<sub>0</sub>(alpha),...,g<sub>n</sub>(alpha))</tt>, where
* <tt>C</tt> is defined as in L.Gonzalez-Vega, I.Necula: Efficient
* topology determination of implicitly defined algebraic plane curves.
* <i>Computer Aided Geometric Design</i> <b>19</b> (2002) 719-743.
* If \c seq is the sequence of principal Sturm-Habicht coefficients,
* \c m is the number of real roots of <tt>f<sub>x=alpha</sub></tt>,
* counted without multiplicity.
*
* If the first elements in the sequence are known to be zero,
* \c first_elements_zero can be set accordingly. The zero test is then
* ommitted for that leading elements.
*/
template<typename InputIterator>
std::pair<int,int> compute_mk(Algebraic_real_1 alpha,
InputIterator seq_begin,
InputIterator seq_end,
int first_elements_zero=0) {
typedef InputIterator Input_iterator;
Algebraic_real_1& alpha_ref=alpha;
int m,k=-1; // Initialize to prevent compiler warning
bool k_fixed=false;
std::ptrdiff_t seq_size = static_cast<std::ptrdiff_t>(std::distance(seq_begin,seq_end));
typedef int VT;
typedef std::vector<VT> A_vector;
A_vector spec_stha(0);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << seq_size << std::endl;
#endif
*/
CGAL_assertion(spec_stha.size()==0);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << seq_size << " elements to consider"
<< std::endl;
#endif
*/
int start_i=first_elements_zero;
for(int i=0;i<start_i;i++) {
spec_stha.push_back(VT(0));
}
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "mk.." << std::flush;
#endif
Input_iterator seq_it = seq_begin;
std::advance(seq_it,start_i);
for(int i=start_i;i< seq_size ;i++,seq_it++ ) {
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << spec_stha.size() << " " << i << std::endl;
CGAL_ACK_DEBUG_PRINT << "Now: " << i << "th stha" << std::flush;
CGAL_ACK_DEBUG_PRINT << "\nTry interval arithmetic.." << std::endl;
#endif
*/
CGAL::Sign ia_try
=kernel()->sign_at_1_object()(*seq_it,
alpha_ref,
CGAL_ACK_COMPUTE_MK_PRECISION);
//CGAL::Sign ia_try=CGAL::ZERO;
if(ia_try!=CGAL::ZERO) {
if(! k_fixed) {
k=i;
k_fixed=true;
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "m.." << std::flush;
#endif
}
spec_stha.push_back(ia_try);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "successful" << std::endl;
#endif
*/
continue;
}
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "no success" << std::endl;
CGAL_ACK_DEBUG_PRINT << "Is root of..." << std::flush;
CGAL_ACK_DEBUG_PRINT << "s." << std::endl;
CGAL_ACK_DEBUG_PRINT << "pol=" << *seq_it << std::endl;
CGAL_ACK_DEBUG_PRINT << "alpha=" << alpha.polynomial() << std::endl;
#endif
*/
bool root_of = kernel()->is_zero_at_1_object()(*seq_it,alpha);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "done "
<< ((root_of) ? "true" : "false")
<< std::endl;
#endif
*/
if(root_of) {
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Is zero" << std::endl;
#endif
*/
spec_stha.push_back(VT(0));
}
else {
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "is nonzero.." << std::flush;
#endif
*/
if(! k_fixed) {
k=i;
k_fixed=true;
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "m.." << std::flush;
#endif
*/
}
/*
#if CGAL_ACK_DEBUG_FLAG
::CGAL::IO::set_ascii_mode(CGAL_ACK_DEBUG_PRINT);
CGAL_ACK_DEBUG_PRINT << "Stha: " << (*seq_it) << std::endl;
#endif
*/
VT beta
=kernel()->sign_at_1_object() (*seq_it,alpha_ref);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Value: " << beta << std::endl;
#endif
*/
spec_stha.push_back(beta);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << " " << spec_stha.size() << std::endl;
#endif
*/
}
}
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "--------" << std::endl;
CGAL_ACK_DEBUG_PRINT << " " << spec_stha.size() << std::endl;
for(int j=0;j<(int)spec_stha.size();j++) {
CGAL_ACK_DEBUG_PRINT << j << ": " << spec_stha[j] << std::endl;
}
CGAL_ACK_DEBUG_PRINT << "--------" << std::endl;
#endif
*/
typename A_vector::iterator it=spec_stha.begin() + k;
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "k=" << k << ", Compute m..." << std::flush;
#endif
*/
m = CGAL::number_of_real_roots(it,spec_stha.end());
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "done" << std::endl;
#endif
*/
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "k=" << k << " m=" << m << ".."<< std::flush;
#endif
return std::make_pair(m,k);
}
Poly_rat_1 mod(Poly_rat_1 a,Poly_rat_1 b) const {
Poly_rat_1 ret=CGAL::mod(a,b);
return ret;
}
/*!
* \brief Constructs a Bitstream Descartes object for
* <tt>f<sub>x=alpha</sub></tt>
*
* Tries to isolate the roots of <tt>f<sub>x=alpha</sub></tt> with the
* Bitstream m-k-Descartes method. As additional information, the value
* \c k is returned which is the greatest common divisor of \c f with its
* derivative. The flag \c root_of_resultant denotes whether alpha is
* a root of the resultant of \c f with its derivative.
* Also, the multiplicity of \c alpha as root of the resultant is given
* It his multiplcity is 1, one can avoid the computations with the
* Sturm-Habicht coefficient by looking at \c arcs_left and \c arcs_right.
*
* This method requires the Sturm-Habicht coefficients of \c f to be
* computed beforehand.
* On failure, the error CGAL::internal::Non_generic_position_exception
* is thrown.
*/
Bitstream_descartes construct_bitstream_descartes(const Algebraic_real_1&
alpha,
int& k,
bool root_of_resultant,
int mult,
int arcs_left,
int arcs_right)
{
Bitstream_traits traits(Bitstream_coefficient_kernel(kernel(),alpha));
if(root_of_resultant) {
#if !CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES
if(kernel()->is_zero_at_1_object()
(CGAL::leading_coefficient(polynomial),alpha)) {
Polynomial_2 trunc_pol =
CGAL::internal::poly_non_vanish_leading_term
(kernel(),polynomial,alpha);
CGAL_assertion(CGAL::degree(trunc_pol,1)+1 ==
CGAL::degree(polynomial,1));
CGAL::internal::Square_free_descartes_tag t;
Bitstream_descartes bit_des(t,trunc_pol,traits);
return bit_des;
}
#endif
int m;
CGAL_assertion(mult>0);
if(mult==1) {
m=(arcs_left+arcs_right) / 2;
k=1;
}
else {
std::pair<int,int> mk
= compute_mk(alpha,
curve.principal_sturm_habicht_begin(),
curve.principal_sturm_habicht_end(),
1);
m = mk.first;
k = mk.second;
}
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Bit Des..." << std::flush;
#endif
CGAL::internal::M_k_descartes_tag t;
Bitstream_descartes bit_des(t,polynomial,m,k,traits);
return bit_des;
}
else {
CGAL::internal::Square_free_descartes_tag t;
Bitstream_descartes bit_des(t,polynomial,traits);
return bit_des;
}
}
/*!
* \brief Checks whether a point is a singularity or not.
*
* This routine is applied in situations where a potential event point
* has one incident arc to the left and to the right. To distinguish
* singularities from other points, this method checks whether the two
* linearly independent partial derivatives \c der_1 and \c der_2 vansh
* at the point \c (alpha,beta). Here, \c beta is implicitly defined as
* \f[\beta=\frac{-costha[k-1]}{k\cdot stha[k]}\f]
* and it is verified first that \c beta is indeed the y-value that
* corresponds to the multiple root in the <tt>bit_des</tt>-instance.
* If it is not, a Non_generic_position_exception is thrown.
*
* If no exception is thrown, the function returns true if and only if
* there is a singularity at <tt>(alpha,beta)</tt>.
*/
bool event_point_checker(Bitstream_descartes& bit_des,
const Polynomial_2& polynomial,
const Algebraic_real_1& alpha,
int k,
const Polynomial_2& der_1,
const Polynomial_2& der_2)
{
//Guess the right expression for y
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << costha.size() << " "
<< stha.size() << std::endl;
CGAL_ACK_DEBUG_PRINT << k << std::endl;
CGAL_ACK_DEBUG_PRINT << "Costha: " << costha[k-1]
<< " Stha: " << stha[k] << std::endl;
#endif
*/
Polynomial_1 p = -curve.coprincipal_sturm_habicht_of_primitive(k);
Polynomial_1 q
= Coefficient(k)*curve.principal_sturm_habicht_of_primitive(k);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << k << " " << CGAL::to_double(alpha)
<< std::endl);
CGAL_ACK_DEBUG_PRINT << p << " " << q << std::endl
<< polynomial << std::endl;
Bound a_d = alpha.low();
CGAL_ACK_DEBUG_PRINT << CGAL::to_double(p.evaluate(a_d)/
q.evaluate(a_d))
<< std::endl;
#endif
*/
// Check whether it lies in the candidates interval
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "iv-test..." << std::flush;
#endif
typedef typename CGAL::Get_arithmetic_kernel<Algebraic_real_1>
::Arithmetic_kernel::Bigfloat_interval BFI;
CGAL::internal::Bitstream_coefficient_kernel_at_alpha
<Algebraic_kernel_with_analysis_2>
alpha_kernel(kernel(),alpha);
int c = this->get_index_of_multiple_root(bit_des);
long old_prec = CGAL::get_precision(BFI());
//std::cout << "p=" << p << std::endl;
//std::cout << "q=" << q << std::endl;
long prec=16;
while(true) {
CGAL::set_precision(BFI(),prec);
//std::cout << "Increased to " << prec << std::endl;
BFI isol_iv
= CGAL::hull(CGAL::convert_to_bfi(bit_des.left_bound(c)),
CGAL::convert_to_bfi(bit_des.right_bound(c)));
BFI q_iv = alpha_kernel.convert_to_bfi_object()(q);
if(! CGAL::in_zero(q_iv)) {
BFI p_iv = alpha_kernel.convert_to_bfi_object()(p);
BFI approx_iv = p_iv/q_iv;
//std::cout << "p_iv=[" << CGAL::lower(p_iv) << "," << CGAL::upper(p_iv) << "]" << std::endl;
//std::cout << "q_iv=[" << CGAL::lower(q_iv) << "," << CGAL::upper(q_iv) << "]" << std::endl;
//std::cout << "isol_iv=[" << CGAL::lower(isol_iv) << "," << CGAL::upper(isol_iv) << "]" << std::endl;
//std::cout << "approx_iv=[" << CGAL::lower(approx_iv) << "," << CGAL::upper(approx_iv) << "]" << std::endl;
if(CGAL::subset(approx_iv,isol_iv)) {
break;
}
if(! CGAL::overlap(approx_iv,isol_iv)) {
throw CGAL::internal::Non_generic_position_exception();
}
}
prec*=2;
}
CGAL::set_precision(BFI(),old_prec);
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "on f..." << std::flush;
#endif
if(! CGAL::internal::zero_test_bivariate
<Algebraic_kernel_with_analysis_2>
(kernel(),alpha,polynomial,p,q)) {
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Detected non-generic position for alpha="
<< CGAL::to_double(alpha) << std::endl;
#endif
throw CGAL::internal::Non_generic_position_exception();
}
// Check whether the two partial derivatives vanish
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "on fx..." << std::flush;
#endif
bool is_singularity
= CGAL::internal::zero_test_bivariate
<Algebraic_kernel_with_analysis_2>
(kernel(),alpha,der_1,p,q);
if(is_singularity) {
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "on fy..." << std::flush;
#endif
return CGAL::internal::zero_test_bivariate
<Algebraic_kernel_with_analysis_2>
(kernel(),alpha,der_2,p,q);
} else {
return false;
}
}
protected:
int get_index_of_multiple_root(const Bitstream_descartes& bit_des) const {
int n = bit_des.number_of_real_roots();
for(int i=0;i<n;i++) {
if(! bit_des.is_certainly_simple_root(i)) {
return i;
}
}
return -1;
}
}; //class Event_line_builder
} // namespace internal
} //namespace CGAL
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif //CGAL_ACK_VERT_EVENT_BUILDER
@@ -0,0 +1,168 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: Some comments are original EXACUS comments and aren't adapted. So
// they may be wrong now.
// TODO: should exponent type be long or Integer ?
#ifndef CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H
#define CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H
#include <CGAL/basic.h>
#if CGAL_USE_LEDA
#include <CGAL/leda_bigfloat.h>
#endif
#if CGAL_USE_CORE
#include <CGAL/CORE_BigFloat.h>
#endif
#if CGAL_USE_MPFR
#include <CGAL/Gmpfr.h>
#endif
#include <CGAL/ipower.h>
namespace CGAL {
namespace internal {
// Don't define default, results in more convinient compiler messages
template< class Type > class Float_traits;
// {
// public:
// typedef Null_functor Get_mantissa;
// typedef Null_functor Get_exponent;
// typedef Null_functor Mul_by_pow_of_2;
// };
#ifdef CGAL_USE_LEDA
// Specialization for leda_bigfloat
template<>
class Float_traits< leda_bigfloat > {
public:
struct Get_mantissa
: public CGAL::cpp98::unary_function< leda_bigfloat, leda_integer > {
leda_integer operator()( const leda_bigfloat& x ) const {
//std::cout << x.get_significant() << std::endl;
return x.get_significant();
}
};
struct Get_exponent
: public CGAL::cpp98::unary_function< leda_bigfloat, long > {
long operator()( const leda_bigfloat& x ) const {
return x.get_exponent().to_long();
}
};
struct Mul_by_pow_of_2
: public CGAL::cpp98::binary_function< leda_bigfloat, long, leda_bigfloat> {
leda_bigfloat operator()( const leda_bigfloat& a, long e ) const {
return leda_bigfloat(a.get_significant(), a.get_exponent()+e);
}
};
};
#endif
#ifdef CGAL_USE_CORE
// Specialization for CORE::BigFloat
template<>
class Float_traits< CORE::BigFloat > {
public:
struct Get_mantissa
: public CGAL::cpp98::unary_function< CORE::BigFloat, CORE::BigInt > {
CORE::BigInt operator()( const CORE::BigFloat& x ) const {
return x.m();
}
};
struct Get_exponent
: public CGAL::cpp98::unary_function< CORE::BigFloat, long > {
long operator()( const CORE::BigFloat& x ) const {
return CORE::CHUNK_BIT*x.exp(); // The basis is 2^CORE::CHUNK_BIT
}
};
struct Mul_by_pow_of_2
: public CGAL::cpp98::binary_function
< CORE::BigFloat, long , CORE::BigFloat> {
CORE::BigFloat operator()( const CORE::BigFloat& a, long e ) const {
return a*CORE::BigFloat::exp2(e);
}
};
};
#endif
#if CGAL_USE_MPFR
template<> class Float_traits< Gmpfr > {
struct Get_mantissa_exponent
: public CGAL::cpp98::unary_function< Gmpfr, std::pair<Gmpz,long> > {
std::pair<Gmpz,long> operator()( const Gmpfr& x ) const {
return x.to_integer_exp();
}
};
public:
struct Get_mantissa
: public CGAL::cpp98::unary_function< Gmpfr, Gmpz > {
Gmpz operator()( const Gmpfr& x ) const {
return Get_mantissa_exponent()(x).first;
}
};
struct Get_exponent
: public CGAL::cpp98::unary_function< Gmpfr, long > {
long operator()( const Gmpfr& x ) const {
return Get_mantissa_exponent()(x).second;
}
};
struct Mul_by_pow_of_2
: public CGAL::cpp98::binary_function< Gmpfr, Gmpz, Gmpfr> {
Gmpfr operator()( const Gmpfr& a, long e ) const {
Gmpfr result(0,a.get_precision()); // just to get the prec of a
if (e >= 0 ){
mpfr_mul_2si (result.fr(), a.fr(), e, mpfr_get_default_rounding_mode());
//std::cout << "INPUT : "<< a <<"+" << e << std::endl;
//std::cout << "result: "<< result << std::endl;
//std::cout << "TRUTH : "<< a * CGAL::ipower(Gmpfr(2),e) << std::endl;
CGAL_postcondition(a * CGAL::ipower(Gmpfr(2),e) == result);
}
else{
mpfr_div_2si (result.fr(), a.fr(), -e, mpfr_get_default_rounding_mode());
CGAL_postcondition(a / CGAL::ipower(Gmpfr(2),-e) == result);
}
return result;
}
};
};
#endif
} //namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H
@@ -0,0 +1,91 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_INTERVAL_EVALUATE_1
#define CGAL_INTERVAL_EVALUATE_1 1
#include <iterator>
#include <CGAL/basic.h>
#include <boost/numeric/interval.hpp>
#include <CGAL/algorithm.h>
#include <CGAL/array.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/Polynomial_traits_d.h>
namespace CGAL {
namespace internal {
template<typename Polynomial_1, typename Bound>
struct Interval_evaluate_1 : public CGAL::cpp98::binary_function
<Polynomial_1,std::pair<Bound,Bound>,
std::pair<typename CGAL::Coercion_traits<typename
CGAL::Polynomial_traits_d<Polynomial_1>::Coefficient_type,Bound>::Type,
typename CGAL::Coercion_traits<typename
CGAL::Polynomial_traits_d<Polynomial_1>::Coefficient_type,Bound>::Type> > {
typedef CGAL::Polynomial_traits_d< Polynomial_1 > PT_1;
typedef typename PT_1::Innermost_coefficient_type Innermost_coefficient_type;
typedef CGAL::Coercion_traits< Innermost_coefficient_type, Bound > CT;
typedef typename CT::Type Coercion_type;
typedef std::pair< Coercion_type, Coercion_type > result_type;
result_type operator()(const Polynomial_1& p,
const std::pair< Bound, Bound >& b) const {
return this->operator()(p, CGAL::make_array(b.first, b.second));
}
result_type operator()(const Polynomial_1& p,
const std::array< Bound, 2 >& b) const {
typename CT::Cast cast;
typedef ::boost::numeric::interval< Coercion_type > Coercion_interval;
typedef typename PT_1::Coefficient_const_iterator
Coefficient_const_iterator;
Coercion_interval ix(cast(b[0]), cast(b[1]));
typedef typename PT_1::Coefficient_const_iterator_range
Coefficient_const_iterator_range;
Coefficient_const_iterator_range range =
typename PT_1::Construct_coefficient_const_iterator_range()(p);
Coefficient_const_iterator it = std::prev(range.second);
Coercion_interval res(cast(*it));
Coefficient_const_iterator p_begin = range.first;
while(it != p_begin) {
it--;
res = res * ix + Coercion_interval(cast(*it));
}
return std::make_pair(res.lower(),res.upper());
}
};
} // namespace internal
} // namespace CGAL
#endif // CGAL_INTERVAL_EVALUATE_1
@@ -0,0 +1,103 @@
// Copyright (c) 2006-2010 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_INTERVAL_EVALUATE_2
#define CGAL_INTERVAL_EVALUATE_2 1
#include <iterator>
#include <CGAL/basic.h>
#include <boost/numeric/interval.hpp>
#include <CGAL/algorithm.h>
#include <CGAL/array.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Algebraic_kernel_d/Interval_evaluate_1.h>
namespace CGAL {
namespace internal {
template<typename Polynomial_2, typename Bound>
struct Interval_evaluate_2 : public CGAL::cpp98::binary_function
<Polynomial_2,std::array<Bound,4>,
std::pair<typename CGAL::Coercion_traits<typename CGAL::Polynomial_traits_d<Polynomial_2>::Innermost_coefficient_type,Bound>::Type,
typename CGAL::Coercion_traits<typename CGAL::Polynomial_traits_d<Polynomial_2>::Innermost_coefficient_type,Bound>::Type> > {
public:
typedef CGAL::Polynomial_traits_d< Polynomial_2 > PT_2;
typedef typename PT_2::Innermost_coefficient_type Innermost_coefficient_type;
typedef CGAL::Coercion_traits< Innermost_coefficient_type, Bound > CT;
typedef typename CT::Type Coercion_type;
typedef std::pair< Coercion_type, Coercion_type > result_type;
result_type operator()(const Polynomial_2& p,
const std::array< Bound, 4 >& b) const {
typename CT::Cast cast;
typedef ::boost::numeric::interval< Coercion_type > Coercion_interval;
typedef typename PT_2::Coefficient_const_iterator
Coefficient_const_iterator;
typedef typename PT_2::Coefficient_const_iterator_range
Coefficient_const_iterator_range;
typedef typename PT_2::Coefficient_type Polynomial_1;
CGAL::internal::Interval_evaluate_1< Polynomial_1,Bound >
interval_evaluate_1;
typedef typename CGAL::internal::Interval_evaluate_1< Polynomial_1,Bound >::
result_type Interval_result_type;
std::pair< Bound, Bound > x_pair = std::make_pair(b[0],b[1]);
Coercion_interval iy(cast(b[2]),cast(b[3]));
// CGAL::Polynomial does not provide Coercion_traits for number
// types => therefore evaluate manually
Coefficient_const_iterator_range range =
typename PT_2::Construct_coefficient_const_iterator_range()(p);
Coefficient_const_iterator it = std::prev(range.second);
Interval_result_type initial_pair = interval_evaluate_1(*it,x_pair);
Coercion_interval res(initial_pair.first,initial_pair.second);
Coefficient_const_iterator p_begin = range.first;
while((it) != p_begin) {
it--;
Interval_result_type curr_iv = interval_evaluate_1(*it,x_pair);
res = res * iy + Coercion_interval(curr_iv.first,curr_iv.second);
}
return std::make_pair(res.lower(),res.upper());
}
};
} // namespace internal
} // namespace CGAL
#endif // CGAL_INTERVAL_EVALUATE_2
@@ -0,0 +1,424 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Pavel Emeliyanenko <asm@mpi-sb.mpg.de>
//
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H
#define CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H
#include <CGAL/basic.h>
#include <CGAL/function_objects.h>
#include <limits>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
using boost::multi_index::multi_index_container;
using boost::multi_index::get;
using boost::multi_index::project;
namespace CGAL {
namespace internal {
//! \brief this class defines hashed map container with LRU capabilities,
//!
//! stores pair of \c KeyType_ and \c ValueType_. Before adding to
//! the map the input is normialized using \c Canonicalizer_
//! \c Pred_ is binary predicate acting as an equivalence relation on
//! values of \c KeyType_, \c Creator_ is a mapping from \c KeyType_ to
//! \c ValueType_, \c Hash_ is function object which returns hash values
//! for the keys
template <
class KeyType_, class ValueType_,
class Hash_ = boost::hash<KeyType_>,
class Pred_ = std::equal_to<KeyType_>,
class Canonicalizer_ = CGAL::Identity<KeyType_>,
class Creator_ = CGAL::Creator_1<KeyType_, ValueType_> >
class LRU_hashed_map
{
public:
//!\name public typedefs
//!@{
//! this instance's first argument
typedef KeyType_ Key_type;
//! this instance's second argument
typedef ValueType_ Value_type;
//! hash function
typedef Hash_ Hash;
//! equality predicate
typedef Pred_ Pred;
//! input data canonicalizer
typedef Canonicalizer_ Canonicalizer;
//! mapping \c KeyType_ -> \c ValueType_
typedef Creator_ Creator;
//! hashed map data type
typedef std::pair<Key_type, Value_type> Data_type;
// We don't use BOOST_MULTI_INDEX_MEMBER but ::boost::multi_index::member_offset
// because VC10 had a problem with it. The reason is that the
// implementation std::pair uses a base class, and std::pair::first is
// not a member of the pair class but of its base class.
// In the following, we assume that the offset of 'first' in
// std::pair<T1, T2> is always 0.
typedef boost::multi_index::multi_index_container<
Data_type,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_unique<
::boost::multi_index::member_offset<Data_type,Key_type,0>,
Hash, Pred > > > Hashed_map;
//!@}
protected:
//!\name private members
//!@{
//! hashed map instance
mutable Hashed_map _m_hashed_map;
//! maximal size allowed
unsigned _m_max_size;
//!@}
public:
//!\name iterator types
//!@{
//! hashed index iterator
typedef typename
boost::multi_index::nth_index_iterator<Hashed_map,1>::type
Hashed_iterator;
//! sequenced index iterator
typedef typename
boost::multi_index::nth_index_iterator<Hashed_map,0>::type
Sequenced_iterator;
//! sequenced index const iterator
typedef typename
boost::multi_index::nth_index_const_iterator<Hashed_map,0>::type
Sequenced_const_iterator;
//! result type of \c find operation: a pair of iterator pointing to
//! \c Data_type and a boolean indicating whether an element with
//! specified key was found
typedef std::pair<Hashed_iterator, bool> Find_result;
//!@}
public:
//!\name constructors and access functions
//!@{
//! \brief default constructor
LRU_hashed_map(unsigned max_size =
(std::numeric_limits< unsigned >::max)()) :
_m_hashed_map(),_m_max_size(max_size)
{ }
virtual ~LRU_hashed_map()
{ }
/*! \brief implements cache-like behaviour of the map
*
* If the object is not in the map, it is constructed using \c Creator
* and added to the map
*/
Value_type operator()(const Key_type& key_) const
{
Canonicalizer canonicalize;
Key_type key = canonicalize(key_);
Find_result p = find(key);
if(!p.second) {
Creator create;
Value_type val = create(key);
insert(Data_type(key, val));
return val;
}
return (p.first)->second;
}
//! \brief looks for an entry with a specified key in the map
//!
//! returns a pair of iterator pointing to \c Data_type and a boolean
//! indicating whether an element with specified key was found
Find_result find(const Key_type& key) const
{
typename boost::multi_index::nth_index<Hashed_map,1>::type&
idx = _m_hashed_map.template get<1>();
Hashed_iterator it = idx.find(key);
if(it == idx.end()) {
return Find_result(it, false);
}
// otherwise put the accessed element on the top
// Comment out because of compiler problems with 3.4
/*
_m_hashed_map.relocate(_m_hashed_map.begin(),
_m_hashed_map.project<0>(it));
*/
return Find_result(it, true);
}
//! \brief inserts an entry to the map
//!
//! on successful insertion, \c p.first points to the element
//! inserted; otherwise \c p.first points to an element that caused
//! the insertion to be banned. If the map's size exceeds \c max_size
//! the least recently used entry is dropped
std::pair<Sequenced_iterator, bool> insert(const Data_type& data) const
{
if(_m_hashed_map.size() > _m_max_size)
_m_hashed_map.pop_back();
return _m_hashed_map.push_front(data);
}
//! clears the map contents
void clear() { _m_hashed_map.clear(); }
//! returns whether the map is empty.
bool is_empty() const { return _m_hashed_map.empty(); }
//! returns the number of items in the map
unsigned size() { return _m_hashed_map.size(); }
//! returns the largest possible size of the map (-1 if not set)
unsigned max_size() const { return _m_max_size; }
//! \brief returns an iterator pointing to the beginning of the map
//!
//! all iterators run over sequenced indices
Sequenced_iterator begin() { return _m_hashed_map.begin(); }
//! returns an iterator pointing to the end of the map
Sequenced_iterator end() { return _m_hashed_map.end(); }
//! returns a const_iterator pointing to the beginning of the map
Sequenced_const_iterator begin() const
{ return _m_hashed_map.begin(); }
//! Returns a const_iterator pointing to the end of the map
Sequenced_const_iterator end() const
{ return _m_hashed_map.end(); }
//!@}
}; // class LRU_hashed_map_with_kernel
//! \brief this class defines hashed map container with LRU capabilities,
//!
//! stores pair of \c KeyType_ and \c ValueType_. Before adding to
//! the map the input is normialized using \c Canonicalizer_
//! \c Pred_ is binary predicate acting as an equivalence relation on
//! values of \c KeyType_, \c Creator_ is a mapping from \c KeyType_ to
//! \c ValueType_, \c Hash_ is function object which returns hash values
//! for the keys
template <
class AlgebraicKernelWithAnalysis_2,
class KeyType_, class ValueType_,
class Hash_ = boost::hash<KeyType_>,
class Pred_ = std::equal_to<KeyType_>,
class Canonicalizer_ = CGAL::Identity<KeyType_>,
class Creator_ = CGAL::Creator_1<KeyType_, ValueType_> >
class LRU_hashed_map_with_kernel
: public LRU_hashed_map<KeyType_,ValueType_,Hash_,
Pred_,Canonicalizer_,Creator_>
{
public:
typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2;
typedef LRU_hashed_map<KeyType_,ValueType_,
Hash_,Pred_,Canonicalizer_,Creator_> Base;
//! this instance's first argument
typedef typename Base::Key_type Key_type;
//! this instance's second argument
typedef typename Base::Value_type Value_type;
//! hash function
typedef typename Base::Hash Hash;
//! equality predicate
typedef typename Base::Pred Pred;
//! input data canonicalizer
typedef typename Base::Canonicalizer Canonicalizer;
//! mapping \c KeyType_ -> \c ValueType_
typedef typename Base::Creator Creator;
//! hashed map data type
typedef typename Base::Data_type Data_type;
typedef typename Base::Hashed_map Hashed_map;
protected:
Algebraic_kernel_with_analysis_2* _m_kernel;
public:
//!\name iterator types
//!@{
//! hashed index iterator
typedef typename Base::Hashed_iterator Hashed_iterator;
//! sequenced index iterator
typedef typename Base::Sequenced_iterator Sequenced_iterator;
//! sequenced index const iterator
typedef typename Base::Sequenced_const_iterator Sequenced_const_iterator;
//! result type of \c find operation: a pair of iterator pointing to
//! \c Data_type and a boolean indicating whether an element with
//! specified key was found
typedef typename Base::Find_result Find_result;
//!@}
//!\name constructors and access functions
//!@{
//! \brief default constructor
LRU_hashed_map_with_kernel(Algebraic_kernel_with_analysis_2* kernel,
unsigned max_size = (std::numeric_limits<unsigned>::max)()) :
Base(max_size),
_m_kernel(kernel)
{ }
~LRU_hashed_map_with_kernel()
{ }
/*! \brief implements cache-like behaviour of the map
*
* If the object is not in the map, it is constructed using \c Creator
* and added to the map
*/
Value_type operator()(const Key_type& key_) const
{
Canonicalizer canonicalize;
Key_type key = canonicalize(key_);
Find_result p = this->find(key);
if(!p.second) {
Creator create(_m_kernel);
Value_type val = create(key);
this->insert(Data_type(key, val));
return val;
}
return (p.first)->second;
}
//!@}
}; // class LRU_hashed_map_with_kernel
/*! \brief
* returns representation id as a hash value
*/
struct Id_hasher
{
template <class T>
size_t operator()(const T& x) const {
return static_cast<size_t>(x.id());
}
};
struct To_double_hasher
{
template <class T>
size_t operator()(const T& x) const {
return static_cast<size_t>(CGAL::to_double(x));
}
};
struct Id_equal_to
{
template <class T>
bool operator()(const T& x1, const T& x2) const {
return (x1.id() == x2.id());
}
};
struct Poly_hasher {
template <class Poly_2>
std::size_t operator()(const Poly_2& p) const {
if(p.is_zero())
return 0xDeadBeef;
typedef typename Poly_2::NT Poly_1;
typedef typename Poly_1::NT NT;
const Poly_1& v = p[0];
typename Poly_1::const_iterator cit;
NT res(0);
int i=0;
// take at most 3 trailing coeffs
for (cit = v.begin(), i = 0; i < 3 && cit != v.end(); cit++, i++) {
res += *cit;
}
if(res == NT(0))
return 0xDeadBeef;
// randomization of the result
return static_cast<std::size_t>(CGAL::to_double(res));
}
};
struct Pair_id_hasher {
typedef size_t result_type;
template <class T1, class T2>
size_t operator()(const std::pair<T1, T2>& p) const {
std::size_t seed = p.first.id() + 0x9e3779b9;
seed ^= p.second.id() + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
};
struct Pair_hasher {
typedef size_t result_type;
template <class T1, class T2>
size_t operator()(const std::pair<T1, T2>& p) const
{
std::size_t seed = 0;
boost::hash_combine(seed, p.first);
boost::hash_combine(seed, p.second);
return seed;
}
};
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H
@@ -0,0 +1,508 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: Some comments are original EXACUS comments and aren't adapted. So
// they may be wrong now.
#ifndef CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H
#define CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/Float_traits.h>
#ifdef CGAL_USE_LEDA
#include <CGAL/leda_integer.h>
#include <CGAL/leda_bigfloat.h>
#include <CGAL/leda_bigfloat_interval.h>
#include <LEDA/numbers/digit.h>
#endif
#ifdef CGAL_USE_CORE
#include <CGAL/CORE_BigFloat.h>
#endif
#ifdef CGAL_USE_GMP
#include <CGAL/Gmpz.h>
#include <CGAL/Gmpq.h>
#endif
#ifdef CGAL_USE_MPFR
#include <CGAL/Gmpfr.h>
#endif
#ifdef CGAL_USE_MPFI
#include <CGAL/Gmpfi.h>
#endif
namespace CGAL {
namespace internal {
// TODO: Implement array in source code file
// extern const signed char floor_log2_4bit[16]; // see src/floor_log2_4bit.C
// Don't define default, results in more convinient compiler messages
template< class Type > class Real_embeddable_extension;
// {
// public:
// typedef Null_functor Ceil_log2_abs;
// typedef Null_functor Floor_log2_abs;
// typedef Null_functor Floor;
// typedef Null_functor Ceil;
// };
// Functor adapting functions
template< class NT >
long floor_log2_abs( const NT& x ) {
return typename Real_embeddable_extension< NT >::Floor_log2_abs()( x );
}
template< class NT >
long ceil_log2_abs( const NT& x ) {
return typename Real_embeddable_extension< NT >::Ceil_log2_abs()( x );
}
template< class NT >
typename Real_embeddable_extension<NT>::Floor::result_type
floor (const NT& x) {
return typename Real_embeddable_extension<NT>::Floor() (x);
}
template< class NT >
typename Real_embeddable_extension<NT>::Ceil::result_type
ceil (const NT& x) {
return typename Real_embeddable_extension<NT>::Ceil() (x);
}
// Specialization for long
template<>
class Real_embeddable_extension< long > {
public:
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< long, long > {
long operator()( long x ) {
if (x < 0) x = -x;
CGAL_precondition(x > 0);
if (x == 1) return 0;
return Floor_log2_abs()(x-1) + 1;
}
};
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< long, long > {
private:
signed char floor_log2_4bit[16];
public:
Floor_log2_abs() {
floor_log2_4bit[ 0] = -42;
floor_log2_4bit[ 1] = 0;
floor_log2_4bit[ 2] = 1;
floor_log2_4bit[ 3] = 1;
floor_log2_4bit[ 4] = 2;
floor_log2_4bit[ 5] = 2;
floor_log2_4bit[ 6] = 2;
floor_log2_4bit[ 7] = 2;
floor_log2_4bit[ 8] = 3;
floor_log2_4bit[ 9] = 3;
floor_log2_4bit[10] = 3;
floor_log2_4bit[11] = 3;
floor_log2_4bit[12] = 3;
floor_log2_4bit[13] = 3;
floor_log2_4bit[14] = 3;
floor_log2_4bit[15] = 3;
}
long operator()( long x ) {
if (x < 0) x = -x;
CGAL_precondition(x > 0);
result_type l = 0;
while (x > 0xFFFF) { l += 16; x >>= 16; }
if (x > 0xFF) { l += 8; x >>= 8; }
if (x > 0xF) { l += 4; x >>= 4; }
CGAL_assertion(x > 0 && x < 16);
return l + int(floor_log2_4bit[x]);
}
};
struct Floor
: public CGAL::cpp98::unary_function< long, long > {
long operator() (long x) { return x;}
};
struct Ceil
: public CGAL::cpp98::unary_function< long, long > {
long operator() (long x) { return x;}
};
};
#ifdef CGAL_USE_LEDA
// Specialization for leda_integer
template<>
class Real_embeddable_extension< leda_integer > {
public:
typedef leda_integer Type;
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< leda_integer, long > {
long operator()( const leda_integer& x ) const {
CGAL_precondition(x != leda_integer(0));
::leda::digit_sz ldgzeros = ::leda::digLeadingZeros(x.highword());
result_type l =
x.used_words() * ::leda::DIGIT_LENGTH - 1 - ldgzeros;
// look if additional 1-bits force to round up
::leda::digit h = 1;
h <<= ::leda::DIGIT_LENGTH - 1 - ldgzeros;
int i = x.used_words() - 1;
CGAL_assertion(x.contents(i) >= h);
if (x.contents(i) > h) return l+1;
while (--i >= 0) {
if (x.contents(i) != 0) return l+1;
}
return l;
}
};
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< leda_integer, long > {
long operator()( const leda_integer& x ) const {
CGAL_precondition(x != leda_integer(0));
::leda::digit_sz ldgzeros
= ::leda::digLeadingZeros(x.highword());
result_type l =
x.used_words() * ::leda::DIGIT_LENGTH - 1 - ldgzeros;
return l;
}
};
struct Floor
: public CGAL::cpp98::unary_function< leda_integer, leda_integer > {
leda_integer operator() (const leda_integer& x) const { return x;}
};
struct Ceil
: public CGAL::cpp98::unary_function< leda_integer, leda_integer > {
leda_integer operator() (const leda_integer& x) const { return x;}
};
};
template<>
class Real_embeddable_extension< leda_bigfloat > {
public:
typedef leda_bigfloat Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< leda_bigfloat, long > {
long operator()( const leda_bigfloat& x ) const {
CGAL_precondition(CGAL::sign(x) != CGAL::ZERO);
::leda::integer abs_sign = abs(x.get_significant());
return (x.get_exponent() + ::leda::log(abs_sign)).to_long();
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< leda_bigfloat, long > {
long operator()( const leda_bigfloat& x ) const {
CGAL_precondition(CGAL::sign(x) != CGAL::ZERO);
return ::leda::ilog2(x).to_long();
}
};
struct Floor
: public CGAL::cpp98::unary_function< leda_bigfloat, leda_integer > {
leda_integer operator() ( const leda_bigfloat& x ) const {
return leda::to_integer( x, leda::TO_N_INF );
}
};
struct Ceil
: public CGAL::cpp98::unary_function< leda_bigfloat, leda_integer > {
leda_integer operator() ( const leda_bigfloat& x ) const {
return leda::to_integer( x, leda::TO_P_INF );
}
};
};
template<>
class Real_embeddable_extension< leda_bigfloat_interval > {
public:
typedef leda_bigfloat_interval Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< leda_bigfloat_interval, long > {
result_type operator() (const argument_type& x) const {
CGAL_precondition(! ::boost::numeric::in_zero(x));
return internal::floor_log2_abs(::boost::numeric::abs(x).lower());
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< leda_bigfloat_interval, long > {
long operator()( const leda_bigfloat_interval& x ) const {
CGAL_precondition(!(::boost::numeric::in_zero(x) &&
::boost::numeric::singleton(x)));
return internal::ceil_log2_abs(::boost::numeric::abs(x).upper());
}
};
struct Floor
: public CGAL::cpp98::unary_function< leda_bigfloat_interval, leda_integer > {
leda_integer operator() ( const leda_bigfloat_interval& x )
const {
return internal::floor( x.lower() );
}
};
struct Ceil
: public CGAL::cpp98::unary_function< leda_bigfloat_interval, leda_integer > {
leda_integer operator() ( const leda_bigfloat_interval& x )
const {
return internal::ceil( x.upper() );
}
};
};
#endif
#ifdef CGAL_USE_CORE
// Specialization for CORE::BigInt
template<>
class Real_embeddable_extension< CORE::BigInt > {
public:
typedef CORE::BigInt Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< CORE::BigInt, long > {
long operator()( const CORE::BigInt& x ) const {
return CORE::floorLg(x);
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< CORE::BigInt, long > {
long operator()( const CORE::BigInt& x ) const {
return CORE::ceilLg(x);
}
};
struct Floor
: public CGAL::cpp98::unary_function< CORE::BigInt, CORE::BigInt > {
CORE::BigInt operator() (const CORE::BigInt& x) const {
return x;
}
};
struct Ceil
: public CGAL::cpp98::unary_function< CORE::BigInt, CORE::BigInt > {
CORE::BigInt operator() (const CORE::BigInt& x) const {
return x;
}
};
};
// Specialization for CORE::BigFloat
template<>
class Real_embeddable_extension< CORE::BigFloat > {
public:
typedef CORE::BigFloat Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< CORE::BigFloat, long > {
long operator()( CORE::BigFloat x ) const {
CGAL_precondition(!CGAL::zero_in(x));
x = CGAL::abs(x);
return CORE::floorLg(x.m()-x.err())+x.exp()*CORE::CHUNK_BIT;
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< CORE::BigFloat, long > {
long operator()( CORE::BigFloat x ) const {
// (already commented out in EXACUS)...
// NiX_precond(!(NiX::in_zero(x) && NiX::singleton(x)));
x = CGAL::abs(x);
return CORE::ceilLg(x.m()+x.err())+x.exp()*CORE::CHUNK_BIT;
}
};
struct Floor
: public CGAL::cpp98::unary_function< CORE::BigFloat, CORE::BigInt > {
CORE::BigInt operator() ( const CORE::BigFloat& x ) const {
CORE::BigInt xi = x.BigIntValue();
if(x.sign() < 0 && x.cmp(xi)!=0) {
xi--;
}
return xi;
}
};
struct Ceil
: public CGAL::cpp98::unary_function< CORE::BigFloat, CORE::BigInt > {
CORE::BigInt operator() ( const CORE::BigFloat& x ) const {
CORE::BigInt xi = x.BigIntValue();
if(x.sign() >0 && x.cmp(xi)!=0) {
xi++;
}
return xi;
}
};
};
#endif // CORE
#if CGAL_USE_GMP
// Specialization for Gmpz
template<>
class Real_embeddable_extension< Gmpz > {
public:
typedef Gmpz Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< Gmpz, long > {
long operator()( const Gmpz& x ) const {
CGAL_precondition(!CGAL::is_zero(x));
return static_cast<long>(mpz_sizeinbase(x.mpz(),2)-1);
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< Gmpz, long > {
long operator()( const Gmpz& x ) const {
long pos = mpz_scan1(x.mpz(),0);
long size = static_cast<long>(mpz_sizeinbase(x.mpz(),2));
if (pos == size-1)
return size-1;
else
return size;
}
};
struct Floor
: public CGAL::cpp98::unary_function< Gmpz, Gmpz > {
Gmpz operator() (const Gmpz& x) const {
return x;
}
};
struct Ceil
: public CGAL::cpp98::unary_function< Gmpz, Gmpz > {
Gmpz operator() (const Gmpz& x) const {
return x;
}
};
};
#endif
#ifdef CGAL_USE_MPFR
template<>
class Real_embeddable_extension< Gmpfr > {
public:
typedef Gmpfr Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< Gmpfr, long > {
long operator()( const Gmpfr& x ) const {
Float_traits<Gmpfr>::Get_mantissa get_mantissa;
Float_traits<Gmpfr>::Get_exponent get_exponent;
CGAL_precondition(!CGAL::is_zero(x));
Real_embeddable_extension<Gmpz>::Floor_log2_abs floor_log2_abs;
return floor_log2_abs(get_mantissa(x))+get_exponent(x);
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< Gmpfr, long > {
long operator()( const Gmpfr& x ) const {
Float_traits<Gmpfr>::Get_mantissa get_mantissa;
Float_traits<Gmpfr>::Get_exponent get_exponent;
CGAL_precondition(!CGAL::is_zero(x));
Real_embeddable_extension<Gmpz>::Ceil_log2_abs ceil_log2_abs;
return ceil_log2_abs(get_mantissa(x))+get_exponent(x);
}
};
struct Floor
: public CGAL::cpp98::unary_function< Gmpfr, Gmpz > {
Gmpz operator() ( const Gmpfr& x ) const {
Gmpz result;
mpfr_get_z (result.mpz(),x.fr(),GMP_RNDD);
return result;
}
};
struct Ceil
: public CGAL::cpp98::unary_function< Gmpfr, Gmpz > {
Gmpz operator() ( const Gmpfr& x ) const {
Gmpz result;
mpfr_get_z (result.mpz(),x.fr(),GMP_RNDU);
return result;
}
};
};
#endif
#ifdef CGAL_USE_MPFI
template<>
class Real_embeddable_extension< Gmpfi > {
public:
typedef Gmpfi Type;
struct Floor_log2_abs
: public CGAL::cpp98::unary_function< Gmpfi, long > {
result_type operator() (const argument_type& x) const {
CGAL_precondition(!x.is_zero());
return internal::floor_log2_abs(x.abs().inf());
}
};
struct Ceil_log2_abs
: public CGAL::cpp98::unary_function< Gmpfi, long > {
long operator()( const Gmpfi& x ) const {
CGAL_precondition(!x.inf().is_zero() || !x.sup().is_zero());
return internal::ceil_log2_abs(x.abs().sup());
}
};
struct Floor
: public CGAL::cpp98::unary_function< Gmpfi, Gmpz > {
Gmpz operator() ( const Gmpfi& x )
const {
return internal::floor( x.inf() );
}
};
struct Ceil
: public CGAL::cpp98::unary_function< Gmpfi, Gmpz > {
Gmpz operator() ( const Gmpfi& x )
const {
return internal::ceil( x.sup() );
}
};
};
#endif
} //namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H
@@ -0,0 +1,291 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
/*! \file NiX/Real_roots.h
\brief This file defines the class NiX::Real_roots.
*/
#ifndef CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_H
#define CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_H
#include <CGAL/basic.h>
#include <CGAL/Polynomial.h>
#include <list>
#include <vector>
#include <queue>
namespace CGAL {
namespace internal {
/*! \ingroup NiX_Real_roots
* \brief This class provides operators for a comfortable construction of
* AlgebraicReal from Polynomials using a specific RealRootIsolator.
*
* A valid template argument for AlgebraicReal is NiX::Algebraic_real.
*/
template < class AlgebraicReal ,
class RealRootIsolator >
class Real_roots{
public:
//! The Real_roots type it self.
typedef Real_roots<AlgebraicReal,RealRootIsolator> Self;
//! First template argument.
typedef AlgebraicReal Algebraic_real;
//! Second template argument.
typedef RealRootIsolator Real_root_isolator;
//! The Polnomial type used by Algebraic_real and the Real_root_isolator.
typedef typename Algebraic_real::Polynomial_1 Polynomial;
private:
typedef typename AlgebraicReal::Coefficient Coefficient;
typedef typename AlgebraicReal::Rational Rational;
private:
template < class PolynomialIterator,
class IntIterator,
class AlgebraicRealOutputIterator,
class IntOutputIterator>
int gen_agebraic_reals_with_mults( PolynomialIterator fac,
PolynomialIterator fac_end,
IntIterator mul,
IntIterator CGAL_precondition_code(mul_end),
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult){
Self real_roots;
typedef std::pair<Algebraic_real, int> PAIR;
// find zeroes of each factor and sort them in ascending order
std::priority_queue< PAIR,std::vector<PAIR>,std::greater<PAIR> > pqueue;
std::vector<Algebraic_real> tmp;
while(fac != fac_end){
CGAL_assertion(mul != mul_end);
tmp.clear();
real_roots(*fac, std::back_inserter(tmp));
for (int j = 0; j < static_cast<int>(tmp.size()); j++) {
pqueue.push(PAIR(tmp[j], *mul));
}
fac++;
mul++;
}
// output factors and multiplicities
int n = 0;
while (!pqueue.empty()) {
*oi_root++ = pqueue.top().first;
*oi_mult++ = pqueue.top().second;
n++;
pqueue.pop();
}
return n;
}
private:
template < class PolynomialConstIterator,
class IntConstIterator,
class PolynomialOutputIterator>
void write_factors_by_multiplicity(PolynomialConstIterator fac,
PolynomialConstIterator fac_end,
IntConstIterator mul,
IntConstIterator CGAL_assertion_code(mul_end),
PolynomialOutputIterator oi_poly){
// output table such that table[m] contains square-free factor of
// multiplicity m (or else constant poly 1)
int m = 0;
while (fac != fac_end) {
CGAL_assertion(mul != mul_end);
while (m < *mul) {
*oi_poly++ = Polynomial(Coefficient(1)); m++;
}
*oi_poly++ = *fac; m++;
++fac; ++mul;
}
}
public:
/*! \brief computes all roots of the square free polynomial P in
* ascending order and returns the number of real roots.
*/
template <class AlgebraicRealOutputIterator>
int operator()(const Polynomial& poly ,
AlgebraicRealOutputIterator it){
CGAL_precondition_msg( typename CGAL::Polynomial_traits_d< Polynomial >::Is_square_free()(poly), "P not square free.");
return (*this)(Real_root_isolator(poly),it);
}
public:
/*! \brief computes all roots of the polynomial P in ascending order
* and their multiplicity and returns the number of real roots.
*
* This operator returns the number \e n of distinct real roots of \c poly.
* Each root is represented as an object of an instance AlgebraicReal.
* The operator writes these \e n real zeroes in ascending order to \c
* oi_root.
* It writes the multiplicities of the zeroes in the same order to
* \c oi_mult .
*/
template <class AlgebraicRealOutputIterator,
class IntOutputIterator>
int operator()(const Polynomial& poly,
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult){
CGAL_precondition(CGAL::degree(poly) >= 0);
// fast exit
if (CGAL::degree(poly) == 0)
return (poly.is_zero())?-1:0;
std::list<Polynomial> sqffac;
std::list<int> facmul;
filtered_square_free_factorize_utcf(poly,
std::back_inserter(sqffac),
std::back_inserter(facmul));
int number_of_real_roots=
gen_agebraic_reals_with_mults(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_root,
oi_mult);
return number_of_real_roots;
}
public:
/*! \brief computes all roots defined by the Real_root_isolator object in
* ascending order
*/
template <class AlgebraicRealOutputIterator>
int operator()(const Real_root_isolator& isolator,
AlgebraicRealOutputIterator it){
Polynomial poly = isolator.polynomial();
//cout << "P: "<<poly<<endl;
// take out exact known roots out of Poly
for(int j = 0 ; j < isolator.number_of_real_roots(); j++){
if(isolator.is_exact_root(j)){
Rational root(isolator.left_bound(j));
CGAL::simplify(root);
typedef CGAL::Fraction_traits<Rational> FT;
typename FT::Numerator_type num;
typename FT::Denominator_type denom;
typename FT::Decompose decomp;
decomp(root,num,denom);
Polynomial linear_factor(Coefficient(-num),
Coefficient(denom));
poly=CGAL::integral_division(poly,linear_factor);
}
}
//cout << "P_without_exact: "<<poly<<endl;
std::vector<AlgebraicReal> conjugated_roots;
std::back_insert_iterator<std::vector<AlgebraicReal> > con_it
= std::back_inserter(conjugated_roots);
// construct AlgebraicReal
for(int j = 0 ; j < isolator.number_of_real_roots(); j++){
if(isolator.is_exact_root(j)){
// exact roots (Rational
Rational root=isolator.left_bound(j);
CGAL::simplify(root);
*it++=AlgebraicReal(root);
}else{
// other roots
Rational left = isolator.left_bound(j);
Rational right= isolator.right_bound(j);
CGAL::simplify(left);
CGAL::simplify(right);
AlgebraicReal tmp(poly,left,right);
*it++=tmp;
*con_it++=tmp;
}
}
AlgebraicReal::conjugate(conjugated_roots.begin(),
conjugated_roots.end());
return isolator.number_of_real_roots();
}
/*! \brief factor \c p by multiplicities, return both factors and their roots
*
* This operator is for those users who have an
* Polynomial \c poly which is not necessarily square-free, and who
* want to get both its square-free factorization and its real roots with
* their respective multiplicities.
*
* This operator returns the number \e n of distinct real roots of \c poly .
* Each root is represented as an object of an instance AlgebraicReal.
* The operator writes these \e n real zeroes in ascending order to \c
* oi_root.
* It writes the multiplicities of the roots in the same order to
* \c oi_mult .
* Finally, it writes the square-free factors of \c p
* to \c oi_poly such that the factor #<I>k</I> written is the factor
* with exponent \e k in the square-free factorization of \c p , or
* the constant polynomial 1 if a factor of multiplicity \e k does
* not occur. Yes, this means that the first factor written, which is
* factor #0, will always be 1.
*
* The data types involved are determined the \c AlgebraicReal
* template argument. In particular, \c p must be of type
* \c NiX::Polynomial<AlgebraicReal::Coefficient>, as are its factors;
* the roots are of type \c AlgebraicReal ; and the multiplicities are
* of type \c int .
*
*/
template <class AlgebraicRealOutputIterator,
class IntOutputIterator,
class PolynomialOutputIterator>
int operator()( const Polynomial& poly,
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult,
PolynomialOutputIterator oi_poly) {
CGAL_precondition(CGAL::degree(poly) >= 0);
// fast exit
if (CGAL::degree(poly) == 0)
return (poly.is_zero())?-1:0;
std::list<Polynomial> sqffac;
std::list<int> facmul;
filtered_square_free_factorize_utcf(poly,
std::back_inserter(sqffac),
std::back_inserter(facmul));
write_factors_by_multiplicity(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_poly);
int numer_of_real_roots =
gen_agebraic_reals_with_mults(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_root,
oi_mult);
return numer_of_real_roots;
}
};
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_ROOTS_H
@@ -0,0 +1,114 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_SHEAR_CONTROLLER
#define CGAL_ACK_SHEAR_CONTROLLER 1
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Random.h>
#include <CGAL/tss.h>
#include<set>
namespace CGAL {
namespace internal {
/*!
* \brief A class that controls the used shear factors
*
* The objects returns positive integers that are used as shear factors.
* It choses integers from the range \c 1..max at random ,
* where \c c is a positive integer
* initially set in the constructor (8 by default). No integer is given
* twice by \c get_shear_factor(), at least if the failed ones are reported
* with the \c report_failure() method.
* If more than half of the integers in the range were bad, the range is
* enlarged to \c 1..2*max.
*/
template<typename Int,int InitialMax=8>
class Shear_controller {
public:
//! Constructor, getting the maximal absolute value of the shear factor
Shear_controller()
:
#if CGAL_ACK_STATIC_SEED
#warning Warning, uses static seed!
rng(CGAL_ACK_STATIC_SEED)
#else
rng()
#endif
, m_max(InitialMax)
, pos_next_factor(0) {
CGAL_assertion(m_max>=1);
}
//! Reports that the shear factor \c factor was bad.
void report_failure(Int factor) {
this->bad_shears.insert(factor);
long failures=static_cast<long>(this->bad_shears.size())+1;
if(2*failures>this->m_max) {
this->m_max*=2;
}
}
//! Gets a shear factor
Int get_shear_factor() {
if(pos_next_factor==static_cast<int>(value_order().size())) {
value_order().push_back(get_new_shear_factor());
}
return value_order()[pos_next_factor++];
}
private:
//! Gets a new shear factor
Int get_new_shear_factor() {
CGAL_assertion(int(this->bad_shears.size())<m_max);
while(true) {
Int s = Int((rng.get_int(0,(std::numeric_limits<int>::max)())%m_max )+1);
if(bad_shears.find(s)==bad_shears.end()) {
return s;
}
}
}
Random rng;
// Maximal absolute value
Int m_max;
static std::vector<Int>& value_order() {
CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(std::vector<Int>, value_order_);
return value_order_;
}
int pos_next_factor;
// Unsuccessful shear factors
std::set<Int> bad_shears;
};
} // namespace internal
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ACK_SHEAR_CONTROLLER
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,613 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Pavel Emeliyanenko <asm@mpi-sb.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H
#define CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H
#include <CGAL/basic.h>
#include <CGAL/Handle_with_policy.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_descartes.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree_traits.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel_at_alpha.h>
namespace CGAL {
namespace internal {
template < class CurveAnalysis_2, class Rep_ >
class Status_line_CA_1;
template <class CurveAnalysis_2, class Rep>
std::ostream& operator<< (std::ostream&,
const Status_line_CA_1<CurveAnalysis_2, Rep>&);
#if !CGAL_ACK_USE_EXACUS
template < typename AlgebraicCurveKernel_2 >
class Event_line_builder;
template < typename AlgebraicCurveKernel_2 >
class Shear_transformation;
#endif
template < class AlgebraicCurveKernel_2 >
class Status_line_CA_1_rep {
public:
// this template argument
typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2;
typedef typename Algebraic_curve_kernel_2::Curve_analysis_2
Curve_analysis_2;
// myself
typedef Status_line_CA_1_rep<Algebraic_curve_kernel_2> Self;
// type of x-coordinate
typedef typename Curve_analysis_2::Algebraic_real_1
Algebraic_real_1;
// type of a curve point
typedef typename Curve_analysis_2::Algebraic_real_2
Algebraic_real_2;
// type of bivariate Polynomial
typedef typename Curve_analysis_2::Polynomial_2
Polynomial_2;
// an instance of a size type
typedef typename Curve_analysis_2::size_type size_type;
// encodes number of arcs to the left and to the right
typedef std::pair<size_type, size_type> Arc_pair;
// container of arcs
typedef std::vector<Arc_pair> Arc_container;
// Isolator type
typedef typename Curve_analysis_2::Bitstream_descartes Bitstream_descartes;
// constructors
// default constructor ()
Status_line_CA_1_rep()
{ }
// constructs status line over interval
Status_line_CA_1_rep(
Algebraic_real_1 x, size_type i,
const Curve_analysis_2& ca, size_type n_arcs) :
_m_kernel(ca.kernel()),
_m_x(x), _m_index(i), _m_ca(ca),/*_m_num_arcs(n_arcs, n_arcs),*/
_m_total_arcs(n_arcs), _m_vertical_line(false), _m_event(false),
_m_num_arcs_minus_inf(0, 0), _m_num_arcs_plus_inf(0, 0),
_m_xy_coords(n_arcs) {
}
// constructs status line at events
Status_line_CA_1_rep(
Algebraic_real_1 x, size_type i,
const Curve_analysis_2& ca,
size_type , size_type ) :
_m_kernel(ca.kernel()),
_m_x(x), _m_index(i), _m_ca(ca),
/*_m_num_arcs(n_arcs_left, n_arcs_right),*/ _m_total_arcs(0),
_m_vertical_line(false), _m_event(true),
_m_num_arcs_minus_inf(0, 0), _m_num_arcs_plus_inf(0, 0) {
};
//! kernel instance
// TODO remove kernel?
const Algebraic_curve_kernel_2 *_m_kernel;
//! x-coordinate of event info
mutable Algebraic_real_1 _m_x;
//! this status line id (# of event or # of interval depending on whether
//! or not this status line encodes an event)
size_type _m_index;
//! underlying curve analysis
Curve_analysis_2 _m_ca;
//! number of incident arcs to the left and to the right
//Arc_pair _m_num_arcs;
//! sequence of arcs crossing this status line (valid only event lines)
mutable boost::optional<Arc_container> _m_arcs;
//! number of arcs intersecting this status line
mutable int _m_total_arcs;
//! curve has vertical line at this x-coordinate
mutable bool _m_vertical_line;
//! decsribes an event
mutable bool _m_event;
//! number of arcs running down the pole
Arc_pair _m_num_arcs_minus_inf;
//! number of arcs running up the pole
Arc_pair _m_num_arcs_plus_inf;
/*// matchings valid?
mutable bool matching_valid_;
// match side arcs to event arcs
mutable std::vector< int > matching_[2];
// total number of arcs
int numarcs_at_;
// arc number of lowest event
int lowest_event_;
// stores multiplicities
std::vector< int > multiplicities_;*/
// stores algebraic real over the vertical line
mutable std::vector<boost::optional< Algebraic_real_2 > >_m_xy_coords;
// stores the isolator instance
mutable boost::optional<Bitstream_descartes> isolator;
// befriending the handle
friend class Status_line_CA_1<Curve_analysis_2, Self>;
//friend class Curve_analysis_2;
//friend class Event_line_builder<Curve_analysis_2>;
//friend class Shear_transformation<Curve_analysis_2>;
};
//! \brief The class provides information about the intersections of a curve
//! with a vertical line at a given finite x-coordinate.
//!
//! Note that a curve can have a vertical line component at this coordinate
//! and non-vertical components may intersect the vertical line respectively.
//! With the help of this class' methods one is able to compute the local
//! topology of the curve at the given vertical line. Note that vertical lines
//! at x = +/-oo are not allowed, since different events (curve ends going to
//! infinity with different non-horizontal asymptotes) would have equal
//! y-coordinate (+/-oo), which confuses more than it helps. Note in addition
//! that curve ends approaching the vertical asymptote introduce an event
//! (depending on whether approaching +oo or -oo - but the event with
//! coordinates (x,?oo), resp. (x,+oo), occur only once, if they occur, and
//! they imply not to be associated with a instance of \c Algebraic_real_2.
template <class AlgebraicCurveKernel_2,
class Rep_ = internal::Status_line_CA_1_rep<AlgebraicCurveKernel_2> >
class Status_line_CA_1
: public ::CGAL::Handle_with_policy< Rep_ > {
public:
//!@{
//!\name typedefs
//! this instance's first template parameter
//! model of AlgebraicKernel_d_2
typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2;
typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 Curve_analysis_2;
//! this instance's second template parameter
typedef Rep_ Rep;
//! this instance itself
typedef Status_line_CA_1<Algebraic_curve_kernel_2, Rep> Self;
//! type of x-coordinate
typedef typename Curve_analysis_2::Algebraic_real_1 Algebraic_real_1;
//! type of a curve point
typedef typename Curve_analysis_2::Algebraic_real_2 Algebraic_real_2;
//! an instance of a size type
typedef typename Curve_analysis_2::size_type size_type;
//! encodes number of arcs to the left and to the right
typedef std::pair<size_type, size_type> Arc_pair;
//! container of arcs
typedef std::vector<Arc_pair> Arc_container;
//! Local isolator type
typedef typename Rep::Bitstream_descartes Bitstream_descartes;
//! the handle superclass
typedef ::CGAL::Handle_with_policy< Rep > Base;
//!@}
public:
//!\name constructors
//!@{
/*!\brief
* Default constructor
*/
Status_line_CA_1() :
Base(Rep()) {
}
/*!\brief
* copy constructor
*/
#ifdef DOXYGEN_RUNNING
Status_line_CA_1(const Self& p) :
Base(static_cast<const Base&>(p)) {
}
#endif
/*!\brief
* constructs a status line over the \c i-th interval with x-coordinate
* \c x
*
* \c n_arcs defines # of curve arcs over the interval
*
* \pre specified x-coordinate belongs to \c i-th interval
*/
Status_line_CA_1(
Algebraic_real_1 x, size_type i, const Curve_analysis_2& ca,
size_type n_arcs) :
Base(Rep(x, i, ca, n_arcs)) {
CGAL_precondition(n_arcs >= 0);
CGAL_precondition_code(
bool is_event;
size_type idx;
ca.x_to_index(x, idx, is_event);
CGAL_precondition(!is_event && idx == i);
);
}
/*!\brief
* constructs a status line at the event with x-coorinate \c x
*
* \c arcs container defines # of incident arcs to the left and to the
* right of each intersection point of the curve \c ca with this status
* line, sorted by y-s in ascending order.
* \c n_arcs_left and \c n_arcs_right specify total number of incident
* arcs to the left and to the right respectively.
* \c has_v_line specifies whether the curve has a vertical line as a
* component at this x-coordinate
*
* \pre there is a curve event at specified x-coordinate
*/
Status_line_CA_1(Algebraic_real_1 x,
size_type i, const Curve_analysis_2& ca,
size_type n_arcs_left, size_type n_arcs_right,
Arc_container arcs, bool has_v_line = false) :
Base(Rep(x, i, ca, n_arcs_left, n_arcs_right)) {
CGAL_precondition(n_arcs_left >= 0 && n_arcs_right >= 0);
CGAL_precondition_code(
bool is_event;
size_type idx;
ca.x_to_index(x, idx, is_event);
CGAL_precondition(idx == i);
);
_set_arcs(arcs);
if(has_v_line)
_set_v_line();
}
/*!\brief
* constructs a status line at the event with x-coorinate \c x
*
* arcs and vertical line flag can be set later
*/
Status_line_CA_1(Algebraic_real_1 x,
size_type i, const Curve_analysis_2& ca,
size_type n_arcs_left, size_type n_arcs_right) :
Base(Rep(x, i, ca, n_arcs_left, n_arcs_right)) {
CGAL_precondition(n_arcs_left >= 0 && n_arcs_right >= 0);
CGAL_precondition_code(
bool is_event;
size_type idx;
ca.x_to_index(x, idx, is_event);
CGAL_precondition(idx == i);
);
}
/*!\brief
* constructs from a given represenation
*/
Status_line_CA_1(Rep rep) :
Base(rep) {
}
//!@}
public:
//!\name access functions
//!@{
/*! \brief
* returns the x-coordinate of the status line (always a finite value)
*/
Algebraic_real_1 x() const {
return this->ptr()->_m_x;
}
/*! \brief
* returns this status line CurveAnalysis_2 object
*/
Curve_analysis_2 curve_analysis_2() const {
return this->ptr()->_m_ca;
}
/*! \brief
* returns this status line index (event or interval index)
*/
size_type index() const {
return this->ptr()->_m_index;
}
/*! \brief
* returns \c true in case the given curve contains the status line
* as a component
*/
bool covers_line() const {
return this->ptr()->_m_vertical_line;
}
/*!\brief
* returns \c true if the curve f has intersection with f_y at x
*/
bool has_f_fy_intersection() const {
return (is_event() && !covers_line());
}
/*! \brief
* returns \c true if one of \c covers_line of \c has_f_fy_intersection
* evaluates to \c true
*/
bool is_event() const {
return this->ptr()->_m_event;
}
/*! \brief
* returns \c true if the ith point is an event point
*/
bool is_event(size_type i) const {
// TODO: Make it possible to detect singularities as well
Arc_pair branches = number_of_incident_branches(i);
return branches.first!=1 || branches.second!=1;
}
/*! \brief
* returns number of distinct and finite intersections of a curve with a
* (intended) vertical line ignoring a real vertical line component of the
* curve at the given x-coordinate.
*/
size_type number_of_events() const {
return this->ptr()->_m_total_arcs;
}
/*!\brief
* returns \c Algebraic_real_2 for j-th event over this vert line
*
* \pre 0 <= j < num_of_events()
*/
Algebraic_real_2 algebraic_real_2(size_type j) const
{
CGAL_precondition(0 <= j&&j < number_of_events());
if(!this->ptr()->_m_xy_coords[j])
this->ptr()->_m_xy_coords[j] = Algebraic_real_2(x(),
this->ptr()->_m_ca, j);
return *(this->ptr()->_m_xy_coords[j]);
}
/*!\brief
* alias for \c get_algebraic_real_2()
*/
Algebraic_real_2 xy_coordinate_2(size_type j) const {
return algebraic_real_2(j);
}
/*!\brief
* returns the number of branches of the curve connected to j-th
* event immediately to the left, to the right, respectively, as a pair of
* unsigned int ignoring vertical curve components at the given
* x-coordinate.
*
* \pre 0 <= j < num_of_events()
*/
Arc_pair number_of_incident_branches(int j) const {
CGAL_precondition(0 <= j&&j < number_of_events());
if(!is_event())
return Arc_pair(1, 1);
return (*(this->ptr()->_m_arcs))[j];
}
/*! \brief
* returns the number of vertical asymptotes at x of the curve
* approaching y=-oo from left and right. A vertical line being component
* of the curve is ignored.
*/
const Arc_pair& number_of_branches_approaching_minus_infinity() const {
return this->ptr()->_m_num_arcs_minus_inf;
}
/*! \brief
* returns the number of vertical asymptotes at x of the curve
* approaching y=+oo from left and right. A vertical line being component
* of the curve is ignored.
*/
const Arc_pair& number_of_branches_approaching_plus_infinity() const {
return this->ptr()->_m_num_arcs_plus_inf;
}
protected:
Algebraic_curve_kernel_2* kernel() const {
return this->ptr()->_m_kernel;
}
//!@}
public:
//!@{
/*!\brief
* sets # of arcs running from left and right to -inf and +inf at vertical
* asymptote
*/
void _set_number_of_branches_approaching_infinity(
const Arc_pair& minus_inf, const Arc_pair& plus_inf) {
CGAL_precondition(minus_inf.first >= 0 && minus_inf.second >= 0);
CGAL_precondition(plus_inf.first >= 0 && plus_inf.second >= 0);
this->ptr()->_m_num_arcs_minus_inf = minus_inf;
this->ptr()->_m_num_arcs_plus_inf = plus_inf;
if(!this->ptr()->_m_event)
this->ptr()->_m_event = (minus_inf.first + minus_inf.second +
plus_inf.first + plus_inf.second > 0);
}
void _set_arcs(const Arc_container& arcs) const {
CGAL_precondition(is_event());
this->ptr()->_m_arcs = arcs;
this->ptr()->_m_total_arcs = static_cast<int>(arcs.size());
this->ptr()->_m_xy_coords.resize(arcs.size());
}
void _set_v_line() const {
CGAL_precondition(is_event());
this->ptr()->_m_vertical_line = true;
}
//!@}
//!\name IO
//!@{
void write(std::ostream& os) const {
os << "status_line [CA@" << this->ptr()->_m_ca.id() << std::flush;
#if CGAL_ACK_USE_EXACUS
os << "; x = " << x() << "; #events: " << number_of_events() << "; "
<< std::flush;
#else
os << "; x = " << CGAL::to_double(x()) << "; #events: "
<< number_of_events() << "; " << std::flush;
#endif
if(is_event()) {
os << "incident branches: {" << std::flush;
// typename Arc_container::const_iterator ait =
// (*this->ptr()->_m_arcs).begin();
for(int i = 0; i < number_of_events(); i++) {
Arc_pair arc_pair = number_of_incident_branches(i);
if(i!=0) {
os << ", " << std::flush;
}
Algebraic_real_2 xy = algebraic_real_2(i);
typedef typename Bitstream_descartes::Bound Bound;
Bound th = CGAL::ipower(Bound(1,2),53);
std::pair<double,double> d_pair
= xy.to_double();
os << "y=" << d_pair.second << ", " << std::flush;
os << "(" << arc_pair.first << ", " << arc_pair.second << ")"
<< std::flush;
}
os << "}";
Arc_pair p = number_of_branches_approaching_minus_infinity();
if(p.first + p.second > 0)
os << "; approaching -oo: (" << p.first << "; " <<
p.second << ")" << std::flush;
p = number_of_branches_approaching_plus_infinity();
if(p.first + p.second > 0)
os << "; approaching +oo: (" << p.first << "; " <<
p.second << ")" << std::flush;
if(covers_line())
os << "; covers line" << std::flush;
} else
os << "interval line" << std::flush;
os << "]" << std::flush;
}
//!@}
//! Sets the isolator instance
void set_isolator (const Bitstream_descartes& isolator) const {
this->ptr()->isolator = isolator;
}
//! Returns the isolator instance
Bitstream_descartes& isolator() const {
CGAL_assertion(bool(this->ptr()->isolator));
return this->ptr()->isolator.get();
}
//! Returns whether an isolator has been given for that status line
bool has_isolator() const {
return this->ptr()->isolator;
}
typename Bitstream_descartes::Bound lower_bound(int index) const {
return isolator().left_bound(index);
}
typename Bitstream_descartes::Bound upper_bound(int index) const {
return isolator().right_bound(index);
}
typename Bitstream_descartes::Bound interval_length(int index) const {
return isolator().right_bound(index)-
isolator().left_bound(index);
}
int get_upper_bound_for_multiplicity(int index) const {
return isolator().get_upper_bound_for_multiplicity(index);
}
void refine(int index) const {
return isolator().refine_interval(index);
}
void refine_to(int index, typename Bitstream_descartes::Bound b) {
while(upper_bound(index) - lower_bound(index) > b) {
refine(index);
}
}
//! these are our friends
//friend class Curve_analysis_2;
}; // class Status_line_CA_1
template <class CurveAnalysis_2, class Rep>
std::ostream& operator<< (
std::ostream& os,
const internal::Status_line_CA_1<CurveAnalysis_2, Rep>& line) {
line.write(os);
return os;
}
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H
@@ -0,0 +1,487 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Pavel Emeliyanenko <asm@mpi-sb.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H
#define CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H
#include <CGAL/basic.h>
#include <CGAL/Handle_with_policy.h>
#include <CGAL/algorithm.h>
namespace CGAL {
namespace internal {
template < class CurvePairAnalysis_2, class Rep_ >
class Status_line_CPA_1;
template <class CurvePairAnalysis_2, class Rep>
std::ostream& operator<< (std::ostream&,
const Status_line_CPA_1<CurvePairAnalysis_2, Rep>&);
template < class CurvePairAnalysis_2 >
class Status_line_CPA_1_rep {
// this template argument
typedef CurvePairAnalysis_2 Curve_pair_analysis_2;
// myself
typedef Status_line_CPA_1_rep<Curve_pair_analysis_2> Self;
// type of x-coordinate
typedef typename Curve_pair_analysis_2::Algebraic_real_1
Algebraic_real_1;
// type of a curve point
typedef typename Curve_pair_analysis_2::Algebraic_real_2
Algebraic_real_2;
// an instance of a size type
typedef typename Curve_pair_analysis_2::size_type size_type;
// encodes number of arcs to the left and to the right
typedef std::pair<size_type, size_type> Arc_pair;
// container of arcs
typedef std::vector<Arc_pair> Arc_container;
// container of integers ?
typedef std::vector<size_type> Int_container;
// constructors
public:
// default constructor ()
Status_line_CPA_1_rep()
{ }
// constructs an empty status line object
Status_line_CPA_1_rep(size_type i, Curve_pair_analysis_2 cpa) :
_m_index(i), _m_cpa(cpa), _m_event(false), _m_intersection(false) {
}
// stores this status line interval or event index of a curve pair
size_type _m_index;
// represents x-coordinate of event of rational value over interval
// computed only by demand
mutable boost::optional<Algebraic_real_1> _m_x;
// for each event point stores a pair of arcnos of the 1st and 2nd curve
// or -1 if respective curve is not involved
mutable Arc_container _m_arcs;
// inverse mapping from arcnos of the 1st and 2nd curve to respective
// y-position
mutable Int_container _m_arcno_to_pos[2];
// stores multiplicities of intersection points (-1 if there is no 2-curve
// intersection)
mutable Int_container _m_mults;
// underlying curve pair analysis
Curve_pair_analysis_2 _m_cpa;
// is there an event
mutable bool _m_event;
// is there is an intersection of both curves
mutable bool _m_intersection;
// befriending the handle
friend class Status_line_CPA_1<Curve_pair_analysis_2, Self>;
};
//! \brief The class provides information about the intersections of a pair of
//! curves with a (intended) vertical line (ignoring vertical lines of the
//! curves themselves).
//!
//! Each intersection of a curve with the vertical line defined by some given x
//! induces an event. An event can be asked for its coordinates
//! (\c Algebraic_real_2) and the involved curve(s). Note that the involvement
//! also holds for curve ends approaching the vertical asymptote.
//! Curve_pair_vertical_line_1 at x = +/-oo are not allowed.
template <class CurvePairAnalysis_2,
class Rep_ = internal::Status_line_CPA_1_rep<CurvePairAnalysis_2> >
class Status_line_CPA_1 :
public ::CGAL::Handle_with_policy< Rep_ >
{
public:
//!@{
//!\name typedefs
//! this instance's first template parameter
typedef CurvePairAnalysis_2 Curve_pair_analysis_2;
//! this instance's second template parameter
typedef Rep_ Rep;
//! this instance itself
typedef Status_line_CPA_1<Curve_pair_analysis_2, Rep> Self;
//! type of x-coordinate
typedef typename Curve_pair_analysis_2::Algebraic_real_1 Algebraic_real_1;
//! type of a curve point
typedef typename Curve_pair_analysis_2::Algebraic_real_2 Algebraic_real_2;
//! an instance of a size type
typedef typename Curve_pair_analysis_2::size_type size_type;
//! encodes number of arcs to the left and to the right
typedef std::pair<size_type, size_type> Arc_pair;
//! container of arcs
typedef std::vector<Arc_pair> Arc_container;
//! container of integers ?
typedef std::vector<size_type> Int_container;
//! the handle superclass
typedef ::CGAL::Handle_with_policy< Rep > Base;
//!@}
public:
//!\name constructors
//!@{
/*!\brief
* Default constructor
*/
Status_line_CPA_1() :
Base(Rep()) {
}
/*!\brief
* copy constructor
*/
#ifdef DOXYGEN_RUNNING
Status_line_CPA_1(const Self& p) :
Base(static_cast<const Base&>(p)) {
}
#endif
/*!\brief
* constructs undefined status line
*/
Status_line_CPA_1(size_type i, Curve_pair_analysis_2 cpa) :
Base(Rep(i, cpa)) {
}
/*!\brief
* constructs a status line at the \c i -th event of a curve pair
*
* each element of \c arcs is a pair with the first item specifying the
* type of event (0 - event of the 1st curve, 1 - of the second curve,
* 2 - of both curves), and the second item - multiplicity of intersection
* or -1 if not available
*/
Status_line_CPA_1(size_type i, const Arc_container& arcs,
Curve_pair_analysis_2 cpa) :
Base(Rep(i, cpa)) {
_set_event_arcs(arcs);
}
/*!\brief
* constructs a status line over the \c i -th interval of a curve pair
*
* each element of \c arcs specifies to which curve a respective arc
* belongs to (0 - arc of the 1st curve, 1 - arc of the 2nd curve)
* \c is_swapped defines that the curves in targeting curve pair analysis
* were swapped during precaching
*/
Status_line_CPA_1(size_type i, const Int_container& arcs,
Curve_pair_analysis_2 cpa) :
Base(Rep(i, cpa)) {
_set_interval_arcs(arcs);
}
protected:
/*!\brief
* constructs from a given represenation
*/
Status_line_CPA_1(Rep rep) :
Base(rep) {
}
//!@}
public:
//!\name access functions
//!@{
/*! \brief
* returns the x-coordinate of the vertical line (always a finite value).
*/
Algebraic_real_1 x() const {
// unless x-coordiate was explicitly set with _set_x: compute its value
if(!this->ptr()->_m_x) {
this->ptr()->_m_x = (is_event() ?
#if CGAL_ACK_USE_EXACUS
this->ptr()->_m_cpa._internal_curve_pair().event_x(index()) :
Algebraic_real_1(this->ptr()->_m_cpa._internal_curve_pair().
bound_value_in_interval(index())));
#else
this->ptr()->_m_cpa.event_x(index()) :
Algebraic_real_1(this->ptr()->_m_cpa.
bound_value_in_interval(index())));
#endif
}
return *(this->ptr()->_m_x);
}
//! returns this vertical line's index (event or interval index)
size_type index() const {
CGAL_precondition(this->ptr()->_m_index>=0);
return this->ptr()->_m_index;
}
/*! \brief
* returns number of distinct and finite intersections of a pair
* of curves with a (intended) vertical line ignoring a real vertical
* line component of the curve at the given x-coordinate.
*/
size_type number_of_events() const {
return static_cast<size_type>(this->ptr()->_m_arcs.size());
}
/*! \brief
* returns the y-position of the k-th event of
* the curve in the sequence of events.
*
* Note that each event is formed by the 1st, 2nd, or both curves
*
* \pre 0 <= k < "number of arcs defined for curve c at x()"
*/
size_type event_of_curve(size_type k,
const typename Curve_pair_analysis_2
::Curve_analysis_2& c) const {
CGAL_assertion(c.id()==this->ptr()->_m_cpa.curve_analysis(false).id()||
c.id()==this->ptr()->_m_cpa.curve_analysis(true).id());
bool b = (c.id()==this->ptr()->_m_cpa.curve_analysis(true).id());
return event_of_curve(k,b);
}
/*! \brief
* returns the y-position of the k-th event of the c-th (0 or 1)
* curve in the sequence of events.
*
* Note that each event is formed by the 1st, 2nd, or both curves
*
* \pre 0 <= k < "number of arcs defined for curve[c] at x()"
*/
size_type event_of_curve(size_type k, bool c) const {
CGAL_precondition_msg(0 <= k &&
k < static_cast<size_type>(this->ptr()->_m_arcno_to_pos[c].size()),
"Invalid arc number of the c-th curve specified");
return this->ptr()->_m_arcno_to_pos[c][k];
}
/*! \brief
* returns the multiplicity of intersection defined at event with
* position \c j. May return -1 in case multiplicity is unknown.
*
* \pre There is an intersection of both curves at j-th event
* \pre 0 <= j < number_of_events()
*/
size_type multiplicity_of_intersection(size_type j) const
{
CGAL_precondition(0 <= j && j < number_of_events());
CGAL_precondition(is_intersection());
CGAL_precondition(this->ptr()->_m_arcs[j].first != -1 &&
this->ptr()->_m_arcs[j].second != -1);
return this->ptr()->_m_mults[j];
}
/*! \brief
* returns a pair of \c int indicating whether event \c j is formed
* by which arc numbers of the first and the second curve, or -1, if the
* corresponding curve is not involved.
*
* \pre 0 <= j < number_of_events()
*/
Arc_pair curves_at_event(size_type j) const
{
CGAL_precondition(0 <= j && j < number_of_events());
const Arc_pair& arc = this->ptr()->_m_arcs[j];
return arc;
}
/*!
* returns an index indicating whether event \c j is formed
* by which arc numbers of the curve \c ca, or -1, if the
* corresponding curve is not involved.
*/
Arc_pair curves_at_event(size_type j,
const typename Curve_pair_analysis_2
::Curve_analysis_2& c1,
const typename Curve_pair_analysis_2
::Curve_analysis_2& CGAL_precondition_code(c2)) const
{
CGAL_precondition(0 <= j && j < number_of_events());
CGAL_assertion(c1.id()!=c2.id());
CGAL_assertion
(c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id()||
c1.id()==this->ptr()->_m_cpa.curve_analysis(true).id());
CGAL_assertion
(c2.id()==this->ptr()->_m_cpa.curve_analysis(false).id()||
c2.id()==this->ptr()->_m_cpa.curve_analysis(true).id());
bool b = (c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id());
const Arc_pair& arc_pair = curves_at_event(j);
return b ? arc_pair : std::make_pair(arc_pair.second, arc_pair.first);
}
/*! \brief
* returns true if a curve has an event or in case there is an
* intersection of both curves.
*/
bool is_event() const {
return this->ptr()->_m_event;
}
/*! \brief
* returns true if there is an intersection of both curves.
*/
bool is_intersection() const {
return this->ptr()->_m_intersection;
}
//!@}
public:
//!@{
/*!\brief
* sets x-coordinate of a status line
*/
void _set_x(Algebraic_real_1 x) const {
this->ptr()->_m_x = x;
}
/*!\brief
* sets arcs at event (use at your own risk!)
*/
void _set_event_arcs(const Arc_container& arcs) const {
size_type k = 0, arcf = 0, arcg = 0;
this->ptr()->_m_arcs.resize(arcs.size());
this->ptr()->_m_mults.resize(arcs.size());
this->ptr()->_m_event = true;
for(typename Arc_container::const_iterator ait = arcs.begin();
ait != arcs.end(); ait++, k++) {
if(ait->first == 0) { // 1st curve
this->ptr()->_m_arcs[k].first = arcf++;
this->ptr()->_m_arcs[k].second = -1;
this->ptr()->_m_arcno_to_pos[0].push_back(k);
} else if(ait->first == 1) { // 2nd curve
this->ptr()->_m_arcs[k].first = -1;
this->ptr()->_m_arcs[k].second = arcg++;
this->ptr()->_m_arcno_to_pos[1].push_back(k);
} else if(ait->first == 2) { // intersection
this->ptr()->_m_arcs[k].first = arcf++;
this->ptr()->_m_arcs[k].second = arcg++;
this->ptr()->_m_arcno_to_pos[0].push_back(k);
this->ptr()->_m_arcno_to_pos[1].push_back(k);
this->ptr()->_m_intersection = true;
} else
CGAL_error_msg("Bogus curve index..");
this->ptr()->_m_mults[k] = ait->second;
}
}
/*!\brief
* sets arcs over interval (use at your own risk!)
*/
void _set_interval_arcs(const Int_container& arcs) const {
this->ptr()->_m_arcs.resize(arcs.size());
this->ptr()->_m_event = false;
this->ptr()->_m_intersection = false;
size_type k = 0, arcf = 0, arcg = 0;
for(typename Int_container::const_iterator ait = arcs.begin();
ait != arcs.end(); ait++, k++) {
if(*ait == 0) { // 1st curve
this->ptr()->_m_arcs[k].first = arcf++;
this->ptr()->_m_arcs[k].second = -1;
this->ptr()->_m_arcno_to_pos[0].push_back(k);
} else if(*ait == 1) { // 2nd curve
this->ptr()->_m_arcs[k].first = -1;
this->ptr()->_m_arcs[k].second = arcg++;
this->ptr()->_m_arcno_to_pos[1].push_back(k);
} else
CGAL_error_msg("Bogus curve index..");
}
}
//!@}
public:
//!\name IO
//!@{
void write(std::ostream& os) const {
os << "status_line [CPA@" << this->ptr()->_m_cpa.id();
os << "; x = " << (index()==-1 ? 999.999 : CGAL::to_double(x())) << "; #events: " << number_of_events() << "; ";
typename Arc_container::const_iterator ait =
this->ptr()->_m_arcs.begin();
if(is_event())
os << "arcs at event: {";
else
os << "arcs of interval: {";
for(; ait != this->ptr()->_m_arcs.end(); ait++) {
if(ait != this->ptr()->_m_arcs.begin())
os << ", ";
os << "(" << ait->first << "; " << ait->second << ")";
}
os << "}, arcno2pos: (";
CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[0].begin(),
this->ptr()->_m_arcno_to_pos[0].end(), ",");
os << "), (";
CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[1].begin(),
this->ptr()->_m_arcno_to_pos[1].end(), ",");
os << ")]";
}
//!@}
}; // class Status_line_CPA_1
template <class CurvePairAnalysis_2, class Rep>
std::ostream& operator<< (std::ostream& os,
const internal::Status_line_CPA_1<CurvePairAnalysis_2, Rep>& sline) {
sline.write(os);
return os;
}
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H
@@ -0,0 +1,777 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Eric Berberich <eric@mpi-inf.mpg.de>
// Pavel Emeliyanenko <asm@mpi-sb.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H
#define CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H
#include <CGAL/basic.h>
#include <boost/numeric/interval.hpp>
#include <CGAL/Bbox_2.h>
#include <CGAL/Arithmetic_kernel.h>
namespace CGAL {
namespace internal {
template < class AlgebraicCurveKernel_2, class Rep_,
class HandlePolicy_ ,
class Allocator_>
//::boost::fast_pool_allocator<Rep_> >
class Xy_coordinate_2;
template < class AlgebraicCurveKernel_2 >
class Xy_coordinate_2_rep {
public:
// this first template argument
typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2;
// myself
typedef Xy_coordinate_2_rep<Algebraic_curve_kernel_2> Self;
typedef typename Algebraic_curve_kernel_2::Curve_analysis_2
Curve_analysis_2;
typedef typename Algebraic_curve_kernel_2::Algebraic_real_1
Algebraic_real_1;
typedef CGAL::Bbox_2 Bbox_2;
typedef CGAL::Handle_with_policy<Self>
Xy_coordinate_2_inst;
// constructors
public:
// default constructor ()
Xy_coordinate_2_rep() : _m_arcno(-1) {
}
// standard constructor
Xy_coordinate_2_rep(const Algebraic_real_1& x,
const Curve_analysis_2& curve, int arcno)
: _m_kernel(curve.kernel()),_m_x(x), _m_curve(curve), _m_arcno(arcno) {
}
// data
const Algebraic_curve_kernel_2* _m_kernel;
// x-coordinate
Algebraic_real_1 _m_x;
// supporting curve
mutable Curve_analysis_2 _m_curve;
// arc number on curve
mutable int _m_arcno;
// y-coordinate
mutable boost::optional< Algebraic_real_1 > _m_y;
//! A bounding box for the given point
mutable boost::optional< std::pair<double,Bbox_2> > _m_bbox_2_pair;
};
//! \brief class \c Xy_coordinate_2 represents a single root of a system of
//! two polynomial equations in two variables that are models
//! \c AlgebraicCurveKernel_2::Polynomial_2
//!
//! \c Xy_coordinate_2 coordinate is represented by an \c Algebraic_real_1,
//! a supporting curve and an arcno and is valid only for finite solutions,
//! i.e., it cannot represent points at infinity
template <class AlgebraicCurveKernel_2,
class Rep_ = internal::Xy_coordinate_2_rep<AlgebraicCurveKernel_2>,
class HandlePolicy_= CGAL::Handle_policy_union,
class Allocator_ = CGAL_ALLOCATOR(Rep_) >
class Xy_coordinate_2 :
public ::CGAL::Handle_with_policy<Rep_, HandlePolicy_, Allocator_>
{
public:
//! \name public typedefs
//!@{
//! this instance's first template parameter
typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2;
//! this instance's second template parameter
typedef Rep_ Rep;
//! this instance's third template parameter
typedef HandlePolicy_ Handle_policy;
//! this instance's fourth template parameter
typedef Allocator_ Allocator;
//! this instance itself
typedef Xy_coordinate_2<Algebraic_curve_kernel_2, Rep, Handle_policy,
Allocator> Self;
//! an instance of AlgebraicKernel_1
typedef typename Algebraic_curve_kernel_2::Algebraic_kernel_d_1
Algebraic_kernel_d_1;
typedef typename Algebraic_curve_kernel_2::Polynomial_1 Polynomial_1;
typedef CGAL::Polynomial_traits_d<Polynomial_1> Polynomial_traits_1;
typedef typename Algebraic_curve_kernel_2::Polynomial_2 Polynomial_2;
typedef CGAL::Polynomial_traits_d<Polynomial_2> Polynomial_traits_2;
//! type of (explicit) x- and y-coordinates
typedef typename Algebraic_curve_kernel_2::Algebraic_real_1
Algebraic_real_1;
//! Coefficient type
typedef typename Algebraic_curve_kernel_2::Coefficient Coefficient;
//! type of curve pair analysis
typedef typename Algebraic_curve_kernel_2::Curve_pair_analysis_2
Curve_pair_analysis_2;
//! type of curve analysis
typedef typename Algebraic_curve_kernel_2::Curve_analysis_2
Curve_analysis_2;
//! the handle superclass
typedef ::CGAL::Handle_with_policy<Rep, Handle_policy, Allocator> Base;
//! type for approximation boundaries
typedef typename Algebraic_curve_kernel_2::Bound Bound;
//! type for bound intervals
typedef boost::numeric::interval<Bound> Bound_interval;
//! Type for the bounding box
typedef typename Rep::Bbox_2 Bbox_2;
//!@}
private:
//! \name private methods
//!@{
/*!\brief
* Simplifies the representation of two points whose supporting curves
* share a common part.
*/
bool _simplify(const Xy_coordinate_2& p, const Xy_coordinate_2& q) const
{
std::vector<Curve_analysis_2> parts_of_f, parts_of_g, common;
if(kernel()->decompose_2_object()(p.curve(), q.curve(),
std::back_inserter(parts_of_f), std::back_inserter(parts_of_g),
std::back_inserter(common))) {
CGAL_assertion((parts_of_f.size() == 1 ||
parts_of_g.size() == 1) && common.size() == 1);
if(parts_of_f.size() == 1) {
p.simplify_by(kernel()->construct_curve_pair_2_object()(
parts_of_f[0], common[0]));
}
if(parts_of_g.size() == 1) {
q.simplify_by(kernel()->construct_curve_pair_2_object()(
parts_of_g[0], common[0]));
}
return true;
}
return false;
}
//!@}
public:
//!\name Constructors
//!@{
/*!\brief
* default constructor
*
* A default-constructed point supports no operation other than
* having \c CGAL::degree(curve()) return \c -1.
*/
Xy_coordinate_2() :
Base(Rep()) {
}
/*!\brief
* copy constructor
*/
#ifdef DOXYGEN_RUNNING
Xy_coordinate_2(const Self& p) :
Base(static_cast<const Base&>(p)) {
}
#endif
/*!\brief
* Point at \c x, on \c curve with \c arcno. Finite points on vertical arcs
* are also constructed in this way
*/
Xy_coordinate_2(const Algebraic_real_1& x, const Curve_analysis_2& curve,
int arcno) :
Base(Rep(x, curve, arcno)) {
CGAL_precondition(arcno >= 0);
CGAL_precondition_code(
typename Curve_analysis_2::Status_line_1 v =
curve.status_line_for_x(x);
);
CGAL_precondition(arcno >= 0 && arcno < v.number_of_events());
}
/*!\brief
* constructs a point from a given represenation
*/
Xy_coordinate_2(Rep rep) :
Base(rep) {
}
//!@}
public:
//!\name Access functions
//!@{
/*!\brief
* x-coordinate of the point
*/
const Algebraic_real_1& x() const {
return this->ptr()->_m_x;
}
/*!
* \brief y-coordinate of this point
*
* Note: In general, this method results in a extremly large polynomial
* for the y-coordinate. It is recommended to use it carefully,
* and using get_approximation_y() instead whenever approximations suffice.
*/
Algebraic_real_1 y() const {
typedef std::vector< Algebraic_real_1 > Roots;
// EBEB 2012-07-05 deactivated map for y-roots for not being used
// typedef typename Curve_analysis_2::Status_line_1 Key;
// EBEB 2012-07-05 deactivated map for y-roots for not being used
// typedef Roots Data;
// EBEB 2012-07-05 deactivated map for y-roots for not being used
// typedef std::map< Key, Data, CGAL::Handle_id_less_than< Key > >
// Y_root_map;
// EBEB 2012-07-05 deactivated map for y-roots for not being used
//static Y_root_map y_root_map;
if (!this->ptr()->_m_y) {
Polynomial_2 f = curve().primitive_polynomial_2();
// This will be the defining polynomial of y
Polynomial_1 y_pol;
// Filter: If we know that the point is critical, we can use
// the resultant of f and f_y with respect to x as polynomial
bool point_is_certainly_critical = false;
typename Curve_analysis_2::Status_line_1 line =
curve().status_line_at_exact_x(x());
// EBEB 2012-07-05 deactivated map for y-roots for not being used
//typename Y_root_map::iterator yit =
// y_root_map.find(line);
// TODO: Cache resultant computation
// exacus-related code shouldn't be used here
//curve().x_to_index(x(),i,is_event);
if (line.is_event()) {
//typename Internal_curve_2::Event1_info ev_info =
// curve().event_info(i);
typename Curve_analysis_2::Status_line_1::Arc_pair ipair =
line.number_of_incident_branches(arcno());
if (ipair.first != 1 || ipair.second != 1) {
point_is_certainly_critical = true;
y_pol = CGAL::make_square_free(
CGAL::resultant
(typename Polynomial_traits_2::Swap() (f,0,1),
typename Polynomial_traits_2::Swap()
(CGAL::differentiate(f),0,1))
);
// BUGFIX: y_pol might be zero:
if(y_pol.is_zero()) {
// force re-computation with bigger resultant
point_is_certainly_critical=false;
}
}
}
if (!point_is_certainly_critical) {
Polynomial_2 r(x().polynomial());
y_pol = CGAL::make_square_free(
CGAL::resultant
(typename Polynomial_traits_2::Swap() (f,0,1),
typename Polynomial_traits_2::Swap() (r,0,1))
);
}
typename Algebraic_kernel_d_1::Solve_1 real_roots;
Roots y_roots;
real_roots(y_pol, std::back_inserter(y_roots), false );
long prec = 16;
typename Algebraic_curve_kernel_2::Approximate_absolute_y_2
approx_y=kernel()->approximate_absolute_y_2_object();
std::pair<Bound,Bound> y_pair = approx_y(*this,prec);
Bound_interval y_iv(y_pair.first,y_pair.second);
typedef typename std::vector<Algebraic_real_1>::const_iterator
Iterator;
std::list< Iterator > candidates;
for (Iterator it = y_roots.begin(); it != y_roots.end(); it++) {
Bound_interval it_interval(it->low(), it->high());
if (boost::numeric::overlap(it_interval, y_iv)) {
candidates.push_back(it);
}
}
CGAL_assertion(!candidates.empty());
while (candidates.size() > 1) {
prec*=2;
y_pair = approx_y(*this,prec);
y_iv = Bound_interval(y_pair.first,y_pair.second);
for (typename std::list< Iterator >::iterator dit, cit =
candidates.begin(); cit != candidates.end(); ) {
bool remove = false;
Bound_interval
cit_interval((*cit)->low(), (*cit)->high());
if (!boost::numeric::overlap(cit_interval, y_iv)) {
dit = cit;
remove = true;
}
cit++;
if (remove) {
candidates.erase(dit);
}
}
}
CGAL_assertion(static_cast< int >(candidates.size()) == 1);
this->ptr()->_m_y =
Algebraic_real_1(
(*candidates.begin())->polynomial(),
(*candidates.begin())->low(),
(*candidates.begin())->high()
);
}
CGAL_postcondition(bool(this->ptr()->_m_y));
return *this->ptr()->_m_y;
}
/*!\brief
* supporting curve of the point
*/
Curve_analysis_2 curve() const {
return this->ptr()->_m_curve;
}
/*!\brief
* arc number of point
*
*/
int arcno() const {
return this->ptr()->_m_arcno;
}
//!@}
public:
//!\name comparison predicates
//!@{
/*!\brief
* compares x-coordinates of \c *this with \c q
*
* do we need this method or one should use Algebraic_curve_kernel_2
* directly ?
*/
CGAL::Comparison_result compare_x(const Self& q) const {
if(this->is_identical(q)) {
return CGAL::EQUAL;
}
return kernel()->compare_1_object()(this->x(), q.x());
}
/*!\brief
* compares \c *this with \c q lexicographically
*/
CGAL::Comparison_result compare_xy(const Self& q,
bool equal_x = false) const {
if(this->is_identical(q))
return CGAL::EQUAL;
CGAL::Comparison_result res = (equal_x ? CGAL::EQUAL : compare_x(q));
if(res == CGAL::EQUAL) {
res = _compare_y_at_x(q);
}
return res;
}
//! equality
bool operator == (const Self& q) const {return q.compare_xy(*this)== 0;}
//! inequality
bool operator != (const Self& q) const {return q.compare_xy(*this)!= 0;}
//! less than in (x,y) lexicographic order
bool operator < (const Self& q) const {return q.compare_xy(*this)> 0;}
//! less-equal in (x,y) lexicographic order
bool operator <= (const Self& q) const {return q.compare_xy(*this)>= 0;}
//! greater than in (x,y) lexicographic order
bool operator > (const Self& q) const {return q.compare_xy(*this)< 0;}
//! greater-equal in (x,y) lexicographic order
bool operator >= (const Self& q) const {return q.compare_xy(*this)<= 0;}
//!@}
//!@{
//! \name
const Algebraic_curve_kernel_2* kernel() const {
return this->ptr()->_m_kernel;
}
private:
/*!\brief
* compares y-coordinates for covertical points \c *this and \c q
*
* \pre x() == q.x()
*/
CGAL::Comparison_result _compare_y_at_x(const Self& q) const
{
CGAL_precondition(this->compare_x(q) == CGAL::EQUAL);
Curve_analysis_2 f = curve(), g = q.curve();
if(f.is_identical(g))
return CGAL::sign(arcno() - q.arcno());
if(Self::_simplify(*this, q))
// restart since supporting curves might be equal now
return _compare_y_at_x(q);
Curve_pair_analysis_2 cpa_2 =
kernel()->construct_curve_pair_2_object()(f, g);
typename Curve_pair_analysis_2::Status_line_1 vline =
cpa_2.status_line_for_x(x());
return CGAL::sign(vline.event_of_curve(arcno(), f) -
vline.event_of_curve(q.arcno(), g));
}
//!@}
public:
//!\name Reconstructing functions
//!@{
/*!\brief
* Simplifies the representation of a point.
*
* Given a decomposition of the point's supporting \c curve() into
* a pair of two curves \c pair, this function searches this point
* in the curve pair and resets the curve and the arcno to this
* found arc. It can happen, that both curves of the pair fit this
* condition (intersection of the two curves at this point), then it
* chooses the simpler one (less total degree).
*
* \pre pair must be a decomposition of curve()
*/
void simplify_by(const Curve_pair_analysis_2& cpa_2) const {
CGAL_precondition_code(
Polynomial_2 mult =
cpa_2.curve_analysis(0).polynomial_2() *
cpa_2.curve_analysis(1).polynomial_2();
);
// common parts
CGAL_precondition(CGAL::resultant(mult,
curve().polynomial_2()).is_zero());
// full parts
CGAL_precondition(CGAL::degree(mult) ==
CGAL::degree(curve().polynomial_2()));
CGAL_precondition(CGAL::total_degree(mult) ==
CGAL::total_degree(curve().polynomial_2()));
typename Curve_pair_analysis_2::Status_line_1 cpv_line =
cpa_2.status_line_for_x(x());
// # of arcs must match
CGAL_precondition_code(
typename Curve_analysis_2::Status_line_1 cv_line =
curve().status_line_for_x(x());
);
CGAL_precondition(cpv_line.number_of_events() ==
cv_line.number_of_events());
bool cid = false;
std::pair<int, int> p = cpv_line.curves_at_event(arcno());
if(p.first != -1 && p.second != -1) {
// both curves involved: choose simpler one
// Remark: In this case, a vertical line in the curves can be
// ignored, since it has not been considered when constructing
// the point from the composed curved (also including this vertical
// line). Therefore, the old arc number is also valid in the curve
// pair.
Polynomial_2 ff = cpa_2.curve_analysis(0).polynomial_2(),
gg = cpa_2.curve_analysis(1).polynomial_2();
if(total_degree(ff) > total_degree(gg))
cid = true;
} else
cid = (p.first == -1);
// overwrite data
this->ptr()->_m_curve = cpa_2.curve_analysis(cid);
this->ptr()->_m_arcno = (cid == 0 ? p.first : p.second);
}
//! befriending output iterator
// friend std::ostream& operator << <>(std::ostream& os, const Self& pt);
//!@}
public:
//! Returns whether the x-coordinate equals zero
bool is_x_zero() const {
return CGAL::is_zero(this->ptr()->_m_x);
}
//! Returns whether the y-coordinate equals zero
bool is_y_zero() const {
CGAL::Sign lower_sign = CGAL::sign(this->lower_bound_y()),
upper_sign = CGAL::sign(this->upper_bound_y());
if( lower_sign == CGAL::ZERO ||upper_sign == CGAL::ZERO) {
if(lower_sign==upper_sign) { //both zero
return true;
} else { // one zero, one not...isol interval is OPEN
return false;
}
} else if( lower_sign==upper_sign) { // zero not in isol interval
return false;
} else { // zero in interval, need to check
Polynomial_1 constant_pol =
CGAL::get_coefficient(curve().primitive_polynomial_2(),0);
bool zero_is_root_of_local_pol
= kernel()->is_zero_at_1_object()(constant_pol,this->ptr()->_m_x);
// Since we know that y_iv is an _isolating_ interval,
// we can immediately return
return zero_is_root_of_local_pol;
}
}
// returns a double approximation of the point
std::pair<double, double> to_double() const {
typedef typename CGAL::Get_arithmetic_kernel<Bound>::Arithmetic_kernel
AT;
typedef typename AT::Bigfloat_interval BFI;
long old_prec = get_precision(BFI());
set_precision (BFI(), 53);
// rely on double conversion of the x-type
double double_x = CGAL::to_double(this->ptr()->_m_x);
double double_y;
if (this->lower_bound_y()==this->upper_bound_y()) {
double_y = CGAL::to_double(convert_to_bfi(this->lower_bound_y()));
} else if(is_y_zero()) {
double_y = 0.;
} else {
while(CGAL::sign(this->lower_bound_y()) !=
CGAL::sign(this->upper_bound_y()) ) {
this->refine_y();
}
long final_prec = set_precision(BFI(),get_precision(BFI())+4);
BFI bfi = CGAL::hull(convert_to_bfi(this->lower_bound_y()),
convert_to_bfi(this->upper_bound_y()));
while( !singleton(bfi) &&
get_significant_bits(bfi) < final_prec ){
this->refine_y();
bfi = CGAL::hull(
convert_to_bfi(this->lower_bound_y()),
convert_to_bfi(this->upper_bound_y()));
}
double_y
= CGAL::to_double((CGAL::lower(bfi)+ CGAL::upper(bfi)) / 2);
}
set_precision(BFI(),old_prec);
return std::make_pair(double_x, double_y);
}
public:
void refine_y() const {
this->curve().status_line_at_exact_x(this->x()).refine(this->arcno());
}
Bound lower_bound_y() const {
return this->curve().status_line_at_exact_x(this->x()).
lower_bound(this->arcno());
}
Bound upper_bound_y() const {
return this->curve().status_line_at_exact_x(this->x()).
upper_bound(this->arcno());
}
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
void refine_x() const {
this->x().refine();
}
Bound lower_bound_x() const {
return this->x().low();
}
Bound upper_bound_x() const {
return this->x().high();
}
#endif
// friend function to provide a fast hashing
friend std::size_t hash_value(const Self& x) {
return static_cast<std::size_t>(x.id());
}
}; // class Xy_coordinate_2
template < class AlgebraicCurveKernel_2, class Rep>
std::ostream& operator<< (std::ostream& os,
const Xy_coordinate_2<AlgebraicCurveKernel_2, Rep>& pt)
{
switch (::CGAL::IO::get_mode(os)) {
case ::CGAL::IO::PRETTY: {
os << "[x-coord: " << CGAL::to_double(pt.x()) << "; curve: " <<
pt.curve().polynomial_2() <<
"; arcno: " << pt.arcno() << "]\n";
break;
}
case ::CGAL::IO::BINARY:
std::cerr << "BINARY format not yet implemented" << std::endl;
break;
default:
// ASCII
os << "Algebraic_real_xca_2(";
os << pt.x();
os << ",";
os << pt.curve();
os << ",";
os << pt.arcno();
os << ")";
}
return os;
}
template < class AlgebraicCurveKernel_2, class Rep_ >
std::istream& operator >> (
std::istream& is,
Xy_coordinate_2< AlgebraicCurveKernel_2, Rep_>& pt) {
CGAL_precondition(CGAL::IO::is_ascii(is));
// this instance's first template argument
typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2;
// this instance's second template argument
typedef Rep_ Rep;
// myself
typedef Xy_coordinate_2< Algebraic_curve_kernel_2, Rep > Xy_coordinate_2;
typedef typename Algebraic_curve_kernel_2::Algebraic_real_1
Algebraic_real_1;
typedef typename Algebraic_curve_kernel_2::Curve_analysis_2
Curve_analysis_2;
// x-coordinate
Algebraic_real_1 x;
// supporting curve
Curve_analysis_2 curve;
// arc number on curve
int arcno;
// read "Algebraic_real_xca_2("
swallow(is, 'A');
swallow(is, 'l');
swallow(is, 'g');
swallow(is, 'e');
swallow(is, 'b');
swallow(is, 'r');
swallow(is, 'a');
swallow(is, 'i');
swallow(is, 'c');
swallow(is, '_');
swallow(is, 'r');
swallow(is, 'e');
swallow(is, 'a');
swallow(is, 'l');
swallow(is, '_');
swallow(is, 'x');
swallow(is, 'c');
swallow(is, 'a');
swallow(is, '_');
swallow(is, '2');
swallow(is, '(');
// read values
is >> x;
swallow(is, ',');
is >> curve;
swallow(is, ',');
is >> arcno;
// read the ")
swallow(is, ')');
pt = Xy_coordinate_2(x, curve, arcno);
return is;
}
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H
@@ -0,0 +1,419 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS
#define CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS 1
#include <iterator>
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/enums.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Algebraic_kernel_d/Float_traits.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/Algebraic_kernel_d/Real_embeddable_extension.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h>
#include <boost/numeric/interval.hpp>
#include <CGAL/Algebraic_kernel_d/bound_between_1.h>
#include <CGAL/Coercion_traits.h>
namespace CGAL {
namespace internal {
/*
* \brief Function for merging two sets
*
* This function is similar to the \c std::union_set operation.
* Additionally, it provides a sequence of CGAL::internal::Three_valued
* providing information to which input set the corresponding root
* in the merged sequence belonged
*
* The BinaryFunction must have the Result type CGAL::Comparison_result.
*/
template<typename BinaryFunction,
typename InputIterator1,typename InputIterator2,
typename OutputIterator1,typename OutputIterator2>
std::pair<OutputIterator1,OutputIterator2>
set_union_with_source(InputIterator1 first_begin,
InputIterator1 first_end,
InputIterator2 second_begin,
InputIterator2 second_end,
OutputIterator1 merged_values,
OutputIterator2 merged_values_info,
BinaryFunction compare) {
InputIterator1 first_it=first_begin;
InputIterator2 second_it=second_begin;
while((first_it != first_end) || (second_it!=second_end)) {
if(first_it == first_end) {
*merged_values=*second_it++;
++merged_values;
*merged_values_info++ = CGAL::internal::ROOT_OF_SECOND_SET;
continue;
}
if(second_it == second_end) {
*merged_values++=*first_it++;
*merged_values_info++ = CGAL::internal::ROOT_OF_FIRST_SET;
continue;
}
CGAL::Comparison_result c = compare(*first_it,*second_it);
if(c==CGAL::EQUAL) {
*merged_values++=*first_it++;
++second_it;
*merged_values_info++ = CGAL::internal::ROOT_OF_BOTH_SETS;
continue;
}
if(c==CGAL::SMALLER) {
*merged_values++=*first_it++;
*merged_values_info++ = CGAL::internal::ROOT_OF_FIRST_SET;
continue;
}
if(c==CGAL::LARGER) {
*merged_values++=*second_it++;
*merged_values_info++ = CGAL::internal::ROOT_OF_SECOND_SET;
continue;
}
}
return std::make_pair(merged_values,merged_values_info);
}
/*
* \brief removes the leading term of the polynomial \c f as long as it
* vanishes at \c alpha
*
*/
template<typename Algebraic_kernel_d_1,typename Poly_2, typename Algebraic_real>
Poly_2 poly_non_vanish_leading_term(Algebraic_kernel_d_1* kernel,
const Poly_2& pol,
Algebraic_real alpha) {
Poly_2 f(pol);
while(true) {
if(kernel->is_zero_at_1_object()
(CGAL::leading_coefficient(f),alpha)) {
typename Poly_2::const_iterator poly_end = f.end();
if(f.begin()==poly_end) {
break;
}
poly_end--;
f=Poly_2(f.begin(),poly_end);
}
else {
break;
}
}
return f;
}
/*!
* \brief finds a Rational value left of an Algebraic real alpha
*/
template<typename AlgebraicKernel_1> typename AlgebraicKernel_1::Bound
bound_left_of(const AlgebraicKernel_1* kernel,
typename AlgebraicKernel_1::Algebraic_real_1 ar) {
typedef AlgebraicKernel_1 Algebraic_kernel_d_1;
typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1;
typedef typename Algebraic_kernel_d_1::Bound Bound;
switch( CGAL::sign( ar ) ) {
case(CGAL::ZERO): {
return Bound(-1);
break;
}
case(CGAL::POSITIVE): {
return Bound(0);
break;
}
case(CGAL::NEGATIVE): {
Algebraic_real_1 small_value
= kernel->construct_algebraic_real_1_object()
(Bound(2)*kernel->approximate_absolute_1_object()(ar,1).first);
return kernel->bound_between_1_object()(small_value,ar);
// = small_value.rational_between(ar);
//= ar.low()-1;
}
}
// never reached
return Bound(0);
}
/*!
* \brief finds a Rational value rightt of an Algebraic real alpha
*/
template<typename AlgebraicKernel_1> typename AlgebraicKernel_1::Bound
bound_right_of(const AlgebraicKernel_1* kernel,
typename AlgebraicKernel_1::Algebraic_real_1 ar) {
return -bound_left_of(kernel,-ar);
}
/*!
* \brief produces intermediate rational values for a list of
* algebraic reals.
*
* For a list of Algebraic real values with \c n elements, a list with
* <tt>n+1</tt> elements of rational values is given such that the
* <tt>i</tt>th element is
* between the <tt>i</tt>th and the <tt>(i+1)</tt>th element of the input list
*
* The input list must be in increasing order
*/
template<typename AlgebraicKernel_1,
typename InputIterator,
typename OutputIterator>
OutputIterator find_intermediate_values(const AlgebraicKernel_1* kernel,
InputIterator start,
InputIterator end,
OutputIterator output) {
CGAL_static_assertion
((::boost::is_same
<typename AlgebraicKernel_1::Algebraic_real_1,
typename std::iterator_traits<InputIterator>::value_type >::value));
typedef typename AlgebraicKernel_1::Bound Bound;
if(start==end) {
// Empty vector, create one element
*output++=Bound(0);
return output;
}
*output++=bound_left_of(kernel,*start);
InputIterator it_1(start),it_2(start);
++it_2;
while(it_2 != end) {
CGAL_assertion(it_1->compare(*it_2)==CGAL::SMALLER);
Bound beta
= kernel->bound_between_1_object()(*it_1,*it_2);
*output++=beta;
++it_1;
++it_2;
}
*output++=bound_right_of(kernel,*it_1);
return output;
}
// Used internally for zero_test_bivariate
namespace for_zero_test_bivariate {
template<typename Poly_coer_1,typename Polynomial_1>
void cast_back_utcf(const Poly_coer_1& p,Polynomial_1& q) {
// We can assume that both template arguments are polynomial types
typedef CGAL::Fraction_traits<Poly_coer_1> FT;
CGAL_static_assertion((::boost::is_same<typename FT::Is_fraction,
CGAL::Tag_true>::value));
typedef typename FT::Numerator_type Numerator;
typedef typename FT::Denominator_type Denominator;
typedef CGAL::Coercion_traits<Numerator,Polynomial_1> Num_coercion;
CGAL_static_assertion((::boost::is_same
<Polynomial_1,
typename Num_coercion::Type>::value));
Numerator p_num;
Denominator p_denom;
typename FT::Decompose()(p,p_num,p_denom);
q = typename Num_coercion::Cast()(p_num);
}
template<typename A> void cast_back_utcf(const A& p, A& q) {
q = p;
}
} // of namespace for_zero_test_bivariate
/*
* \brief Symbolic zero test.
*
* Checks whether <tt>h(x,y(x))=0</tt>, where <tt>y(x)</tt> is a rational
* expression in terms of \c x, i.e. <tt>y=p/q</tt> with <tt>p,q</tt>
* univariate polynomials
*/
template<typename AlgebraicCurveKernel_2>
bool zero_test_bivariate
(const AlgebraicCurveKernel_2* kernel,
const typename AlgebraicCurveKernel_2::Algebraic_real_1& alpha,
const typename AlgebraicCurveKernel_2::Polynomial_2& h,
const typename AlgebraicCurveKernel_2::Polynomial_1& p,
const typename AlgebraicCurveKernel_2::Polynomial_1& q) {
bool result;
typedef typename AlgebraicCurveKernel_2::Polynomial_1 Polynomial_1;
#if !CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT
//typedef typename AlgebraicCurveKernel_2::Algebraic_real_1 Algebraic_real_1;
typedef typename AlgebraicCurveKernel_2::Bound Bound;
typedef typename AlgebraicCurveKernel_2::Coefficient Coefficient;
typedef typename AlgebraicCurveKernel_2::Polynomial_2 Polynomial_2;
typedef CGAL::Coercion_traits<Bound,Coefficient> Coercion;
typedef typename Coercion::Type Coercion_type;
typedef typename CGAL::Polynomial_traits_d<Polynomial_2>
::template Rebind<Coercion_type,1>::Other::Type Poly_coer_1;
typename Coercion::Cast cast;
bool general = ! alpha.is_rational();
Poly_coer_1 p_rat = typename CGAL::Polynomial_traits_d<Poly_coer_1>
::Construct_polynomial()
(boost::make_transform_iterator
(p.begin(),cast),
boost::make_transform_iterator
(p.end(),cast));
Poly_coer_1 q_rat = typename CGAL::Polynomial_traits_d<Poly_coer_1>
::Construct_polynomial()
(boost::make_transform_iterator
(q.begin(),cast),
boost::make_transform_iterator
(q.end(),cast));
if(general) {
Poly_coer_1 modulus = typename CGAL::Polynomial_traits_d<Poly_coer_1>
::Construct_polynomial()
(boost::make_transform_iterator
(alpha.polynomial().begin(),cast),
boost::make_transform_iterator
(alpha.polynomial().end(),cast));
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "Mod: " << modulus << std::endl;
#endif
*/
p_rat=CGAL::mod(p_rat,modulus);
q_rat=CGAL::mod(q_rat,modulus);
int n = CGAL::degree(h,1);
// Create the powers of p and q mod modulus
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "precomp powers.." << std::flush;
#endif
*/
std::vector<Poly_coer_1> p_powers(n+1),q_powers(n+1);
p_powers[0]=Poly_coer_1(Bound(1));
q_powers[0]=Poly_coer_1(Bound(1));
Poly_coer_1 intermediate;
for(int i=1;i<=n;i++) {
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << i << ": mult.." << std::flush;
#endif
*/
intermediate=p_powers[i-1]*p_rat;
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "mod.." << std::flush;
#endif
*/
p_powers[i]=CGAL::mod(intermediate,modulus);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "simpl.." << std::flush;
#endif
*/
p_powers[i].simplify_coefficients();
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "mult.." << std::flush;
#endif
*/
intermediate=q_powers[i-1]*q_rat;
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "mod.." << std::flush;
#endif
*/
q_powers[i]=CGAL::mod(intermediate,modulus);
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "simpl.." << std::flush;
#endif
*/
q_powers[i].simplify_coefficients();
}
/*
#if CGAL_ACK_DEBUG_FLAG
CGAL_ACK_DEBUG_PRINT << "done\ncomp rat pol.." << std::flush;
#endif
*/
Poly_coer_1 curr_coeff,curr_fac;
Poly_coer_1 h_0_rat(Coercion_type(0));
for(int i=0;i<=n;i++) {
Poly_coer_1 tmp_pol = typename CGAL::Polynomial_traits_d<Poly_coer_1>
::Construct_polynomial()
(boost::make_transform_iterator
(h[i].begin(),cast),
boost::make_transform_iterator
(h[i].end(),cast));
curr_fac=CGAL::mod
(tmp_pol*p_powers[i]*q_powers[n-i], modulus);
h_0_rat+=curr_fac;
}
Polynomial_1 h_0_utcf;
for_zero_test_bivariate::cast_back_utcf(h_0_rat,h_0_utcf);
return kernel->is_zero_at_1_object() (h_0_utcf,alpha);
}
else {
Coercion_type b = cast(alpha.rational()),
p_b=CGAL::evaluate(p_rat,b),q_b=CGAL::evaluate(q_rat,b);
int n = CGAL::degree(h,1);
Coercion_type eval(0);
for(int i=0;i<=n;i++) {
Poly_coer_1 h_i_rat = typename CGAL::Polynomial_traits_d<Poly_coer_1>
::Construct_polynomial()
(boost::make_transform_iterator
(CGAL::get_coefficient(h,i).begin(),cast),
boost::make_transform_iterator
(CGAL::get_coefficient(h,i).end(),cast));
eval+=CGAL::evaluate(h_i_rat,b)
*CGAL::ipower(p_b,i)*CGAL::ipower(q_b,n-i);
}
result=(CGAL::sign(eval)==CGAL::ZERO);
}
#else
#warning Uses no reduction modulo resultant!
Polynomial_1 h_0=CGAL::evaluate_homogeneous(h,p,q);
result= kernel->is_zero_at_1_object() (h_0,alpha);
#endif
return result;
}
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS
@@ -0,0 +1,259 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_BOUND_BETWEEN_1_H
#define CGAL_BOUND_BETWEEN_1_H 1
#include <iterator>
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/enums.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Algebraic_kernel_d/Float_traits.h>
#include <CGAL/convert_to_bfi.h>
#include <CGAL/Algebraic_kernel_d/Real_embeddable_extension.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h>
#include <CGAL/Bigfloat_interval_traits.h>
#include <boost/numeric/interval.hpp>
#include <CGAL/Coercion_traits.h>
namespace CGAL {
namespace internal {
/*! \brief tries to find a SIMPLE rational q with a<q<b.
*
* In this context, simple means that the denominator of <tt>q</tt>
* is a power of two, and is not too big. There is no guarantee to find
* the rational value between <tt>a</tt> and <tt>b</tt> of minimal
* bit size.
*/
template<typename Algebraic_real>
typename Algebraic_real::Rational
simple_bound_between(const Algebraic_real& a,
const Algebraic_real&b) {
//srb.start();
typedef typename Algebraic_real::Rational Rational;
typename CGAL::Fraction_traits<Rational>::Compose compose;
typedef typename
CGAL::Get_arithmetic_kernel<Rational>::Arithmetic_kernel AK;
typedef typename AK::Bigfloat_interval Bigfloat_interval;
typedef typename CGAL::Bigfloat_interval_traits<Bigfloat_interval>
::Bound Bigfloat;
typedef typename AK::Integer Integer;
long old_prec = CGAL::get_precision(Bigfloat_interval());
CGAL_assertion(a!=b);
if(a>b) {
return simple_bound_between(b,a);
}
//std::cout << "Intermediate1: " << CGAL::to_double(a) << " " << CGAL::to_double(b) << std::endl;
/*
* First, refine a and b until their isolating intervals are disjoint
* Therefore, the bigger interval is refined in each substep
*/
//srb_a.start();
if(a.high() >= b.low()) {
Rational size_a=a.high()-a.low(),
size_b=b.high() - b.low();
while(a.high() >= b.low()) {
if(size_a < size_b) {
b.refine();
size_b=b.high() - b.low();
} else {
a.refine();
size_a=a.high()-a.low();
}
}
}
//srb_a.stop();
//srb_b.start();
Bigfloat x=CGAL::upper(CGAL::convert_to_bfi(a.high()));
Bigfloat y=CGAL::lower(CGAL::convert_to_bfi(b.low()));
if(x>=y) {
Rational size_a=a.high() - a.low(),
size_b=b.high() - b.low(),
size_max = size_a>size_b ? size_a : size_b,
size_int = b.low()-a.high();
while(x>=y) {
//std::cout << "x and y: " << x << " and " << y << std::endl;
//std::cout << "sizes: " << CGAL::to_double(size_int) << " " << CGAL::to_double(size_max) << std::endl;
if(size_int>size_max) {
CGAL::set_precision(Bigfloat_interval(),
2*CGAL::get_precision(Bigfloat_interval()));
x=CGAL::upper(CGAL::convert_to_bfi(a.high()));
y=CGAL::lower(CGAL::convert_to_bfi(b.low()));
} else {
if(size_a < size_b) {
b.refine();
size_b=b.high() - b.low();
y=CGAL::lower(CGAL::convert_to_bfi(b.low()));
} else {
a.refine();
size_a=a.high()-a.low();
x=CGAL::upper(CGAL::convert_to_bfi(a.high()));
}
size_max = size_a>size_b ? size_a : size_b;
size_int = b.low()-a.high();
}
}
}
CGAL_assertion(x<y);
//srb_b.stop();
//std::cout << "Intermediate2: " << x << " " << y << std::endl;
typename CGAL::internal::Float_traits<Bigfloat>::Get_mantissa mantissa;
typename CGAL::internal::Float_traits<Bigfloat>::Get_exponent exponent;
// std::cout << CGAL::to_double(x) << " < " << CGAL::to_double(y) << std::endl;
Integer x_m = mantissa(x), y_m=mantissa(y);
long x_e = exponent(x), y_e = exponent(y);
//std::cout << "Floats1: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl;
if (((x_m > 0) && (y_m < 0)) || ((x_m < 0) && (y_m > 0))) {
//srb.stop();
return Rational(0);
}
bool negative=false;
if(x_m<=0 && y_m <=0) {
x_m=-x_m;
y_m=-y_m;
std::swap(x_m,y_m);
std::swap(x_e,y_e);
negative=true;
}
// Now, we have that (x_m,x_e) represents a number smaller than (y_m,y_e)
//srb_c.start();
//std::cout << "Floats2: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl;
// As long as the mantissa is even, simplify
while(x_m != 0 && (x_m & 1)==0 ) {
x_m=x_m >> 1;
x_e++;
}
while(y_m != 0 && (y_m & 1)==0 ) {
y_m=y_m >> 1;
y_e++;
}
//srb_c.stop();
//std::cout << "Floats3: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl;
// Bring both numbers to a common exponent
//srb_d.start();
long min_e = x_e < y_e ? x_e : y_e;
while(x_e > min_e) {
x_m=x_m << 1;
x_e--;
}
while(y_e > min_e) {
y_m=y_m << 1;
y_e--;
}
//srb_d.stop();
CGAL_assertion(y_e==x_e && x_e==min_e);
CGAL_assertion(x_m < y_m);
//std::cout << "Floats4: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl;
// Avoid mantissas to have difference one
if(y_m-x_m==Integer(1)) {
x_m=x_m << 1;
y_m=y_m << 1;
x_e--;
y_e--;
min_e--;
}
//std::cout << "Floats5: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl;
Integer final_mantissa(0);
//srb_e.start();
long x_log = x_m==Integer(0) ? -1 : CGAL::internal::floor_log2_abs(x_m),
y_log = y_m==Integer(0) ? -1 : CGAL::internal::floor_log2_abs(y_m),
old_log = y_log;
//std::cout << x_log << " < " << y_log << std::endl;
while(x_log==y_log) {
//std::cout << "here" << std::endl;
while(old_log > y_log) {
final_mantissa = final_mantissa << 1;
old_log--;
}
CGAL_assertion((x_m & ((Integer(1) << x_log) - 1)) == x_m - CGAL::ipower(Integer(2),x_log));
x_m = x_m & ((Integer(1) << x_log) - 1); // x_m - CGAL::ipower(Integer(2),x_log);
y_m = y_m & ((Integer(1) << y_log) - 1); // y_m - CGAL::ipower(Integer(2),y_log);
final_mantissa++;
old_log=y_log;
x_log = x_m==0 ? -1 : CGAL::internal::floor_log2_abs(x_m);
y_log = y_m==0 ? -1 : CGAL::internal::floor_log2_abs(y_m);
}
//srb_e.stop();
// Now, x_log != y_log, in fact, y_log is greater
CGAL_assertion(x_log<y_log);
//srb_f.start();
while(old_log > y_log) {
final_mantissa = final_mantissa << 1;
old_log--;
}
if((y_m & ((Integer(1) << y_log) - 1 ))==0) { // y_m - CGAL::ipower(Integer(2),y_log)==0) {
// Now, the constructed value would be equal to
while(y_log!=0 && x_log==y_log-1) {
final_mantissa = final_mantissa << 1;
final_mantissa++;
y_log--;
x_m = x_m==0 ? 0 : x_m & ((Integer(1) << x_log) - 1); //x_m - CGAL::ipower(Integer(2),x_log);
x_log = x_m==0 ? -1 : CGAL::internal::floor_log2_abs(x_m);
}
final_mantissa = final_mantissa << 1;
final_mantissa++;
y_log--;
} else {
final_mantissa++;
}
//srb_f.stop();
min_e += y_log;
Rational rat_between;
//std::cout << "Min_e: " << min_e << std::endl;
if(min_e > 0) {
rat_between = compose(final_mantissa << min_e,
Integer(1));
} else {
rat_between = compose(final_mantissa, Integer(1) << -min_e);
}
if(negative) {
rat_between = -rat_between;
}
//std::cout << "Result: " << a.high() << " " << rat_between << " " << b.low() << std::endl;
CGAL_assertion(a.high() < rat_between);
CGAL_assertion(b.low() > rat_between);
CGAL::set_precision(Bigfloat_interval(),old_prec);
//srb.stop();
return rat_between;
}
} // namespace internal
} //namespace CGAL
#endif // CGAL_BOUND_BETWEEN_1_H
@@ -0,0 +1,133 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H
#define CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H
#include <CGAL/basic.h>
#include <CGAL/ipower.h>
#ifdef CGAL_USE_LEDA
#include <CGAL/leda_integer.h>
#include <CGAL/leda_rational.h>
#endif
#ifdef CGAL_USE_CORE
#include <CGAL/CORE_BigInt.h>
#include <CGAL/CORE_BigRat.h>
#endif
#include <limits>
namespace CGAL {
namespace internal {
// Generic construct_binary function, using ipower
template< class Integer >
inline void construct_binary( const Integer& e, Integer& x ) {
CGAL_precondition( e >= 0 );
Integer exponent(e);
x = Integer(1);
const Integer max_ipower = (exponent > Integer((std::numeric_limits<int>::max)())) ?
CGAL::ipower( Integer(2), (std::numeric_limits<int>::max)() ) :
Integer(0);
while( exponent > Integer((std::numeric_limits<int>::max)()) ) {
x *= max_ipower;
exponent -= Integer((std::numeric_limits<int>::max)());
}
x *= CGAL::ipower( Integer(2), (int)CGAL::to_double(exponent) );
}
template< class Integer, class Rational >
inline void construct_binary( const Integer& m, const Integer& e, Rational& x ) {
Integer den(1), num;
if(e>0) {
construct_binary( e, num );
num *= m;
}
else {
num = m;
construct_binary( -e, den );
}
x = Rational(num, den);
}
// Specialization for LEDA
#ifdef CGAL_USE_LEDA
// Constructs 2^e from an integer e. Needed in Descartes
inline void construct_binary(const ::leda::integer& e, ::leda::integer& x) {
typedef ::leda::integer Integer;
x = Integer(1) << e.to_long();
}
// Constructs m*2^e from two integers m,e. Needed in Descartes
inline void construct_binary(const ::leda::integer& m, const ::leda::integer& e,
::leda::rational& x) {
typedef ::leda::integer Integer;
typedef ::leda::rational Rational;
Integer den(1);
Integer num(m);
if(e>0) {
num <<= e.to_long();
}
else {
den <<= (-e).to_long();
}
x = Rational(num, den);
}
#endif // CGAL_USE_LEDA
// Specialization for CORE
#ifdef CGAL_USE_CORE
// Constructs 2^e from an integer e. Needed in Descartes
inline void construct_binary(const ::CORE::BigInt& e, ::CORE::BigInt& x) {
typedef ::CORE::BigInt Integer;
x = Integer(1) << ::CORE::ulongValue(e);
}
// Constructs m*2^e from two integers m,e. Needed in Descardes
inline void construct_binary(const ::CORE::BigInt& m, const ::CORE::BigInt& e,
::CORE::BigRat& x) {
typedef ::CORE::BigInt Integer;
typedef ::CORE::BigRat Rational;
Integer den(1);
Integer num(m);
if(e>0) {
num <<= ::CORE::ulongValue(e);
}
else {
den <<= ::CORE::ulongValue(-e);
}
x = Rational(num, den);
}
#endif // CGAL_USE_CORE
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H
@@ -0,0 +1,49 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_ENUMS_H
#define CGAL_ACK_ENUMS_H 1
namespace CGAL {
namespace internal {
enum Three_valued {
ROOT_OF_FIRST_SET = 1,
ROOT_OF_BOTH_SETS = 0,
ROOT_OF_SECOND_SET=-1
};
} // namespace internal
/*!
* \brief represents different strategies how to handle
* degenerate cases during the analysis
*
* Currently, there are two possible strategies implemented. See the
* constructor of \c Curve_analysis_2 for more details.
*/
enum Degeneracy_strategy {
SHEAR_STRATEGY = 0,
EXCEPTION_STRATEGY = 1,
SHEAR_ONLY_AT_IRRATIONAL_STRATEGY = 2
};
} //namespace CGAL
#endif
@@ -0,0 +1,69 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_KERNEL_EXCEPTIONS_H
#define CGAL_ALGEBRAIC_KERNEL_EXCEPTIONS_H
namespace CGAL {
namespace internal {
/*!
* \brief Exception class for not sufficiently generic positions.
*
* Must be thrown whenever a curve cannot be analysed because its position
* is not "good enough".
*/
class Non_generic_position_exception {
public:
//! Default constructible
Non_generic_position_exception() {}
};
/*!
* \brief Exception class for not sufficiently generic positions.
*
* Must be thrown whenever a curve cannot be analysed because its position
* is not "good enough".
*/
template<typename Polynomial>
class Zero_resultant_exception {
Polynomial curve1,curve2;
bool one_curve_failure;
public:
Zero_resultant_exception(Polynomial c)
: curve1(c), curve2(c),one_curve_failure(true)
{}
Zero_resultant_exception(Polynomial c1,Polynomial c2)
: curve1(c1),curve2(c2),one_curve_failure(false)
{}
};
} // namespace internal
} //namespace CGAL
#endif
@@ -0,0 +1,208 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_FLAGS_H
#define CGAL_ACK_FLAGS_H 1
// TODO: use new interface and remove this flag
#ifndef CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 0
#endif
// Is debug-information printed?
#ifndef CGAL_ACK_DEBUG_FLAG
#define CGAL_ACK_DEBUG_FLAG 0
#endif
// If CGAL_ACK_DEBUG_FLAG is set, which output stream is used for debug?
#ifndef CGAL_ACK_DEBUG_PRINT
#define CGAL_ACK_DEBUG_PRINT std::cout
#endif
// If enabled, needs includes from experimental package
#ifndef CGAL_ACK_WITH_FILTERED_KERNEL
#define CGAL_ACK_WITH_FILTERED_KERNEL 0
#endif
// If enabled, needs includes from experimental package
#ifndef CGAL_ACK_WITH_ROTATIONS
#define CGAL_ACK_WITH_ROTATIONS 0
#endif
/**
* The threshold that is used in the Filtered_algebraic_curve_kernel_2
*/
#ifndef CGAL_ACK_THRESHOLD_FOR_FILTERED_KERNEL
#define CGAL_ACK_THRESHOLD_FOR_FILTERED_KERNEL 0.01
#endif
/**
* For random choices in the algorithm, this seed is used
* If set to zero, a random seed is used
*/
#ifndef CGAL_ACK_STATIC_SEED
#define CGAL_ACK_STATIC_SEED 0
#endif
/**
* Allows to use the Bitstream tree described in Eigenwillig's thesis
*/
#ifndef CGAL_ACK_BITSTREAM_USES_E08_TREE
#define CGAL_ACK_BITSTREAM_USES_E08_TREE 1
#endif
/**
* If set, the program uses the AlciX-code
* for the curve- and curve-pair-analysis.
* This flag is only for debugging purposes.
*/
#ifndef CGAL_ACK_USE_EXACUS
#define CGAL_ACK_USE_EXACUS 0
#endif
/**
* If set, the curve and curve pair analysis are using specialized code
* to analyse conic curves, i.e. curves of degree 2
*/
#ifndef CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX
#define CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX 0
#endif
/**
* The curve analysis does not distinguish between "(1,1)-singularities"
* (i.e., vertical cusps, isolated points on arcs), and usual regular points.
* The candidate point on each status line can be checked for being singular
* using this flag. This gives additional information but increases
* compuation time
*
* WARNING: Currently, the status line does not store the additional
* information whether a point is singluar or not.
* Therefore, there is currently no reasons to set this flag. It is still
* contained for possible further extension of the status line.
*/
#ifndef CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY
#define CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY 0
#endif
/**
* If set to 1, curve pairs are not checked for coprimality. Only do this
* if you know what you are doing!
*/
#ifndef CGAL_ACK_DONT_CHECK_POLYNOMIALS_FOR_COPRIMALITY
#define CGAL_ACK_DONT_CHECK_POLYNOMIALS_FOR_COPRIMALITY 0
#endif
/**
* The "resultant first" strategy means: instead of computing the full
* subresultant sequence (or Sturm-Habicht sequence), the algorithm
* only computed the resultant in a first step. This suffices already for
* many curves (i.e., regular ones). The full subresultant is computed
* if it is needed for the first time.
*
* This strategy only makes sense if computing resultants is faster than
* computing subresultants, otherwise, it wastes computation time.
* Since resultant computation is done by interpolation,
* it is faster than the pseudo-remainder based subresultant computation.
*/
#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY
#define CGAL_ACK_RESULTANT_FIRST_STRATEGY 1
#endif
/**
* If CGAL_ACK_RESULTANT_FIRST_STRATEGY is set, this flag determines
* for which curves the "resultant first" strategy is used. Depending
* on the resultant algorithm, the strategy might only be advantageous
* for higher degree curves
*
* If CGAL_ACK_RESULTANT_FIRST_STRATEGY is not set, this flag has no effect
*/
#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD
#define CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD 0
#endif
/**
* Subresultants can be computed by a polynomial remainder sequence (default),
* or by evaluating minors of the bezout matrix by setting this flag.
* Tests have shown that the polynomial remainder sequence is more efficient
* so it is not recommended to set this flag.
*/
#ifndef CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS
#define CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS 0
#endif
/**
* Allows to switch off the specialized method for Status_line_CPA_1
* if multiplicity is zero or one.
* Since this methods improves the performance,
* it is not recommended to set this flag unless for testing
*/
#ifndef ACK_CGAL_NO_ARC_FLIP
#define ACK_CGAL_NO_ARC_FLIP 0
#endif
/**
* This flags defines the default strategy to handle degenerate curves
* There are three choices currently available:
* SHEAR_STRATEGY performs a shear whenever a degenerate situation occurs.
* SHEAR_ONLY_AT_IRRATIONAL_STRATEGY handles rational coordinates with
* a more direct method, but performs a shear for irrational x-coordinates
* that have a degeneracy. Finally, EXCEPTION_STRATEGY throws an exception
* whenever a degeneracy occurs.
*/
#ifndef CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY
//#define CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY
#define CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY CGAL::SHEAR_STRATEGY
#endif
/**
* The algorithm can also handle non-y-regular curves without shearing,
* in case that the resultant multiplicity at vertical asymptotes is one.
* This special treatement can be switched off by setting this flag.
* It is not recommended to do this because of efficiency
*/
#ifndef CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES
#define CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES 0
#endif
/**
* At some points in the algorithm, it is checked whether a polynomial
* H(x):=h(p(x),q(x)) vanishes for an algebraic number x_0 with polynomial r.
* For that check, the computation of H is done modulo r for efficiency.
* This can be switched off by this flag, though it is recommended not to
* do so.
*/
#ifndef CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT
#define CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT 0
#endif
#ifndef CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN
#define CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN 0
#endif
/**
* These flags are experimental, concerning interval arithmetic methods
* Don't change them!
*/
#ifndef CGAL_ACK_USE_DERIVATIVE_OPTION
#define CGAL_ACK_USE_DERIVATIVE_OPTION 0
#endif
#ifndef CGAL_ACK_USE_BISECTION_OPTION
#define CGAL_ACK_USE_BISECTION_OPTION 0
#endif
#endif // CGAL_ACK_FLAGS_H
@@ -0,0 +1,74 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Eric Berberich <eric@mpi-inf.mpg.de>
// Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_MACROS_H
#define CGAL_ACK_MACROS_H 1
/*!\file include/CGAL/Algebraic_kernel_d/macros.d
* \brief Macro definitions wrt algebraic kernels
*/
#include <CGAL/config.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Polynomial.h>
#include <CGAL/Sqrt_extension.h>
namespace CGAL {
#define CGAL_ACK_SNAP_ALGEBRAIC_CURVE_KERNEL_2_TYPEDEFS(Curve_analysis_2) \
typedef typename Algebraic_kernel_with_analysis_2::Coefficient Coefficient; \
typedef typename Algebraic_kernel_with_analysis_2::Bound Bound; \
typedef typename CGAL::Get_arithmetic_kernel<Bound> \
::Arithmetic_kernel Arithmetic_kernel; \
typedef typename Arithmetic_kernel::Integer Integer; \
typedef typename Algebraic_kernel_with_analysis_2::Algebraic_real_1 Algebraic_real_1; \
typedef typename Algebraic_kernel_with_analysis_2::Polynomial_1 Polynomial_1; \
typedef typename Algebraic_kernel_with_analysis_2::Polynomial_2 Polynomial_2; \
typedef typename Algebraic_kernel_with_analysis_2::Solve_1 Solve_1; \
typedef CGAL::internal::Bitstream_coefficient_kernel_at_alpha \
< Algebraic_kernel_with_analysis_2 > Bitstream_coefficient_kernel; \
typedef CGAL::internal::Bitstream_descartes_rndl_tree_traits \
< Bitstream_coefficient_kernel > Bitstream_traits; \
typedef CGAL::internal::Bitstream_descartes<Bitstream_traits> \
Bitstream_descartes; \
typedef CGAL::internal::Status_line_CA_1< Algebraic_kernel_with_analysis_2 > \
Status_line_1 \
#define CGAL_SNAP_AK_3_TYPEDEFS(Arithmetic_kernel) \
CGAL_SNAP_ARITHMETIC_KERNEL_TYPEDEFS(Arithmetic_kernel); \
typedef CGAL::Polynomial< Integer > Poly_int1; \
typedef CGAL::Polynomial< Poly_int1 > Poly_int2; \
typedef CGAL::Polynomial< Poly_int2 > Poly_int3; \
typedef CGAL::Polynomial< Rational > Poly_rat1; \
typedef CGAL::Polynomial< Poly_rat1 > Poly_rat2; \
typedef CGAL::Polynomial< Poly_rat2 > Poly_rat3; \
typedef CGAL::Sqrt_extension< Rational, Integer > Extn; \
typedef CGAL::Sqrt_extension< Extn, Extn > Nested_extn; \
typedef CGAL::Polynomial< Extn > Poly_extn1; \
typedef CGAL::Polynomial< Poly_extn1 > Poly_extn2; \
typedef CGAL::Polynomial< Poly_extn2 > Poly_extn3; \
typedef CGAL::Polynomial< Nested_extn > Poly_nested_extn1; \
typedef CGAL::Polynomial< Poly_nested_extn1 > Poly_nested_extn2; \
typedef CGAL::Polynomial< Poly_nested_extn2 > Poly_nested_extn3 \
// end #define CGAL_SNAP_AK_3_TYPEDEFS(AT)
} //namespace CGAL
#endif //CGAL_ACK_MACROS_H
// EOF
@@ -0,0 +1,205 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
#ifndef CGAL_REFINE_ZERO_AGAINST_H
#define CGAL_REFINE_ZERO_AGAINST_H
#include <CGAL/basic.h>
#include <CGAL/Polynomial.h>
namespace CGAL {
namespace internal {
/* computes an upper bound on the number of roots ]low,high[ using Descartes'
* Sign Rule
*/
template <class Polynomial, class Field>
int descartes(Polynomial& p, const Field& low,const Field& high){
// decompose interval length and upper bound
CGAL_precondition(low<high);
typedef typename Polynomial::NT Coefficient;
typedef typename Fraction_traits<Field>::Numerator_type Numerator;
typedef typename Fraction_traits<Field>::Denominator_type Denominator;
typename Fraction_traits<Field>::Decompose decomp;
//typename Algebraic_structure_traits<Field>::Simplify simplify;
//simplify(low);
//simplify(high);
Numerator num_high, num_low_sub_high;
Denominator den_high, den_low_sub_high;
decomp(high, num_high, den_high);
decomp(low - high, num_low_sub_high, den_low_sub_high);
Coefficient tmp(num_high);
// apply Descartes' rule to count zeros of q in ]low,high[
Polynomial transf = // q(high + (low-high)/(1+x))
CGAL::translate_by_one(
CGAL::reversal(
CGAL::scale_homogeneous(
CGAL::translate_homogeneous(p
,Coefficient(num_high)
,Coefficient(den_high))
,Coefficient(num_low_sub_high)
,Coefficient(den_low_sub_high)
)
)
);
return sign_variations(transf);
}
/*! \ingroup \NiX_univariate_polynomial_utils
* \brief refine isolating interval for \c p w.r.t \c q
*
* This function refines the interval ]<TT>low</TT>, <TT>high</TT>[
* such that it does not contain any zero of \c q different from the
* unique zero of \c p in ]<TT>low</TT>, <TT>high</TT>[. It is returned
* whether \c q has a zero in ]<TT>low</TT>, <TT>high</TT>[ equal to
* that of \c p . Note that zeroes of \c q at the boundaries are
* ignored.
*
* This function is implemented using bisection and Descartes' Rule.
* If the interval boundaries have denominators 2<SUP>k</SUP>, then
* this property will still hold after refinement. Although this
* function works similar to \c NiX::Algebraic_real<>.compare() ,
* it is different insofar that it always maintains an open interval
* and never simplifies.
*
* \pre Both polynomials must be square-free. \c p must not vanish at the
* interval boundaries \c low and \c high .
*
* \todo Provide a means to let an \c NiX::Algebraic_real benefit
* from the interval refinement if it is the origin of the respective
* input data.
*/
template <class Polynomial, class Field>
bool refine_zero_against(Field& low, Field& high, Polynomial p, Polynomial q) {
typename Algebraic_structure_traits<Field>::Simplify simplify;
CGAL_precondition(low < high);
CGAL_precondition(CGAL::degree(p) > 0);
CGAL_precondition((CGAL::degree(q) >= 0) && !q.is_zero());
if (CGAL::degree(q) == 0) return false;
CGAL::Sign sign_p_low = p.sign_at(low);
CGAL::Sign sign_p_high = p.sign_at(high);
CGAL_precondition(sign_p_low != CGAL::ZERO);
CGAL_precondition(sign_p_high != CGAL::ZERO);
CGAL_precondition(sign_p_high != sign_p_low);
Polynomial gcd_pq; // computed below if necessary
for (;;) {
int sv = internal::descartes(q,low,high);
CGAL_assertion(sv >= 0);
if (sv == 0) {
// q has no zero in ]low,high[
return false;
} else if (sv == 1) {
if (CGAL::degree(gcd_pq) < 0) {
if (may_have_common_factor(p, q)) {
gcd_pq = gcd_utcf(p, q);
} else {
gcd_pq = Polynomial(1);
}
}
std::cout << CGAL::to_double(low) << " "
<< CGAL::to_double(high) << " "
<< CGAL::degree(gcd_pq) << " "
<< gcd_pq
<< std::endl;
if (CGAL::degree(gcd_pq) > 0 // constant poly cannot change sign
&& gcd_pq.sign_at(low) != gcd_pq.sign_at(high)) {
// q has exactly one zero in ]low,high[
// and it's equal to that of p
return true;
}
}
// q may have a zero in ]low,high[ not equal to that of p
Field mid = (low+high)/Field(2);
CGAL::Sign s = p.sign_at(mid);
if (s == CGAL::ZERO) {
mid = (low+mid)/Field(2);
simplify(mid);
s = p.sign_at(mid);
}
CGAL_postcondition(s != CGAL::ZERO);
if (s == sign_p_low) {
low = mid;
sign_p_low = s;
} else {
CGAL_postcondition(s == sign_p_high);
high = mid;
sign_p_high = s;
}
}
}
// Uses refine_zero_against first and refines the interval further, if any
// of the interval boarders has sign zero.
template < class Polynomial, class Field >
static bool strong_refine_zero_against(Field& low, Field& high,
Polynomial p, Polynomial q){
std::cout << "comp has_common_root" << std::endl;
bool has_common_root = refine_zero_against(low,high,p,q);
std::cout << "done, " << has_common_root << std::endl;
CGAL::Sign sign_p_low = p.sign_at(low);
CGAL::Sign sign_p_high = p.sign_at(high);
Field mid;
CGAL::Sign s;
while ((q.sign_at(low)==CGAL::ZERO)||(q.sign_at(high)==CGAL::ZERO)) {
mid = (low+high)/Field(2);
simplify(mid);
s = p.sign_at(mid);
if (s == CGAL::ZERO) {
mid = (low+mid)/Field(2);
simplify(mid);
s = p.sign_at(mid);
}
CGAL_postcondition(s != CGAL::ZERO);
if (s == sign_p_low) {
low = mid;
sign_p_low = s; //bogus?
}
else {
CGAL_assertion(s == sign_p_high);
high = mid;
sign_p_high = s; //bogus?
}
}
return has_common_root;
}
} //namespace internal
} //namespace CGAL
#endif //CGAL_REFINE_ZERO_AGAINST_H
@@ -0,0 +1,62 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ACK_SHEAR_H
#define CGAL_ACK_SHEAR_H 1
#include <CGAL/basic.h>
#include <CGAL/Polynomial_traits_d.h>
#include <utility>
#include <vector>
#include <functional>
#include <iterator>
#include <CGAL/boost/iterator/transform_iterator.hpp>
#include <CGAL/boost/iterator/counting_iterator.hpp>
namespace CGAL {
namespace internal {
/*! \ingroup NiX_bivariate_polynomial_hacks
* \brief Computes the polynomial f(x+sy,y)
*/
template<class NT>
CGAL::Polynomial<CGAL::Polynomial<NT> >
shear(const CGAL::Polynomial<CGAL::Polynomial<NT> >& f,NT s) {
typedef CGAL::Polynomial<NT> Poly_1;
typedef CGAL::Polynomial<Poly_1> Poly_2;
Poly_1 x(NT(0),NT(1));
Poly_1 zero(NT(0));
Poly_1 one(NT(1));
Poly_2 for_x(x,Poly_1(NT(s)));
Poly_2 for_y(zero,one);
std::vector<Poly_2> coeffs;
coeffs.push_back(for_x);
coeffs.push_back(for_y);
return typename CGAL::Polynomial_traits_d<Poly_2>::Substitute()
(f,coeffs.begin(), coeffs.end());
}
} // namespace internal
} //namespace CGAL
#endif // NiX_BIVARIATE_POLYNOMIAL_HACKS_H
// EOF
@@ -0,0 +1,99 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
#ifndef CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H
#define CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H
#include <CGAL/Polynomial.h>
namespace CGAL {
namespace internal {
//! return an upper bound on the absolute value of all real roots of \c P.
/*! The upper bound is a power of two. Only works for univariate polynomials.
* \pre \c NT must be \c RealComparable.
* \relates CGAL::Polynomial
*/
template <class NT>
NT weak_upper_root_bound(const Polynomial<NT>& P) {
// code comes from Kurt Mehlhorn
// see [Mignotte, 1992], p.144 for a proof
CGAL_precondition(Polynomial_traits_d<NT>::d == 0);
typename Real_embeddable_traits<NT>::Abs abs;
const int n = CGAL::degree(P);
NT x(1);
NT val;
for (;;) {
val = -abs(P[n]);
for (int i = n-1; i >= 0; i--) {
val = val*x + abs(P[i]);
}
if (val < NT(0)) return x;
x *= NT(2);
}
}
//! return the number of sign variations in the coefficient sequence of \c P.
/*! This is the number of sign changes (+ to - or - to +) in the
* coefficient sequence of the polynomial, ignoring zeroes.
* Only meaningful for univariate polynomials.
* \pre \c NT must be \c RealComparable.
* \relates CGAL::Polynomial
*/
template <class NT>
int sign_variations(const Polynomial<NT>& P) {
const int n = CGAL::degree(P);
int variations = 0;
int old_sign = CGAL::sign(P[n]); // never zero unless P is zero
for (int i = n-1; i >= 0; i--) {
int s = CGAL::sign(P[i]);
if (s == 0) continue;
if (old_sign != s) {
old_sign = s;
variations++;
}
}
return variations;
}
/*! \ingroup CGAL_polynomial_utils
* \brief checks whether a univariate polynomial is square-free
*/
/*template < class NT >
bool is_square_free(const Polynomial<NT>& p) {
if( may_have_multiple_factor(p) ) {
Polynomial<NT> d = p; d.diff();
return CGAL::degree(gcd_utcf(p, d)) == 0;
} else {
return true;
}
}
template< class NT >
bool is_square_free( const Polynomail< Polynomial< NT > >& ) {
return true;
} */
} // namespace internal
} //namespace CGAL
#endif // CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H
@@ -0,0 +1,671 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
// Sebastian Limbach <slimbach@mpi-inf.mpg.de>
// Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_KERNEL_D_1_H
#define CGAL_ALGEBRAIC_KERNEL_D_1_H
#include <CGAL/disable_warnings.h>
#ifndef CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 0
#endif
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/flags.h>
#include <CGAL/Polynomial.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h>
#include <CGAL/Algebraic_kernel_d/Descartes.h>
#include <CGAL/Algebraic_kernel_d/Real_roots.h>
#include <CGAL/Algebraic_kernel_d/refine_zero_against.h>
#include <CGAL/Algebraic_kernel_d/Interval_evaluate_1.h>
#include <CGAL/Algebraic_kernel_d/bound_between_1.h>
#include <CGAL/ipower.h>
namespace CGAL {
namespace internal {
template< class AlgebraicReal1, class Isolator_ >
class Algebraic_kernel_d_1_base {
public:
typedef AlgebraicReal1 Algebraic_real_1;
typedef Isolator_ Isolator;
typedef typename Algebraic_real_1::Coefficient Coefficient;
typedef typename Algebraic_real_1::Bound Bound;
typedef typename Algebraic_real_1::Polynomial_1 Polynomial_1;
// TODO: Other choice?
typedef int size_type;
typedef int Multiplicity_type;
private:
typedef CGAL::Polynomial_traits_d< Polynomial_1 > PT_1;
protected:
// Some functors used for STL calls
template<typename A,typename B>
struct Pair_first : public CGAL::cpp98::unary_function<std::pair<A,B>,A> {
A operator() (std::pair<A,B> pair) const { return pair.first; }
};
template<typename A,typename B>
struct Pair_second : public CGAL::cpp98::unary_function<std::pair<A,B>,B> {
B operator() (std::pair<A,B> pair) const { return pair.second; }
};
public:
class Algebraic_real_traits {
public:
typedef Algebraic_real_1 Type;
struct Bound_between
: public CGAL::cpp98::binary_function< Type, Type, Bound > {
Bound operator()( const Type& t1,
const Type& t2 ) const {
#if CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN
#warning uses deprecated bound_between_1 functor
return t1.rational_between( t2 );
#else
return internal::simple_bound_between(t1,t2);
#endif
}
};
struct Lower_bound
: public CGAL::cpp98::unary_function< Type, Bound > {
Bound operator()( const Type& t ) const {
return t.low();
}
};
struct Upper_bound
: public CGAL::cpp98::unary_function< Type, Bound > {
Bound operator()( const Type& t ) const {
return t.high();
}
};
struct Refine
: public CGAL::cpp98::unary_function< Type, void > {
void operator()( const Type& t ) const {
t.refine();
}
void operator()( Type& t, int rel_prec ) const {
// If t is zero, we can refine the interval to
// infinite precission
if( CGAL::is_zero( t ) ) {
t = Type(0);
} else {
// Refine until both boundaries have the same sign
while( CGAL::sign( t.high() ) !=
CGAL::sign( t.low() ) )
t.refine();
CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO &&
CGAL::sign( t.low() ) != CGAL::ZERO );
// Calculate the needed precision
Bound prec = Bound(1) /
CGAL::ipower( Bound(2), rel_prec );
// Refine until precision is reached
while( CGAL::abs( t.high() - t.low() ) /
(CGAL::max)( CGAL::abs( t.high() ),
CGAL::abs( t.low() ) ) > prec ) {
t.refine();
CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO &&
CGAL::sign( t.low() ) != CGAL::ZERO );
}
}
}
};
struct Approximate_absolute_1:
public CGAL::cpp98::binary_function<Algebraic_real_1,int,std::pair<Bound,Bound> >{
std::pair<Bound,Bound>
operator()(const Algebraic_real_1& x, int prec) const {
Lower_bound lower;
Upper_bound upper;
Refine refine;
Bound l = lower(x);
Bound u = upper(x);
Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec));
while((prec>0)?((u-l)*error>Bound(1)):((u-l)>error)){
refine(x);
u = upper(x);
l = lower(x);
}
return std::make_pair(l,u);
}
};
struct Approximate_relative_1:
public CGAL::cpp98::binary_function<Algebraic_real_1,int,std::pair<Bound,Bound> >{
std::pair<Bound,Bound>
operator()(const Algebraic_real_1& x, int prec) const {
if(CGAL::is_zero(x)) return std::make_pair(Bound(0),Bound(0));
Lower_bound lower;
Upper_bound upper;
Refine refine;
Bound l = lower(x);
Bound u = upper(x);
Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec));
Bound min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l));
while((prec>0)?((u-l)*error>min_b):((u-l)>error*min_b)){
refine(x);
u = upper(x);
l = lower(x);
min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l));
}
return std::make_pair(l,u);
}
};
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
typedef Lower_bound Lower_boundary;
typedef Upper_bound Upper_boundary;
typedef Bound_between Boundary_between;
#endif
}; // class Algebraic_real_traits
struct Construct_algebraic_real_1;
// Functors of Algebraic_kernel_d_1
struct Solve_1 {
public:
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_1& p, OutputIterator oi) const {
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#else
CGAL_precondition(!CGAL::is_zero(p));
#endif
internal::Real_roots< Algebraic_real_1, Isolator > real_roots;
std::list< int > mults;
std::list< Algebraic_real_1 > roots;
real_roots( p, std::back_inserter(roots), std::back_inserter( mults ) );
CGAL_assertion(roots.size()==mults.size());
std::list<int>::iterator mit =mults.begin();
typename std::list< Algebraic_real_1 >::iterator rit = roots.begin();
while(rit != roots.end()) {
//*oi++ = std::make_pair(*rit, (unsigned int)(*mit));
*oi++ = std::make_pair(*rit, *mit);
rit++;
mit++;
}
return oi;
}
#if 1 || CGAL_AK_ENABLE_DEPRECATED_INTERFACE
template< class OutputIterator >
OutputIterator operator()(
const Polynomial_1& p,
OutputIterator oi ,
bool known_to_be_square_free) const {
return this->operator()(p,known_to_be_square_free,oi);
}
#endif
template< class OutputIterator >
OutputIterator operator()(
const Polynomial_1& p,
bool known_to_be_square_free,
OutputIterator oi) const {
internal::Real_roots< Algebraic_real_1, Isolator > real_roots;
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#else
CGAL_precondition(!CGAL::is_zero(p));
#endif
std::list<Algebraic_real_1> roots;
if( known_to_be_square_free ){
real_roots(p,std::back_inserter(roots));
}else{
std::list<int> dummy;
real_roots(p,std::back_inserter(roots),std::back_inserter(dummy));
}
return std::copy(roots.begin(),roots.end(),oi);
}
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
template< class OutputIteratorRoots , class OutputIteratorMults >
std::pair<OutputIteratorRoots,OutputIteratorMults>
operator()(
const Polynomial_1& p,
OutputIteratorRoots roi,
OutputIteratorMults moi) const {
internal::Real_roots< Algebraic_real_1, Isolator > real_roots;
real_roots(p,roi,moi);
return std::make_pair(roi,moi);
}
#endif
protected:
/*
// TODO: Can we avoid to use this?
struct Greater_compare :
public CGAL::cpp98::binary_function<Algebraic_real_1,Algebraic_real_1,bool> {
bool operator() (const Algebraic_real_1& a, const Algebraic_real_1& b)
const {
return a>b;
}
};
*/
public:
template< class OutputIterator >
OutputIterator operator()(const Polynomial_1& p, Bound l, Bound u,
OutputIterator res) const {
std::vector<std::pair<Algebraic_real_1,Multiplicity_type> > roots;
this->operator() (p,std::back_inserter(roots));
Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l);
Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u);
typedef typename
std::vector<std::pair<Algebraic_real_1,Multiplicity_type> >::iterator
Iterator;
Pair_first<Algebraic_real_1,Multiplicity_type> pair_first;
Iterator it_start=std::lower_bound
(::boost::make_transform_iterator(roots.begin(),pair_first),
::boost::make_transform_iterator(roots.end(),pair_first),
alg_l).base();
Iterator it_end=std::upper_bound
(::boost::make_transform_iterator(it_start,pair_first),
::boost::make_transform_iterator(roots.end(),pair_first),
alg_u).base();
std::copy(it_start,it_end,res);
return res;
}
template< class OutputIterator >
OutputIterator operator()(const Polynomial_1& p,
bool known_to_be_square_free,
Bound l, Bound u,
OutputIterator res) const {
std::vector<Algebraic_real_1 > roots;
this->operator() (p,known_to_be_square_free,std::back_inserter(roots));
Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l);
Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u);
typedef typename
std::vector<Algebraic_real_1>::iterator
Iterator;
Iterator it_start=std::lower_bound(roots.begin(),roots.end(),alg_l);
Iterator it_end=std::upper_bound(it_start,roots.end(),alg_u);
std::copy(it_start,it_end,res);
return res;
}
};
class Number_of_solutions_1
: public CGAL::cpp98::unary_function<Polynomial_1,size_type> {
public:
size_type operator()
(const Polynomial_1& p) const {
std::vector<std::pair<Algebraic_real_1,Multiplicity_type> > roots;
Solve_1()(p,std::back_inserter(roots));
return static_cast<size_type>(roots.size());
}
};
struct Sign_at_1
: public CGAL::cpp98::binary_function< Polynomial_1, Algebraic_real_1, CGAL::Sign > {
CGAL::Sign operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const {
if(CGAL::is_zero(p)) return ZERO;
if(CGAL::degree(p)==0) return p.sign_at(0);
if( ar.low() == ar.high() ) return p.sign_at( ar.low() );
if (p == ar.polynomial()) {
return ZERO;
}
Polynomial_1 g = gcd_utcf(p,ar.polynomial());
if (g.sign_at(ar.low()) != g.sign_at(ar.high())) return ZERO;
while(internal::descartes(p,ar.low(),ar.high()) > 0) ar.refine();
while( p.sign_at(ar.low()) == ZERO ) ar.refine();
while( p.sign_at(ar.high()) == ZERO ) ar.refine();
CGAL::Sign result = p.sign_at(ar.low());
CGAL_assertion(result == p.sign_at(ar.high()));
return result;
}
};
struct Is_zero_at_1
: public CGAL::cpp98::binary_function< Polynomial_1, Algebraic_real_1, bool > {
bool operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const {
if(CGAL::is_zero(p)) return true;
if( ar.low() == ar.high() ) return p.sign_at( ar.low() ) == ZERO;
Polynomial_1 g = gcd_utcf(p,ar.polynomial());
return g.sign_at(ar.low()) != g.sign_at(ar.high());
}
};
struct Is_square_free_1
: public CGAL::cpp98::unary_function< Polynomial_1, bool > {
bool operator()( const Polynomial_1& p ) const {
typename CGAL::Polynomial_traits_d< Polynomial_1 >::Is_square_free isf;
return isf(p);
}
};
struct Is_coprime_1
: public CGAL::cpp98::binary_function< Polynomial_1, Polynomial_1, bool > {
bool operator()( const Polynomial_1& p1, const Polynomial_1& p2 ) const {
typename CGAL::Polynomial_traits_d< Polynomial_1 >::Total_degree total_degree;
// TODO: Is GCD already filtered?
return( total_degree( gcd_utcf( p1, p2 ) ) == 0 );
}
};
struct Make_square_free_1
: public CGAL::cpp98::unary_function< Polynomial_1, Polynomial_1 > {
Polynomial_1 operator()( const Polynomial_1& p ) const {
return typename CGAL::Polynomial_traits_d< Polynomial_1 >::Make_square_free()( p );
}
};
struct Make_coprime_1 {
typedef bool result_type;
typedef Polynomial_1 first_argument_type;
typedef Polynomial_1 second_argument_type;
typedef Polynomial_1 third_argument_type;
typedef Polynomial_1 fourth_argument_type;
typedef Polynomial_1 fifth_argument_type;
bool operator()( const Polynomial_1& p1,
const Polynomial_1& p2,
Polynomial_1& g, // ggT utcf
Polynomial_1& q1, // Rest utcf
Polynomial_1& q2 ) const {
g = typename CGAL::Polynomial_traits_d< Polynomial_1 >::Gcd_up_to_constant_factor()( p1, p2 );
q1 = p1 / g;
q2 = p2 / g;
return CGAL::is_one(g);
}
};
struct Square_free_factorize_1 {
template< class OutputIterator>
OutputIterator operator()( const Polynomial_1& p, OutputIterator it) const {
typename PT_1::Square_free_factorize_up_to_constant_factor sqff;
return sqff(p,it);
}
};
struct Compute_polynomial_1 : public CGAL::cpp98::unary_function<Algebraic_real_1,
Polynomial_1> {
Polynomial_1 operator()(const Algebraic_real_1& x) const {
return x.polynomial();
}
};
struct Construct_algebraic_real_1 {
public:
typedef Algebraic_real_1 result_type;
result_type operator() (int a) const {
return Algebraic_real_1(a);
}
result_type operator() (Bound a) const {
return Algebraic_real_1(a);
}
result_type operator()
(typename CGAL::First_if_different<Coefficient,Bound>::Type a) const {
Coefficient coeffs[2] = {a,Coefficient(-1)};
Polynomial_1 p = typename PT_1::Construct_polynomial()
(coeffs,coeffs+2);
std::vector<Algebraic_real_1 > roots;
Solve_1()(p,true,std::back_inserter(roots));
CGAL_assertion(roots.size() == size_type(1));
return roots[0];
}
result_type operator() (Polynomial_1 p,size_type i)
const {
std::vector<Algebraic_real_1 > roots;
Solve_1()(p,true,std::back_inserter(roots));
CGAL_assertion( size_type(roots.size()) > i);
return roots[i];
}
result_type operator() (Polynomial_1 p,
Bound l, Bound u) const {
CGAL_precondition(l<u);
return Algebraic_real_1(p,l,u);
}
};
struct Compare_1
: public CGAL::cpp98::binary_function<Algebraic_real_1,
Algebraic_real_1,
CGAL::Comparison_result>{
typedef CGAL::Comparison_result result_type;
result_type operator() (Algebraic_real_1 a,Algebraic_real_1 b) const {
return typename Real_embeddable_traits<Algebraic_real_1>
::Compare() (a,b);
}
result_type operator() (Algebraic_real_1 a,int b) const {
return this->operator()(a,Construct_algebraic_real_1()(b));
}
result_type operator() (Algebraic_real_1 a,Bound b) const {
return this->operator()(a,Construct_algebraic_real_1()(b));
}
result_type operator()
(Algebraic_real_1 a,
typename CGAL::First_if_different<Coefficient,Bound>::Type b) const {
return this->operator()(a,Construct_algebraic_real_1()(b));
}
result_type operator() (int a, Algebraic_real_1 b) const {
return this->operator()(Construct_algebraic_real_1()(a),b);
}
result_type operator() (Bound a,Algebraic_real_1 b) const {
return this->operator()(Construct_algebraic_real_1()(a),b);
}
result_type operator()
(typename CGAL::First_if_different<Coefficient,Bound>::Type a,
Algebraic_real_1 b) const {
return this->operator()(Construct_algebraic_real_1()(a),b);
}
};
public:
struct Isolate_1 : public CGAL::cpp98::binary_function
< Algebraic_real_1,Polynomial_1,std::pair<Bound,Bound> > {
public:
std::pair<Bound,Bound> operator() (const Algebraic_real_1 a,
const Polynomial_1 p) const {
if(p == a.polynomial()) return std::make_pair(a.low(),a.high());
std::vector<Algebraic_real_1> roots;
// First isolate p...
Solve_1()(p,false,std::back_inserter(roots));
typedef typename std::vector<Algebraic_real_1>::iterator Iterator;
// Binary search on the root to find a place where a could be inserted
std::pair<Iterator,Iterator> it_pair
= equal_range(roots.begin(),roots.end(),a);
CGAL_assertion(std::distance(it_pair.first,it_pair.second)==0 ||
std::distance(it_pair.first,it_pair.second)==1);
// If we can insert a in two places, it must have been in roots already
bool a_in_roots = std::distance(it_pair.first,it_pair.second)==1;
if(a_in_roots) {
// TODO: can we rely on the property that the isolating intervals
// of the roots in p are isolating from each other. What
// if p was factorized during isolation? Is that still
// guaranteed? To be sure, we do it this way:
if(it_pair.first!=roots.begin()) {
it_pair.first->strong_refine(*(it_pair.first-1));
}
if(it_pair.second!=roots.end()) {
it_pair.first->strong_refine(*(it_pair.second));
}
return std::make_pair(it_pair.first->low(),it_pair.first->high());
} else {
// Refine a until disjoint from neighbors
// This is probably not even necessary since the isolating
// interval of a isolates against all roots of p thanks to the
// comparisons. But to be sure...
if(it_pair.first!=roots.begin()) {
a.strong_refine(*(it_pair.first-1));
}
if(it_pair.first!=roots.end()) {
a.strong_refine(*(it_pair.first));
}
return std::make_pair(a.low(),a.high());
}
}
};
typedef typename Algebraic_real_traits::Bound_between Bound_between_1;
typedef typename Algebraic_real_traits::Approximate_absolute_1 Approximate_absolute_1;
typedef typename Algebraic_real_traits::Approximate_relative_1 Approximate_relative_1;
#define CGAL_ALGEBRAIC_KERNEL_1_PRED(Y,Z) Y Z() const { return Y(); }
#define CGAL_ALGEBRAIC_KERNEL_1_PRED_WITH_KERNEL \
Y Z() const { return Y((const Algebraic_kernel_d_1*)this); }
CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_square_free_1,
is_square_free_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_square_free_1,
make_square_free_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Square_free_factorize_1,
square_free_factorize_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_coprime_1,
is_coprime_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_coprime_1,
make_coprime_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Solve_1,
solve_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Number_of_solutions_1,
number_of_solutions_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Construct_algebraic_real_1,
construct_algebraic_real_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Sign_at_1,
sign_at_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_zero_at_1,
is_zero_at_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Compare_1,compare_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Bound_between_1,
bound_between_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_absolute_1,
approximate_absolute_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_relative_1,
approximate_relative_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Compute_polynomial_1,
compute_polynomial_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Isolate_1,
isolate_1_object);
// Deprecated
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
typedef Bound Boundary;
typedef typename Algebraic_real_traits::Refine Refine_1;
typedef typename Algebraic_real_traits::Lower_bound Lower_bound_1;
typedef typename Algebraic_real_traits::Upper_bound Upper_bound_1;
typedef typename Algebraic_real_traits::Lower_bound Lower_boundary_1;
typedef typename Algebraic_real_traits::Upper_bound Upper_boundary_1;
typedef Bound_between_1 Boundary_between_1;
CGAL_ALGEBRAIC_KERNEL_1_PRED(Refine_1, refine_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_bound_1, lower_bound_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_bound_1, upper_bound_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_boundary_1, lower_boundary_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_boundary_1, upper_boundary_1_object);
CGAL_ALGEBRAIC_KERNEL_1_PRED(Boundary_between_1, boundary_between_1_object);
#endif
#undef CGAL_ALGEBRAIC_KERNEL_1_PRED
};
} // namespace internal
template< class Coefficient,
class Bound = typename CGAL::Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Rational,
class RepClass = internal::Algebraic_real_rep< Coefficient, Bound >,
class Isolator = internal::Descartes< typename CGAL::Polynomial_type_generator<Coefficient,1>::Type, Bound > >
class Algebraic_kernel_d_1
: public internal::Algebraic_kernel_d_1_base<
// Template argument #1 (AlgebraicReal1)
internal::Algebraic_real_d_1<
Coefficient,
Bound,
::CGAL::Handle_policy_no_union,
RepClass >,
// Template argument #2 (Isolator_)
Isolator >
{};
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_D_1_H
@@ -0,0 +1,36 @@
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_ALGEBRAIC_KERNEL_D_2_H
#define CGAL_ALGEBRAIC_KERNEL_D_2_H
#include <CGAL/disable_warnings.h>
#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h>
namespace CGAL {
template<typename Coefficient> class Algebraic_kernel_d_2
: public CGAL::Algebraic_curve_kernel_2
< CGAL::Algebraic_kernel_d_1 <Coefficient> >
{};
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_D_1_H
@@ -0,0 +1,222 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_2_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_2_H
#include <CGAL/license/Circular_kernel_2.h>
#include <CGAL/Algebraic_kernel_for_circles/internal_functions_on_roots_and_polynomials_2_2.h>
#include <CGAL/Algebraic_kernel_for_circles/internal_functions_on_roots_and_polynomial_1_2_and_2_2.h>
#include <CGAL/Algebraic_kernel_for_circles/internal_functions_comparison_root_for_circles_2_2.h>
namespace CGAL {
namespace AlgebraicFunctors {
template < class AK >
class Solve
{
typedef typename AK::Polynomial_for_circles_2_2 Equation_Circle;
typedef typename AK::Polynomial_1_2 Equation_Line;
public:
typedef void result_type;
template < class OutputIterator >
OutputIterator
operator()(const Equation_Circle & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()(const Equation_Line & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()(const Equation_Circle & e1,
const Equation_Line & e2,
OutputIterator res) const
{ return AlgebraicFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()(const Equation_Line & e1,
const Equation_Line & e2,
OutputIterator res) const
{ return AlgebraicFunctors::solve<AK> ( e1, e2, res); }
};
template < class AK >
class Construct_polynomial_for_circles_2_2
{
typedef typename AK::RT RT;
typedef typename AK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2;
public:
typedef Polynomial_for_circles_2_2 result_type;
result_type
operator()(const RT& xc, const RT& yc, const RT& r_sq) const
{ return Polynomial_for_circles_2_2(xc, yc, r_sq); }
};
template < class AK >
class Construct_polynomial_1_2
{
typedef typename AK::RT RT;
typedef typename AK::Polynomial_1_2 Polynomial_1_2;
public:
typedef Polynomial_1_2 result_type;
result_type
operator()( const RT& a, const RT& b, const RT& c) const
{ return Polynomial_1_2(a, b, c); }
};
template < class AK >
class Sign_at
{
typedef typename AK::Polynomial_1_2 Polynomial_1_2;
typedef typename AK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
public:
typedef CGAL::Sign result_type;
result_type
operator()( const Polynomial_for_circles_2_2 & equation,
const Root_for_circles_2_2 & r ) const
{ return AlgebraicFunctors::sign_at<AK>(equation, r); }
result_type
operator()( const Polynomial_1_2 & equation,
const Root_for_circles_2_2 & r ) const
{ return AlgebraicFunctors::sign_at<AK>(equation, r); }
};
template < class AK >
class X_critical_points
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
typedef typename AK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2;
public:
typedef void result_type;
Root_for_circles_2_2
operator()(const Polynomial_for_circles_2_2 & c,
bool i) const
{ return AlgebraicFunctors::x_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_for_circles_2_2 & c,
OutputIterator res) const
{ return AlgebraicFunctors::x_critical_points<AK>(c,res); }
};
template < class AK >
class Y_critical_points
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
typedef typename AK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2;
public:
typedef void result_type;
Root_for_circles_2_2
operator()(const Polynomial_for_circles_2_2 & c,
bool i) const
{ return AlgebraicFunctors::y_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_for_circles_2_2 & c,
OutputIterator res) const
{ return AlgebraicFunctors::y_critical_points<AK>(c,res); }
};
template < class AK >
class Compare_x
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
typedef typename AK::RT RT;
public:
typedef CGAL::Comparison_result result_type;
result_type
operator()(const Root_for_circles_2_2& r1,
const Root_for_circles_2_2& r2) const
{ return AlgebraicFunctors::compare_x<RT>(r1, r2); }
};
template < class AK >
class Compare_y
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
typedef typename AK::RT RT;
public:
typedef CGAL::Comparison_result result_type;
result_type
operator()(const Root_for_circles_2_2& r1,
const Root_for_circles_2_2& r2) const
{ return AlgebraicFunctors::compare_y<RT>(r1, r2); }
};
template < class AK >
class Compare_xy
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
typedef typename AK::RT RT;
public:
typedef CGAL::Comparison_result result_type;
result_type
operator()(const Root_for_circles_2_2& r1,
const Root_for_circles_2_2& r2) const
{ return AlgebraicFunctors::compare_xy<RT>(r1, r2); }
};
} // namespace AlgebraicFunctors
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_2_H
@@ -0,0 +1,52 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion, Julien Hazebrouck
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_COMPARISON_ROOT_FOR_CIRCLES_2_2_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_COMPARISON_ROOT_FOR_CIRCLES_2_2_H
#include <CGAL/license/Circular_kernel_2.h>
namespace CGAL {
namespace AlgebraicFunctors{
template <typename RT>
Comparison_result
compare_x(const CGAL::Root_for_circles_2_2<RT>& r1, const CGAL::Root_for_circles_2_2<RT>& r2){
return compare(r1.x(), r2.x());
}
template <typename RT>
Comparison_result
compare_y(const CGAL::Root_for_circles_2_2<RT>& r1, const CGAL::Root_for_circles_2_2<RT>& r2){
return compare(r1.y(), r2.y());
}
template <typename RT>
Comparison_result
compare_xy(const CGAL::Root_for_circles_2_2<RT>& r1, const CGAL::Root_for_circles_2_2<RT>& r2){
Comparison_result compx = compare_x(r1, r2);
if(compx != 0)
return compx;
return compare_y(r1, r2);
}
} // namespace AlgebraicFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_COMPARISON_ROOT_FOR_CIRCLES_2_2_H
@@ -0,0 +1,184 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion, Julien Hazebrouck
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_2_AND_2_2_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_2_AND_2_2_H
#include <CGAL/license/Circular_kernel_2.h>
namespace CGAL {
namespace AlgebraicFunctors {
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_1_2 & e1,
const typename AK::Polynomial_for_circles_2_2 & e2,
OutputIterator res )
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
if (is_zero(e1.a())){//horizontal line
const FT hy = -e1.c()/e1.b();
const FT hdisc = e2.r_sq() - CGAL::square(hy - e2.b());
CGAL::Sign sign_hdisc = CGAL::sign(hdisc);
if(sign_hdisc == NEGATIVE) return res;
if(sign_hdisc == ZERO) {
*res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(e2.a()),
Root_of_2(hy)), 2u);
return res;
}
const Root_of_2 x_res1 = make_root_of_2(e2.a(),FT(-1),hdisc);
const Root_of_2 x_res2 = make_root_of_2(e2.a(),FT(1),hdisc);
const Root_of_2 y_res = Root_of_2(hy);
*res++ = std::make_pair
( Root_for_circles_2_2(x_res1, y_res), 1u);
*res++ = std::make_pair
( Root_for_circles_2_2(x_res2, y_res), 1u);
return res;
}
else if(is_zero(e1.b())){//vertical line
const FT vx = -e1.c()/e1.a();
const FT vdisc = e2.r_sq() - CGAL::square(vx - e2.a());
CGAL::Sign sign_vdisc = CGAL::sign(vdisc);
if(sign_vdisc == NEGATIVE) return res;
if(sign_vdisc == ZERO) {
*res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(vx),
Root_of_2(e2.b())), 2u);
return res;
}
const Root_of_2 x_res = Root_of_2(vx);
const Root_of_2 y_res1 = make_root_of_2(e2.b(),FT(-1),vdisc);
const Root_of_2 y_res2 = make_root_of_2(e2.b(),FT(1),vdisc);
*res++ = std::make_pair
( Root_for_circles_2_2(x_res, y_res1), 1u);
*res++ = std::make_pair
( Root_for_circles_2_2(x_res, y_res2), 1u);
return res;
}
else {
const FT line_factor = CGAL::square(e1.a()) + CGAL::square(e1.b());
const FT disc = line_factor*e2.r_sq() -
CGAL::square(e1.a()*e2.a() + e1.b()*e2.b() + e1.c());
CGAL::Sign sign_disc = CGAL::sign(disc);
if (sign_disc == NEGATIVE) return res;
const FT aux = e1.b()*e2.a() - e1.a()*e2.b();
const FT x_base = (aux*e1.b() - e1.a()*e1.c()) / line_factor;
const FT y_base = (-aux*e1.a() - e1.b()*e1.c()) / line_factor;
if (sign_disc == ZERO) {
*res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(x_base),
Root_of_2(y_base)), 2u);
return res;
}
// We have two intersection points, whose coordinates are one-root numbers.
const FT x_root_coeff = e1.b() / line_factor;
const FT y_root_coeff = e1.a() / line_factor;
if (CGAL::sign(e1.b()) == POSITIVE) {
*res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
make_root_of_2(y_base, y_root_coeff, disc)), 1u);
*res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
make_root_of_2(y_base, -y_root_coeff, disc)), 1u);
} else {
*res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
make_root_of_2(y_base, -y_root_coeff, disc)), 1u);
*res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
make_root_of_2(y_base, y_root_coeff, disc)), 1u);
}
return res;
}
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_for_circles_2_2 & e1,
const typename AK::Polynomial_1_2 & e2,
OutputIterator res )
{
return solve<AK> (e2, e1, res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_1_2 & e1,
const typename AK::Polynomial_1_2 & e2,
OutputIterator res )
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
//parallele case
const FT delta = e1.a()*e2.b() - e2.a()*e1.b();
if(is_zero(delta)) return res;
//case : e2 horizontal
if(is_zero(e2.a())){
const FT sol = -e2.c()/e2.b();
*res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(-(e1.b()*sol + e1.c())/e1.a()),
Root_of_2(sol)), 1u);
return res;
}
//general case
const FT sol = (e2.a()*e1.c() - e2.c()*e1.a()) / delta;
*res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(-(e2.b()*sol + e2.c())/e2.a()),
Root_of_2(sol)), 1u);
return res;
}
template < class AK >
inline
Sign sign_at( const typename AK::Polynomial_1_2 & equation,
const typename AK::Root_for_circles_2_2 & r)
{
Comparison_result c = compare(r.x()*equation.a(),
-equation.c() - r.y()*equation.b());
if(c == EQUAL) return ZERO;
if(c == LARGER) return POSITIVE;
return NEGATIVE;
}
} // namespace AlgebraicFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_2_AND_2_2_H
@@ -0,0 +1,227 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_H
#include <CGAL/license/Circular_kernel_2.h>
#include <CGAL/basic.h>
namespace CGAL {
namespace AlgebraicFunctors {
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_for_circles_2_2 & e1,
const typename AK::Polynomial_for_circles_2_2 & e2,
OutputIterator res )
{
CGAL_precondition( ! (e1 == e2) ); // polynomials of this type cannot be multiple
// of one another if they are not equal
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
const FT dx = e2.a() - e1.a();
const FT dy = e2.b() - e1.b();
const FT dx2 = CGAL::square(dx);
const FT dy2 = CGAL::square(dy);
const FT dist2 = dx2 + dy2; // squared distance between centers
const FT diff_sqr_rad = e1.r_sq() - e2.r_sq();
const FT disc = 2*dist2*(e1.r_sq() + e2.r_sq()) -
(CGAL::square(diff_sqr_rad) + CGAL::square(dist2));
CGAL::Sign sign_disc = CGAL::sign(disc);
if (sign_disc == NEGATIVE) return res;
const FT x_base = ((e1.a() + e2.a()) + dx*diff_sqr_rad / dist2) / 2;
const FT y_base = ((e1.b() + e2.b()) + dy*diff_sqr_rad / dist2) / 2;
if (sign_disc == ZERO) {
// one double root,
// no need to care about the boolean of the Root_of
*res++ = std::make_pair
( Root_for_circles_2_2
(Root_of_2(x_base), Root_of_2(y_base)),
static_cast<unsigned>(2) ); // multiplicity = 2
return res;
}
CGAL::Sign sign_dy = CGAL::sign (dy);
CGAL::Sign sign_dx = CGAL::sign (dx);
// else, 2 distinct roots
if (sign_dy == ZERO) {
const FT y_root_coeff = dx / (2 * dist2);
if(sign_dx == NEGATIVE) {
* res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(x_base),
make_root_of_2(y_base, y_root_coeff, disc)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(x_base),
make_root_of_2(y_base, -y_root_coeff, disc)),
static_cast<unsigned>(1) );
} else {
* res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(x_base),
make_root_of_2(y_base, -y_root_coeff, disc)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(Root_of_2(x_base),
make_root_of_2(y_base, y_root_coeff, disc)),
static_cast<unsigned>(1) );
}
return res;
}
if (sign_dx == ZERO) {
const FT x_root_coeff = dy / (2 * dist2);
if(sign_dy == POSITIVE) {
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
Root_of_2(y_base)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
Root_of_2(y_base)),
static_cast<unsigned>(1) );
} else {
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
Root_of_2(y_base)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
Root_of_2(y_base)),
static_cast<unsigned>(1) );
}
return res;
}
const FT x_root_coeff = dy / (2 * dist2);
const FT y_root_coeff = dx / (2 * dist2);
if (sign_dy == POSITIVE) {
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
make_root_of_2(y_base, y_root_coeff, disc)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
make_root_of_2(y_base, -y_root_coeff, disc)),
static_cast<unsigned>(1) );
} else {
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, x_root_coeff, disc),
make_root_of_2(y_base, -y_root_coeff, disc)),
static_cast<unsigned>(1) );
* res++ = std::make_pair
( Root_for_circles_2_2(make_root_of_2(x_base, -x_root_coeff, disc),
make_root_of_2(y_base, y_root_coeff, disc)),
static_cast<unsigned>(1) );
}
return res;
}
template < class AK >
inline
Sign sign_at( const typename AK::Polynomial_for_circles_2_2 & equation,
const typename AK::Root_for_circles_2_2 & r)
{
Comparison_result c = compare(square(r.x() - equation.a()),
equation.r_sq() -
square(r.y() - equation.b()));
if(c == EQUAL) return ZERO;
if(c == LARGER) return POSITIVE;
return NEGATIVE;
}
template <class AK>
typename AK::Root_for_circles_2_2
x_critical_point(const typename AK::Polynomial_for_circles_2_2 & c,
bool i)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::FT FT;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
const Root_of_2 a1 = make_root_of_2(c.a(),FT(i?-1:1),c.r_sq());
return Root_for_circles_2_2(a1, c.b());
}
template <class AK, class OutputIterator>
OutputIterator
x_critical_points(const typename AK::Polynomial_for_circles_2_2 & c,
OutputIterator res)
{
typedef typename AK::FT FT;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
*res++ = Root_for_circles_2_2(
make_root_of_2(c.a(),FT(-1),c.r_sq()), c.b());
*res++ = Root_for_circles_2_2(
make_root_of_2(c.a(),FT(1),c.r_sq()), c.b());
return res;
}
template <class AK>
typename AK::Root_for_circles_2_2
y_critical_point(const typename AK::Polynomial_for_circles_2_2 &c,
bool i)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::FT FT;
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
const Root_of_2 b1 = make_root_of_2(c.b(),FT(i?-1:1),c.r_sq());
return Root_for_circles_2_2(c.a(),b1);
}
template <class AK, class OutputIterator>
OutputIterator
y_critical_points(const typename AK::Polynomial_for_circles_2_2 & c,
OutputIterator res)
{
typedef typename AK::Root_for_circles_2_2 Root_for_circles_2_2;
*res++ = Root_for_circles_2_2(c.a(),
make_root_of_2(c.b(),-1,c.r_sq()));
*res++ = Root_for_circles_2_2(c.a(),
make_root_of_2(c.b(),1,c.r_sq()));
return res;
}
} // namespace AlgebraicFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_H
@@ -0,0 +1,95 @@
// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud, Sylvain Pion
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_2_2_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_2_2_H
#include <CGAL/license/Circular_kernel_2.h>
#include <CGAL/Quotient.h>
#include <CGAL/Root_of_traits.h>
#include <CGAL/Polynomials_2_2.h>
#include <CGAL/Polynomials_1_2.h>
#include <CGAL/Root_for_circles_2_2.h>
#include <CGAL/Algebraic_kernel_for_circles/function_objects_on_roots_and_polynomials_2_2.h>
namespace CGAL {
template< class RT_ >
struct Algebraic_kernel_for_circles_2_2
{
typedef Algebraic_kernel_for_circles_2_2<RT_> Self;
typedef RT_ RT;
typedef typename Root_of_traits< RT >::RootOf_1 FT;
typedef CGAL::Polynomial_1_2<RT> Polynomial_1_2;
typedef CGAL::Polynomial_for_circles_2_2<RT> Polynomial_for_circles_2_2;
// problem RT / FT ?
typedef typename Root_of_traits< RT >::RootOf_2 Root_of_2;
typedef CGAL::Root_for_circles_2_2< RT > Root_for_circles_2_2;
typedef AlgebraicFunctors::Construct_polynomial_1_2<Self>
Construct_polynomial_1_2;
typedef AlgebraicFunctors::Construct_polynomial_for_circles_2_2<Self>
Construct_polynomial_for_circles_2_2;
typedef AlgebraicFunctors::Solve<Self> Solve;
typedef AlgebraicFunctors::Sign_at<Self> Sign_at;
typedef AlgebraicFunctors::X_critical_points<Self> X_critical_points;
typedef AlgebraicFunctors::Y_critical_points<Self> Y_critical_points;
typedef AlgebraicFunctors::Compare_x<Self> Compare_x;
typedef AlgebraicFunctors::Compare_y<Self> Compare_y;
typedef AlgebraicFunctors::Compare_xy<Self> Compare_xy;
Construct_polynomial_1_2
construct_polynomial_1_2_object() const
{ return Construct_polynomial_1_2(); }
Construct_polynomial_for_circles_2_2
construct_polynomial_for_circles_2_2_object() const
{ return Construct_polynomial_for_circles_2_2(); }
Solve solve_object() const
{ return Solve(); }
Sign_at sign_at_object() const
{ return Sign_at(); }
X_critical_points x_critical_points_object() const
{ return X_critical_points(); }
Y_critical_points y_critical_points_object() const
{ return Y_critical_points(); }
Compare_x compare_x_object() const
{ return Compare_x(); }
Compare_y compare_y_object() const
{ return Compare_y(); }
Compare_xy compare_xy_object() const
{ return Compare_xy(); }
};
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_CIRCLES_2_2_H
@@ -0,0 +1,399 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_3_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_3_H
#include <CGAL/license/Circular_kernel_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/internal_functions_comparison_root_for_spheres_2_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/internal_functions_on_roots_and_polynomials_2_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/internal_functions_on_roots_and_polynomial_1_3_and_2_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/internal_functions_on_roots_and_polynomials_1_3.h>
namespace CGAL {
namespace AlgebraicSphereFunctors {
template < class AK >
class Solve
{
typedef typename AK::Polynomial_for_spheres_2_3
Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3
Polynomial_1_3;
typedef std::pair<
Polynomial_for_spheres_2_3,
Polynomial_1_3> Equation_Circle;
typedef typename AK::Polynomials_for_line_3 Polynomials_for_line_3;
public:
template < class OutputIterator >
OutputIterator
operator()
(const Equation_Circle & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Equation_Circle & e1,
const Polynomials_for_line_3 & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomials_for_line_3 & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Equation_Circle & e1,
const Polynomial_1_3 & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_1_3 & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> (e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Equation_Circle & e1,
const Polynomial_for_spheres_2_3 & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_for_spheres_2_3 & e1,
const Equation_Circle & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_for_spheres_2_3 & e1,
const Polynomial_1_3 & e2,
const Polynomial_1_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_for_spheres_2_3 & e1,
const Polynomials_for_line_3 & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomials_for_line_3 & e1,
const Polynomial_for_spheres_2_3 & e2,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_for_spheres_2_3 & e1,
const Polynomial_for_spheres_2_3 & e2,
const Polynomial_1_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_1_3 & e1,
const Polynomial_for_spheres_2_3 & e2,
const Polynomial_for_spheres_2_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_1_3 & e1,
const Polynomial_1_3 & e2,
const Polynomial_for_spheres_2_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_for_spheres_2_3 & e1,
const Polynomial_for_spheres_2_3 & e2,
const Polynomial_for_spheres_2_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
template < class OutputIterator >
OutputIterator
operator()
(const Polynomial_1_3 & e1,
const Polynomial_1_3 & e2,
const Polynomial_1_3 & e3,
OutputIterator res) const
{ return AlgebraicSphereFunctors::solve<AK> ( e1, e2, e3, res); }
};
template < class AK >
class Construct_polynomial_for_spheres_2_3
{
typedef typename AK::RT RT;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
public:
Polynomial_for_spheres_2_3
operator()(const RT& xc, const RT& yc,const RT& zc, const RT& r_sq) const
{ return Polynomial_for_spheres_2_3(xc, yc, zc, r_sq); }
};
template < class AK >
class Construct_polynomial_1_3
{
typedef typename AK::RT RT;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
public:
Polynomial_1_3
operator()(const RT& a, const RT& b,const RT& c, const RT& d) const
{ return Polynomial_1_3(a, b, c, d); }
};
template < class AK >
class Construct_polynomials_for_line_3
{
typedef typename AK::FT FT;
typedef typename AK::Polynomials_for_line_3 Polynomials_for_line_3;
public:
Polynomials_for_line_3
operator()(const FT& a1, const FT& b1,
const FT& a2, const FT& b2,
const FT& a3, const FT& b3) const
{ return Polynomials_for_line_3(a1, b1, a2, b2, a3, b3); }
};
template < class AK >
class Sign_at
{
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
public:
typedef CGAL::Sign result_type;
result_type
operator()( const Polynomial_for_spheres_2_3 & equation,
const Root_for_spheres_2_3 & r ) const
{ return AlgebraicSphereFunctors::sign_at<AK>(equation, r); }
result_type
operator()( const Polynomial_1_3 & equation,
const Root_for_spheres_2_3 & r ) const
{ return AlgebraicSphereFunctors::sign_at<AK>(equation, r); }
};
template < class AK >
class X_critical_points
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
public:
typedef void result_type;
Root_for_spheres_2_3
operator()(const Polynomial_for_spheres_2_3 & c,
bool i) const
{ return AlgebraicSphereFunctors::x_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_for_spheres_2_3 & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::x_critical_points<AK>(c,res); }
Root_for_spheres_2_3
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
bool i) const
{ return AlgebraicSphereFunctors::x_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::x_critical_points<AK>(c,res); }
};
template < class AK >
class Y_critical_points
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
public:
typedef void result_type;
Root_for_spheres_2_3
operator()(const Polynomial_for_spheres_2_3 & c,
bool i) const
{ return AlgebraicSphereFunctors::y_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_for_spheres_2_3 & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::y_critical_points<AK>(c,res); }
Root_for_spheres_2_3
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
bool i) const
{ return AlgebraicSphereFunctors::y_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::y_critical_points<AK>(c,res); }
};
template < class AK >
class Z_critical_points
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
public:
typedef void result_type;
Root_for_spheres_2_3
operator()(const Polynomial_for_spheres_2_3 & c,
bool i) const
{ return AlgebraicSphereFunctors::z_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const Polynomial_for_spheres_2_3 & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::z_critical_points<AK>(c,res); }
Root_for_spheres_2_3
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
bool i) const
{ return AlgebraicSphereFunctors::z_critical_point<AK>(c,i); }
template <class OutputIterator>
OutputIterator
operator()(const std::pair< Polynomial_for_spheres_2_3, Polynomial_1_3 > & c,
OutputIterator res) const
{ return AlgebraicSphereFunctors::z_critical_points<AK>(c,res); }
};
template <typename RT>
class Compare_x
{
public:
Comparison_result
operator()(const Root_for_spheres_2_3<RT>& r1,
const Root_for_spheres_2_3<RT>& r2) const
{ return AlgebraicSphereFunctors::compare_x<RT>(r1, r2); }
};
template <typename RT>
class Compare_y
{
public:
Comparison_result
operator()(const Root_for_spheres_2_3<RT>& r1,
const Root_for_spheres_2_3<RT>& r2) const
{ return AlgebraicSphereFunctors::compare_y<RT>(r1, r2); }
};
template <typename RT>
class Compare_z
{
public:
Comparison_result
operator()(const Root_for_spheres_2_3<RT>& r1,
const Root_for_spheres_2_3<RT>& r2) const
{ return AlgebraicSphereFunctors::compare_z<RT>(r1, r2); }
};
template <typename RT>
class Compare_xy
{
public:
Comparison_result
operator()(const Root_for_spheres_2_3<RT>& r1,
const Root_for_spheres_2_3<RT>& r2) const
{ return AlgebraicSphereFunctors::compare_xy<RT>(r1, r2); }
};
template <typename RT>
class Compare_xyz
{
public:
Comparison_result
operator()(const Root_for_spheres_2_3<RT>& r1,
const Root_for_spheres_2_3<RT>& r2) const
{ return AlgebraicSphereFunctors::compare_xyz<RT>(r1, r2); }
};
} // namespace AlgebraicSphereFunctors
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_FUNCTION_OBJECTS_ON_ROOTS_AND_POLYNOMIALS_3_H
@@ -0,0 +1,70 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
#ifndef CGAL_ALGEBRAIC_KERNEL_COMPARISON_ROOT_FOR_SPHERES_2_3_H
#define CGAL_ALGEBRAIC_KERNEL_COMPARISON_ROOT_FOR_SPHERES_2_3_H
#include <CGAL/license/Circular_kernel_3.h>
namespace CGAL {
namespace AlgebraicSphereFunctors{
template <typename RT>
Comparison_result
compare_x(const CGAL::Root_for_spheres_2_3<RT>& r1, const CGAL::Root_for_spheres_2_3<RT>& r2){
return CGAL::compare(r1.x(), r2.x());
}
template <typename RT>
Comparison_result
compare_y(const CGAL::Root_for_spheres_2_3<RT>& r1, const CGAL::Root_for_spheres_2_3<RT>& r2){
return CGAL::compare(r1.y(), r2.y());
}
template <typename RT>
Comparison_result
compare_z(const CGAL::Root_for_spheres_2_3<RT>& r1, const CGAL::Root_for_spheres_2_3<RT>& r2){
return CGAL::compare(r1.z(), r2.z());
}
template <typename RT>
Comparison_result
compare_xy(const CGAL::Root_for_spheres_2_3<RT>& r1, const CGAL::Root_for_spheres_2_3<RT>& r2){
Comparison_result compx = compare_x(r1, r2);
if(compx != 0)
return compx;
return compare_y(r1, r2);
}
template <typename RT>
Comparison_result
compare_xyz(const CGAL::Root_for_spheres_2_3<RT>& r1, const CGAL::Root_for_spheres_2_3<RT>& r2){
Comparison_result compxy = compare_xy(r1, r2);
if(compxy != 0)
return compxy;
return compare_z(r1, r2);
}
} // namespace AlgebraicSphereFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_COMPARISON_ROOT_FOR_SPHERES_2_3_H
@@ -0,0 +1,576 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
#ifndef CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_3_AND_2_3_H
#define CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_3_AND_2_3_H
#include <CGAL/license/Circular_kernel_3.h>
#include <vector>
#include <iterator> // for std::back_inserter
#include <utility> // for std::pair and std::make_pair
#include <CGAL/enum.h> // for CGAL::Sign
#include <CGAL/use.h> // for CGAL_USE_TYPE()
namespace CGAL {
namespace AlgebraicSphereFunctors {
template < class AK >
inline
Sign sign_at( const typename AK::Polynomial_for_spheres_2_3 & equation,
const typename AK::Root_for_spheres_2_3 &r){
return CGAL_NTS sign(r.evaluate(equation));
}
template < class AK >
inline
Sign sign_at(const typename AK::Polynomial_1_3 & equation,
const typename AK::Root_for_spheres_2_3 &r){
return CGAL_NTS sign(r.evaluate(equation));
}
template < class AK >
inline
bool contains(const typename AK::Polynomials_for_line_3 & equation,
const typename AK::Root_for_spheres_2_3 &r){
return r.is_on_line(equation);
}
template <class AK>
bool intersect(const typename AK::Polynomial_1_3 & p1,
const typename AK::Polynomial_1_3 & p2) {
typedef typename AK::RT RT;
CGAL_USE_TYPE(RT);
CGAL_kernel_precondition(!(same_solutions<RT>(p1,p2)));
if(p1.empty_space()) return false;
if(p2.empty_space()) return false;
return !((p2.b() * p1.a() == p1.b() * p2.a()) &&
(p2.c() * p1.b() == p1.c() * p2.b()) &&
(p2.c() * p1.a() == p1.c() * p2.a()));
}
template <class AK>
inline
typename AK::Polynomials_for_line_3
line_from_2_planes(const typename AK::Polynomial_1_3 & p1,
const typename AK::Polynomial_1_3 & p2)
{
typedef typename AK::Polynomials_for_line_3 Polynomials_for_line_3;
typedef typename AK::FT FT;
CGAL_kernel_precondition(intersect<AK>(p1,p2));
const FT a1 = p1.b() * p2.c() - p1.c() * p2.b();
const FT a2 = p1.c() * p2.a() - p1.a() * p2.c();
const FT a3 = p1.a() * p2.b() - p1.b() * p2.a();
if(!is_zero(a1)) {
const FT b1 = 0;
const FT b2 = (p2.d() * p1.c() - p2.c() * p1.d()) / a1;
const FT b3 = (p2.b() * p1.d() - p2.d() * p1.b()) / a1;
return Polynomials_for_line_3(a1, b1, a2, b2, a3, b3);
}
if(!is_zero(a2)) {
const FT b1 = (p1.d() * p2.c() - p1.c() * p2.d()) / a2;
const FT b2 = 0;
const FT b3 = (p1.a() * p2.d() - p1.d() * p2.a()) / a2;
return Polynomials_for_line_3(a1, b1, a2, b2, a3, b3);
}
// a3 must not be 0
CGAL_kernel_precondition(!is_zero(a3));
const FT b1 = (p2.d() * p1.b() - p2.b() * p1.d()) / a3;
const FT b2 = (p2.a() * p1.d() - p2.d() * p1.a()) / a3;
const FT b3 = 0;
return Polynomials_for_line_3(a1, b1, a2, b2, a3, b3);
}
template <class AK>
inline
bool intersect(const typename AK::Polynomial_for_spheres_2_3 & s1,
const typename AK::Polynomial_for_spheres_2_3 & s2) {
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
const FT dx = s2.a() - s1.a();
const FT dy = s2.b() - s1.b();
const FT dz = s2.c() - s1.c();
const FT d2 = CGAL::square(dx) +
CGAL::square(dy) +
CGAL::square(dz);
const FT sq_r1r2 = s1.r_sq()*s2.r_sq();
const FT sq_r1_p_sq_r2 = s1.r_sq() + s2.r_sq();
Root_of_2 left_1 = make_root_of_2(d2,FT(-2),sq_r1r2);
if(left_1 > sq_r1_p_sq_r2) return false;
Root_of_2 left_2 = make_root_of_2(d2,FT(2),sq_r1r2);
if(left_2 < sq_r1_p_sq_r2) return false;
return true;
}
template <class AK>
inline
bool intersect(const typename AK::Polynomial_1_3 & p,
const typename AK::Polynomial_for_spheres_2_3 & s) {
return CGAL::square(p.a()*s.a() + p.b()*s.b() + p.c()*s.c() + p.d()) <=
((CGAL::square(p.a()) + CGAL::square(p.b()) + CGAL::square(p.c())) *
s.r_sq());
}
template <class AK>
inline
bool tangent(const typename AK::Polynomial_for_spheres_2_3 & s1,
const typename AK::Polynomial_for_spheres_2_3 & s2) {
typedef typename AK::RT RT;
typedef typename AK::Root_of_2 Root_of_2;
const RT dx = s2.a() - s1.a();
const RT dy = s2.b() - s1.b();
const RT dz = s2.c() - s1.c();
const RT d2 = CGAL::square(dx) +
CGAL::square(dy) +
CGAL::square(dz);
const RT sq_r1r2 = s1.r_sq()*s2.r_sq();
const RT sq_r1_p_sq_r2 = s1.r_sq() + s2.r_sq();
Root_of_2 left_1 = make_root_of_2(d2,RT(-2),sq_r1r2);
if(left_1 == sq_r1_p_sq_r2) return true;
Root_of_2 left_2 = make_root_of_2(d2,RT(2),sq_r1r2);
if(left_2 == sq_r1_p_sq_r2) return true;
return false;
}
template <class AK>
inline
bool tangent(const typename AK::Polynomial_1_3 & p,
const typename AK::Polynomial_for_spheres_2_3 & s) {
return CGAL::square(p.a()*s.a() + p.b()*s.b() + p.c()*s.c() + p.d()) ==
((CGAL::square(p.a()) + CGAL::square(p.b()) + CGAL::square(p.c())) *
s.r_sq());
}
template <class AK>
typename AK::Polynomial_1_3
plane_from_2_spheres(const typename AK::Polynomial_for_spheres_2_3 & s1,
const typename AK::Polynomial_for_spheres_2_3 & s2)
{
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
typedef typename AK::RT RT;
// In order to have a radical plane
// the spheres given must intersect
CGAL_kernel_precondition(intersect<AK>(s1,s2));
const RT a = 2*(s2.a() - s1.a());
const RT b = 2*(s2.b() - s1.b());
const RT c = 2*(s2.c() - s1.c());
const RT d = CGAL::square(s1.a()) +
CGAL::square(s1.b()) +
CGAL::square(s1.c()) - s1.r_sq() -
CGAL::square(s2.a()) -
CGAL::square(s2.b()) -
CGAL::square(s2.c()) + s2.r_sq();
return Polynomial_1_3(a, b, c, d);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomials_for_line_3 &p,
const typename AK::Polynomial_for_spheres_2_3& s,
OutputIterator res )
{
typedef typename AK::FT FT;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Root_of_2 Root_of_2;
// we must have a line
CGAL_kernel_precondition(!p.degenerated());
const FT sq_a1 = CGAL::square(p.a1());
const FT sq_a2 = CGAL::square(p.a2());
const FT sq_a3 = CGAL::square(p.a3());
const FT sq_a = CGAL::square(s.a());
const FT sq_b = CGAL::square(s.b());
const FT sq_c = CGAL::square(s.c());
const FT a = sq_a1 + sq_a2 + sq_a3;
const FT b = p.a1() * (p.b1() - s.a()) +
p.a2() * (p.b2() - s.b()) +
p.a3() * (p.b3() - s.c());
const FT c = CGAL::square(p.b1()) +
CGAL::square(p.b2()) +
CGAL::square(p.b3()) +
sq_a + sq_b + sq_c -
2*(s.a() * p.b1() +
s.b() * p.b2() +
s.c() * p.b3()) - s.r_sq();
const FT alpha = -b/a;
const FT gama = CGAL::square(alpha) - (c/a);
if(is_negative(gama)) return res;
if(is_zero(gama)) {
*res++ = std::make_pair(
Root_for_spheres_2_3(Root_of_2(p.a1() * alpha + p.b1()),
Root_of_2(p.a2() * alpha + p.b2()),
Root_of_2(p.a3() * alpha + p.b3())),
2);
return res;
}
const Root_of_2 t1 = make_root_of_2(alpha,FT(-1),gama);
const Root_of_2 t2 = make_root_of_2(alpha,FT(1),gama);
bool first_t1 = true;
Sign sign_a1 = CGAL_NTS sign(p.a1());
Sign sign_a2 = CGAL_NTS sign(p.a2());
Sign sign_a3 = CGAL_NTS sign(p.a3());
if(sign_a1 == ZERO) {
if(sign_a2 == ZERO) {
first_t1 = (sign_a3 == POSITIVE);
} else first_t1 = (sign_a2 == POSITIVE);
} else first_t1 = (sign_a1 == POSITIVE);
if(first_t1) {
*res++ = std::make_pair(
Root_for_spheres_2_3(p.a1() * t1 + p.b1(),
p.a2() * t1 + p.b2(),
p.a3() * t1 + p.b3()),
1);
*res++ = std::make_pair(
Root_for_spheres_2_3(p.a1() * t2 + p.b1(),
p.a2() * t2 + p.b2(),
p.a3() * t2 + p.b3()),
1);
} else {
*res++ = std::make_pair(
Root_for_spheres_2_3(p.a1() * t2 + p.b1(),
p.a2() * t2 + p.b2(),
p.a3() * t2 + p.b3()),
1);
*res++ = std::make_pair(
Root_for_spheres_2_3(p.a1() * t1 + p.b1(),
p.a2() * t1 + p.b2(),
p.a3() * t1 + p.b3()),
1);
}
return res;
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_for_spheres_2_3& s,
const typename AK::Polynomials_for_line_3 &p,
OutputIterator res )
{
return solve<AK>(p,s,res);
}
namespace internal {
template < class AK, class OutputIterator >
inline
OutputIterator
solve_tangent(const typename AK::Polynomial_1_3 & p,
const typename AK::Polynomial_for_spheres_2_3& s,
OutputIterator res )
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
// It returns no solution when there is infinitely solution
// For now, this solve is only for internal computations purpose
CGAL_kernel_precondition(
CGAL::square(p.a()*s.a() + p.b()*s.b() + p.c()*s.c() + p.d()) ==
((CGAL::square(p.a()) + CGAL::square(p.b()) + CGAL::square(p.c())) *
s.r_sq()));
const FT t = -(p.a()*s.a() + p.b()*s.b() + p.c()*s.c() + p.d()) /
(CGAL::square(p.a()) + CGAL::square(p.b()) + CGAL::square(p.c()));
*res++ = std::make_pair(
Root_for_spheres_2_3(Root_of_2(p.a() * t + s.a()),
Root_of_2(p.b() * t + s.b()),
Root_of_2(p.c() * t + s.c())),
2);
return res;
}
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_1_3 & e1,
const typename AK::Polynomial_1_3 & e2,
const typename AK::Polynomial_for_spheres_2_3& e3,
OutputIterator res )
{
typedef typename AK::RT RT;
typedef typename AK::Polynomials_for_line_3 Polynomials_for_line_3;
// we put as a precondition that the polynomial for spheres represents
// a sphere and not an isolated point or an empty_space
CGAL_kernel_precondition(!(e3.empty_space() || e3.isolated_point()));
// if the planes are the same
// since the solution can only be points or nothing
// the only case that remains is a plane tangent to a sphere
if(same_solutions<RT>(e1,e2)) {
// they are tangent
return internal::solve_tangent<AK>(e1,e3,res);
}
if(!intersect<AK>(e1,e2)) return res;
Polynomials_for_line_3 pl = line_from_2_planes<AK>(e1,e2);
return solve<AK>(pl,e3,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_for_spheres_2_3& e1,
const typename AK::Polynomial_1_3 & e2,
const typename AK::Polynomial_1_3 & e3,
OutputIterator res )
{
return solve<AK>(e2,e3,e1,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_for_spheres_2_3& e1,
const typename AK::Polynomial_for_spheres_2_3& e2,
const typename AK::Polynomial_1_3 & e3,
OutputIterator res )
{
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
// we put as a precondition that the polynomial for spheres represents
// a sphere and not an isolated point or an empty_space
CGAL_kernel_precondition(!(e1.empty_space() || e1.isolated_point()));
CGAL_kernel_precondition(!(e2.empty_space() || e2.isolated_point()));
// The solve can only be points or nothing
if(e1 == e2) {
if(tangent<AK>(e3,e1)) {
return internal::solve_tangent<AK>(e3,e1,res);
}
CGAL_kernel_precondition(!(intersect<AK>(e3,e1)));
return res;
}
if(intersect<AK>(e1,e2)) {
const Polynomial_1_3 p1 = plane_from_2_spheres<AK>(e1,e2);
return solve<AK>(p1,e3,e1,res);
} return res;
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_1_3 & e1,
const typename AK::Polynomial_for_spheres_2_3& e2,
const typename AK::Polynomial_for_spheres_2_3& e3,
OutputIterator res )
{
return solve<AK>(e2,e3,e1,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e1,
const typename AK::Polynomial_1_3 & e2,
OutputIterator res )
{
return solve<AK>(e1.first,e1.second,e2,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_1_3 & e1,
const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e2,
OutputIterator res )
{
return solve<AK>(e2,e1,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e1,
const typename AK::Polynomial_for_spheres_2_3 & e2,
OutputIterator res )
{
return solve<AK>(e1.first, e2, e1.second,res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve(const typename AK::Polynomial_for_spheres_2_3 & e1,
const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e2,
OutputIterator res )
{
return solve<AK>(e2,e1, res);
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e1,
const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e2,
OutputIterator res )
{
typedef typename AK::RT RT;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s1 = e1.first;
const Polynomial_for_spheres_2_3 &s2 = e2.first;
const Polynomial_1_3 &p1 = e1.second;
const Polynomial_1_3 &p2 = e2.second;
// The two circles cannot be equal
// this equality function assumes that the polynomial for sphere represent
// the sphere with the least radius that produces the circle
// this is an unique representation, and it is more efficient
// since the function to see if 2 circles are equal are much more efficient
CGAL_kernel_precondition((!(e1 == e2)) || (same_solutions<RT>(p1,p2)));
// Let say that the 2 pairs of equation must be a circle or a point at least
// ASK: What about removing this pre-condition since it is an Algebraic Kernel?
CGAL_kernel_precondition((intersect<AK>(p1,s1)));
CGAL_kernel_precondition((intersect<AK>(p2,s2)));
if(p1.empty_space()) return res;
if(p2.empty_space()) return res;
if(p1.undefined()) {
return solve<AK>(s1, s2, p2, res);
}
if(p2.undefined()) {
return solve<AK>(s1, s2, p1, res);
}
if(same_solutions<RT>(p1, p2)) {
return solve<AK>(s1, s2, p1, res);
}
typedef std::vector< std::pair<Root_for_spheres_2_3, int> > solutions_container;
solutions_container solutions;
solve<AK>(p1, p2, s1, std::back_inserter(solutions));
if(solutions.size() == 0) return res;
if(solutions.size() == 1) {
if(sign_at<AK>(s2, solutions[0].first) == ZERO) {
*res++ = solutions[0];
} return res;
}
// number of solution = 2, we need to set the correct multiplicity
bool k1 = (sign_at<AK>(s2, solutions[0].first) == ZERO),
k2 = (sign_at<AK>(s2, solutions[1].first) == ZERO);
if(k1 && k2) {
*res++ = solutions[0];
*res++ = solutions[1];
return res;
}
if(k1) {
solutions[0].second = 2u;
*res++ = solutions[0];
return res;
}
if(k2) {
solutions[1].second = 2u;
*res++ = solutions[1];
return res;
}
return res;
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e1,
const typename AK::Polynomials_for_line_3 & l,
OutputIterator res )
{
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s1 = e1.first;
const Polynomial_1_3 &p1 = e1.second;
// Let say that the 2 pairs of equation must be a circle or a point at least
// ASK: What about removing this pre-condition since it is an Algebraic Kernel?
CGAL_kernel_precondition((intersect<AK>(p1,s1)));
CGAL_kernel_precondition(!(l.degenerated()));
if(p1.empty_space()) return res;
if(p1.undefined()) {
return solve<AK>(s1, l, res);
}
typedef std::vector< std::pair<Root_for_spheres_2_3, int> > solutions_container;
solutions_container solutions;
solve<AK>(s1, l, std::back_inserter(solutions));
if(solutions.size() == 0) return res;
if(solutions.size() == 1) {
if(sign_at<AK>(p1, solutions[0].first) == ZERO) {
*res++ = solutions[0];
} return res;
}
// number of solution = 2, we need to set the correct multiplicity
bool k1 = (sign_at<AK>(p1, solutions[0].first) == ZERO),
k2 = (sign_at<AK>(p1, solutions[1].first) == ZERO);
if(k1 && k2) {
*res++ = solutions[0];
*res++ = solutions[1];
return res;
}
if(k1) {
solutions[0].second = 2u;
*res++ = solutions[0];
return res;
}
if(k2) {
solutions[1].second = 2u;
*res++ = solutions[1];
return res;
}
return res;
}
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomials_for_line_3 & l,
const std::pair<typename AK::Polynomial_for_spheres_2_3, typename AK::Polynomial_1_3 > & e1,
OutputIterator res ) {
return solve<AK>(e1, l, res);
}
} // namespace AlgebraicSphereFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIAL_1_3_AND_2_3_H
@@ -0,0 +1,67 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
#ifndef CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_1_3_H
#define CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_1_3_H
#include <CGAL/license/Circular_kernel_3.h>
namespace CGAL {
namespace AlgebraicSphereFunctors {
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_1_3 & e1,
const typename AK::Polynomial_1_3 & e2,
const typename AK::Polynomial_1_3 & e3,
OutputIterator res )
{
typedef typename AK::FT FT;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
CGAL_kernel_precondition(!(same_solutions<FT>(e1,e2) || same_solutions<FT>(e1,e3) ||
same_solutions<FT>(e2,e3)));
const FT &a1 = e1.a();
const FT &a2 = e2.a();
const FT &a3 = e3.a();
const FT &b1 = e1.b();
const FT &b2 = e2.b();
const FT &b3 = e3.b();
const FT &c1 = e1.c();
const FT &c2 = e2.c();
const FT &c3 = e3.c();
const FT &d1 = e1.d();
const FT &d2 = e2.d();
const FT &d3 = e3.d();
FT denominateur = (a1*b2*c3-a1*b3*c2-a2*b1*c3+a2*b3*c1-a3*b2*c1+a3*b1*c2);
//if denominateur == 0 it's because the planes are parallel
if (denominateur == 0) return res;
FT z = -(a2*b3*d1-a1*b3*d2+a1*b2*d3-a3*b2*d1-a2*b1*d3+a3*b1*d2)/denominateur;
FT y = (-a1*d2*c3+a1*c2*d3-a2*c1*d3-a3*c2*d1+a3*c1*d2+a2*c3*d1)/denominateur;
FT x = -(-b1*d2*c3+b1*c2*d3+b3*c1*d2-b2*c1*d3+b2*d1*c3-b3*c2*d1)/denominateur;
*res++ = std::make_pair(Root_for_spheres_2_3(x,y,z),
static_cast<unsigned>(1));
return res;
}
}
}
#endif //CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_1_3_H
@@ -0,0 +1,464 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
#ifndef CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_3_H
#define CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_3_H
#include <CGAL/license/Circular_kernel_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/internal_functions_on_roots_and_polynomial_1_3_and_2_3.h>
namespace CGAL {
namespace AlgebraicSphereFunctors {
template < class AK, class OutputIterator >
inline
OutputIterator
solve( const typename AK::Polynomial_for_spheres_2_3 &e1,
const typename AK::Polynomial_for_spheres_2_3 &e2,
const typename AK::Polynomial_for_spheres_2_3 &e3,
OutputIterator res )
{
typedef typename AK::FT FT;
CGAL_kernel_precondition(!((e1 == e2) && (e2 == e3)));
// we put as a precondition that the polynomial for spheres represents
// a sphere and not an isolated point or an empty_space
CGAL_kernel_precondition(!(e1.empty_space() || e1.isolated_point()));
CGAL_kernel_precondition(!(e2.empty_space() || e2.isolated_point()));
CGAL_kernel_precondition(!(e3.empty_space() || e3.isolated_point()));
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
// The degenerated cases are 2 tangent spheres
// os 2 non-intersecting spheres
// beacause we cannot have infinitely many solutions
if(e1 == e2) {
if(tangent<AK>(e1,e3)) {
Polynomial_1_3 p = plane_from_2_spheres<AK>(e1,e3);
return internal::solve_tangent<AK>(p,e1,res);
}
CGAL_kernel_precondition(!(intersect<AK>(e1,e3)));
return res;
}
if((e1 == e3) || (e2 == e3)) {
if(tangent<AK>(e1,e2)) {
Polynomial_1_3 p = plane_from_2_spheres<AK>(e1,e2);
return internal::solve_tangent<AK>(p,e1,res);
}
CGAL_kernel_precondition(!(intersect<AK>(e1,e2)));
return res;
}
// non degenerated case
if(intersect<AK>(e1,e2)) {
Polynomial_1_3 p1 = plane_from_2_spheres<AK>(e1,e2);
if(intersect<AK>(e2,e3)) {
Polynomial_1_3 p2 = plane_from_2_spheres<AK>(e2,e3);
if(same_solutions<FT>(p1,p2)) {
const FT sq_d1 = CGAL::square(p1.a()*e1.a() + p1.b()*e1.b() +
p1.c()*e1.c() + p1.d()) /
(square(p1.a()) + square(p1.b()) + square(p1.c()));
const FT r1_sqr = e1.r_sq() - sq_d1;
const FT sq_d2 = CGAL::square(p2.a()*e2.a() + p2.b()*e2.b() +
p2.c()*e2.c() + p2.d()) /
(square(p2.a()) + square(p2.b()) + square(p2.c()));
const FT r2_sqr = e2.r_sq() - sq_d2;
if(r1_sqr != r2_sqr) return res;
// otherwise there are an infinite number of points
// this is not allowed
CGAL_kernel_precondition(r1_sqr == 0);
return internal::solve_tangent<AK>(p1,e1,res);
}
return solve<AK>(p1,p2,e2,res);
} return res;
} return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
x_critical_point(const typename AK::Polynomial_for_spheres_2_3 & s, bool i)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
return Root_for_spheres_2_3(
make_root_of_2(s.a(),typename AK::FT(i?-1:1),s.r_sq()),
Root_of_2(s.b()),
Root_of_2(s.c()));
}
template <class AK, class OutputIterator>
OutputIterator
x_critical_points(const typename AK::Polynomial_for_spheres_2_3 & s, OutputIterator res)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::FT FT;
*res++ = Root_for_spheres_2_3(make_root_of_2(s.a(),FT(-1),s.r_sq()),
Root_of_2(s.b()),
Root_of_2(s.c()));
*res++ = Root_for_spheres_2_3(make_root_of_2(s.a(),FT(1),s.r_sq()),
Root_of_2(s.b()),
Root_of_2(s.c()));
return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
y_critical_point(const typename AK::Polynomial_for_spheres_2_3 &s, bool i)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
return Root_for_spheres_2_3(
Root_of_2(s.a()),
make_root_of_2(s.b(),typename AK::FT(i?-1:1),s.r_sq()),
Root_of_2(s.c()));
}
template <class AK, class OutputIterator>
OutputIterator
y_critical_points(const typename AK::Polynomial_for_spheres_2_3 & s, OutputIterator res)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::FT FT;
*res++ = Root_for_spheres_2_3(Root_of_2(s.a()),
make_root_of_2(s.b(),FT(-1),s.r_sq()),
Root_of_2(s.c()));
*res++ = Root_for_spheres_2_3(Root_of_2(s.a()),
make_root_of_2(s.b(),FT(1),s.r_sq()),
Root_of_2(s.c()));
return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
z_critical_point(const typename AK::Polynomial_for_spheres_2_3 &s, bool i)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
return Root_for_spheres_2_3(Root_of_2(s.a()),
Root_of_2(s.b()),
make_root_of_2(s.c(),typename AK::FT(i?-1:1),s.r_sq()));
}
template <class AK, class OutputIterator>
OutputIterator
z_critical_points(const typename AK::Polynomial_for_spheres_2_3 & s, OutputIterator res)
{
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::FT FT;
*res++ = Root_for_spheres_2_3(Root_of_2(s.a()),
Root_of_2(s.b()),
make_root_of_2(s.c(),FT(-1),s.r_sq()));
*res++ = Root_for_spheres_2_3(Root_of_2(s.a()),
Root_of_2(s.b()),
make_root_of_2(s.c(),FT(1),s.r_sq()));
return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
x_critical_point( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c, bool i)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.b()) && is_zero(p.c())));
const FT sqbc = CGAL::square(p.b()) + CGAL::square(p.c());
const FT sq_sum = sqbc + CGAL::square(p.a());
const FT delta = (sqbc * s.r_sq())/sq_sum;
const FT cy = (p.a()*p.b())/sqbc;
const FT cz = (p.a()*p.c())/sqbc;
const Root_of_2 x = make_root_of_2(s.a(),FT(i?-1:1),delta);
const Root_of_2 y = make_root_of_2(s.b(),FT(i?(cy):FT(-cy)),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?(cz):FT(-cz)),delta);
return Root_for_spheres_2_3(x,y,z);
}
template <class AK, class OutputIterator>
OutputIterator
x_critical_points( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c,
OutputIterator res)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.b()) && is_zero(p.c())));
const FT sqbc = CGAL::square(p.b()) + CGAL::square(p.c());
const FT sq_sum = sqbc + CGAL::square(p.a());
const FT delta = (sqbc * s.r_sq())/sq_sum;
const FT cy = (p.a()*p.b())/sqbc;
const FT cz = (p.a()*p.c())/sqbc;
const Root_of_2 x1 = make_root_of_2(s.a(),-1,delta);
const Root_of_2 y1 = make_root_of_2(s.b(),cy,delta);
const Root_of_2 z1 = make_root_of_2(s.c(),cz,delta);
const Root_of_2 x2 = make_root_of_2(s.a(),1,delta);
const Root_of_2 y2 = make_root_of_2(s.b(),-cy,delta);
const Root_of_2 z2 = make_root_of_2(s.c(),-cz,delta);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x2,y2,z2);
return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
y_critical_point( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c, bool i)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.a()) && is_zero(p.c())));
const FT sqac = CGAL::square(p.a()) + CGAL::square(p.c());
const FT sq_sum = sqac + CGAL::square(p.b());
const FT delta = (sqac * s.r_sq())/sq_sum;
const FT cx = (p.a()*p.b())/sqac;
const FT cz = (p.c()*p.b())/sqac;
if(!is_positive(cx)) {
const Root_of_2 x = make_root_of_2(s.a(),FT(i?(cx):FT(-cx)),delta);
const Root_of_2 y = make_root_of_2(s.b(),FT(i?-1:1),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?(cz):FT(-cz)),delta);
return Root_for_spheres_2_3(x,y,z);
} else {
const Root_of_2 x = make_root_of_2(s.a(),FT(i?FT(-cx):(cx)),delta);
const Root_of_2 y = make_root_of_2(s.b(),FT(i?1:-1),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?FT(-cz):(cz)),delta);
return Root_for_spheres_2_3(x,y,z);
}
}
template <class AK, class OutputIterator>
OutputIterator
y_critical_points( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c,
OutputIterator res)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.a()) && is_zero(p.c())));
const FT sqac = CGAL::square(p.a()) + CGAL::square(p.c());
const FT sq_sum = sqac + CGAL::square(p.b());
const FT delta = (sqac * s.r_sq())/sq_sum;
const FT cx = (p.a()*p.b())/sqac;
const FT cz = (p.c()*p.b())/sqac;
const Root_of_2 x1 = make_root_of_2(s.a(),cx,delta);
const Root_of_2 y1 = make_root_of_2(s.b(),FT(-1),delta);
const Root_of_2 z1 = make_root_of_2(s.c(),cz,delta);
const Root_of_2 x2 = make_root_of_2(s.a(),-cx,delta);
const Root_of_2 y2 = make_root_of_2(s.b(),FT(1),delta);
const Root_of_2 z2 = make_root_of_2(s.c(),-cz,delta);
if(!is_positive(cx)) {
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x2,y2,z2);
} else {
*res++ = Root_for_spheres_2_3(x2,y2,z2);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
}
return res;
}
template <class AK>
typename AK::Root_for_spheres_2_3
z_critical_point( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c, bool i)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.a()) && is_zero(p.b())));
const FT sqab = CGAL::square(p.a()) + CGAL::square(p.b());
const FT sq_sum = sqab + CGAL::square(p.c());
const FT delta = (sqab * s.r_sq())/sq_sum;
const FT cx = (p.a()*p.c())/sqab;
const FT cy = (p.c()*p.b())/sqab;
if(is_negative(cx)) {
const Root_of_2 x = make_root_of_2(s.a(),FT(i?(cx):FT(-cx)),delta);
const Root_of_2 y = make_root_of_2(s.b(),FT(i?(cy):FT(-cy)),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?-1:1),delta);
return Root_for_spheres_2_3(x,y,z);
} else if(is_zero(cx)) {
if(!is_positive(cy)) {
const Root_of_2 x = s.a();
const Root_of_2 y = make_root_of_2(s.b(),FT(i?(cy):FT(-cy)),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?-1:1),delta);
return Root_for_spheres_2_3(x,y,z);
} else {
const Root_of_2 x = s.a();
const Root_of_2 y = make_root_of_2(s.b(),FT(i?FT(-cy):(cy)),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?1:-1),delta);
return Root_for_spheres_2_3(x,y,z);
}
} else {
const Root_of_2 x = make_root_of_2(s.a(),FT(i?FT(-cx):(cx)),delta);
const Root_of_2 y = make_root_of_2(s.b(),FT(i?FT(-cy):(cy)),delta);
const Root_of_2 z = make_root_of_2(s.c(),FT(i?1:-1),delta);
return Root_for_spheres_2_3(x,y,z);
}
}
template <class AK, class OutputIterator>
OutputIterator
z_critical_points( const std::pair<typename AK::Polynomial_for_spheres_2_3,
typename AK::Polynomial_1_3 > &c,
OutputIterator res)
{
typedef typename AK::FT FT;
typedef typename AK::Root_of_2 Root_of_2;
typedef typename AK::Root_for_spheres_2_3 Root_for_spheres_2_3;
typedef typename AK::Polynomial_for_spheres_2_3 Polynomial_for_spheres_2_3;
typedef typename AK::Polynomial_1_3 Polynomial_1_3;
const Polynomial_for_spheres_2_3 &s = c.first;
const Polynomial_1_3 &p = c.second;
// It has to be the equation of a diametral circle
CGAL_kernel_precondition((intersect<AK>(p,s)));
CGAL_kernel_precondition(CGAL_NTS sign(p.a() * s.a() + p.b() * s.b() +
p.c() * s.c() + p.d()) == ZERO);
CGAL_kernel_precondition(!(is_zero(p.a()) && is_zero(p.b())));
const FT sqab = CGAL::square(p.a()) + CGAL::square(p.b());
const FT sq_sum = sqab + CGAL::square(p.c());
const FT delta = (sqab * s.r_sq())/sq_sum;
const FT cx = (p.a()*p.c())/sqab;
const FT cy = (p.c()*p.b())/sqab;
if(is_negative(cx)) {
const Root_of_2 x1 = make_root_of_2(s.a(),(cx),delta);
const Root_of_2 y1 = make_root_of_2(s.b(),(cy),delta);
const Root_of_2 z1 = make_root_of_2(s.c(),-1,delta);
const Root_of_2 x2 = make_root_of_2(s.a(),(-cx),delta);
const Root_of_2 y2 = make_root_of_2(s.b(),(-cy),delta);
const Root_of_2 z2 = make_root_of_2(s.c(),1,delta);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x2,y2,z2);
} else if(is_zero(cx)) {
if(!is_positive(cy)) {
const Root_of_2 x1 = s.a();
const Root_of_2 y1 = make_root_of_2(s.b(),(cy),delta);
const Root_of_2 z1 = make_root_of_2(s.c(),FT(-1),delta);
const Root_of_2 y2 = make_root_of_2(s.b(),(-cy),delta);
const Root_of_2 z2 = make_root_of_2(s.c(),FT(1),delta);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x1,y2,z2);
} else {
const Root_of_2 x1 = s.a();
const Root_of_2 y1 = make_root_of_2(s.b(),(-cy),delta);
const Root_of_2 z1 = make_root_of_2(s.c(),FT(1),delta);
const Root_of_2 y2 = make_root_of_2(s.b(),(cy),delta);
const Root_of_2 z2 = make_root_of_2(s.c(),FT(-1),delta);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x1,y2,z2);
}
} else {
const Root_of_2 x1 = make_root_of_2(s.a(),(-cx),delta);
const Root_of_2 y1 = make_root_of_2(s.b(),(-cy),delta);
const Root_of_2 z1 = make_root_of_2(s.c(),FT(1),delta);
const Root_of_2 x2 = make_root_of_2(s.a(),(cx),delta);
const Root_of_2 y2 = make_root_of_2(s.b(),(cy),delta);
const Root_of_2 z2 = make_root_of_2(s.c(),FT(-1),delta);
*res++ = Root_for_spheres_2_3(x1,y1,z1);
*res++ = Root_for_spheres_2_3(x2,y2,z2);
}
return res;
}
} // namespace AlgebraicSphereFunctors
} // namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FUNCTIONS_ON_ROOTS_AND_POLYNOMIALS_2_3_H
@@ -0,0 +1,121 @@
// Copyright (c) 2005-2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// Partially supported by the IST Programme of the EU as a Shared-cost
// RTD (FET Open) Project under Contract No IST-2000-26473
// (ECG - Effective Computational Geometry for Curves and Surfaces)
// and a STREP (FET Open) Project under Contract No IST-006413
// (ACS -- Algorithms for Complex Shapes)
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
// Sylvain Pion
// Pedro Machado
// Julien Hazebrouck
// Damien Leroy
#ifndef CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_2_3_H
#define CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_2_3_H
#include <CGAL/license/Circular_kernel_3.h>
#include <CGAL/Root_of_traits.h>
#include <CGAL/Polynomials_2_3.h>
#include <CGAL/Polynomials_1_3.h>
#include <CGAL/Polynomials_for_line_3.h>
#include <CGAL/Root_for_spheres_2_3.h>
#include <CGAL/Algebraic_kernel_for_spheres/function_objects_on_roots_and_polynomials_2_3.h>
#include <CGAL/global_functions_on_roots_and_polynomials_1_3.h>
#include <CGAL/global_functions_on_roots_and_polynomials_2_3.h>
#include <CGAL/global_functions_on_root_for_sphere_2_3.h>
namespace CGAL {
template< class RT_ >
struct Algebraic_kernel_for_spheres_2_3
{
typedef Algebraic_kernel_for_spheres_2_3<RT_> Self;
typedef RT_ RT;
typedef typename Root_of_traits< RT >::RootOf_1 FT;
typedef CGAL::Polynomials_for_line_3<FT> Polynomials_for_line_3;
typedef CGAL::Polynomial_for_spheres_2_3<FT> Polynomial_for_spheres_2_3;
typedef CGAL::Polynomial_1_3<FT> Polynomial_1_3;
// problem RT / FT ?
typedef typename Root_of_traits< RT >::RootOf_2 Root_of_2;
typedef CGAL::Root_for_spheres_2_3< RT > Root_for_spheres_2_3;
typedef AlgebraicSphereFunctors::Construct_polynomial_for_spheres_2_3<Self>
Construct_polynomial_for_spheres_2_3;
typedef AlgebraicSphereFunctors::Construct_polynomial_1_3<Self>
Construct_polynomial_1_3;
typedef AlgebraicSphereFunctors::Construct_polynomials_for_line_3<Self>
Construct_polynomials_for_line_3;
typedef AlgebraicSphereFunctors::Solve<Self> Solve;
typedef AlgebraicSphereFunctors::Sign_at<Self> Sign_at;
typedef AlgebraicSphereFunctors::X_critical_points<Self> X_critical_points;
typedef AlgebraicSphereFunctors::Y_critical_points<Self> Y_critical_points;
typedef AlgebraicSphereFunctors::Z_critical_points<Self> Z_critical_points;
typedef AlgebraicSphereFunctors::Compare_x<RT> Compare_x;
typedef AlgebraicSphereFunctors::Compare_y<RT> Compare_y;
typedef AlgebraicSphereFunctors::Compare_z<RT> Compare_z;
typedef AlgebraicSphereFunctors::Compare_xy<RT> Compare_xy;
typedef AlgebraicSphereFunctors::Compare_xyz<RT> Compare_xyz;
Construct_polynomial_for_spheres_2_3
construct_polynomial_for_spheres_2_3_object() const
{ return Construct_polynomial_for_spheres_2_3(); }
Construct_polynomial_1_3
construct_polynomial_1_3_object() const
{ return Construct_polynomial_1_3(); }
Construct_polynomials_for_line_3
construct_polynomials_for_line_3_object() const
{ return Construct_polynomials_for_line_3(); }
Solve solve_object() const
{ return Solve(); }
Sign_at sign_at_object() const
{ return Sign_at(); }
X_critical_points x_critical_points_object() const
{ return X_critical_points(); }
Y_critical_points y_critical_points_object() const
{ return Y_critical_points(); }
Z_critical_points z_critical_points_object() const
{ return Z_critical_points(); }
Compare_x compare_x_object() const
{ return Compare_x(); }
Compare_y compare_y_object() const
{ return Compare_y(); }
Compare_z compare_z_object() const
{ return Compare_z(); }
Compare_xy compare_xy_object() const
{ return Compare_xy(); }
Compare_xyz compare_xyz_object() const
{ return Compare_xyz(); }
};
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_FOR_SPHERES_2_3_H
@@ -0,0 +1,114 @@
// Copyright (c) 2006-2013 INRIA Nancy-Grand Est (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author: Luis Peñaranda <luis.penaranda@gmx.com>
#ifndef CGAL_ALGEBRAIC_KERNEL_RS_GMPQ_D_1
#define CGAL_ALGEBRAIC_KERNEL_RS_GMPQ_D_1
#include <CGAL/disable_warnings.h>
#include <CGAL/Gmpq.h>
#include <CGAL/Gmpfr.h>
#include <CGAL/Polynomial.h>
#include "RS/rs2_isolator_1.h"
#ifdef CGAL_USE_RS3
#include "RS/rs23_k_isolator_1.h"
#include "RS/rs3_refiner_1.h"
#include "RS/rs3_k_refiner_1.h"
#else
#include "RS/bisection_refiner_1.h"
#endif
#ifdef CGAL_RS_USE_NATIVE_GMPQ_KERNEL
#include "RS/ak_1.h"
#else
#include "RS/ak_z_1.h"
#endif
// The RS algebraic kernel for non-Gmpz types comes in two flavors. The
// native kernel converts, before each operation, the input polynomial to a
// Polynomial<Gmpz>. The z-kernel only converts to a Polynomial<Gmpz>
// before isolation and stores both polynomials in the algebraic number.
// The latter is the default behavior, but the former can be selected by
// setting the compilation flag CGAL_RS_USE_NATIVE_GMPQ_KERNEL.
namespace CGAL{
#ifdef CGAL_RS_USE_NATIVE_GMPQ_KERNEL // Use the native kernel.
// Choice of the isolator: RS default or RS-k.
#ifdef CGAL_RS_USE_K
typedef CGAL::RS23_k_isolator_1<CGAL::Polynomial<CGAL::Gmpq>,CGAL::Gmpfr>
QIsolator;
#else
typedef CGAL::RS2::RS2_isolator_1<CGAL::Polynomial<CGAL::Gmpq>,CGAL::Gmpfr>
QIsolator;
#endif
// Choice of the refiner: bisection, RS3 or RS3-k.
#ifdef CGAL_USE_RS3
#ifdef CGAL_RS_USE_K
typedef CGAL::RS3::RS3_k_refiner_1<CGAL::Polynomial<CGAL::Gmpq>,CGAL::Gmpfr>
QRefiner;
#else
typedef CGAL::RS3::RS3_refiner_1<CGAL::Polynomial<CGAL::Gmpq>,CGAL::Gmpfr>
QRefiner;
#endif
#else
typedef CGAL::Bisection_refiner_1<CGAL::Polynomial<CGAL::Gmpq>,CGAL::Gmpfr>
QRefiner;
#endif
typedef CGAL::RS_AK1::Algebraic_kernel_1<
CGAL::Polynomial<CGAL::Gmpq>,
CGAL::Gmpfr,
QIsolator,
QRefiner>
Algebraic_kernel_rs_gmpq_d_1;
#else // Use the z-kernel.
// Choice of the z-isolator: RS default or RS-k.
#ifdef CGAL_RS_USE_K
typedef CGAL::RS23_k_isolator_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
ZIsolator;
#else
typedef CGAL::RS2::RS2_isolator_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
ZIsolator;
#endif
// Choice of the z-refiner: bisection, RS3 or RS3-k.
#ifdef CGAL_USE_RS3
#ifdef CGAL_RS_USE_K
typedef CGAL::RS3::RS3_k_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
ZRefiner;
#else
typedef CGAL::RS3::RS3_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
ZRefiner;
#endif
#else
typedef CGAL::Bisection_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
ZRefiner;
#endif
typedef CGAL::RS_AK1::Algebraic_kernel_z_1<
CGAL::Polynomial<CGAL::Gmpq>,
CGAL::Polynomial<CGAL::Gmpz>,
CGAL::RS_AK1::Polynomial_converter_1<CGAL::Polynomial<CGAL::Gmpq>,
CGAL::Polynomial<CGAL::Gmpz> >,
CGAL::Gmpfr,
ZIsolator,
ZRefiner>
Algebraic_kernel_rs_gmpq_d_1;
#endif
} // namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_RS_GMPQ_D_1
@@ -0,0 +1,65 @@
// Copyright (c) 2006-2013 INRIA Nancy-Grand Est (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author: Luis Peñaranda <luis.penaranda@gmx.com>
#ifndef CGAL_ALGEBRAIC_KERNEL_RS_GMPZ_D_1
#define CGAL_ALGEBRAIC_KERNEL_RS_GMPZ_D_1
#include <CGAL/disable_warnings.h>
#include <CGAL/Gmpz.h>
#include <CGAL/Gmpfr.h>
#include <CGAL/Polynomial.h>
#include "RS/rs2_isolator_1.h"
#ifdef CGAL_USE_RS3
#include "RS/rs23_k_isolator_1.h"
#include "RS/rs3_refiner_1.h"
#include "RS/rs3_k_refiner_1.h"
#else
#include "RS/bisection_refiner_1.h"
#endif
#include "RS/ak_1.h"
namespace CGAL{
// Choice of the isolator: RS default or RS-k.
#ifdef CGAL_RS_USE_K
typedef CGAL::RS23_k_isolator_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
Isolator;
#else
typedef CGAL::RS2::RS2_isolator_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
Isolator;
#endif
// Choice of the refiner: bisection, RS3 or RS3-k.
#ifdef CGAL_USE_RS3
#ifdef CGAL_RS_USE_K
typedef CGAL::RS3::RS3_k_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
Refiner;
#else
typedef CGAL::RS3::RS3_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
Refiner;
#endif
#else
typedef CGAL::Bisection_refiner_1<CGAL::Polynomial<CGAL::Gmpz>,CGAL::Gmpfr>
Refiner;
#endif
typedef CGAL::RS_AK1::Algebraic_kernel_1<
CGAL::Polynomial<CGAL::Gmpz>,
CGAL::Gmpfr,
Isolator,
Refiner>
Algebraic_kernel_rs_gmpz_d_1;
}
#include <CGAL/enable_warnings.h>
#endif // CGAL_ALGEBRAIC_KERNEL_RS_GMPZ_D_1
@@ -0,0 +1,618 @@
// Copyright (c) 2006-2007 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// =============================================================================
#ifndef CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H
#define CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H
#include <functional>
#include <CGAL/tags.h>
#include <CGAL/type_traits.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/assertions.h>
#include <CGAL/use.h>
namespace CGAL {
// REMARK: Some of the following comments and references are just copy & pasted
// from EXACUS and have to be adapted/removed in the future.
// The tags for Algebra_type corresponding to the number type concepts
// ===================================================================
//! corresponds to the \c IntegralDomainWithoutDiv concept.
struct Integral_domain_without_division_tag {};
//! corresponds to the \c IntegralDomain concept.
struct Integral_domain_tag : public Integral_domain_without_division_tag {};
//! corresponds to the \c UFDomain concept.
struct Unique_factorization_domain_tag : public Integral_domain_tag {};
//! corresponds to the \c EuclideanRing concept.
struct Euclidean_ring_tag : public Unique_factorization_domain_tag {};
//! corresponds to the \c Field concept.
struct Field_tag : public Integral_domain_tag {};
//! corresponds to the \c FieldWithSqrt concept.
struct Field_with_sqrt_tag : public Field_tag {};
//! corresponds to the \c FieldWithKthRoot concept
struct Field_with_kth_root_tag : public Field_with_sqrt_tag {};
//! corresponds to the \c FieldWithRootOF concept.
struct Field_with_root_of_tag : public Field_with_kth_root_tag {};
// The algebraic structure traits template
// =========================================================================
template< class Type_ >
class Algebraic_structure_traits {
public:
typedef Type_ Type;
typedef Null_tag Algebraic_category;
typedef Null_tag Is_exact;
typedef Null_tag Is_numerical_sensitive;
typedef Null_functor Simplify;
typedef Null_functor Unit_part;
typedef Null_functor Integral_division;
typedef Null_functor Is_square;
typedef Null_functor Gcd;
typedef Null_functor Div_mod;
typedef Null_functor Div;
typedef Null_functor Mod;
typedef Null_functor Square;
typedef Null_functor Is_zero;
typedef Null_functor Is_one;
typedef Null_functor Sqrt;
typedef Null_functor Kth_root;
typedef Null_functor Root_of;
typedef Null_functor Divides;
typedef Null_functor Inverse;
};
// The algebraic structure traits base class
// =========================================================================
template< class Type, class Algebra_type >
class Algebraic_structure_traits_base;
//! The template specialization that can be used for types that are not any
//! of the number type concepts. All functors are set to \c Null_functor
//! or suitable defaults. The \c Simplify functor does nothing by default.
template< class Type_ >
class Algebraic_structure_traits_base< Type_, Null_tag > {
public:
typedef Type_ Type;
typedef Null_tag Algebraic_category;
typedef Tag_false Is_exact;
typedef Null_tag Is_numerical_sensitive;
typedef Null_tag Boolean;
// does nothing by default
class Simplify
: public CGAL::cpp98::unary_function< Type&, void > {
public:
void operator()( Type& ) const {}
};
typedef Null_functor Unit_part;
typedef Null_functor Integral_division;
typedef Null_functor Is_square;
typedef Null_functor Gcd;
typedef Null_functor Div_mod;
typedef Null_functor Div;
typedef Null_functor Mod;
typedef Null_functor Square;
typedef Null_functor Is_zero;
typedef Null_functor Is_one;
typedef Null_functor Sqrt;
typedef Null_functor Kth_root;
typedef Null_functor Root_of;
typedef Null_functor Divides;
typedef Null_functor Inverse;
};
//! The template specialization that is used if the number type is
//! a model of the \c IntegralDomainWithoutDiv concept. The \c Simplify
//! does nothing by default and the \c Unit_part is equal to
//! \c Type(-1) for negative numbers and
//! \c Type(1) otherwise
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Integral_domain_without_division_tag >
: public Algebraic_structure_traits_base< Type_,
Null_tag > {
public:
typedef Type_ Type;
typedef Integral_domain_without_division_tag Algebraic_category;
typedef bool Boolean;
// returns Type(1) by default
class Unit_part
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return( x < Type(0)) ?
Type(-1) : Type(1);
}
};
class Square
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return x*x;
}
};
class Is_zero
: public CGAL::cpp98::unary_function< Type, bool > {
public:
bool operator()( const Type& x ) const {
return x == Type(0);
}
};
class Is_one
: public CGAL::cpp98::unary_function< Type, bool > {
public:
bool operator()( const Type& x ) const {
return x == Type(1);
}
};
};
//! The template specialization that is used if the number type is
//! a model of the \c IntegralDomain concept. It is equivalent to the
//! specialization
//! for the \c IntegralDomainWithoutDiv concept. The additionally required
//! \c Integral_division functor needs to be implemented in the
//! \c Algebraic_structure_traits itself.
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Integral_domain_tag >
: public Algebraic_structure_traits_base< Type_,
Integral_domain_without_division_tag > {
public:
typedef Type_ Type;
typedef Integral_domain_tag Algebraic_category;
};
//! The template specialization that is used if the number type is
//! a model of the \c UFDomain concept. It is equivalent to the specialization
//! for the \c IntegralDomain concept. The additionally required
//! \c Integral_div functor
//! and \c Gcd functor need to be implemented in the
//! \c Algebraic_structure_traits itself.
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Unique_factorization_domain_tag >
: public Algebraic_structure_traits_base< Type_,
Integral_domain_tag > {
public:
typedef Type_ Type;
typedef Unique_factorization_domain_tag Algebraic_category;
// Default implementation of Divides functor for unique factorization domains
// x divides y if gcd(y,x) equals x up to inverses
class Divides
: public CGAL::cpp98::binary_function<Type,Type,bool>{
public:
bool operator()( const Type& x, const Type& y) const {
typedef CGAL::Algebraic_structure_traits<Type> AST;
typename AST::Gcd gcd;
typename AST::Unit_part unit_part;
typename AST::Integral_division idiv;
return gcd(y,x) == idiv(x,unit_part(x));
}
// second operator computing q = x/y
bool operator()( const Type& x, const Type& y, Type& q) const {
typedef CGAL::Algebraic_structure_traits<Type> AST;
typename AST::Integral_division idiv;
bool result = (*this)(x,y);
if( result == true )
q = idiv(x,y);
return result;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool)
};
};
//! The template specialization that is used if the number type is
//! a model of the \c EuclideanRing concept.
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Euclidean_ring_tag >
: public Algebraic_structure_traits_base< Type_,
Unique_factorization_domain_tag > {
public:
typedef Type_ Type;
typedef Euclidean_ring_tag Algebraic_category;
// maps to \c Div by default.
class Integral_division
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()(
const Type& x,
const Type& y) const {
typedef Algebraic_structure_traits<Type> AST;
typedef typename AST::Is_exact Is_exact;
CGAL_USE_TYPE(Is_exact);
typename AST::Div actual_div;
CGAL_precondition_msg(
!Is_exact::value || actual_div( x, y) * y == x,
"'x' must be divisible by 'y' in "
"Algebraic_structure_traits<...>::Integral_div()(x,y)" );
return actual_div( x, y);
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
// Algorithm from NiX/euclids_algorithm.h
class Gcd
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()(
const Type& x,
const Type& y) const {
typedef Algebraic_structure_traits<Type> AST;
typename AST::Mod mod;
typename AST::Unit_part unit_part;
typename AST::Integral_division integral_div;
// First: the extreme cases and negative sign corrections.
if (x == Type(0)) {
if (y == Type(0))
return Type(0);
return integral_div( y, unit_part(y) );
}
if (y == Type(0))
return integral_div(x, unit_part(x) );
Type u = integral_div( x, unit_part(x) );
Type v = integral_div( y, unit_part(y) );
// Second: assuming mod is the most expensive op here,
// we don't compute it unnecessarily if u < v
if (u < v) {
v = mod(v,u);
// maintain invariant of v > 0 for the loop below
if ( v == Type(0) )
return u;
}
// Third: generic case of two positive integer values and u >= v.
// The standard loop would be:
// while ( v != 0) {
// int tmp = mod(u,v);
// u = v;
// v = tmp;
// }
// return u;
//
// But we want to save us all the variable assignments and unroll
// the loop. Before that, we transform it into a do {...} while()
// loop to reduce branching statements.
Type w;
do {
w = mod(u,v);
if ( w == Type(0))
return v;
u = mod(v,w);
if ( u == Type(0))
return w;
v = mod(w,u);
} while (v != Type(0));
return u;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
// based on \c Div and \c Mod.
class Div_mod {
public:
typedef Type first_argument_type;
typedef Type second_argument_type;
typedef Type& third_argument_type;
typedef Type& fourth_argument_type;
typedef void result_type;
void operator()( const Type& x,
const Type& y,
Type& q, Type& r) const {
typedef Algebraic_structure_traits<Type> Traits;
typename Traits::Div actual_div;
typename Traits::Mod actual_mod;
q = actual_div( x, y );
r = actual_mod( x, y );
return;
}
template < class NT1, class NT2 >
void operator()(
const NT1& x,
const NT2& y,
Type& q,
Type& r ) const {
typedef Coercion_traits< NT1, NT2 > CT;
typedef typename CT::Type Coercion_type_NT1_NT2;
CGAL_USE_TYPE(Coercion_type_NT1_NT2);
CGAL_static_assertion((
::boost::is_same<Coercion_type_NT1_NT2 , Type >::value));
typename Coercion_traits< NT1, NT2 >::Cast cast;
operator()( cast(x), cast(y), q, r );
}
};
// based on \c Div_mod.
class Div
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y) const {
typename Algebraic_structure_traits<Type>
::Div_mod actual_div_mod;
Type q;
Type r;
actual_div_mod( x, y, q, r );
return q;
};
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
// based on \c Div_mod.
class Mod
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y) const {
typename Algebraic_structure_traits<Type>
::Div_mod actual_div_mod;
Type q;
Type r;
actual_div_mod( x, y, q, r );
return r;
};
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
// Divides for Euclidean Ring
class Divides
: public CGAL::cpp98::binary_function<Type, Type, bool>{
public:
bool operator()( const Type& x, const Type& y) const {
typedef Algebraic_structure_traits<Type> AST;
typename AST::Mod mod;
CGAL_precondition(typename AST::Is_zero()(x) == false );
return typename AST::Is_zero()(mod(y,x));
}
// second operator computing q
bool operator()( const Type& x, const Type& y, Type& q) const {
typedef Algebraic_structure_traits<Type> AST;
typename AST::Div_mod div_mod;
CGAL_precondition(typename AST::Is_zero()(x) == false );
Type r;
div_mod(y,x,q,r);
return (typename AST::Is_zero()(r));
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool)
};
};
//! The template specialization that is used if the number type is
//! a model of the \c Field concept. \c Unit_part ()(x)
//! returns \c NT(1) if the value \c x is equal to \c NT(0) and
//! otherwise the value \c x itself. The \c Integral_div
//! maps to the \c operator/.
//! See also \link NiX_NT_traits_functors concept NT_traits \endlink .
//! \ingroup NiX_NT_traits_bases
//
template< class Type_ >
class Algebraic_structure_traits_base< Type_, Field_tag >
: public Algebraic_structure_traits_base< Type_,
Integral_domain_tag > {
public:
typedef Type_ Type;
typedef Field_tag Algebraic_category;
// returns the argument \a a by default
class Unit_part
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return( x == Type(0)) ? Type(1) : x;
}
};
// maps to \c operator/ by default.
class Integral_division
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y) const {
typedef Algebraic_structure_traits<Type> AST;
typedef typename AST::Is_exact Is_exact;
CGAL_USE_TYPE(Is_exact);
CGAL_precondition_code( bool ie = Is_exact::value; )
CGAL_precondition_msg( !ie || (x / y) * y == x,
"'x' must be divisible by 'y' in "
"Algebraic_structure_traits<...>::Integral_div()(x,y)" );
return x / y;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
// maps to \c 1/x by default.
class Inverse
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return Type(1)/x;
}
};
// Default implementation of Divides functor for Field:
// returns always true
// \pre: x != 0
class Divides
: public CGAL::cpp98::binary_function< Type, Type, bool > {
public:
bool operator()( const Type& CGAL_precondition_code(x), const Type& /* y */) const {
CGAL_precondition_code( typedef Algebraic_structure_traits<Type> AST);
CGAL_precondition( typename AST::Is_zero()(x) == false );
return true;
}
// second operator computing q
bool operator()( const Type& x, const Type& y, Type& q) const {
CGAL_precondition_code(typedef Algebraic_structure_traits<Type> AST);
CGAL_precondition( typename AST::Is_zero()(x) == false );
q = y/x;
return true;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool)
};
};
//! The template specialization that is used if the number type is a model
//! of the \c FieldWithSqrt concept. It is equivalent to the
//! specialization for the \c Field concept. The additionally required
//! \c NiX::NT_traits::Sqrt functor need to be
//! implemented in the \c NT_traits itself.
//! \ingroup NiX_NT_traits_bases
//
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Field_with_sqrt_tag>
: public Algebraic_structure_traits_base< Type_,
Field_tag> {
public:
typedef Type_ Type;
typedef Field_with_sqrt_tag Algebraic_category;
struct Is_square
:public CGAL::cpp98::binary_function<Type,Type&,bool>
{
bool operator()(const Type& ) const {return true;}
bool operator()(
const Type& x,
Type & result) const {
typename Algebraic_structure_traits<Type>::Sqrt sqrt;
result = sqrt(x);
return true;
}
};
};
//! The template specialization that is used if the number type is a model
//! of the \c FieldWithKthRoot concept. It is equivalent to the
//! specialization for the \c Field concept. The additionally required
//! \c NiX::NT_traits::Kth_root functor need to be
//! implemented in the \c Algebraic_structure_traits itself.
//! \ingroup NiX_NT_traits_bases
//
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Field_with_kth_root_tag>
: public Algebraic_structure_traits_base< Type_,
Field_with_sqrt_tag> {
public:
typedef Type_ Type;
typedef Field_with_kth_root_tag Algebraic_category;
};
//! The template specialization that is used if the number type is a model
//! of the \c FieldWithRootOf concept. It is equivalent to the
//! specialization for the \c FieldWithKthRoot concept. The additionally
//! required \c NiX::NT_traits::Root_of functor need to be
//! implemented in the \c NT_traits itself.
//! \ingroup NiX_NT_traits_bases
//
template< class Type_ >
class Algebraic_structure_traits_base< Type_,
Field_with_root_of_tag >
: public Algebraic_structure_traits_base< Type_,
Field_with_kth_root_tag > {
public:
typedef Type_ Type;
typedef Field_with_root_of_tag Algebraic_category;
};
// Some common functors to be used by AST specializations
namespace INTERN_AST {
template< class Type >
class Div_per_operator
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y ) const {
return x / y;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
template< class Type >
class Mod_per_operator
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y ) const {
return x % y;
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type )
};
template< class Type >
class Is_square_per_sqrt
: public CGAL::cpp98::binary_function< Type, Type&,
bool > {
public:
bool operator()( const Type& x,
Type& y ) const {
typename Algebraic_structure_traits< Type >::Sqrt
actual_sqrt;
y = actual_sqrt( x );
return y * y == x;
}
bool operator()( const Type& x) const {
Type dummy;
return operator()(x,dummy);
}
};
} // INTERN_AST
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,104 @@
// Copyright (c) 1997, 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Tran Kai Frank DA
#ifndef CGAL_ALPHA_SHAPE_CELL_BASE_3_H
#define CGAL_ALPHA_SHAPE_CELL_BASE_3_H
#include <CGAL/license/Alpha_shapes_3.h>
#include <vector>
#include <CGAL/Compact_container.h>
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
#include <CGAL/Alpha_shapes_3/internal/Lazy_alpha_nt_3.h>
#include <CGAL/Default.h>
namespace CGAL {
template < class NT_>
class Alpha_status
: public Compact_container_base
{
bool _is_Gabriel;
bool _is_on_chull;
NT_ _alpha_min;
NT_ _alpha_mid;
NT_ _alpha_max;
public:
typedef NT_ NT;
Alpha_status() : _is_Gabriel(false), _is_on_chull(false) {}
void set_alpha_min(NT alpha) {_alpha_min = alpha;}
void set_alpha_mid(NT alpha) {_alpha_mid = alpha;}
void set_alpha_max(NT alpha) {_alpha_max = alpha;}
void set_is_Gabriel(bool yesorno) { _is_Gabriel = yesorno;}
void set_is_on_chull(bool yesorno) {_is_on_chull = yesorno;}
NT alpha_min() const { return _alpha_min;}
NT alpha_mid() const { return _alpha_mid;}
NT alpha_max() const { return _alpha_max;}
bool is_Gabriel() const {return _is_Gabriel;}
bool is_on_chull() const {return _is_on_chull;}
};
template < class Gt,
class Cb_ = Default,
class ExactAlphaComparisonTag = Tag_false,
class Weighted_tag = Tag_false >
class Alpha_shape_cell_base_3
: public Default::Get<Cb_, Delaunay_triangulation_cell_base_3<Gt> >::type
{
typedef typename Default::Get<Cb_, Delaunay_triangulation_cell_base_3<Gt> >::type Cb;
public:
typedef typename Cb::Vertex_handle Vertex_handle;
typedef typename Cb::Cell_handle Cell_handle;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Cb::template Rebind_TDS<TDS2>::Other Cb2;
typedef Alpha_shape_cell_base_3<Gt, Cb2,ExactAlphaComparisonTag,Weighted_tag> Other;
};
typedef typename internal::Alpha_nt_selector_3<
Gt,ExactAlphaComparisonTag,Weighted_tag>::Type_of_alpha NT;
typedef CGAL::Alpha_status<NT> Alpha_status;
typedef Compact_container<Alpha_status> Alpha_status_container;
typedef typename Alpha_status_container::const_iterator Alpha_status_const_iterator;
typedef typename Alpha_status_container::iterator Alpha_status_iterator;
private:
Alpha_status_iterator facet_status[4];
NT A;
public:
Alpha_shape_cell_base_3()
: Cb() {}
Alpha_shape_cell_base_3(Vertex_handle v0, Vertex_handle v1,
Vertex_handle v2, Vertex_handle v3)
: Cb(v0, v1, v2, v3) {}
Alpha_shape_cell_base_3(Vertex_handle v0, Vertex_handle v1,
Vertex_handle v2, Vertex_handle v3,
Cell_handle n0, Cell_handle n1,
Cell_handle n2, Cell_handle n3)
: Cb(v0, v1, v2, v3, n0, n1, n2, n3) {}
NT get_alpha() const { return A; }
void set_alpha(const NT & AA) { A = AA;}
Alpha_status_iterator get_facet_status(int i) {return facet_status[i]; }
Alpha_status_const_iterator get_facet_status(int i) const { return facet_status[i]; }
void set_facet_status(int i, Alpha_status_iterator as) { facet_status[i]= as; }
};
} // namespace CGAL
#endif // CGAL_ALPHA_SHAPE_CELL_BASE_3_H
@@ -0,0 +1,94 @@
// Copyright (c) 1997, 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Tran Kai Frank DA <Frank.Da@sophia.inria.fr>
#ifndef CGAL_ALPHA_SHAPE_FACE_BASE_2_H
#define CGAL_ALPHA_SHAPE_FACE_BASE_2_H
#include <CGAL/license/Alpha_shapes_2.h>
#include <CGAL/utility.h>
#include <CGAL/Alpha_shapes_2/internal/Lazy_alpha_nt_2.h>
#include <CGAL/Default.h>
#include <CGAL/Triangulation_face_base_2.h>
namespace CGAL {
template <class Gt,
class Fb_ = Default,
class ExactAlphaComparisonTag = Tag_false,
class Weighted_tag = Tag_false>
class Alpha_shape_face_base_2
: public Default::Get<Fb_, Triangulation_face_base_2<Gt> >::type
{
typedef typename Default::Get<Fb_, Triangulation_face_base_2<Gt> >::type Fb;
public:
typedef typename Fb::Vertex_handle Vertex_handle;
typedef typename Fb::Face_handle Face_handle;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
typedef Alpha_shape_face_base_2<
Gt, Fb2, ExactAlphaComparisonTag, Weighted_tag> Other;
};
typedef typename internal::Alpha_nt_selector_2<
Gt, ExactAlphaComparisonTag, Weighted_tag>::Type_of_alpha Type_of_alpha;
typedef Type_of_alpha NT;
typedef Type_of_alpha FT;
typedef Triple<Type_of_alpha, Type_of_alpha, Type_of_alpha> Interval_3;
private:
Interval_3 vec_edge[3];
Type_of_alpha A;
public:
Alpha_shape_face_base_2() : Fb() {}
Alpha_shape_face_base_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2)
: Fb(v0, v1, v2) {}
Alpha_shape_face_base_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2,
Face_handle n0, Face_handle n1, Face_handle n2)
: Fb(v0, v1, v2, n0, n1, n2)
{}
const Type_of_alpha & get_alpha() const
{
return A;
}
void set_alpha(const Type_of_alpha & AA)
{
A = AA;
}
const Interval_3 & get_ranges(int i) const
{
return vec_edge[i];
}
void set_ranges(int i, const Interval_3& Inter)
{
vec_edge[i]=Inter;
}
};
} //namespace CGAL
#endif //ALPHA_SHAPE_FACE_BASE_2_H
@@ -0,0 +1,80 @@
// Copyright (c) 1997, 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Tran Kai Frank DA <Frank.Da@sophia.inria.fr>
#ifndef CGAL_ALPHA_SHAPE_VERTEX_BASE_2_H
#define CGAL_ALPHA_SHAPE_VERTEX_BASE_2_H
#include <CGAL/license/Alpha_shapes_2.h>
#include <utility>
#include <CGAL/Triangulation_vertex_base_2.h>
#include <CGAL/Alpha_shapes_2/internal/Lazy_alpha_nt_2.h>
//-------------------------------------------------------------------
namespace CGAL {
//-------------------------------------------------------------------
template <class Gt,
class Vb_ = Default,
class ExactAlphaComparisonTag = Tag_false,
class Weighted_tag = Tag_false>
class Alpha_shape_vertex_base_2
: public Default::Get<Vb_, Triangulation_vertex_base_2<Gt> >::type
{
typedef typename Default::Get<Vb_, Triangulation_vertex_base_2<Gt> >::type Vb;
public:
typedef typename Vb::Vertex_handle Vertex_handle;
typedef typename Vb::Face_handle Face_handle;
typedef typename Vb::Point Point;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
typedef Alpha_shape_vertex_base_2<
Gt, Vb2, ExactAlphaComparisonTag, Weighted_tag> Other;
};
typedef typename internal::Alpha_nt_selector_2<
Gt, ExactAlphaComparisonTag, Weighted_tag>::Type_of_alpha Type_of_alpha;
typedef Type_of_alpha NT;
typedef std::pair< Type_of_alpha, Type_of_alpha > Interval2;
private:
Interval2 I;
public:
Alpha_shape_vertex_base_2()
: Vb()
{}
Alpha_shape_vertex_base_2(const Point & p)
: Vb(p)
{}
Alpha_shape_vertex_base_2(const Point & p, Face_handle f)
: Vb(p, f)
{}
public:
inline Interval2 get_range() { return I; }
inline void set_range(Interval2 Inter) { I = Inter; }
};
//-------------------------------------------------------------------
} //namespace CGAL
//-------------------------------------------------------------------
#endif //ALPHA_SHAPE_VERTEX_BASE_2_H
@@ -0,0 +1,72 @@
// Copyright (c) 1997, 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Tran Kai Frank DA
#ifndef CGAL_ALPHA_SHAPE_VERTEX_BASE_3_H
#define CGAL_ALPHA_SHAPE_VERTEX_BASE_3_H
#include <CGAL/license/Alpha_shapes_3.h>
#include <utility>
#include <CGAL/Compact_container.h>
#include <CGAL/Triangulation_vertex_base_3.h>
#include <CGAL/Alpha_shape_cell_base_3.h>
#include <CGAL/Default.h>
namespace CGAL {
template <class Gt,
class Vb_ = Default,
class ExactAlphaComparisonTag = Tag_false,
class Weighted_tag = Tag_false>
class Alpha_shape_vertex_base_3
: public Default::Get<Vb_, Triangulation_vertex_base_3<Gt> >::type
{
typedef typename Default::Get<Vb_, Triangulation_vertex_base_3<Gt> >::type Vb;
public:
typedef typename Vb::Cell_handle Cell_handle;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
typedef Alpha_shape_vertex_base_3<Gt, Vb2, ExactAlphaComparisonTag, Weighted_tag> Other;
};
typedef typename Vb::Point Point;
typedef typename internal::Alpha_nt_selector_3<
Gt, ExactAlphaComparisonTag, Weighted_tag>::Type_of_alpha NT;
typedef CGAL::Alpha_status<NT> Alpha_status;
typedef Compact_container<Alpha_status> Alpha_status_container;
typedef typename Alpha_status_container::const_iterator Alpha_status_const_iterator;
typedef typename Alpha_status_container::iterator Alpha_status_iterator;
private:
Alpha_status _as;
public:
Alpha_shape_vertex_base_3()
: Vb() {}
Alpha_shape_vertex_base_3(const Point& p)
: Vb(p) {}
Alpha_shape_vertex_base_3(const Point& p, Cell_handle c)
: Vb(p, c) {}
Alpha_status* get_alpha_status() { return &_as;}
void set_alpha_status(Alpha_status_iterator as) {_as= as;}
};
} //namespace CGAL
#endif // CGAL_ALPHA_SHAPE_VERTEX_BASE_3_H
@@ -0,0 +1,477 @@
// Copyright (c) 2012, 2017 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Sébastien Loriot <sebastien.loriot@geometryfactory.com>
// Mael Rouxel-Labbé
#ifndef CGAL_INTERNAL_LAZY_ALPHA_NT_2_H
#define CGAL_INTERNAL_LAZY_ALPHA_NT_2_H
#include <CGAL/license/Alpha_shapes_2.h>
#include <CGAL/assertions.h>
#include <CGAL/Number_types/internal/Exact_type_selector.h>
#include <CGAL/number_type_basic.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/Has_conversion.h>
#include <boost/mpl/has_xxx.hpp>
#include <boost/type_traits.hpp>
#include <iostream>
namespace CGAL {
namespace internal {
// check whether Cartesian_converter can do the following conversions
// -- Input_traits::(Weighted_)Point_2 to K2::(Weighted_)Point_2
// -- Input_traits::(Weighted_)Point_2 to K3::(Weighted_)Point_2
//
template < class Input_traits, class Kernel_approx, class Kernel_exact,
class Weighted_tag >
class Is_traits_point_convertible_2
{
typedef typename Kernel_traits<typename Input_traits::Point_2>::Kernel Kernel_input;
typedef typename Input_traits::Point_2 K1P;
typedef typename Kernel_approx::Point_2 K2P;
typedef typename Kernel_exact::Point_2 K3P;
public:
static const bool value
= (Has_conversion<Kernel_input, Kernel_approx, K1P, K2P>::value &&
Has_conversion<Kernel_input, Kernel_exact, K1P, K3P>::value);
};
template < class Input_traits, class Kernel_approx, class Kernel_exact >
class Is_traits_point_convertible_2<Input_traits, Kernel_approx, Kernel_exact,
::CGAL::Tag_true /* Weighted_tag */>
{
typedef typename Kernel_traits<typename Input_traits::Point_2>::Kernel Kernel_input;
typedef typename Input_traits::Weighted_point_2 K1WP;
typedef typename Kernel_approx::Weighted_point_2 K2WP;
typedef typename Kernel_exact::Weighted_point_2 K3WP;
public:
static const bool value
= (Has_conversion<Kernel_input, Kernel_approx, K1WP, K2WP>::value &&
Has_conversion<Kernel_input, Kernel_exact, K1WP, K3WP>::value);
};
template <class T>
struct Input_points_for_lazy_alpha_nt_2
{
int nbpts;
const T* p0;
const T* p1;
const T* p2;
};
//non-weighted case
template <class Weighted_tag, class Input_traits, class Kernel_input,
class Kernel_approx, class Kernel_exact>
struct Types_for_alpha_nt_2
{
//Converter types
typedef CGAL::Cartesian_converter<Kernel_input, Kernel_approx> To_approx;
typedef CGAL::Cartesian_converter<Kernel_input, Kernel_exact> To_exact;
//Point types
typedef typename Kernel_approx::Point_2 Approx_point;
typedef typename Kernel_exact::Point_2 Exact_point;
typedef typename Input_traits::Point_2 Input_point;
//Constructions
typedef typename Kernel_approx::Compute_squared_radius_2 Approx_squared_radius;
typedef typename Kernel_exact::Compute_squared_radius_2 Exact_squared_radius;
};
//weighted case
template <class Input_traits, class Kernel_input,
class Kernel_approx, class Kernel_exact>
struct Types_for_alpha_nt_2< ::CGAL::Tag_true /* Weighted_tag */,
Input_traits, Kernel_input,
Kernel_approx, Kernel_exact >
{
//Converter types
typedef CGAL::Cartesian_converter<Kernel_input, Kernel_approx> To_approx;
typedef CGAL::Cartesian_converter<Kernel_input, Kernel_exact> To_exact;
//Point types
typedef typename Kernel_approx::Weighted_point_2 Approx_point;
typedef typename Kernel_exact::Weighted_point_2 Exact_point;
typedef typename Input_traits::Weighted_point_2 Input_point;
//Constructions
typedef typename Kernel_approx::Compute_squared_radius_smallest_orthogonal_circle_2 Approx_squared_radius;
typedef typename Kernel_exact::Compute_squared_radius_smallest_orthogonal_circle_2 Exact_squared_radius;
};
template<class Input_traits, bool mode, class Weighted_tag>
class Lazy_alpha_nt_2
{
//NT & kernels
typedef CGAL::Interval_nt<mode> NT_approx;
//Gmpq or Quotient<MP_float>
typedef Exact_field_selector<double>::Type NT_exact;
typedef CGAL::Simple_cartesian<NT_approx> Kernel_approx;
typedef CGAL::Simple_cartesian<NT_exact> Kernel_exact;
typedef typename Kernel_traits<typename Input_traits::Point_2>::Kernel Kernel_input;
//Helper class for weighted and non-weighted case
typedef Types_for_alpha_nt_2<Weighted_tag, Input_traits, Kernel_input,
Kernel_approx, Kernel_exact> Types;
//Converters
typedef typename Types::To_approx To_approx;
typedef typename Types::To_exact To_exact;
//Constructions class
typedef typename Types::Approx_squared_radius Approx_squared_radius;
typedef typename Types::Exact_squared_radius Exact_squared_radius;
//Point
typedef typename Types::Approx_point Approx_point;
typedef typename Types::Exact_point Exact_point;
typedef typename Types::Input_point Input_point;
//Convertion functions
Approx_point to_approx(const Input_point& wp) const
{
// The traits class' Point_2 must be convertible using the Cartesian converter
CGAL_static_assertion((Is_traits_point_convertible_2<
Input_traits, Kernel_approx, Kernel_exact, Weighted_tag>::value));
To_approx converter;
return converter(wp);
}
Exact_point to_exact(const Input_point& wp) const
{
// The traits class' Point_2 must be convertible using the Cartesian converter
CGAL_static_assertion((Is_traits_point_convertible_2<
Input_traits, Kernel_approx, Kernel_exact, Weighted_tag>::value));
To_exact converter;
return converter(wp);
}
//members
//the members can be updated when calling method exact()
mutable boost::optional<NT_exact> exact_;
mutable NT_approx approx_;
//private functions
typedef Input_points_for_lazy_alpha_nt_2<Input_point> Data_vector;
Data_vector input_points;
const Data_vector& data() const{ return input_points;}
Data_vector& data(){ return input_points;}
static double & relative_precision_of_to_double_internal()
{
CGAL_STATIC_THREAD_LOCAL_VARIABLE(double, relative_precision_of_to_double, 0.00001);
return relative_precision_of_to_double;
}
public:
static const double & get_relative_precision_of_to_double()
{
return relative_precision_of_to_double_internal();
}
static void set_relative_precision_of_to_double(double d)
{
CGAL_assertion((0 < d) & (d < 1));
relative_precision_of_to_double_internal() = d;
}
typedef NT_exact Exact_nt;
typedef NT_approx Approximate_nt;
void update_exact() const
{
switch(data().nbpts) {
case 1:
exact_ = Exact_squared_radius()( to_exact(*data().p0) );
break;
case 2:
exact_ = Exact_squared_radius()( to_exact(*data().p0),to_exact(*data().p1) );
break;
case 3:
exact_ = Exact_squared_radius()( to_exact(*data().p0),to_exact(*data().p1),to_exact(*data().p2) );
break;
default:
CGAL_assertion(false);
}
}
void set_approx()
{
switch(data().nbpts) {
case 1:
approx_ = Approx_squared_radius()( to_approx(*data().p0) );
break;
case 2:
approx_ = Approx_squared_radius()( to_approx(*data().p0),to_approx(*data().p1) );
break;
case 3:
approx_ = Approx_squared_radius()( to_approx(*data().p0),to_approx(*data().p1),to_approx(*data().p2) );
break;
default:
CGAL_assertion(false);
}
}
const NT_exact& exact() const
{
if (exact_ == boost::none) {
update_exact();
approx_=to_interval(*exact_);
}
return *exact_;
}
const NT_approx& approx() const {
return approx_;
}
//Constructors
Lazy_alpha_nt_2()
: exact_(Exact_nt(0)), approx_(0)
{
data().nbpts=0;
data().p0=nullptr;
data().p1=nullptr;
data().p2=nullptr;
}
Lazy_alpha_nt_2(double d)
: exact_(Exact_nt(d)), approx_(d)
{
data().nbpts=0;
data().p0=nullptr;
data().p1=nullptr;
data().p2=nullptr;
}
Lazy_alpha_nt_2(const Input_point& wp0)
{
data().nbpts=1;
data().p0=&wp0;
data().p1=nullptr;
data().p2=nullptr;
set_approx();
}
Lazy_alpha_nt_2(const Input_point& wp0,
const Input_point& wp1)
{
data().nbpts=2;
data().p0=&wp0;
data().p1=&wp1;
data().p2=nullptr;
set_approx();
}
Lazy_alpha_nt_2(const Input_point& wp0,
const Input_point& wp1,
const Input_point& wp2)
{
data().nbpts=3;
data().p0=&wp0;
data().p1=&wp1;
data().p2=&wp2;
set_approx();
}
#define CGAL_LANT_COMPARE_FUNCTIONS(CMP) \
bool \
operator CMP (const Lazy_alpha_nt_2<Input_traits,mode,Weighted_tag> &other) const \
{ \
Uncertain<bool> res = this->approx() CMP other.approx(); \
if (res.is_certain()) \
return res; \
else \
return this->exact() CMP other.exact(); \
} \
CGAL_LANT_COMPARE_FUNCTIONS(<)
CGAL_LANT_COMPARE_FUNCTIONS(>)
CGAL_LANT_COMPARE_FUNCTIONS(>=)
CGAL_LANT_COMPARE_FUNCTIONS(<=)
CGAL_LANT_COMPARE_FUNCTIONS(==)
CGAL_LANT_COMPARE_FUNCTIONS(!=)
#undef CGAL_LANT_COMPARE_FUNCTIONS
};
template<class Input_traits, bool mode, class Weighted_tag>
std::ostream&
operator<< (std::ostream& os,
const Lazy_alpha_nt_2<Input_traits, mode, Weighted_tag>& a){
return os << ::CGAL::to_double(a.approx());
}
// small classes to select the functors in weighted or unweighted cases
template <class GeomTraits, class Weighted_tag>
struct iCompute_squared_radius_2;
template <class GeomTraits>
struct iCompute_squared_radius_2<GeomTraits, Tag_false /* Weighted_tag*/>
{
template <class As>
typename GeomTraits::Compute_squared_radius_2
operator()(const As& as) const {
return static_cast<const typename As::Triangulation&>(as).geom_traits().
compute_squared_radius_2_object();
}
};
template <class GeomTraits>
struct iCompute_squared_radius_2<GeomTraits, Tag_true /* Weighted_tag*/>
{
template <class As>
typename GeomTraits::Compute_squared_radius_smallest_orthogonal_circle_2
operator()(const As& as) const {
return static_cast<const typename As::Triangulation&>(as).geom_traits().
compute_squared_radius_smallest_orthogonal_circle_2_object();
}
};
template <class GeomTraits, class Weighted_tag>
struct iSide_of_bounded_circle_2;
template <class GeomTraits>
struct iSide_of_bounded_circle_2<GeomTraits, Tag_false /* Weighted_tag*/>
{
template <class As>
typename GeomTraits::Side_of_bounded_circle_2
operator()(const As& as) const {
return static_cast<const typename As::Triangulation&>(as).geom_traits().
side_of_bounded_circle_2_object();
}
};
template <class GeomTraits>
struct iSide_of_bounded_circle_2<GeomTraits, Tag_true /* Weighted_tag*/>
{
template <class As>
typename GeomTraits::Power_side_of_bounded_power_circle_2
operator()(const As& as) const {
return static_cast<const typename As::Triangulation&>(as).geom_traits().
power_side_of_bounded_power_circle_2_object();
}
};
template <class Type_of_alpha, class Point>
struct Lazy_compute_squared_radius_2
{
Type_of_alpha operator()(const Point& p,
const Point& q,
const Point& r)
{ return Type_of_alpha(p,q,r); }
Type_of_alpha operator()(const Point& p,
const Point& q)
{ return Type_of_alpha(p,q); }
Type_of_alpha operator()(const Point& p)
{ return Type_of_alpha(p); }
};
template <class GeomTraits, class ExactAlphaComparisonTag, class Weighted_tag>
struct Alpha_nt_selector_impl_2;
template <class GeomTraits, class Weighted_tag>
struct Alpha_nt_selector_impl_2<GeomTraits,
Tag_false /* ExactAlphaComparisonTag */,
Weighted_tag>
{
typedef typename GeomTraits::FT Type_of_alpha;
typedef iCompute_squared_radius_2<GeomTraits, Weighted_tag> Compute_squared_radius_2;
typedef iSide_of_bounded_circle_2<GeomTraits, Weighted_tag> Side_of_bounded_circle_2;
};
template <class GeomTraits, class Weighted_tag>
struct Alpha_nt_selector_impl_2<GeomTraits,
Tag_true /* ExactAlphaComparisonTag */,
Weighted_tag>
{
typedef Lazy_alpha_nt_2<
GeomTraits, true /* mode */, Tag_false /* Weighted_tag */> Type_of_alpha;
typedef Lazy_compute_squared_radius_2<
Type_of_alpha, typename GeomTraits::Point_2> Functor;
struct Compute_squared_radius_2
{
template<class As>
Functor operator()(const As&){return Functor();}
};
typedef iSide_of_bounded_circle_2<GeomTraits, Weighted_tag> Side_of_bounded_circle_2;
};
template <class GeomTraits>
struct Alpha_nt_selector_impl_2<GeomTraits,
Tag_true /* ExactAlphaComparisonTag */,
Tag_true /* Weighted_tag */ >
{
typedef Lazy_alpha_nt_2<
GeomTraits, true /* mode */, Tag_true /* Weighted_tag */> Type_of_alpha;
typedef Lazy_compute_squared_radius_2<
Type_of_alpha, typename GeomTraits::Weighted_point_2> Functor;
struct Compute_squared_radius_2
{
template<class As>
Functor operator()(const As&){return Functor();}
};
typedef iSide_of_bounded_circle_2<GeomTraits, Tag_true> Side_of_bounded_circle_2;
};
template <class GeomTraits, class ExactAlphaComparisonTag, class Weighted_tag>
struct Alpha_nt_selector_2
: public Alpha_nt_selector_impl_2<
GeomTraits,
// If the base traits is already exact then we don't need to do anything,
// and we can simply directly use the traits class
Boolean_tag<boost::is_floating_point<typename GeomTraits::FT>::value &&
ExactAlphaComparisonTag::value >,
Weighted_tag>
{ };
} // namespace internal
template<class Input_traits, bool mode, class Weighted_tag>
double to_double(const internal::Lazy_alpha_nt_2<Input_traits, mode, Weighted_tag>& a)
{
double r;
if (fit_in_double(a.approx(), r))
return r;
// If it isn't precise enough,
// we trigger the exact computation first,
// which will refine the approximation.
if (!has_smaller_relative_precision(a.approx(), a.get_relative_precision_of_to_double()))
a.exact();
return CGAL_NTS to_double(a.approx());
}
} // namespace CGAL
#endif // CGAL_INTERNAL_LAZY_ALPHA_NT_2_H
@@ -0,0 +1,26 @@
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Sebastien Loriot
//
#ifndef CGAL_INTERNAL_CLASSIFICATION_TYPE_H
#define CGAL_INTERNAL_CLASSIFICATION_TYPE_H
#include <CGAL/license/Alpha_shapes_3.h>
namespace CGAL{
namespace internal{
enum Classification_type {EXTERIOR,SINGULAR,REGULAR,INTERIOR};
}
}
#endif //CGAL_INTERNAL_CLASSIFICATION_TYPE_H
@@ -0,0 +1,446 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Sébastien Loriot <sebastien.loriot@geometryfactory.com>
// Mael Rouxel-Labbé
#ifndef CGAL_INTERNAL_LAZY_ALPHA_NT_3_H
#define CGAL_INTERNAL_LAZY_ALPHA_NT_3_H
#include <CGAL/license/Alpha_shapes_3.h>
#include <CGAL/assertions.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/Number_types/internal/Exact_type_selector.h>
#include <CGAL/Has_conversion.h>
#include <memory>
#include <boost/type_traits.hpp>
#include <boost/optional.hpp>
#include <iostream>
namespace CGAL {
namespace internal{
// check whether Cartesian_converter can do the following conversions
// -- Input_traits::(Weighted_)Point_3 to K2::(Weighted_)Point_3
// -- Input_traits::(Weighted_)Point_3 to K3::(Weighted_)Point_3
//
template < class Input_traits, class Kernel_approx, class Kernel_exact,
class Weighted_tag >
class Is_traits_point_convertible_3
{
typedef typename Kernel_traits<typename Input_traits::Point_3>::Kernel Kernel_input;
typedef typename Input_traits::Point_3 K1P;
typedef typename Kernel_approx::Point_3 K2P;
typedef typename Kernel_exact::Point_3 K3P;
public:
static const bool value
= (Has_conversion<Kernel_input, Kernel_approx, K1P, K2P>::value &&
Has_conversion<Kernel_input, Kernel_exact, K1P, K3P>::value);
};
template < class Input_traits, class Kernel_approx, class Kernel_exact >
class Is_traits_point_convertible_3<Input_traits, Kernel_approx, Kernel_exact,
::CGAL::Tag_true /* Weighted_tag */>
{
typedef typename Kernel_traits<typename Input_traits::Point_3>::Kernel Kernel_input;
typedef typename Input_traits::Weighted_point_3 K1WP;
typedef typename Kernel_approx::Weighted_point_3 K2WP;
typedef typename Kernel_exact::Weighted_point_3 K3WP;
public:
static const bool value
= (Has_conversion<Kernel_input, Kernel_approx, K1WP, K2WP>::value &&
Has_conversion<Kernel_input, Kernel_exact, K1WP, K3WP>::value);
};
template <class T>
struct Input_points_for_lazy_alpha_nt_3
{
int nbpts;
const T* p0;
const T* p1;
const T* p2;
const T* p3;
};
//non-weighted case
template <class Weighted_tag,class Input_traits,class Kernel_input,class Kernel_approx,class Kernel_exact>
struct Types_for_alpha_nt_3
{
//Converter types
typedef CGAL::Cartesian_converter<Kernel_input,Kernel_approx> To_approx;
typedef CGAL::Cartesian_converter<Kernel_input,Kernel_exact> To_exact;
//Point types
typedef typename Kernel_approx::Point_3 Approx_point;
typedef typename Kernel_exact::Point_3 Exact_point;
typedef typename Input_traits::Point_3 Input_point;
//Constructions
typedef typename Kernel_approx::Compute_squared_radius_3 Approx_squared_radius;
typedef typename Kernel_exact::Compute_squared_radius_3 Exact_squared_radius;
};
//weighted case
template <class Input_traits,class Kernel_input,class Kernel_approx,class Kernel_exact>
struct Types_for_alpha_nt_3< ::CGAL::Tag_true,Input_traits,Kernel_input,Kernel_approx,Kernel_exact>
{
//Converter types
typedef CGAL::Cartesian_converter<Kernel_input,Kernel_approx> To_approx;
typedef CGAL::Cartesian_converter<Kernel_input,Kernel_exact> To_exact;
//Point types
typedef typename Kernel_approx::Weighted_point_3 Approx_point;
typedef typename Kernel_exact::Weighted_point_3 Exact_point;
typedef typename Input_traits::Weighted_point_3 Input_point;
//Constructions
typedef typename Kernel_approx::Compute_squared_radius_smallest_orthogonal_sphere_3 Approx_squared_radius;
typedef typename Kernel_exact::Compute_squared_radius_smallest_orthogonal_sphere_3 Exact_squared_radius;
};
template<class Input_traits, bool mode, class Weighted_tag>
class Lazy_alpha_nt_3{
//NT & kernels
typedef CGAL::Interval_nt<mode> NT_approx;
//Gmpq or Quotient<MP_float>
typedef Exact_field_selector<double>::Type NT_exact;
typedef CGAL::Simple_cartesian<NT_approx> Kernel_approx;
typedef CGAL::Simple_cartesian<NT_exact> Kernel_exact;
typedef typename Kernel_traits<typename Input_traits::Point_3>::Kernel Kernel_input;
//Helper class for weighted and non-weighted case
typedef Types_for_alpha_nt_3<Weighted_tag,Input_traits,Kernel_input,Kernel_approx,Kernel_exact> Types;
//Converters
typedef typename Types::To_approx To_approx;
typedef typename Types::To_exact To_exact;
//Constructions class
typedef typename Types::Approx_squared_radius Approx_squared_radius;
typedef typename Types::Exact_squared_radius Exact_squared_radius;
//Point
typedef typename Types::Approx_point Approx_point;
typedef typename Types::Exact_point Exact_point;
typedef typename Types::Input_point Input_point;
//Convertion functions
Approx_point to_approx(const Input_point& wp) const
{
// The traits class' Point_3 must be convertible using the Cartesian converter
CGAL_static_assertion((Is_traits_point_convertible_3<
Input_traits, Kernel_approx, Kernel_exact, Weighted_tag>::value));
To_approx converter;
return converter(wp);
}
Exact_point to_exact(const Input_point& wp) const
{
// The traits class' Point_3 must be convertible using the Cartesian converter
CGAL_static_assertion((Is_traits_point_convertible_3<
Input_traits, Kernel_approx, Kernel_exact, Weighted_tag>::value));
To_exact converter;
return converter(wp);
}
//members
//the members can be updated when calling method exact()
mutable boost::optional<NT_exact> exact_;
mutable NT_approx approx_;
//private functions
typedef Input_points_for_lazy_alpha_nt_3<Input_point> Data_vector;
Data_vector input_points;
const Data_vector& data() const{ return input_points;}
Data_vector& data(){ return input_points;}
static double & relative_precision_of_to_double_internal()
{
CGAL_STATIC_THREAD_LOCAL_VARIABLE(double, relative_precision_of_to_double, 0.00001);
return relative_precision_of_to_double;
}
public:
static const double & get_relative_precision_of_to_double()
{
return relative_precision_of_to_double_internal();
}
static void set_relative_precision_of_to_double(double d)
{
CGAL_assertion((0 < d) & (d < 1));
relative_precision_of_to_double_internal() = d;
}
typedef NT_exact Exact_nt;
typedef NT_approx Approximate_nt;
void update_exact() const{
switch (data().nbpts){
case 1:
exact_ = Exact_squared_radius()( to_exact(*data().p0) );
break;
case 2:
exact_ = Exact_squared_radius()( to_exact(*data().p0),to_exact(*data().p1) );
break;
case 3:
exact_ = Exact_squared_radius()( to_exact(*data().p0),to_exact(*data().p1),to_exact(*data().p2) );
break;
case 4:
exact_ = Exact_squared_radius()( to_exact(*data().p0),to_exact(*data().p1),to_exact(*data().p2),to_exact(*data().p3) );
break;
default:
CGAL_assertion(false);
}
}
void set_approx(){
switch (data().nbpts){
case 1:
approx_ = Approx_squared_radius()( to_approx(*data().p0) );
break;
case 2:
approx_ = Approx_squared_radius()( to_approx(*data().p0),to_approx(*data().p1) );
break;
case 3:
approx_ = Approx_squared_radius()( to_approx(*data().p0),to_approx(*data().p1),to_approx(*data().p2) );
break;
case 4:
approx_ = Approx_squared_radius()( to_approx(*data().p0),to_approx(*data().p1),to_approx(*data().p2),to_approx(*data().p3) );
break;
default:
CGAL_assertion(false);
}
}
const NT_exact& exact() const {
if (exact_ == boost::none){
update_exact();
approx_=to_interval(*exact_);
}
return *exact_;
}
const NT_approx& approx() const{
return approx_;
}
//Constructors
Lazy_alpha_nt_3()
: exact_(Exact_nt(0)),approx_(0)
{
data().nbpts=0;
data().p0=nullptr;
data().p1=nullptr;
data().p2=nullptr;
data().p3=nullptr;
}
Lazy_alpha_nt_3(double d)
: exact_(Exact_nt(d)),approx_(d)
{
data().nbpts=0;
data().p0=nullptr;
data().p1=nullptr;
data().p2=nullptr;
data().p3=nullptr;
}
Lazy_alpha_nt_3(const Input_point& wp1)
{
data().nbpts=1;
data().p0=&wp1;
data().p1=nullptr;
data().p2=nullptr;
data().p3=nullptr;
set_approx();
}
Lazy_alpha_nt_3(const Input_point& wp1,
const Input_point& wp2)
{
data().nbpts=2;
data().p0=&wp1;
data().p1=&wp2;
data().p2=nullptr;
data().p3=nullptr;
set_approx();
}
Lazy_alpha_nt_3(const Input_point& wp1,
const Input_point& wp2,
const Input_point& wp3)
{
data().nbpts=3;
data().p0=&wp1;
data().p1=&wp2;
data().p2=&wp3;
data().p3=nullptr;
set_approx();
}
Lazy_alpha_nt_3(const Input_point& wp1,
const Input_point& wp2,
const Input_point& wp3,
const Input_point& wp4)
{
data().nbpts=4;
data().p0=&wp1;
data().p1=&wp2;
data().p2=&wp3;
data().p3=&wp4;
set_approx();
}
#define CGAL_LANT_COMPARE_FUNCTIONS(CMP) \
bool \
operator CMP (const Lazy_alpha_nt_3<Input_traits,mode,Weighted_tag> &other) const \
{ \
Uncertain<bool> res = this->approx() CMP other.approx(); \
if (res.is_certain()) \
return res; \
else \
return this->exact() CMP other.exact(); \
} \
CGAL_LANT_COMPARE_FUNCTIONS(<)
CGAL_LANT_COMPARE_FUNCTIONS(>)
CGAL_LANT_COMPARE_FUNCTIONS(>=)
CGAL_LANT_COMPARE_FUNCTIONS(<=)
CGAL_LANT_COMPARE_FUNCTIONS(==)
CGAL_LANT_COMPARE_FUNCTIONS(!=)
#undef CGAL_LANT_COMPARE_FUNCTIONS
};
template<class Input_traits, bool mode, class Weighted_tag>
std::ostream&
operator<< (std::ostream& os,const Lazy_alpha_nt_3<Input_traits,mode,Weighted_tag>& a){
return os << ::CGAL::to_double(a.approx());
}
//small class to select predicate in weighted and unweighted case
template <class GeomTraits,class Weighted_tag>
struct iCompute_squared_radius_3;
template <class GeomTraits>
struct iCompute_squared_radius_3<GeomTraits,Tag_false>
{
template <class As>
typename GeomTraits::Compute_squared_radius_3
operator()(const As& as) const{
return static_cast<const typename As::Triangulation&>(as).geom_traits().compute_squared_radius_3_object();
}
};
template <class GeomTraits>
struct iCompute_squared_radius_3<GeomTraits,Tag_true>
{
template <class As>
typename GeomTraits::Compute_squared_radius_smallest_orthogonal_sphere_3
operator()(const As& as) const{
return static_cast<const typename As::Triangulation&>(as).geom_traits().compute_squared_radius_smallest_orthogonal_sphere_3_object();
}
};
template <class Type_of_alpha,class Point>
struct Lazy_compute_squared_radius_3 {
Type_of_alpha operator() (const Point& p,
const Point& q ,
const Point& r,
const Point& s)
{return Type_of_alpha(p,q,r,s);}
Type_of_alpha operator() ( const Point& p,
const Point& q ,
const Point& r)
{return Type_of_alpha(p,q,r); }
Type_of_alpha operator() (const Point& p,
const Point& q )
{return Type_of_alpha(p,q); }
Type_of_alpha operator() (const Point& p)
{return Type_of_alpha(p);}
};
template <class GeomTraits,class ExactAlphaComparisonTag,class Weighted_tag>
struct Alpha_nt_selector_impl_3;
template <class GeomTraits,class Weighted_tag>
struct Alpha_nt_selector_impl_3<GeomTraits,Tag_false,Weighted_tag>
{
typedef typename GeomTraits::FT Type_of_alpha;
typedef iCompute_squared_radius_3<GeomTraits,Weighted_tag> Compute_squared_radius_3;
};
template <class GeomTraits,class Weighted_tag>
struct Alpha_nt_selector_impl_3<GeomTraits,Tag_true,Weighted_tag>
{
typedef Lazy_alpha_nt_3<GeomTraits,true,Tag_false> Type_of_alpha;
typedef Lazy_compute_squared_radius_3<Type_of_alpha,typename GeomTraits::Point_3> Functor;
struct Compute_squared_radius_3{
template<class As>
Functor operator()(const As&){return Functor();}
};
};
template <class GeomTraits>
struct Alpha_nt_selector_impl_3<GeomTraits,Tag_true,Tag_true>
{
typedef Lazy_alpha_nt_3<GeomTraits,true,Tag_true> Type_of_alpha;
typedef Lazy_compute_squared_radius_3<Type_of_alpha,typename GeomTraits::Weighted_point_3> Functor;
struct Compute_squared_radius_3{
template<class As>
Functor operator()(const As&){return Functor();}
};
};
template <class GeomTraits,class ExactAlphaComparisonTag,class Weighted_tag>
struct Alpha_nt_selector_3
: public Alpha_nt_selector_impl_3<
GeomTraits,
// If the base traits is already exact then we don't need to do anything,
// and we can simply directly use the traits class
Boolean_tag<boost::is_floating_point<typename GeomTraits::FT>::value &&
ExactAlphaComparisonTag::value >,
Weighted_tag>
{ };
} //namespace internal
template<class Input_traits, bool mode, class Weighted_tag>
double to_double(const internal::Lazy_alpha_nt_3<Input_traits, mode, Weighted_tag>& a)
{
double r;
if (fit_in_double(a.approx(), r))
return r;
// If it isn't precise enough,
// we trigger the exact computation first,
// which will refine the approximation.
if (!has_smaller_relative_precision(a.approx(), a.get_relative_precision_of_to_double()))
a.exact();
return CGAL_NTS to_double(a.approx());
}
} //namespace CGAL
#endif //CGAL_INTERNAL_LAZY_ALPHA_NT_3_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,549 @@
// Copyright (c) 2003,2004,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_HIERARCHY_2_IMPL_H
#define CGAL_APOLLONIUS_GRAPH_HIERARCHY_2_IMPL_H
#include <CGAL/license/Apollonius_graph_2.h>
// class implementation
//---------------------
namespace CGAL {
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
init_hierarchy(const Geom_traits& gt)
{
hierarchy[0] = this;
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i) {
hierarchy[i] = new Apollonius_graph_base(gt);
}
}
template<class Gt, class Agds, class LTag>
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
Apollonius_graph_hierarchy_2(const Geom_traits& gt)
: Apollonius_graph_base(gt)
{
init_hierarchy(gt);
}
// copy constructor duplicates vertices and faces
template<class Gt, class Agds, class LTag>
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
Apollonius_graph_hierarchy_2
(const Apollonius_graph_hierarchy_2<Gt,Agds,LTag>& agh)
: Apollonius_graph_base(agh.geom_traits())
{
init_hierarchy(agh.geom_traits());
copy(agh);
}
//Assignement
template<class Gt, class Agds, class LTag>
Apollonius_graph_hierarchy_2<Gt,Agds,LTag> &
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
operator=(const Apollonius_graph_hierarchy_2<Gt,Agds,LTag> &agh)
{
copy(agh);
return *this;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
copy
(const Apollonius_graph_hierarchy_2<Gt,Agds,LTag> &agh)
{
std::map< Vertex_handle, Vertex_handle > V;
for(unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
// hierarchy[i]->copy_triangulation(*awvd.hierarchy[i]);
*(hierarchy[i]) = *agh.hierarchy[i];
}
//up and down have been copied in straightforward way
// compute a map at lower level
for( Finite_vertices_iterator it = hierarchy[0]->finite_vertices_begin();
it != hierarchy[0]->finite_vertices_end(); ++it) {
if ( it->up() != Vertex_handle() ) V[ it->up()->down() ] = it;
}
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i) {
for( Finite_vertices_iterator it = hierarchy[i]->finite_vertices_begin();
it != hierarchy[i]->finite_vertices_end(); ++it) {
// down pointer goes in original instead in copied triangulation
it->set_down(V[it->down()]);
// make reverse link
it->down()->set_up( it );
// make map for next level
if ( it->up() != Vertex_handle() ) V[ it->up()->down() ] = it;
}
}
}
template<class Gt, class Agds, class LTag>
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
~Apollonius_graph_hierarchy_2()
{
clear();
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i) {
delete hierarchy[i];
}
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
clear()
{
for(unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
hierarchy[i]->clear();
}
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
is_valid(bool verbose, int level) const
{
bool result(true);
//verify correctness of triangulation at all levels
for(unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
if ( verbose ) {
std::cerr << "Level " << i << ": " << std::flush;
}
result = result && hierarchy[i]->is_valid(verbose, level);
if ( verbose ) {
std::cerr << std::endl;
}
}
//verify that lower level has no down pointers
for( Finite_vertices_iterator it = hierarchy[0]->finite_vertices_begin();
it != hierarchy[0]->finite_vertices_end(); ++it) {
result = result && ( it->down() == 0 );
}
//verify that other levels has down pointer and reciprocal link is fine
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i) {
for( Finite_vertices_iterator it = hierarchy[i]->finite_vertices_begin();
it != hierarchy[i]->finite_vertices_end(); ++it) {
result = result && ( &*it == &*(it->down()->up()) );
}
}
return result;
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
insert(const Site_2 &p)
{
int vertex_level = random_level();
size_type n = this->number_of_vertices();
Vertex_handle vertex;
Vertex_handle vnear[ag_hierarchy_2__maxlevel];
typename Apollonius_graph_base::List l;
typename Apollonius_graph_base::Face_map fm;
typename Apollonius_graph_base::Vertex_map v_hidden;
if ( n <= 2 ) {
if ( n == 0 ) {
vertex = insert_first(p);
} else if ( n == 1 ) {
vertex = insert_second(p);
} else if ( n == 2 ) {
vertex = insert_third(p);
}
// if it hidden just return it right away
if ( vertex == Vertex_handle() ) {
return vertex;
}
Vertex_handle previous = vertex;
Vertex_handle first = vertex;
int level = 1;
while (level <= vertex_level ){
vertex = hierarchy[level]->insert(p, vnear[level]);
vertex->set_down(previous); // link with level above
previous->set_up(vertex);
previous = vertex;
level++;
}
return first;
}
std::size_t n_hidden = 0;
// locate the nearest neighbor using hierarchy
nearest_neighbor(p.point(), vnear);
CGAL_assertion( vnear[0] != Vertex_handle() );
// check if it is hidden
Site_2 wp_nearest = vnear[0]->site();
if ( is_hidden(wp_nearest, p) ) {
vnear[0]->add_hidden_site(p);
return Vertex_handle();
}
// find the first conflict
typename Apollonius_graph_base::Face_circulator fc_start =
hierarchy[0]->incident_faces(vnear[0]);
typename Apollonius_graph_base::Face_circulator fc = fc_start;
Face_handle start_f;
Sign s;
do {
Face_handle f(fc);
s = incircle(f, p);
if ( s == NEGATIVE ) {
start_f = f;
break;
}
++fc;
} while ( fc != fc_start );
if ( s != NEGATIVE ) {
typename Apollonius_graph_base::Edge_circulator ec_start =
hierarchy[0]->incident_edges(vnear[0]);
typename Apollonius_graph_base::Edge_circulator ec = ec_start;
bool interior_in_conflict(false);
typename Apollonius_graph_base::Edge e;
do {
e = *ec;
interior_in_conflict = edge_interior(e, p, false);
if ( interior_in_conflict ) { break; }
++ec;
} while ( ec != ec_start );
CGAL_assertion( interior_in_conflict );
vertex = insert_degree_2(e, p);
// insert at other levels
Vertex_handle previous = vertex;
Vertex_handle first = vertex;
int level = 1;
while (level <= vertex_level ){
vertex = hierarchy[level]->insert(p, vnear[level]);
vertex->set_down(previous); // link with level above
previous->set_up(vertex);
previous = vertex;
level++;
}
return first;
}
initialize_conflict_region(start_f, l);
expand_conflict_region(start_f, p, l, fm, v_hidden, nullptr);
n_hidden = v_hidden.size();
if ( n_hidden != 0 ) {
std::size_t n_non_hidden = this->number_of_vertices() - n_hidden;
if ( n_non_hidden < 2 ) {
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i) {
hierarchy[i]->clear();
}
if ( n_non_hidden == 1 ) {
Vertex_handle non_hidden;
Finite_vertices_iterator vit = this->finite_vertices_begin();
do {
non_hidden = Vertex_handle(vit);
++vit;
} while ( v_hidden.find(non_hidden) != v_hidden.end() );
non_hidden->set_up( Vertex_handle() );
}
} else {
typename Apollonius_graph_base::Vertex_map::iterator it;
for (it = v_hidden.begin(); it != v_hidden.end(); it++) {
Vertex_handle v = (*it).first;
Vertex_handle u = v->up();
if ( u != Vertex_handle() ) {
v = u;
u = v->up();
unsigned int l = 1;
while ( true ) {
hierarchy[l++]->remove(v);
if ( u == Vertex_handle() ) break;
if(l >= ag_hierarchy_2__maxlevel) { break; }
v = u;
u = v->up();
}
}
}
}
}
// now really insert at level 0
vertex = retriangulate_conflict_region(p, l, fm, v_hidden);
fm.clear();
v_hidden.clear();
// end of insertion at level 0
// insert at other levels
Vertex_handle previous = vertex;
Vertex_handle first = vertex;
if ( n_hidden != 0 ) {
nearest_neighbor(p.point(), vnear);
}
int level = 1;
while (level <= vertex_level ){
vertex = hierarchy[level]->insert(p, vnear[level]);
vertex->set_down(previous); // link with level above
previous->set_up(vertex);
previous = vertex;
level++;
}
return first;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
remove(Vertex_handle v)
{
CGAL_triangulation_precondition( v != Vertex_handle());
CGAL_triangulation_precondition( !is_infinite(v));
// get the hidden circles
typename Apollonius_graph_base::Site_list wp_list;
typename Apollonius_graph_base::Vertex::Hidden_sites_iterator wpit;
for (wpit = v->hidden_sites_begin();
wpit != v->hidden_sites_end(); ++wpit) {
wp_list.push_back(*wpit);
}
v->clear_hidden_sites_container();
// do the actual removal
Vertex_handle u = v->up();
unsigned int l = 0;
while ( true ) {
hierarchy[l++]->remove(v);
if ( u == Vertex_handle() ) break;
if(l >= ag_hierarchy_2__maxlevel) break;
v = u;
u = v->up();
}
insert(wp_list.begin(), wp_list.end());
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
nearest_neighbor(const Point_2& p) const
{
Vertex_handle vnear[ag_hierarchy_2__maxlevel];
nearest_neighbor(p, vnear);
return vnear[0];
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
swap(Apollonius_graph_hierarchy_2<Gt,Agds,LTag>& agh)
{
Ag_base* temp;
Ag_base::swap(agh);
for(unsigned int i = 1; i < ag_hierarchy_2__maxlevel; ++i){
temp = hierarchy[i];
hierarchy[i] = agh.hierarchy[i];
agh.hierarchy[i]= temp;
}
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
nearest_neighbor(const Point_2& p,
Vertex_handle vnear[ag_hierarchy_2__maxlevel]) const
{
Vertex_handle nearest = 0;
unsigned int level = ag_hierarchy_2__maxlevel;
// find the highest level with enough vertices
while ( hierarchy[--level]->number_of_vertices()
< ag_hierarchy_2__minsize ) {
if ( !level ) break; // do not go below 0
}
for (unsigned int i = level+1; i < ag_hierarchy_2__maxlevel; ++i) {
vnear[i] = 0;
}
while ( level > 0 ) {
vnear[level] = nearest =
hierarchy[level]->nearest_neighbor(p, nearest);
CGAL_assertion( !hierarchy[level]->is_infinite(vnear[level]) );
// go at the same vertex on level below
nearest = nearest->down();
--level;
}
vnear[0] =
hierarchy[level]->nearest_neighbor(p, nearest); // at level 0
}
template<class Gt, class Agds, class LTag>
int
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
random_level()
{
boost::geometric_distribution<> proba(1.0/ag_hierarchy_2__ratio);
boost::variate_generator<boost::rand48&, boost::geometric_distribution<> > die(random, proba);
return (std::min)(die(), (int)ag_hierarchy_2__maxlevel)-1;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
file_input(std::istream& is)
{
typedef std::vector<Vertex_handle> Vertex_vector;
// firstly, read the Apollonius graph at each level
clear();
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
hierarchy[i]->file_input(is);
}
Vertex_vector* V = new Vertex_vector[ag_hierarchy_2__maxlevel];
// secondly, create the map of vertex indices
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
V[i].resize(hierarchy[i]->number_of_vertices());
int j = 0;
for (Finite_vertices_iterator vit = hierarchy[i]->finite_vertices_begin();
vit != hierarchy[i]->finite_vertices_end(); ++vit, ++j) {
V[i][j] = vit;
}
}
// read the correspondences between up and down pointers and set
// them appropriately
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
unsigned int level;
int vnum;
is >> level >> vnum;
for (int k = 0; k < vnum; k++) {
int ithis, iup, idown;
is >> ithis >> idown >> iup;
if ( idown != -1 ) { V[i][ithis]->set_down(V[i-1][idown]); }
if ( iup != -1 ) { V[i][ithis]->set_up(V[i+1][iup]); }
}
}
delete[] V;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_hierarchy_2<Gt,Agds,LTag>::
file_output(std::ostream& os) const
{
typedef std::map<Vertex_handle,int> Vertex_map;
// write each level of the hierarchy
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
hierarchy[i]->file_output(os);
if ( IO::is_ascii(os) ) { os << std::endl << std::endl; }
}
Vertex_map* V = new Vertex_map[ag_hierarchy_2__maxlevel];
// create the map of vertex indices
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
int inum = 0;
for (Finite_vertices_iterator vit = hierarchy[i]->finite_vertices_begin();
vit != hierarchy[i]->finite_vertices_end(); ++vit) {
V[i][vit] = inum++;
}
}
Vertex_map* V_up = new Vertex_map[ag_hierarchy_2__maxlevel];
Vertex_map* V_down = new Vertex_map[ag_hierarchy_2__maxlevel];
// create the map of up and down pointers
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
for (Finite_vertices_iterator vit = hierarchy[i]->finite_vertices_begin();
vit != hierarchy[i]->finite_vertices_end(); ++vit) {
if ( vit->up() != Vertex_handle() ) {
V_up[i][vit] = V[i+1][vit->up()];
} else {
V_up[i][vit] = -1;
}
if ( vit->down() != Vertex_handle() ) {
V_down[i][vit] = V[i-1][vit->down()];
} else {
V_down[i][vit] = -1;
}
}
}
// write up and down pointer info
if ( IO::is_ascii(os) ) { os << std::endl << std::endl; }
for (unsigned int i = 0; i < ag_hierarchy_2__maxlevel; ++i) {
os << i;
if ( IO::is_ascii(os) ) { os << " "; }
os << hierarchy[i]->number_of_vertices();
if ( IO::is_ascii(os) ) { os << std::endl; }
for (Finite_vertices_iterator vit = hierarchy[i]->finite_vertices_begin();
vit != hierarchy[i]->finite_vertices_end(); ++vit) {
os << V[i][vit];
if ( IO::is_ascii(os) ) { os << " "; }
os << V_down[i][vit];
if ( IO::is_ascii(os) ) { os << " "; }
os << V_up[i][vit];
if ( IO::is_ascii(os) ) { os << std::endl; }
}
if ( IO::is_ascii(os) ) { os << std::endl << std::endl; }
}
delete[] V;
delete[] V_up;
delete[] V_down;
}
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_HIERARCHY_2_IMPL_H
@@ -0,0 +1,98 @@
// Copyright (c) 2003,2004,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_2_BOUNDED_SIDE_OF_CCW_CIRCLE_C2_H
#define CGAL_APOLLONIUS_GRAPH_2_BOUNDED_SIDE_OF_CCW_CIRCLE_C2_H
#include <CGAL/license/Apollonius_graph_2.h>
#include <CGAL/Apollonius_graph_2/basic.h>
#include <CGAL/Apollonius_graph_2/Predicate_constructions_C2.h>
namespace CGAL {
namespace ApolloniusGraph_2 {
//--------------------------------------------------------------------
template< class K >
class Sign_of_Voronoi_radius
{
public:
typedef Voronoi_radius_2<K> Voronoi_radius;
typedef typename K::FT FT;
typedef typename K::Sign Sign;
public:
inline
Sign operator()(const Voronoi_radius& vr, const Field_with_sqrt_tag&) const
{
FT r = vr.c1() + vr.c2() * CGAL::sqrt(vr.delta());
return CGAL::sign(r);
}
inline
Sign operator()(const Voronoi_radius& vr, const Integral_domain_without_division_tag&) const
{
// this is another way of doing this; the degree becomes 10
// instead of 5 in this case.
// return sign_a_plus_b_x_sqrt_c(vr.c1(), vr.c2(), vr.delta());
bool is_first_root = CGAL::is_negative(vr.c2());
Sign s_beta = CGAL::sign(vr.b());
Sign s_gamma = CGAL::sign(vr.c());
// the existence test
Sign sign_of_root;
if ( is_first_root ) {
sign_of_root = sign_of_first_root(s_beta, s_gamma);
} else {
sign_of_root = sign_of_second_root(s_beta, s_gamma);
}
return sign_of_root;
}
};
template< class K >
class Bounded_side_of_CCW_circle_2
{
private:
Sign_of_Voronoi_radius<K> test;
public:
typedef Voronoi_radius_2<K> Voronoi_radius;
typedef typename K::Bounded_side Bounded_dide;
public:
template<class Tag>
inline Bounded_side
operator()(const Voronoi_radius& vr, const Tag& tag)
{
return enum_cast<Bounded_side>( -test(vr, tag ) );
}
};
//--------------------------------------------------------------------
} //namespace ApolloniusGraph_2
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_2_BOUNDED_SIDE_OF_CCW_CIRCLE_C2_H
@@ -0,0 +1,52 @@
// Copyright (c) 2003,2004,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_2_COMPARE_WEIGHT_2_H
#define CGAL_APOLLONIUS_GRAPH_2_COMPARE_WEIGHT_2_H
#include <CGAL/license/Apollonius_graph_2.h>
#include <CGAL/Apollonius_graph_2/basic.h>
//--------------------------------------------------------------------
namespace CGAL {
namespace ApolloniusGraph_2 {
template<class K>
class Compare_weight_2
{
public:
typedef K Kernel;
typedef typename K::Site_2 Site_2;
typedef typename K::Comparison_result result_type;
typedef Site_2 argument_type;
inline
result_type operator()(const Site_2& s1, const Site_2& s2) const
{
return CGAL::compare(s1.weight(), s2.weight());
}
};
//--------------------------------------------------------------------
} //namespace ApolloniusGraph_2
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_2_COMPARE_WEIGHT_2_H
@@ -0,0 +1,52 @@
// Copyright (c) 2003,2004,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_2_COMPARE_X_2_H
#define CGAL_APOLLONIUS_GRAPH_2_COMPARE_X_2_H
#include <CGAL/license/Apollonius_graph_2.h>
#include <CGAL/Apollonius_graph_2/basic.h>
//--------------------------------------------------------------------
namespace CGAL {
namespace ApolloniusGraph_2 {
template<class K>
class Compare_x_2
{
public:
typedef K Kernel;
typedef typename K::Site_2 Site_2;
typedef typename K::Comparison_result result_type;
typedef Site_2 argument_type;
inline
result_type operator()(const Site_2& s1, const Site_2& s2) const
{
return CGAL::compare(s1.x(), s2.x());
}
};
//--------------------------------------------------------------------
} //namespace ApolloniusGraph_2
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_2_COMPARE_X_2_H
@@ -0,0 +1,52 @@
// Copyright (c) 2003,2004,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_2_COMPARE_Y_2_H
#define CGAL_APOLLONIUS_GRAPH_2_COMPARE_Y_2_H
#include <CGAL/license/Apollonius_graph_2.h>
#include <CGAL/Apollonius_graph_2/basic.h>
//--------------------------------------------------------------------
namespace CGAL {
namespace ApolloniusGraph_2 {
template<class K>
class Compare_y_2
{
public:
typedef K Kernel;
typedef typename K::Site_2 Site_2;
typedef typename K::Comparison_result result_type;
typedef Site_2 argument_type;
inline
result_type operator()(const Site_2& s1, const Site_2& s2) const
{
return CGAL::compare(s1.y(), s2.y());
}
};
//--------------------------------------------------------------------
} //namespace ApolloniusGraph_2
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_2_COMPARE_Y_2_H
@@ -0,0 +1,430 @@
// Copyright (c) 2003,2006 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_APOLLONIUS_GRAPH_2_CONSTRUCTIONS_C2_H
#define CGAL_APOLLONIUS_GRAPH_2_CONSTRUCTIONS_C2_H 1
#include <CGAL/license/Apollonius_graph_2.h>
#include <CGAL/Apollonius_graph_2/basic.h>
#include <CGAL/Parabola_segment_2.h>
#include <CGAL/Hyperbola_2.h>
#include <CGAL/Hyperbola_segment_2.h>
#include <CGAL/Hyperbola_ray_2.h>
#include <CGAL/Apollonius_graph_2/Constructions_ftC2.h>
namespace CGAL {
namespace ApolloniusGraph_2 {
//***********************************************************************
//***********************************************************************
// CONSTRUCTIONS
//***********************************************************************
//***********************************************************************
//-----------------------------------------------------------------------
// Apollonius vertex
//-----------------------------------------------------------------------
template < class Gt >
inline
typename Gt::Point_2
ad_circumcenter_2(const typename Gt::Site_2& p,
const typename Gt::Site_2& q,
const typename Gt::Site_2& r)
{
typedef typename Gt::Point_2 Point_2;
typename Gt::FT x,y;
ad_circumcenterC2(p.x(),p.y(),p.weight(),
q.x(),q.y(),q.weight(),
r.x(),r.y(),r.weight(),x,y);
return Point_2(x,y);
}
template < class Gt >
class Construct_Apollonius_vertex_2
{
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Site_2 Site_2;
typedef Point_2 result_type;
Point_2 operator() (const Site_2& p, const Site_2& q,
const Site_2& r) const
{
return ad_circumcenter_2< Gt >(p,q,r);
}
};
//-----------------------------------------------------------------------
// Apollonius site (dual site)
//-----------------------------------------------------------------------
template < class Gt >
inline
typename Gt::Site_2
ad_circumcircle_2(const typename Gt::Site_2& p,
const typename Gt::Site_2& q,
const typename Gt::Site_2& r)
{
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Point_2 Point_2;
typename Gt::FT x, y, wt;
ad_circumcircleC2(p.x(),p.y(),p.weight(),
q.x(),q.y(),q.weight(),
r.x(),r.y(),r.weight(),x,y,wt);
return Site_2(Point_2(x,y), wt);
}
template < class Gt >
inline
typename Gt::Line_2
ad_left_bitangent_line_2(const typename Gt::Site_2& p,
const typename Gt::Site_2& q)
{
typedef typename Gt::Line_2 Line_2;
typename Gt::FT a, b, c;
ad_left_bitangent_lineC2(p.x(),p.y(),p.weight(),
q.x(),q.y(),q.weight(),
a,b,c);
return Line_2(a, b, c);
}
template < class Gt >
class Construct_Apollonius_site_2
{
public:
typedef typename Gt::Line_2 Line_2;
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Site_2 Site_2;
#if 0
// WARNING: the following type is just a hack; it is not
// really valid
typedef Site_2 result_type;
#endif
inline Site_2 operator()(const Site_2& p,
const Site_2& q,
const Site_2& r) const
{
// CGAL_precondition( ! collinear(p, q, r) );
return ad_circumcircle_2< Gt >(p,q,r);
}
inline Line_2 operator()(const Site_2 &p,
const Site_2 &q) const
{
return ad_left_bitangent_line_2< Gt >(p, q);
}
};
//-----------------------------------------------------------------------
// Apollonius bisector
//-----------------------------------------------------------------------
template< class Gt >
class Construct_Apollonius_bisector_2
{
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Line_2 Line_2;
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Object_2 Object_2;
typedef typename Gt::Construct_object_2 Construct_object_2;
typedef CGAL::Hyperbola_2<Gt> Hyperbola_2;
private:
template<class T>
Object_2 make_object(const T& t) const
{
return Construct_object_2()(t);
}
public:
Object_2 operator() (const Site_2& p, const Site_2& q) const
{
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Line_2 l1(p.point(), q.point());
Line_2 l = l1.perpendicular(midpoint(p.point(), q.point()));
return make_object(l);
}
Hyperbola_2 h(p, q);
return make_object(h);
}
};
//-----------------------------------------------------------------------
// Apollonius bisector ray
//-----------------------------------------------------------------------
template< class Gt >
class Construct_Apollonius_bisector_ray_2
{
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Line_2 Line_2;
typedef typename Gt::Ray_2 Ray_2;
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Object_2 Object_2;
typedef typename Gt::Construct_object_2 Construct_object_2;
typedef typename Gt::Construct_Apollonius_vertex_2 Apollonius_vertex_2;
typedef CGAL::Hyperbola_ray_2<Gt> Hyperbola_ray_2;
typedef CGAL::Sign Hyperbola_direction;
private:
template<class T>
Object_2 make_object(const T& t) const
{
return Construct_object_2()(t);
}
public:
Object_2
operator() (const Site_2& p,
const Site_2& q,
const Point_2& r,
const Hyperbola_direction& direction) const {
//
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Line_2 l1(p.point(), q.point());
Line_2 l = l1.perpendicular(midpoint(p.point(), q.point()));
Ray_2 ray(r, l.direction());
return make_object(ray);
}
Hyperbola_ray_2 hr(p, q, r, direction);
return make_object(hr);
}
Object_2
operator() (const Site_2& p,
const Site_2& q,
const Site_2& r) const {
Point_2 c = Apollonius_vertex_2()(p, q, r);
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Line_2 l1(q.point(), p.point());
Line_2 l = l1.perpendicular(midpoint(p.point(), q.point()));
Ray_2 ray(c, l.direction());
return make_object(ray);
}
Hyperbola_ray_2 hr(p, q, c, NEGATIVE);
return make_object(hr);
}
};
//-----------------------------------------------------------------------
// Apollonius bisector segment
//-----------------------------------------------------------------------
template< class Gt >
class Construct_Apollonius_bisector_segment_2
{
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Segment_2 Segment_2;
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Object_2 Object_2;
typedef typename Gt::Construct_object_2 Construct_object_2;
typedef typename Gt::Construct_Apollonius_vertex_2 Apollonius_vertex_2;
typedef CGAL::Hyperbola_segment_2<Gt> Hyperbola_segment_2;
private:
template<class T>
Object_2 make_object(const T& t) const
{
return Construct_object_2()(t);
}
public:
inline Object_2 operator() (const Site_2& p,
const Site_2& q,
const Point_2& r, const Point_2& s) const {
//
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Segment_2 seg(r, s);
return make_object(seg);
}
Hyperbola_segment_2 hs(p, q, r, s);
return make_object(hs);
}
inline Object_2 operator() (const Site_2& p,
const Site_2& q,
const Site_2& r,
const Site_2& s) const {
Apollonius_vertex_2 apollonius_vertex_2;
Point_2 c_pqr = apollonius_vertex_2(p,q,r);
Point_2 c_qps = apollonius_vertex_2(q,p,s);
//
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Segment_2 seg(c_pqr, c_qps);
return make_object(seg);
}
Hyperbola_segment_2 hs(p, q, c_pqr, c_qps);
return make_object(hs);
}
};
//-----------------------------------------------------------------------
// Apollonius primal ray
//-----------------------------------------------------------------------
template< class Gt >
class Construct_Apollonius_primal_ray_2
{
private:
typedef typename Gt::RT RT;
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Line_2 Line_2;
typedef typename Gt::Ray_2 Ray_2;
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Construct_Apollonius_site_2 Apollonius_circle_2;
inline Ray_2 operator() (const Site_2& p,
const Site_2& r,
const Site_2& s) const {
//
Apollonius_circle_2 apollonius_circle_2;
Line_2 l1 = apollonius_circle_2(r, p);
Line_2 l2 = apollonius_circle_2(p, s);
RT d1 = CGAL::sqrt( CGAL::square(l1.a()) + CGAL::square(l1.b()) );
RT d2 = CGAL::sqrt( CGAL::square(l2.a()) + CGAL::square(l2.b()) );
RT a = l1.a() / d1 - l2.a() / d2;
RT b = l1.b() / d1 - l2.b() / d2;
Point_2 c(p.x() + b, p.y() - a);
return Ray_2(p.point(), c);
}
};
//-----------------------------------------------------------------------
// Apollonius primal segment
//-----------------------------------------------------------------------
template< class Gt >
class Construct_Apollonius_primal_segment_2
{
public:
typedef typename Gt::Point_2 Point_2;
typedef typename Gt::Line_2 Line_2;
typedef typename Gt::Segment_2 Segment_2;
typedef typename Gt::Site_2 Site_2;
typedef typename Gt::Object_2 Object_2;
typedef typename Gt::Construct_object_2 Construct_object_2;
typedef typename Gt::RT Weight;
typedef CGAL::Hyperbola_segment_2<Gt> Hyperbola_segment_2;
typedef CGAL::Parabola_segment_2<Gt> Parabola_segment_2;
typedef typename Gt::Construct_Apollonius_site_2 Apollonius_circle_2;
typedef typename Gt::Construct_Apollonius_vertex_2 Apollonius_vertex_2;
typedef typename Gt::Is_degenerate_edge_2 Is_degenerate_edge_2;
private:
template<class T>
Object_2 make_object(const T& t) const
{
return Construct_object_2()(t);
}
public:
inline Segment_2
operator() (const Site_2& p,
const Site_2& q) const {
//
return Segment_2(p.point(), q.point());
}
inline Object_2
operator() (const Site_2& p,
const Site_2& q,
const Point_2& r, const Point_2& s) const {
//
Comparison_result cr = CGAL::compare(p.weight(), q.weight());
if ( cr == EQUAL ) {
Segment_2 seg(r, s);
return make_object(seg);
}
Hyperbola_segment_2 hs(p, q, r, s);
return make_object(hs);
}
inline Object_2
operator() (const Site_2& p,
const Site_2& q,
const Site_2& r,
const Site_2& s) const {
if ( Is_degenerate_edge_2()(p, q, r, s) ) {
Point_2 v = Apollonius_vertex_2()(p, q, r);
Segment_2 seg1(p.point(), v);
Segment_2 seg2(v, q.point());
return make_object(std::pair<Segment_2,Segment_2>(seg1, seg2));
}
Apollonius_circle_2 apollonius_circle_2;
Site_2 c_pqr = apollonius_circle_2(p, q, r);
Site_2 c_qps = apollonius_circle_2(q, p, s);
//
Comparison_result cr = CGAL::compare(c_pqr.weight(), c_qps.weight());
if ( cr == EQUAL ) {
Segment_2 seg(p.point(), q.point());
return make_object(seg);
}
Hyperbola_segment_2 hs(c_pqr, c_qps, p.point(), q.point());
return make_object(hs);
}
inline Parabola_segment_2
operator() (const Site_2& p,
const Site_2& q,
const Site_2& r) const {
//
Apollonius_circle_2 apollonius_circle_2;
Site_2 c = apollonius_circle_2(p, q, r);
Line_2 l = apollonius_circle_2(q, p);
return Parabola_segment_2(c, l, q.point(), p.point());
}
};
} //namespace ApolloniusGraph_2
} //namespace CGAL
#endif // CGAL_APOLLONIUS_GRAPH_2_CONSTRUCTIONS_C2_H

Some files were not shown because too many files have changed in this diff Show More