mirror of https://github.com/CGAL/cgal
255 lines
8.3 KiB
C++
255 lines
8.3 KiB
C++
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $Source: /CVSROOT/CGAL/Packages/Envelope_3/include/CGAL/Envelope_caching_traits_3.h,v $
|
|
// $Revision$ $Date$
|
|
// $Name: $
|
|
//
|
|
// Author(s) : Michal Meyerovitch <gorgymic@post.tau.ac.il>
|
|
|
|
#ifndef ENVELOPE_CACHING_TRAITS_3_H
|
|
#define ENVELOPE_CACHING_TRAITS_3_H
|
|
|
|
/*! \file
|
|
* The caching traits class for the envelope package.
|
|
*/
|
|
|
|
#include <map>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
* \class A decorator for a traits class of the envelope divide-and-conquer
|
|
* algorithm, adding a caching ability.
|
|
*/
|
|
template <class EnvelopeTraits_3>
|
|
class Envelope_caching_traits_3 : public EnvelopeTraits_3
|
|
{
|
|
public:
|
|
typedef EnvelopeTraits_3 Base_traits_3;
|
|
typedef Envelope_caching_traits_3<Base_traits_3> Self;
|
|
|
|
typedef typename Base_traits_3::Point_2 Point_2;
|
|
typedef typename Base_traits_3::Curve_2 Curve_2;
|
|
typedef typename Base_traits_3::X_monotone_curve_2 X_monotone_curve_2;
|
|
typedef typename Base_traits_3::Surface_3 Surface_3;
|
|
typedef typename Base_traits_3::Xy_monotone_surface_3 Xy_monotone_surface_3;
|
|
|
|
protected:
|
|
typedef std::pair<Curve_2, Intersection_type> Intersection_curve;
|
|
|
|
// caching for intersections
|
|
typedef std::list<Object> Intersections_list;
|
|
typedef std::pair<Xy_monotone_surface_3,
|
|
Xy_monotone_surface_3> Surface_pair;
|
|
|
|
struct Less_surface_pair
|
|
{
|
|
bool operator() (const Surface_pair& sp1,
|
|
const Surface_pair& sp2) const
|
|
{
|
|
// Compare the pairs of IDs lexicographically.
|
|
return (sp1.first < sp2.first ||
|
|
(sp1.first == sp2.first && sp1.second < sp2.second));
|
|
}
|
|
};
|
|
|
|
// caching for construct_projected_intersections traits method's result
|
|
typedef std::map<Surface_pair,
|
|
Intersections_list, Less_surface_pair> Intersections_cache;
|
|
|
|
// caching for compare_distance_to_envelope traits method's result
|
|
typedef std::map<Surface_pair,
|
|
Comparison_result, Less_surface_pair> Compare_cache;
|
|
|
|
public:
|
|
|
|
class Construct_projected_intersections_2
|
|
{
|
|
protected:
|
|
const Self& parent;
|
|
Intersections_cache& inter_cache;
|
|
unsigned int& intersections_number;
|
|
|
|
public:
|
|
Construct_projected_intersections_2(const Self* p,
|
|
Intersections_cache& inter,
|
|
unsigned int& inter_num)
|
|
: parent(*p), inter_cache(inter),
|
|
intersections_number(inter_num)
|
|
{}
|
|
|
|
// insert into OutputIterator all the (2d) projections on the xy plane of
|
|
// the intersection objects between the 2 surfaces
|
|
// the data type of OutputIterator is Object
|
|
template <class OutputIterator>
|
|
OutputIterator
|
|
operator()(const Xy_monotone_surface_3& s1,
|
|
const Xy_monotone_surface_3& s2,
|
|
OutputIterator o) const
|
|
{
|
|
Intersections_list inter_list;
|
|
|
|
typename Intersections_cache::iterator cache_iter;
|
|
Surface_pair spair(s1, s2);
|
|
|
|
// search for this pair in the cache
|
|
cache_iter = inter_cache.find(spair);
|
|
if (cache_iter == inter_cache.end())
|
|
{
|
|
parent.Base_traits_3::construct_projected_intersections_2_object()
|
|
(s1, s2, std::back_inserter(inter_list));
|
|
inter_cache[spair] = inter_list;
|
|
|
|
// update statistics
|
|
if (inter_list.size() > 0)
|
|
++intersections_number;
|
|
}
|
|
else
|
|
{
|
|
inter_list = (*cache_iter).second;
|
|
}
|
|
|
|
// report intersections
|
|
typename Intersections_list::const_iterator iter;
|
|
for (iter = inter_list.begin(); iter != inter_list.end(); ++iter)
|
|
*o++ = *iter;
|
|
return o;
|
|
}
|
|
};
|
|
|
|
/*! Get a Construct_projected_intersections_2 functor object. */
|
|
Construct_projected_intersections_2
|
|
construct_projected_intersections_2_object() const
|
|
{
|
|
return Construct_projected_intersections_2(this, inter_cache,
|
|
intersections_number);
|
|
}
|
|
|
|
class Compare_distance_to_envelope_3
|
|
{
|
|
protected:
|
|
const Self& parent;
|
|
Compare_cache& compare_cache;
|
|
public:
|
|
Compare_distance_to_envelope_3(const Self* p, Compare_cache& comp_cache)
|
|
: parent(*p), compare_cache(comp_cache)
|
|
{}
|
|
|
|
// check which of the surfaces is closer to the envelope at the xy
|
|
// coordinates of point (i.e. lower if computing the lower envelope, or
|
|
// upper if computing the upper envelope)
|
|
// precondition: the surfaces are defined in point
|
|
Comparison_result operator()(const Point_2& p,
|
|
const Xy_monotone_surface_3& s1,
|
|
const Xy_monotone_surface_3& s2) const
|
|
{
|
|
return compare_distance_to_envelope(p,s1,s2);
|
|
}
|
|
|
|
// check which of the surfaces is closer to the envelope at the xy
|
|
// coordinates of cv (i.e. lower if computing the lower envelope, or upper
|
|
// if computing the upper envelope)
|
|
// precondition: the surfaces are defined in all points of cv, and the
|
|
// answer is the same for each of these points
|
|
Comparison_result operator()(const X_monotone_curve_2& cv,
|
|
const Xy_monotone_surface_3& s1,
|
|
const Xy_monotone_surface_3& s2) const
|
|
{
|
|
return compare_distance_to_envelope(cv,s1,s2);
|
|
}
|
|
|
|
protected:
|
|
template <class Geometry>
|
|
Comparison_result compare_distance_to_envelope(Geometry& g,
|
|
const Xy_monotone_surface_3& s1,
|
|
const Xy_monotone_surface_3& s2) const
|
|
{
|
|
// check that s1 and s2 do not intersect
|
|
Intersections_list inter_list;
|
|
parent.construct_projected_intersections_2_object()(s1, s2,
|
|
std::back_inserter(inter_list));
|
|
|
|
// if they do not intersect, we can use the cache
|
|
if (inter_list.empty())
|
|
{
|
|
// then we should check the cache of compare_distance, and only if it's empty
|
|
// use the traits
|
|
Surface_pair spair(s1, s2);
|
|
|
|
typename Compare_cache::iterator comp_cache_iter;
|
|
comp_cache_iter = compare_cache.find(spair);
|
|
if (comp_cache_iter == compare_cache.end())
|
|
{
|
|
Comparison_result res =
|
|
parent.Base_traits_3::compare_distance_to_envelope_3_object()(g, s1, s2);
|
|
compare_cache[spair] = res;
|
|
return res;
|
|
}
|
|
else
|
|
return (*comp_cache_iter).second;
|
|
}
|
|
else
|
|
// they intersect, so must use the traits
|
|
return parent.Base_traits_3::compare_distance_to_envelope_3_object()(g, s1, s2);
|
|
}
|
|
};
|
|
|
|
/*! Get a Compare_distance_to_envelope_3 functor object. */
|
|
Compare_distance_to_envelope_3
|
|
compare_distance_to_envelope_3_object() const
|
|
{
|
|
return Compare_distance_to_envelope_3(this, compare_cache);
|
|
}
|
|
|
|
Envelope_caching_traits_3() : Base_traits_3(), intersections_number(0)
|
|
{}
|
|
|
|
virtual ~Envelope_caching_traits_3()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
// methods for benchmarks
|
|
void reset()
|
|
{
|
|
intersections_number = 0;
|
|
inter_cache.clear();
|
|
compare_cache.clear();
|
|
}
|
|
void print_bench() const
|
|
{
|
|
std::cout << intersections_number;
|
|
}
|
|
void print_bench_header() const
|
|
{
|
|
std::cout << "projected intersections# ";
|
|
}
|
|
void print_statistics() const
|
|
{
|
|
std::cout << "number of projected intersection found: "
|
|
<< intersections_number << std::endl;
|
|
}
|
|
|
|
protected:
|
|
|
|
mutable Intersections_cache inter_cache;
|
|
mutable unsigned int intersections_number;
|
|
|
|
mutable Compare_cache compare_cache;
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif
|