Added new traversal rule and dists vector to Orthogonal search

Functions min_dist_to_rectangle and max... have an overload with
std::vector<FT>& dists now. That is required for ortho searches, so
we have no backwards compatibility.
The values for extended internal nodes have also been changed.
This commit is contained in:
m.overtheil 2014-12-02 10:36:36 +01:00
parent e6019889cc
commit af343d926e
10 changed files with 340 additions and 45 deletions

View File

@ -87,10 +87,11 @@ int main(int argc,char *argv[])
for (Neighbor_search_3::iterator it = search.begin(); it != search.end();it++, i++) {
result[i] = it->first;
if(dump){
std::cerr << result[i].x()<<" "<<result[i].y()<< std::endl;
std::cerr << result[i].x()<<" "<<result[i].y()<<" "<<result[i].z()<< std::endl;
}
}
if(dump)
search.statistics(std::cerr);
dump = false;
}
t.stop();

View File

@ -108,6 +108,26 @@ namespace CGAL {
return distance;
}
inline FT min_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,D>& r,std::vector<FT>& dists) {
FT distance = FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),
qe = construct_it(q,1);
for(unsigned int i = 0;qit != qe; i++, qit++){
if((*qit) < r.min_coord(i)){
dists[i] = (r.min_coord(i)-(*qit));
distance += dists[i] * dists[i];
}
else if ((*qit) > r.max_coord(i)){
dists[i] = ((*qit)-r.max_coord(i));
distance += dists[i] * dists[i];
}
}
return distance;
}
inline FT max_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,D>& r) const {
FT distance=FT(0);
@ -123,6 +143,25 @@ namespace CGAL {
return distance;
}
inline FT max_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,D>& r,std::vector<FT>& dists ) {
FT distance=FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),
qe = construct_it(q,1);
for(unsigned int i = 0;qit != qe; i++, qit++){
if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)){
dists[i] = (r.max_coord(i)-(*qit));
distance += dists[i] * dists[i];
}
else{
dists[i] = ((*qit)-r.min_coord(i));
distance += dists[i] * dists[i];
}
};
return distance;
}
inline FT new_distance(FT dist, FT old_off, FT new_off,
int /* cutting_dimension */) const {

View File

@ -107,6 +107,28 @@ namespace CGAL {
return distance;
}
inline FT min_distance_to_rectangle(const Sphere_d& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
Point_d c= Construct_center_d()(q);
FT distance = FT(0);
Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
Cartesian_const_iterator_d cit = construct_it(c),
ce = construct_it(c,1);
for (unsigned int i = 0; cit != ce; ++i, ++cit) {
if ((*cit) < r.min_coord(i)){
dists[i] =(r.min_coord(i)-(*cit));
distance += dists[i] * dists[i];
}
else if ((*cit) > r.max_coord(i)){
dists[i] = ((*cit)-r.max_coord(i));
distance += dists[i] * dists[i];
}
};
distance += - Compute_squared_radius_d()(q);
if (distance<0) distance=FT(0);
return distance;
}
inline FT max_distance_to_rectangle(const Sphere_d& q,
const Kd_tree_rectangle<FT,Dimension>& r) const {
Construct_center_d construct_center_d;
@ -126,6 +148,29 @@ namespace CGAL {
return distance;
}
inline FT max_distance_to_rectangle(const Sphere_d& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
Construct_center_d construct_center_d;
Point_d c = construct_center_d(q);
FT distance=FT(0);
Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
Cartesian_const_iterator_d cit = construct_it(c),
ce = construct_it(c,1);
for (unsigned int i = 0; cit != ce; ++i, ++cit) {
if ((*cit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)){
dists[i] = (r.max_coord(i)-(*cit));
distance += dists[i] * dists[i];
}
else{
dists[i] = ((*cit)-r.min_coord(i));
distance += dists[i] * dists[i];
}
};
distance += - Compute_squared_radius_d()(q);
if (distance<0) distance=FT(0);
return distance;
}
inline FT transformed_distance(FT d) const {

View File

@ -175,8 +175,13 @@ private:
split(node.separator(), c, c_low);
int cd = node.separator().cutting_dimension();
if(!c_low.empty())
node.low_val = c_low.tight_bounding_box().max_coord(cd);
else
node.low_val = c_low.bounding_box().min_coord(cd);
if(!c.empty())
node.high_val = c.tight_bounding_box().min_coord(cd);
else
node.high_val = c.bounding_box().max_coord(cd);
CGAL_assertion(node.separator().cutting_value() >= node.low_val);

View File

@ -175,14 +175,14 @@ namespace CGAL {
std::ostream&
print(std::ostream& s) const
{
s << "Rectangle dimension = " << D;
s << "Rectangle dimension = " << D::value;
s << "\n lower: ";
for (int i=0; i < D; ++i)
for (int i=0; i < D::value; ++i)
s << lower_[i] << " ";
// std::copy(lower_, lower_ + D,
// std::ostream_iterator<FT>(s," "));
s << "\n upper: ";
for (int j=0; j < D; ++j)
for (int j=0; j < D::value; ++j)
s << upper_[j] << " ";
// std::copy(upper_, upper_ + D,
// std::ostream_iterator<FT>(s," "));

View File

@ -101,6 +101,28 @@ namespace CGAL {
return distance;
}
inline FT min_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
FT distance = FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=
traits.construct_cartesian_const_iterator_d_object();
typename SearchTraits::Construct_min_vertex_d construct_min_vertex;
typename SearchTraits::Construct_max_vertex_d construct_max_vertex;
typename SearchTraits::Cartesian_const_iterator_d qmaxit = construct_it(construct_max_vertex(q)),
qe = construct_it(construct_max_vertex(q),1), qminit = construct_it(construct_min_vertex(q));
for (unsigned int i = 0; qmaxit != qe; ++ qmaxit, ++qminit, ++i) {
if (r.min_coord(i)>(*qmaxit)) {
dists[i]=(r.min_coord(i)-(*qmaxit));
distance +=dists[i];
}
if (r.max_coord(i)<(*qminit)) {
dists[i]=((*qminit)-r.max_coord(i));
distance += dists[i];
}
}
return distance;
}
inline
FT
max_distance_to_rectangle(const Query_item& q,
@ -123,6 +145,30 @@ namespace CGAL {
inline
FT
max_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
FT distance=FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=
traits.construct_cartesian_const_iterator_d_object();
typename SearchTraits::Construct_min_vertex_d construct_min_vertex;
typename SearchTraits::Construct_max_vertex_d construct_max_vertex;
typename SearchTraits::Cartesian_const_iterator_d qmaxit = construct_it(construct_max_vertex(q)),
qe = construct_it(construct_max_vertex(q),1), qminit = construct_it(construct_min_vertex(q));
for (unsigned int i = 0; qmaxit != qe; ++ qmaxit, ++qminit, ++i) {
if ( r.max_coord(i)-(*qminit) >(*qmaxit)-r.min_coord(i) ) {
dists[i]=(r.max_coord(i)-(*qminit));
distance += dists[i];
}
else {
dists[i]=((*qmaxit)-r.min_coord(i));
distance += dists[i];
}
}
return distance;
}
inline
FT
transformed_distance(FT d) const
{
return d;

View File

@ -43,23 +43,30 @@ public:
{
if (tree.empty()) return;
FT distance_to_root;
if (this->search_nearest)
distance_to_root = this->distance_instance.min_distance_to_rectangle(q, tree.bounding_box());
else
distance_to_root = this->distance_instance.max_distance_to_rectangle(q, tree.bounding_box());
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=tree.traits().construct_cartesian_const_iterator_d_object();
query_object_it = construct_it(this->query_object);
compute_neighbors_orthogonally(tree.root(), distance_to_root);
int dim = static_cast<int>(std::distance(query_object_it, construct_it(this->query_object,0)));
std::vector<FT> dists(dim);
for(int i=0;i<dim;i++)
dists[i]=0;
FT distance_to_root;
if (this->search_nearest)
distance_to_root = this->distance_instance.min_distance_to_rectangle(q, tree.bounding_box(),dists);
else
distance_to_root = this->distance_instance.max_distance_to_rectangle(q, tree.bounding_box(),dists);
compute_neighbors_orthogonally(tree.root(), distance_to_root,dists);
if (sorted) this->queue.sort();
}
private:
void compute_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd)
void compute_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd,std::vector<FT>& dists)
{
if (!(N->is_leaf()))
{
@ -67,43 +74,46 @@ private:
static_cast<Tree::Internal_node_const_handle>(N);
this->number_of_internal_nodes_visited++;
int new_cut_dim=node->cutting_dimension();
FT old_off, new_rd;
FT new_off = *(query_object_it + new_cut_dim) - node->cutting_value();
if ( ((new_off < FT(0.0)) && (this->search_nearest)) ||
((new_off >= FT(0.0)) && (!this->search_nearest)) )
Base::Node_const_handle bestChild, otherChild;
FT new_off;
FT val = *(query_object_it + new_cut_dim);
FT diff1 = val - node->high_value();
FT diff2 = val - node->low_value();
if ( ((diff1 + diff2 < FT(0.0)) && (this->search_nearest)) ||
((diff1 + diff2 >= FT(0.0)) && (!this->search_nearest)) )
{
compute_neighbors_orthogonally(node->lower(),rd);
if (this->search_nearest) {
old_off= *(query_object_it + new_cut_dim) - node->low_value();
if (old_off>FT(0.0))
old_off=FT(0.0);
new_off = diff1;
bestChild = node->lower();
otherChild = node->upper();
}
else {
old_off= *(query_object_it + new_cut_dim) - node->high_value();
if (old_off<FT(0.0))
old_off=FT(0.0);
new_off= diff2;
bestChild = node->upper();
otherChild = node->lower();
}
new_rd = this->distance_instance.new_distance(rd,old_off,new_off,new_cut_dim);
if (this->branch(new_rd))
compute_neighbors_orthogonally(node->upper(), new_rd);
}
else // compute new distance
{
compute_neighbors_orthogonally(node->upper(),rd);
if (this->search_nearest) {
old_off= node->high_value() - *(query_object_it + new_cut_dim);
if (old_off>FT(0.0))
old_off=FT(0.0);
new_off= diff2;
bestChild = node->upper();
otherChild = node->lower();
}
else {
old_off= node->low_value() - *(query_object_it + new_cut_dim);
if (old_off<FT(0.0))
old_off=FT(0.0);
new_off= diff1;
bestChild = node->lower();
otherChild = node->upper();
}
new_rd = this->distance_instance. new_distance(rd,old_off,new_off,new_cut_dim);
}
compute_neighbors_orthogonally(bestChild, rd,dists);
FT dst=dists[new_cut_dim];
FT new_rd = this->distance_instance.new_distance(rd,dst,new_off,new_cut_dim);
dists[new_cut_dim]=new_off;
if (this->branch(new_rd))
compute_neighbors_orthogonally(node->lower(), new_rd);
}
compute_neighbors_orthogonally(otherChild, new_rd,dists);
dists[new_cut_dim]=dst;
}
else
{

View File

@ -157,11 +157,22 @@ public:
return static_cast<const Base_distance*>(this)->min_distance_to_rectangle(p,b);
}
template <class FT,class Dimension>
FT min_distance_to_rectangle(const Query_item& p, const CGAL::Kd_tree_rectangle<FT,Dimension>& b,std::vector<FT>& dists)
{
return static_cast<Base_distance*>(this)->min_distance_to_rectangle(p,b,dists);
}
template <class FT,class Dimension>
FT max_distance_to_rectangle(const Query_item& p,const CGAL::Kd_tree_rectangle<FT,Dimension>& b) const
{
return static_cast<const Base_distance*>(this)->max_distance_to_rectangle(p,b);
}
template <class FT,class Dimension>
FT max_distance_to_rectangle(const Query_item& p,const CGAL::Kd_tree_rectangle<FT,Dimension>& b,std::vector<FT>& dists)
{
return static_cast<Base_distance*>(this)->max_distance_to_rectangle(p,b,dists);
}
};
}//namespace CGAL

View File

@ -178,6 +178,49 @@ namespace CGAL {
return distance;
}
inline
FT
min_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
FT distance = FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=
traits.construct_cartesian_const_iterator_d_object();
Coord_iterator qit = construct_it(q), qe = construct_it(q,1);
if (power == FT(0))
{
for (unsigned int i = 0; qit != qe; ++qit, ++i) {
if (the_weights[i]*(r.min_coord(i) -
(*qit)) > distance){
dists[i] = (r.min_coord(i)-
(*qit));
distance = the_weights[i] * dists[i];
}
if (the_weights[i] * ((*qit) - r.max_coord(i)) >
distance){
dists[i] =
((*qit)-r.max_coord(i));
distance = the_weights[i] * dists[i];
}
}
}
else
{
for (unsigned int i = 0; qit != qe; ++qit, ++i) {
if ((*qit) < r.min_coord(i)){
dists[i] = r.min_coord(i)-(*qit);
distance += the_weights[i] *
std::pow(dists[i],power);
}
if ((*qit) > r.max_coord(i)){
dists[i] = (*qit)-r.max_coord(i);
distance += the_weights[i] *
std::pow(dists[i],power);
}
}
};
return distance;
}
inline
FT
max_distance_to_rectangle(const Query_item& q,
@ -217,6 +260,51 @@ namespace CGAL {
inline
FT
max_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,Dimension>& r,std::vector<FT>& dists) {
FT distance=FT(0);
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=
traits.construct_cartesian_const_iterator_d_object();
Coord_iterator qit = construct_it(q), qe = construct_it(q,1);
if (power == FT(0))
{
for (unsigned int i = 0; qit != qe; ++qit, ++i) {
if ((*qit) >= (r.min_coord(i) +
r.max_coord(i))/FT(2.0)) {
if (the_weights[i] * ((*qit) -
r.min_coord(i)) > distance){
dists[i] = (*qit)-r.min_coord(i);
distance = the_weights[i] *
(dists[i]);
}
else
if (the_weights[i] *
(r.max_coord(i) - (*qit)) > distance){
dists[i] = r.max_coord(i)-(*qit);
distance = the_weights[i] *
(dists[i]);
}
}
}
}
else
{
for (unsigned int i = 0; qit != qe; ++qit, ++i) {
if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)){
dists[i] = r.max_coord(i)-(*qit);
distance += the_weights[i] * std::pow(dists[i],power);
}
else{
dists[i] = (*qit)-r.min_coord(i);
distance += the_weights[i] * std::pow(dists[i],power);
}
}
};
return distance;
}
inline
FT
new_distance(FT dist, FT old_off, FT new_off,
int cutting_dimension) const
{

View File

@ -24,6 +24,39 @@ struct Distance {
return distance;
}
template <class TreeTraits>
double min_distance_to_rectangle(const Point& p,
const CGAL::Kd_tree_rectangle<TreeTraits>& b,std::vector<double>& dists){
double distance(0.0), h = p.x();
if (h < b.min_coord(0)){
dists[0] = (b.min_coord(0)-h);
distance += dists[0]*dists[0];
}
if (h > b.max_coord(0)){
dists[0] = (h-b.max_coord(0));
distance += dists[0]*dists[0];
}
h=p.y();
if (h < b.min_coord(1)){
dists[1] = (b.min_coord(1)-h);
distance += dists[1]*dists[1];
}
if (h > b.max_coord(1)){
dists[1] = (h-b.max_coord(1));
distance += dists[1]*dists[1];
}
h=p.z();
if (h < b.min_coord(2)){
dists[2] = (b.min_coord(2)-h);
distance += dists[2]*dists[2];
}
if (h > b.max_coord(2)){
dists[2] = (h-b.max_coord(2));
distance += dists[2]*dists[2];
}
return distance;
}
template <class TreeTraits>
double max_distance_to_rectangle(const Point& p,
const CGAL::Kd_tree_rectangle<TreeTraits>& b) const {
@ -41,6 +74,23 @@ struct Distance {
return d0 + d1 + d2;
}
template <class TreeTraits>
double max_distance_to_rectangle(const Point& p,
const CGAL::Kd_tree_rectangle<TreeTraits>& b,std::vector<double>& dists){
double h = p.x();
dists[0] = (h >= (b.min_coord(0)+b.max_coord(0))/2.0) ?
(h-b.min_coord(0)) : (b.max_coord(0)-h);
h=p.y();
dists[1] = (h >= (b.min_coord(1)+b.max_coord(1))/2.0) ?
(h-b.min_coord(1)) : (b.max_coord(1)-h);
h=p.z();
dists[2] = (h >= (b.min_coord(2)+b.max_coord(2))/2.0) ?
(h-b.min_coord(2)) : (b.max_coord(2)-h);
return dists[0] * dists[0] + dists[1] * dists[1] + dists[2] * dists[2];
}
double new_distance(double& dist, double old_off, double new_off,
int /*cutting_dimension*/) const {
return dist + new_off*new_off - old_off*old_off;