[vtkusers] vtkPointLocator
Bryn Lloyd
blloyd at vision.ee.ethz.ch
Fri Oct 24 10:24:57 EDT 2008
Hi again,
If anybody is interested in this functionality, I have written the
functions necessary for finding the N closest points (in point the
insertion mode), i.e. vtkPointLocator::FindClosestNInsertedPoints and
vtkPointLocator::FindInsertedPointsWithinRadius.
Maybe these functions could be added to the CVS? Thanks!
Cheers, Bryn
void vtkPointLocator::FindClosestNInsertedPoints(int N, double x, double
y, double z,
vtkIdList *result)
{
double xyz[3];
xyz[0] = x;
xyz[1] = y;
xyz[2] = z;
this->FindClosestNInsertedPoints(N,xyz,result);
}
void vtkPointLocator::FindClosestNInsertedPoints(int N, const double
x[3], vtkIdList *result)
{
int i, j;
double dist2;
double *pt;
int level;
vtkIdType ptId, cno;
vtkIdList *ptIds;
int ijk[3], *nei;
vtkNeighborPoints buckets;
// clear out the result
result->Reset();
/// this->BuildLocator(); // will subdivide if modified; otherwise
returns
//
// Find bucket point is in.
//
for (j=0; j<3; j++)
{
ijk[j] = static_cast<int>(
((x[j] - this->Bounds[2*j]) /
(this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]);
if (ijk[j] < 0)
{
ijk[j] = 0;
}
else if (ijk[j] >= this->Divisions[j])
{
ijk[j] = this->Divisions[j] - 1;
}
}
// there are two steps, first a simple expanding wave of buckets until
// we have enough points. Then a refinement to make sure we have the
// N closest points.
level = 0;
double maxDistance = 0.0;
int currentCount = 0;
idsort *res = new idsort [N];
this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level);
while (buckets.GetNumberOfNeighbors() && currentCount < N)
{
for (i=0; i<buckets.GetNumberOfNeighbors(); i++)
{
nei = buckets.GetPoint(i);
cno = nei[0] + nei[1]*this->Divisions[0] +
nei[2]*this->Divisions[0]*this->Divisions[1];
if ( (ptIds = this->HashTable[cno]) != NULL )
{
for (j=0; j < ptIds->GetNumberOfIds(); j++)
{
ptId = ptIds->GetId(j);
/// pt = this->DataSet->GetPoint(ptId);
pt = this->Points->GetPoint(ptId);
dist2 = vtkMath::Distance2BetweenPoints(x,pt);
if (currentCount < N)
{
res[currentCount].dist = dist2;
res[currentCount].id = ptId;
if (dist2 > maxDistance)
{
maxDistance = dist2;
}
currentCount++;
if (currentCount == N)
{
qsort(res, currentCount, sizeof(idsort), vtkidsortcompare);
}
}
else if (dist2 < maxDistance)
{
res[N-1].dist = dist2;
res[N-1].id = ptId;
qsort(res, N, sizeof(idsort), vtkidsortcompare);
maxDistance = res[N-1].dist;
}
}
}
}
level++;
this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level);
}
// do a sort
qsort(res, currentCount, sizeof(idsort), vtkidsortcompare);
// Now do the refinement
this->GetOverlappingBuckets (&buckets, x, ijk,
sqrt(maxDistance),level-1);
for (i=0; i<buckets.GetNumberOfNeighbors(); i++)
{
nei = buckets.GetPoint(i);
cno = nei[0] + nei[1]*this->Divisions[0] +
nei[2]*this->Divisions[0]*this->Divisions[1];
if ( (ptIds = this->HashTable[cno]) != NULL )
{
for (j=0; j < ptIds->GetNumberOfIds(); j++)
{
ptId = ptIds->GetId(j);
/// pt = this->DataSet->GetPoint(ptId);
pt = this->Points->GetPoint(ptId);
dist2 = vtkMath::Distance2BetweenPoints(x,pt);
if (dist2 < maxDistance)
{
res[N-1].dist = dist2;
res[N-1].id = ptId;
qsort(res, N, sizeof(idsort), vtkidsortcompare);
maxDistance = res[N-1].dist;
}
}
}
}
// Fill in the IdList
result->SetNumberOfIds(currentCount);
for (i = 0; i < currentCount; i++)
{
result->SetId(i,res[i].id);
}
delete [] res;
}
void vtkPointLocator::FindInsertedPointsWithinRadius(double R, double x,
double y, double z,
vtkIdList *result)
{
double xyz[3];
xyz[0] = x;
xyz[1] = y;
xyz[2] = z;
this->FindInsertedPointsWithinRadius(R,xyz,result);
}
void vtkPointLocator::FindInsertedPointsWithinRadius(double R, const
double x[3],
vtkIdList *result)
{
int i, j;
double dist2;
double *pt;
vtkIdType ptId, cno;
vtkIdList *ptIds;
int ijk[3], *nei;
double R2 = R*R;
vtkNeighborPoints buckets;
/// this->BuildLocator(); // will subdivide if modified; otherwise
returns
//
// Find bucket point is in.
//
for (j=0; j<3; j++)
{
ijk[j] = static_cast<int>(
((x[j] - this->Bounds[2*j]) /
(this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]);
if (ijk[j] < 0)
{
ijk[j] = 0;
}
else if (ijk[j] >= this->Divisions[j])
{
ijk[j] = this->Divisions[j] - 1;
}
}
// get all buckets within a distance
this->GetOverlappingBuckets (&buckets, x, ijk, R, 0);
// add the original bucket
buckets.InsertNextPoint(ijk);
// clear out the result
result->Reset();
for (i=0; i<buckets.GetNumberOfNeighbors(); i++)
{
nei = buckets.GetPoint(i);
cno = nei[0] + nei[1]*this->Divisions[0] +
nei[2]*this->Divisions[0]*this->Divisions[1];
if ( (ptIds = this->HashTable[cno]) != NULL )
{
for (j=0; j < ptIds->GetNumberOfIds(); j++)
{
ptId = ptIds->GetId(j);
/// pt = this->DataSet->GetPoint(ptId);
pt = this->Points->GetPoint(ptId);
dist2 = vtkMath::Distance2BetweenPoints(x,pt);
if (dist2 <= R2)
{
result->InsertNextId(ptId);
}
}
}
}
}
>
>
> I would like to use the vtkPointLocator in the point insertion mode,
> i.e. I would like to incrementally insert points and search for them.
>
> The incremental point insertion mode works with the functions:
> InsertNextPoint, IsInsertedPoint, FindClosestInsertedPoint
>
>
> There is, however, no method to search for the N closest points.
>
> I tried FindClosestNPoints with no success. I tried first calling
> BuildLocator on the locator but get error messages (No points to
> subdivide).
> What do I need to do, in order to use the function FindClosestNPoints in
> point insertion mode?
>
>
>
> Another function that is "missing" is point removal, although I can
> probably live with this.
>
> Is there a better code for doing what I need?
>
>
>
> Thanks for any suggestions & help.
>
> Bryn
>
> _______________________________________________
> This is the private VTK discussion list.
> Please keep messages on-topic. Check the FAQ at:
> http://www.vtk.org/Wiki/VTK_FAQ
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers
>
More information about the vtkusers
mailing list