vcglib/apps/nexus/vpartition.cpp

170 lines
4.9 KiB
C++

/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.4 2005/02/21 17:55:48 ponchio
debug debug debug
Revision 1.3 2005/01/21 17:09:13 ponchio
Porting and debug.
Revision 1.2 2004/12/04 13:24:27 ponchio
Fixed a couple of memory leak...
Revision 1.1 2004/11/30 22:50:30 ponchio
Level 0.
****************************************************************************/
#include <stdio.h>
#include "vpartition.h"
#include <ANN/ANN.h>
using namespace std;
using namespace vcg;
using namespace nxs;
VPartition::~VPartition() {
if(bd) delete bd;
}
void VPartition::Init() {
if(bd) delete bd;
buffer.resize(size() * 3);
for(unsigned int i = 0; i < size(); i++) {
for(int k = 0; k < 3; k++)
buffer[i*3+k] = operator[](i)[k];
}
points.resize(size());
for(unsigned int i = 0; i < size(); i++) {
points[i] = &buffer[i*3];
}
bd = new ANNkd_tree(&*points.begin(), size(), 3);
}
void VPartition::Closest(const vcg::Point3f &p, unsigned int nsize,
vector<int> &nears,
vector<float> &dist) {
double point[3];
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
if(nsize > size()) nsize = size();
nears.resize(nsize);
dist.resize(nsize);
vector<double> dists;
dists.resize(nsize);
bd->annkSearch(&point[0], nsize, &*nears.begin(), &*dists.begin());
for(unsigned int i = 0; i < nsize; i++)
dist[i] = (float)dists[i];
}
void VPartition::Closest(const vcg::Point3f &p,
int &target, float &dist) {
double point[3];
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
double dists;
bd->annkSearch(&point[0], 1, &target, &dists);
assert(target >= 0);
assert(target < size());
dist = (float)dists;
}
void VPartition::Closest(const vcg::Point3f &p,
vector<int> &targets,
vector<double> &dists,
float max_distance) {
double point[3]; point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
int seeds = 6;
while(1) {
if(seeds > size()) seeds = size();
targets.resize(seeds);
dists.resize(seeds);
bd->annkSearch(&point[0], seeds, &(targets[0]), &(dists[0]));
for(int i = 0; i < seeds; i++) {
if(dists[i] > max_distance) {
targets.resize(i);
dists.resize(i);
break;
}
}
if(targets.size() < seeds) break;
if(seeds == size()) break;
seeds *= 2;
}
}
void VPartition::Closest(const vcg::Point3f &p, unsigned int nsize,
int *targets,
double *dists) {
double point[3];
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
bd->annkSearch(&point[0], nsize, targets, dists);
}
int VPartition::Locate(const vcg::Point3f &p) {
double point[3];
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
int target = -1;
double dists;
bd->annkSearch(&point[0], 1, &target, &dists);
return target;
}
float VPartition::Radius(unsigned int seed) {
assert(size() > 1);
int nears[2];
double dists[2];
double point[3];
Point3f &p = operator[](seed);
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
bd->annkSearch(&point[0], 2, nears, dists);
if(dists[1] == 0) return 0.0f;
assert(nears[0] == seed);
assert(dists[0] == 0);
return (float)sqrt(dists[1]);
}