mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-05 16:49:04 +00:00
Public source code release
This commit is contained in:
@@ -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_
|
||||
@@ -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_
|
||||
|
||||
@@ -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
+102
@@ -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
|
||||
+73
@@ -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
|
||||
+85
@@ -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
|
||||
+142
@@ -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
|
||||
+55
@@ -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
|
||||
+503
@@ -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
|
||||
+222
@@ -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
|
||||
+52
@@ -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
|
||||
+184
@@ -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
|
||||
+227
@@ -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
|
||||
+399
@@ -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
|
||||
+70
@@ -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
|
||||
+576
@@ -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
|
||||
+67
@@ -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
|
||||
+464
@@ -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
Reference in New Issue
Block a user