13#ifndef vtkStaticPointLocator2DPrivate_h
14#define vtkStaticPointLocator2DPrivate_h
30VTK_ABI_NAMESPACE_BEGIN
32#define Distance2BetweenPoints2D(p1, p2) \
33 ((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]))
41 const double min[2],
const double max[2],
const double center[2],
double r2)
44 for (
int i = 0; i < 2; ++i)
46 if (center[i] < min[i])
48 d2 += (center[i] - min[i]) * (center[i] - min[i]);
50 else if (center[i] >
max[i])
52 d2 += (center[i] -
max[i]) * (center[i] -
max[i]);
64 const double min[2],
const double max[2],
const double center[2],
double r2)
66 double dmin = 0.0, dmax = 0.0;
67 for (
int i = 0; i < 2; ++i)
69 double a = (center[i] - min[i]) * (center[i] - min[i]);
70 double b = (center[i] -
max[i]) * (center[i] -
max[i]);
71 dmax += std::max(a, b);
72 if (min[i] <= center[i] && center[i] <=
max[i])
74 dmin += std::min(a, b);
77 return (!(dmin <=
r2 &&
r2 <= dmax));
94struct NeighborBuckets2D;
124 this->NumPts = numPts;
125 this->NumBuckets = numBuckets;
126 this->BatchSize = 10000;
131 double spacing[3], bounds[6];
135 this->hX = this->H[0] = spacing[0];
136 this->hY = this->H[1] = spacing[1];
137 this->hX2 = this->hX / 2.0;
138 this->hY2 = this->hY / 2.0;
139 this->fX = 1.0 / spacing[0];
140 this->fY = 1.0 / spacing[1];
141 this->bX = this->Bounds[0] = bounds[0];
142 this->Bounds[1] = bounds[1];
143 this->bY = this->Bounds[2] = bounds[2];
144 this->Bounds[3] = bounds[3];
145 this->xD = this->Divisions[0];
146 this->yD = this->Divisions[1];
149 this->FastPoints =
nullptr;
150 this->BinRadius = sqrt(
hX *
hX +
hY *
hY) / 2.0;
151 this->MaxLevel = std::max({ this->xD, this->yD, this->zD });
160 NeighborBuckets2D* buckets,
const int ij[2],
const int ndivs[2],
int level);
177 ij[0] = std::min(std::max<vtkIdType>(tmp0, 0),
xD - 1);
178 ij[1] = std::min(std::max<vtkIdType>(tmp1, 0),
yD - 1);
186 return ij[0] + ij[1] *
xD;
194 center[0] = this->bX + this->hX2 + i * this->hX;
195 center[1] = this->bY + this->hY2 + j * this->hY;
203 min[0] = this->bX + i * this->hX;
204 min[1] = this->bY + j * this->hY;
206 max[0] = min[0] + this->hX;
207 max[1] = min[1] + this->hY;
216 double xMin = this->bX + i * this->hX;
217 double xMax = xMin + this->hX;
218 double yMin = this->bY + j * this->hY;
219 double yMax = yMin + this->hY;
220 double dx0 = center[0] - xMin, dx1 = center[0] - xMax;
221 double dy0 = center[1] - yMin, dy1 = center[1] - yMax;
222 double dmax2 = std::max(dx0 * dx0, dx1 * dx1) + std::max(dy0 * dy0, dy1 * dy1);
231template <
typename TIds>
244 this->Map[numPts].
Bucket = numBuckets;
245 this->Offsets =
new TIds[numBuckets + 1];
246 this->Offsets[numBuckets] = numPts;
253 delete[] this->Offsets;
260 if (bucketNum < 0 || bucketNum >= this->
NumBuckets)
264 return (this->Offsets[bucketNum + 1] - this->Offsets[bucketNum]);
270 return this->Map + this->Offsets[bucketNum];
279 for (
int i = 0; i < numIds; i++)
281 bList->
SetId(i, ids[i].PtId);
288 double radius,
const double x[3],
double inputDataLength,
double& dist2);
291 double minDist2 = (-0.1),
bool sort =
true,
vtkDoubleArray* petals =
nullptr);
305 NeighborBuckets2D* buckets,
const double x[3],
const int ij[2],
double dist,
int level);
307 int prevMinLevel[2],
int prevMaxLevel[2]);
310 template <
typename T>
326 for (; ptId < end; ++ptId, ++t)
335 template <
typename T,
typename TPo
intsArray>
352 for (; ptId < end; ++ptId, ++x, ++t)
363 template <
typename TPo
intsArray>
375 template <
typename T>
385 this->NumPts = this->BList->
NumPts;
392 T* offsets = this->BList->
Offsets;
397 endBatchPt = (endBatchPt > endPt ? endPt : endBatchPt);
402 if (curPt == this->BList->
Map)
404 prevPt = this->BList->
Map;
405 std::fill_n(offsets, curPt->
Bucket + 1, 0);
420 for (curPt = prevPt; curPt < endBatchPt;)
422 for (; curPt->
Bucket == prevPt->
Bucket && curPt <= endBatchPt; ++curPt)
428 offsets + prevPt->
Bucket + 1, curPt->
Bucket - prevPt->
Bucket, curPt - this->BList->Map);
436 template <
typename T>
447 this->DataSet = blist->
DataSet;
459 for (; bucket < endBucket; ++bucket)
463 ids = bList->
GetIds(bucket);
464 for (i = 0; i < numIds; i++)
467 if (mergeMap[ptId] < 0)
469 mergeMap[ptId] = ptId;
471 for (j = i + 1; j < numIds; j++)
474 if (mergeMap[ptId2] < 0)
477 if (p[0] == p2[0] && p[1] == p2[1])
479 mergeMap[ptId2] = ptId;
494 template <
typename T>
509 this->DataSet = blist->
DataSet;
528 for (; ptId < endPtId; ++ptId)
530 if (mergeMap[ptId] < 0)
532 mergeMap[ptId] = ptId;
537 for (i = 0; i < numIds; i++)
539 nearId = nearby->
GetId(i);
540 if (ptId < nearId && (mergeMap[nearId] < 0 || ptId < mergeMap[nearId]))
542 mergeMap[nearId] = ptId;
557 auto points = this->
DataSet->GetPoints()->GetData();
560 points, worker,
this))
562 worker(points,
this);
580 int numBatches =
static_cast<int>(ceil(
static_cast<double>(this->
NumPts) / this->
BatchSize));
596 { 0, -1 }, { 0, 1 }, { -1, 0 }, { 1, 0 },
597 { -1, -1 }, { 1, 1 }, { 1, -1 }, { -1, 1 }
601 { -2, 0 }, { 2, 0 }, { 0, -2 }, { 0, 2 },
602 { -1, -2 }, { 1, 2 }, { -2, -1 }, { 2, 1 },
603 { 1, -2 }, { -1, 2 }, { -2, 1 }, { 2, -1 }, { -2, -2 }, { 2, 2 }, { 2, -2 }, { -2, 2 }
607 { -1, -3 }, { 1, 3 }, { 3, -1 }, { -3, 1 }, { 1, -3 }, { -1, 3 }, { 3, 1 }, { -3, -1 },
608 { -2, -3 }, { 2, 3 }, { 3, -2 }, { -3, 2 }, { 2, -3 }, { -2, 3 }, { 3, 2 }, { -3, -2 },
609 { -3, -3 }, { 3, 3 }, { 3, -3 }, { -3, 3 } };
612 { -1, -4 }, { 1, 4 }, { 4, -1 }, { -4, 1 }, { 1, -4 }, { -1, 4 }, { 4, 1 }, { -4, -1 },
613 { -2, -4 }, { 2, 4 }, { 4, -2 }, { -4, 2 }, { 2, -4 }, { -2, 4 }, { 4, 2 }, { -4, -2 },
614 { -3, -4 }, { 3, 4 }, { 4, -3 }, { -4, 3 }, { 3, -4 }, { -3, 4 }, { 4, 3 }, { -4, -3 },
615 { -4, -4 }, { 4, 4 }, { 4, -4 }, { -4, 4 } };
618 { -1, -5 }, { 1, 5 }, { 5, -1 }, { -5, 1 }, { 1, -5 }, { -1, 5 }, { 5, 1 }, { -5, -1 },
619 { -2, -5 }, { 2, 5 }, { 5, -2 }, { -5, 2 }, { 2, -5 }, { -2, 5 }, { 5, 2 }, { -5, -2 },
620 { -3, -5 }, { 3, 5 }, { 5, -3 }, { -5, 3 }, { 3, -5 }, { -3, 5 }, { 5, 3 }, { -5, -3 },
621 { -4, -5 }, { 4, 5 }, { 5, -4 }, { -5, 4 }, { 4, -5 }, { -4, 5 }, { 5, 4 }, { -5, -4 },
622 { -5, -5 }, { 5, 5 }, { 5, -5 }, { -5, 5 } };
647 this->Divs[0] = divs[0];
648 this->Divs[1] = divs[1];
649 this->MaxLevel = maxLevel;
660 if (this->IJ[0] < 0 || this->IJ[0] >= this->Divs[0] || this->IJ[1] < 0 ||
661 this->IJ[1] >= this->Divs[1])
683 this->Center[0] = center[0];
684 this->Center[1] = center[1];
689 this->IJ[0] = this->Center[0];
690 this->IJ[1] = this->Center[1];
699 this->Span = 2 * level + 1;
704 : (this->Span * this->Span) - ((2 * (level - 1) + 1) * (2 * (level - 1) + 1)));
709 this->Interior =
true;
710 if ((this->Center[0] - level) < 0 || (this->Center[0] + level) >= this->Divs[0] ||
711 (this->Center[1] - level) < 0 || (this->Center[1] + level) >= this->Divs[1])
713 this->Interior =
false;
746 this->IJ[0] = this->Center[0];
747 this->IJ[1] = this->Center[1] - level;
770 int level = this->Level;
771 if (level == 0 || this->BinNum >= this->NumBins || level > this->MaxLevel)
805 if (this->BinNum < 4)
807 if (this->BinNum == 1)
809 this->IJ[0] = this->Center[0];
810 this->IJ[1] = this->Center[1] + level;
812 else if (this->BinNum == 2)
814 this->IJ[0] = this->Center[0] - level;
815 this->IJ[1] = this->Center[1];
819 this->IJ[0] = this->Center[0] + level;
820 this->IJ[1] = this->Center[1];
825 else if (this->BinNum >= (this->NumBins - 4))
827 if (this->BinNum == (this->NumBins - 4))
829 this->IJ[0] = this->Center[0] - level;
830 this->IJ[1] = this->Center[1] - level;
832 else if (this->BinNum == (this->NumBins - 3))
834 this->IJ[0] = this->Center[0] + level;
835 this->IJ[1] = this->Center[1] + level;
837 else if (this->BinNum == (this->NumBins - 2))
839 this->IJ[0] = this->Center[0] + level;
840 this->IJ[1] = this->Center[1] - level;
844 this->IJ[0] = this->Center[0] - level;
845 this->IJ[1] = this->Center[1] + level;
852 int idx = (this->BinNum - 4) % 8;
853 int offset = ((this->BinNum - 4) / 8) + 1;
856 this->IJ[0] = this->Center[0] - offset;
857 this->IJ[1] = this->Center[1] - level;
861 this->IJ[0] = this->Center[0] + offset;
862 this->IJ[1] = this->Center[1] + level;
866 this->IJ[0] = this->Center[0] - level;
867 this->IJ[1] = this->Center[1] - offset;
871 this->IJ[0] = this->Center[0] + level;
872 this->IJ[1] = this->Center[1] + offset;
876 this->IJ[0] = this->Center[0] + offset;
877 this->IJ[1] = this->Center[1] - level;
881 this->IJ[0] = this->Center[0] - offset;
882 this->IJ[1] = this->Center[1] + level;
886 this->IJ[0] = this->Center[0] - level;
887 this->IJ[1] = this->Center[1] + offset;
891 this->IJ[0] = this->Center[0] + level;
892 this->IJ[1] = this->Center[1] - offset;
ValueType * GetPointer(vtkIdType valueIdx)
Get the address of a particular data index.
object to represent cell connectivity
abstract class to specify dataset behavior
virtual double * GetPoint(vtkIdType ptId)=0
Get point coordinates with ptId such that: 0 <= ptId < NumberOfPoints.
dynamic, self-adjusting array of double
static vtkDoubleArray * SafeDownCast(vtkObjectBase *o)
list of point or cell ids
void SetNumberOfIds(vtkIdType number)
Specify the number of ids for this object to hold.
vtkIdType GetNumberOfIds() const noexcept
Return the number of id's in the list.
vtkIdType GetId(vtkIdType i)
Return the id at location i.
void SetId(vtkIdType i, vtkIdType id)
Set the id at location i.
vtkTypeBool Reserve(vtkIdType size)
Reserve the id list to the requested number of ids and preserve data.
virtual vtkDataSet * GetDataSet()
Build the locator from the points/cells defining this dataset.
represent and manipulate 3D points
concrete dataset represents vertices, lines, polygons, and triangle strips
Thread local storage for VTK objects.
T *& Local()
Returns an object local to the current thread.
quickly locate points in 2-space
void GetBounds(double *bounds) override
Provide an accessor to the bounds.
virtual double * GetSpacing()
Provide an accessor to the bucket spacing.
virtual int * GetDivisions()
Set the number of divisions in x-y directions.
A SafeCastFromDouble(double value)
Cast from double, and clamp to output type limits to avoid overlow.
VTK_ITER_INLINE auto DataArrayTupleRange(const ArrayTypePtr &array, TupleIdType start=-1, TupleIdType end=-1) -> typename detail::SelectTupleRange< ArrayTypePtr, TupleSize >::type
Generate an stl and for-range compatible range of tuple iterators from a vtkDataArray.
MapDataSet(BucketList2D< T > *blist, vtkDataSet *ds)
void operator()(vtkIdType ptId, vtkIdType end)
BucketList2D< T > * BList
MapOffsets(BucketList2D< T > *blist)
BucketList2D< T > * BList
void operator()(vtkIdType batch, vtkIdType batchEnd)
void operator()(TPointsArray *points, BucketList2D *blist)
BucketList2D< T > * BList
void operator()(vtkIdType ptId, vtkIdType end)
MapPointsArray(BucketList2D< T > *blist, TPointsArray *pts)
BucketList2D< T > * BList
MergeClose(BucketList2D< T > *blist, double tol, vtkIdType *mergeMap)
vtkSMPThreadLocalObject< vtkIdList > PIds
void operator()(vtkIdType ptId, vtkIdType endPtId)
BucketList2D< T > * BList
void operator()(vtkIdType bucket, vtkIdType endBucket)
MergePrecise(BucketList2D< T > *blist, vtkIdType *mergeMap)
void FindClosestNPoints(int N, const double x[3], vtkIdList *result)
double FindCloseNBoundedPoints(int N, const double x[3], vtkIdList *result)
const vtkLocatorTuple< TIds > * GetIds(vtkIdType bucketNum)
void FindPointsInShell(const double x[3], vtkDist2TupleArray &results, double minDist2, double maxDist2, bool sort, vtkDoubleArray *petals)
BucketList2D(vtkStaticPointLocator2D *loc, vtkIdType numPts, int numBuckets)
void MergePoints(double tol, vtkIdType *pointMap)
void GetOverlappingBuckets(NeighborBuckets2D *buckets, const double x[3], const int ij[2], double dist, int level)
void GetOverlappingBuckets(NeighborBuckets2D *buckets, const double x[3], double dist, int prevMinLevel[2], int prevMaxLevel[2])
void BuildLocator() override
vtkLocatorTuple< TIds > * Map
void FindPointsWithinRadius(double R, const double x[3], vtkIdList *result)
int IntersectWithLine(double a0[3], double a1[3], double tol, double &t, double lineX[3], double ptX[3], vtkIdType &ptId)
vtkIdType GetNumberOfIds(vtkIdType bucketNum)
bool BucketIntersectsCircle(int i, int j, const double center[3], double R2)
void GetIds(vtkIdType bucketNum, vtkIdList *bList)
vtkIdType FindClosestPointWithinRadius(double radius, const double x[3], double inputDataLength, double &dist2)
vtkIdType FindClosestPoint(const double x[3])
double FindNPointsInShell(int N, const double x[3], vtkDist2TupleArray &results, double minDist2=(-0.1), bool sort=true, vtkDoubleArray *petals=nullptr)
void GenerateRepresentation(int level, vtkPolyData *pd)
Dispatch a single array against all array types mentioned in the ArrayList template parameter.
double Distance2ToBucket(const double x[3], const int nei[3])
void GetBucketBounds(int i, int j, double min[3], double max[3])
double Distance2ToBounds(const double x[3], const double bounds[6])
void GetBucketIndices(const double *x, int ij[2]) const
void GenerateFace(int face, int i, int j, int k, vtkPoints *pts, vtkCellArray *polys)
vtkIdType GetBucketIndex(const double *x) const
bool BucketInsideCircle(int i, int j, const double center[3], double r2)
virtual ~vtkBucketList2D()=default
vtkStaticPointLocator2D * Locator
virtual void BuildLocator()=0
void GetBucketCenter(int i, int j, double center[3])
void GetBucketNeighbors(NeighborBuckets2D *buckets, const int ij[2], const int ndivs[2], int level)
vtkBucketList2D(vtkStaticPointLocator2D *loc, vtkIdType numPts, int numBuckets)
void Initialize(int divs[3], int maxLevel)
vtkBucketPatchIterator()=default
vtkIdType Begin(int level, int center[2])
Represent an array of vtkDist2Tuples.
STL-compatible iterable ranges that provide access to vtkDataArray elements.
constexpr int vtkBucketPatchLevel3[24][2]
bool InsideCircle(const double min[2], const double max[2], const double center[2], double r2)
Performant method to determine if a box if fully inside a circle.
constexpr int vtkBucketPatchLevel4[32][2]
constexpr int vtkBucketPatchLevel2[16][2]
constexpr int vtkBucketPatchLevel1[8][2]
bool IntersectsCircle(const double min[2], const double max[2], const double center[2], double r2)
Performant method to intersect a box with a circle.
constexpr int vtkBucketPatchLevel5[40][2]