cgal/Packages/Spatial_searching/include/CGAL/Weighted_Minkowski_distance.h

195 lines
5.0 KiB
C++

// ======================================================================
//
// Copyright (c) 2002 The CGAL Consortium
//
// This software and related documentation is part of an INTERNAL release
// of the Computational Geometry Algorithms Library (CGAL). It is not
// intended for general use.
//
// ----------------------------------------------------------------------
//
// release :
// release_date :
//
// file : include/CGAL/Weighted_Minkowski_distance.h
// package : ASPAS
// revision : 2.4
// revision_date : 2002/16/08
// authors : Hans Tangelder (<hanst@cs.uu.nl>)
// maintainer : Hans Tangelder (<hanst@cs.uu.nl>)
// coordinator : Utrecht University
//
// ======================================================================
// Note: this implementation is based on a weight vector,
// another traits class for weighted Minkowski distances based on a
// weight matrix will be added to ASPAS in the future
// Note: Use p=0 to denote the weighted Linf-distance
// For 0<p<1 Lp is not a metric
#ifndef CGAL_WEIGHTED_MINKOWSKI_DISTANCE_H
#define CGAL_WEIGHTED_MINKOWSKI_DISTANCE_H
#include <math.h>
#include <CGAL/Kd_tree_rectangle.h>
namespace CGAL {
template <class Query_item, class Item>
class Weighted_Minkowski_distance {
public:
typedef typename Item::R::FT NT;
typedef std::vector<NT> Weight_vector;
private:
NT p; // p denotes the power
unsigned int The_dimension;
Weight_vector *The_weights;
public:
// default constructor
// default case dim=2, L2.
Weighted_Minkowski_distance() : p(NT(2)), The_dimension(2)
{
The_weights = new Weight_vector(2);
(*The_weights)[0]=NT(1);
(*The_weights)[1]=NT(1);
}
Weighted_Minkowski_distance (NT power, int dim,
Weight_vector Weights) : p(power), The_dimension(dim)
{
assert(p >= NT(0));
assert(The_dimension==Weights.size());
for (unsigned int i = 0; i < Weights.size(); ++i)
assert(Weights[i]>=NT(0));
The_weights = new Weight_vector(Weights.size());
for (unsigned int i = 0; i < Weights.size(); ++i)
(*The_weights)[i]=Weights[i];
}
~Weighted_Minkowski_distance() {
delete The_weights;
};
inline NT distance(const Query_item& p1, const Item& p2) {
NT distance = NT(0);
if (p == NT(0)) {
for (unsigned int i = 0; i < The_dimension; ++i)
if ((*The_weights)[i] * fabs(p1[i] - p2[i]) > distance)
distance = (*The_weights)[i] * fabs(p1[i]-p2[i]);
}
else
for (unsigned int i = 0; i < The_dimension; ++i)
distance +=
(*The_weights)[i] * pow(fabs(p1[i]-p2[i]),p);
return distance;
}
inline NT min_distance_to_queryitem(const Query_item& Point,
const Kd_tree_rectangle<NT>& r) {
NT distance = NT(0);
if (p == NT(0))
{
for (int i = 0; i < r.dimension(); ++i) {
if ((*The_weights)[i]*(r.min_coord(i) -
Point[i]) > distance)
distance = (*The_weights)[i] * (r.min_coord(i)-
Point[i]);
if ((*The_weights)[i] * (Point[i] - r.max_coord(i)) >
distance)
distance = (*The_weights)[i] *
(Point[i]-r.max_coord(i));
}
}
else
{
for (int i = 0; i < r.dimension(); ++i) {
if (Point[i] < r.min_coord(i))
distance += (*The_weights)[i] *
pow(r.min_coord(i)-Point[i],p);
if (Point[i] > r.max_coord(i))
distance += (*The_weights)[i] *
pow(Point[i]-r.max_coord(i),p);
}
};
return distance;
}
inline NT max_distance_to_queryitem(const Query_item& Point,
const Kd_tree_rectangle<NT>& r) {
NT distance=NT(0);
if (p == NT(0))
{
for (int i = 0; i < r.dimension(); ++i) {
if (Point[i] >= (r.min_coord(i) +
r.max_coord(i))/NT(2.0))
if ((*The_weights)[i] * (Point[i] -
r.min_coord(i)) > distance)
distance = (*The_weights)[i] *
(Point[i]-r.min_coord(i));
else
if ((*The_weights)[i] *
(r.max_coord(i) - Point[i]) > distance)
distance = (*The_weights)[i] *
( r.max_coord(i)-Point[i]);
}
}
else
{
for (int i = 0; i < r.dimension(); ++i) {
if (Point[i] <= (r.min_coord(i)+r.max_coord(i))/NT(2.0))
distance += (*The_weights)[i] * pow(r.max_coord(i)-Point[i],p);
else
distance += (*The_weights)[i] * pow(Point[i]-r.min_coord(i),p);
}
};
return distance;
}
inline NT new_distance(NT& dist, NT old_off, NT new_off,
int cutting_dimension) {
NT new_dist;
if (p == NT(0))
{
if ((*The_weights)[cutting_dimension]*fabs(new_off)
> dist)
new_dist=
(*The_weights)[cutting_dimension]*fabs(new_off);
else new_dist=dist;
}
else
{
new_dist = dist + (*The_weights)[cutting_dimension] *
(pow(fabs(new_off),p)-pow(fabs(old_off),p));
}
return new_dist;
}
inline NT transformed_distance(NT d) {
if (p <= NT(0)) return d;
else return pow(d,p);
}
inline NT inverse_of_transformed_distance(NT d) {
if (p <= NT(0)) return d;
else return pow(d,1/p);
}
}; // class Weighted_Minkowski_distance
} // namespace CGAL
#endif // WEIGHTED_MINKOWSKI_DISTANCE_H