VTK  9.6.20260309
vtkVoronoiTile.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2// SPDX-License-Identifier: BSD-3-Clause
45
46#ifndef vtkVoronoiTile_h
47#define vtkVoronoiTile_h
48
49#include "vtkDoubleArray.h" // Support double points
50#include "vtkFiltersMeshingModule.h" // For export macro
51#include "vtkMath.h" // Euclidean norm
52#include "vtkVoronoiCore.h" // Enum: clip intersection status
53
54#include <vector> // array support
55
56VTK_ABI_NAMESPACE_BEGIN
57
58class vtkPolyData;
59class vtkSpheres;
60
61//======= Define the convex polygon class used to produce Voronoi tiles.
62
63// The data structure for representing a Voronoi tile vertex and implicitly,
64// the connected Voronoi tile edge. The tile vertex has a position X, and the
65// current value of the half-space clipping function. In the counterclockwise
66// direction, the NeiId refers to the point id in the neighboring tile that,
67// together with this tile's point id, produced a tile edge between the two
68// points (i.e., a spoke).
70{
71 double X[2]; // position of this vertex
72 vtkIdType NeiId; // generating point id for the associated edge
73 double Val; // current value of the current half-space clipping function
74 double R2; // Radius**2 of circumcircle / flower petal
75
76 vtkTilePoint(double tileX[2], double x[2], vtkIdType neiId)
77 : X{ x[0], x[1] }
78 , NeiId(neiId)
79 , Val(0.0)
80 {
81 this->R2 = vtkMath::Distance2BetweenPoints2D(X, tileX);
82 }
83
84 vtkTilePoint(const vtkTilePoint& v) = default;
85};
86
87// Typedefs defined for convenience.
88using PointRingType = std::vector<vtkTilePoint>;
89using PointRingIterator = std::vector<vtkTilePoint>::iterator;
90
95class VTKFILTERSMESHING_EXPORT vtkVoronoiTile
96{
97public:
103 : PtId(-1)
104 , X{ 0, 0, 0 } // z-component specifies location in z-plane
105 , NumClips(0)
106 , PruneTolerance(1.0e-13)
108 , RecomputePetals(true)
109 , CircumFlower2(0.0)
110 , MinRadius2(0.0)
111 , MaxRadius2(0.0)
112 {
113 // Preallocate some space
114 this->Points.reserve(256);
115 this->NewPoints.reserve(256);
116
117 // Supporting data structures
118 this->SortP.reserve(256);
120 this->Petals->SetNumberOfComponents(3); // x-y-R2
121 this->Petals->Allocate(256); // initial allocation
122 }
123
128 : PtId(-1)
129 , X{ 0, 0, 0 } // z-component specifies location in z-plane
130 , NumClips(0)
131 , PruneTolerance(1.0e-13)
133 , RecomputePetals(true)
134 , CircumFlower2(0.0)
135 , MinRadius2(0.0)
136 , MaxRadius2(0.0)
137 {
138 // Preallocate some space
139 this->Points.reserve(256);
140 this->NewPoints.reserve(256);
141
142 // Each tile owns its own vtkDoubleArray.
143 this->SortP.reserve(256);
145 this->Petals->SetNumberOfComponents(3); // x-y-R2
146 this->Petals->Allocate(256); // initial allocation
147 }
148
149 vtkVoronoiTile& operator=(const vtkVoronoiTile&) { return *this; }
150
156 void Initialize(vtkIdType genPtId, const double genPt[3], double bds[4]);
157
164 vtkIdType ptId, const double x[3], vtkPoints* pts, vtkIdType nPts, const vtkIdType* p);
165
172 ClipIntersectionStatus Clip(vtkIdType neiPtId, const double neiPt[2]);
173
182 {
183 if (this->RecomputeCircumFlower)
184 {
185 this->ComputeCircumFlower();
186 }
187 return this->CircumFlower2;
188 }
189 bool InCircumFlower(double r2) // radius**2 of point from generator
190 {
191 // Only recompute the circumflower if necessary; that is, when
192 // a maximal point is eliminated by a plane clip.
193 if (this->RecomputeCircumFlower)
194 {
195 this->ComputeCircumFlower();
196 }
198 }
199 bool InFlower(const double x[2]);
200 void UpdatePetals(double cf2);
202 {
203 if (this->RecomputePetals)
204 {
205 this->UpdatePetals(this->CircumFlower2);
206 }
207 return (this->Petals->GetNumberOfTuples() > 0 ? this->Petals : nullptr);
208 }
209
216 void ProducePolyData(vtkPolyData* pd) { this->ProducePolyData(pd, nullptr); }
217
223 double* GetGeneratorPosition() { return this->X; }
224 vtkIdType GetNumberOfPoints() { return this->Points.size(); }
225 const PointRingType& GetPoints() { return this->Points; }
226
227 // Data members purposely left public for using classes to extract
228 // information.
229
230 // Information used to define the polyhedron- its generating point id and
231 // position, plus region classification. Indicate whether degenerate faces
232 // (i.e., those having ~zero area) can be deleted (i.e., pruned).
233 vtkIdType PtId; // Generating point id
234 double X[3]; // Generating point position. Note X[2] is z-plane position
235 vtkIdType NumClips; // The total number of clip operations since Initialize()
236 double PruneTolerance; // Specify the prune tolerance
237
238 // These data members represent the constructed polygon.
239 PointRingType Points; // counterclockwise ordered loop of points/vertices defining the tile
240 PointRingType NewPoints; // accumulate new points/vertices to construct the tile
241
242protected:
243 // Convenience method for moving around the modulo ring of the tile
244 // vertices.
246 {
247 if (itr == (this->Points.end() - 1))
248 {
249 return this->Points.begin();
250 }
251 return (itr + 1);
252 }
253
254 // The core geometric intersection operation.
255 ClipIntersectionStatus IntersectWithLine(double origin[2], double normal[2], vtkIdType neiPtId);
256
257 // These tolerances are for managing degeneracies.
258 double Tol;
259 double Tol2;
260
261 // Indicate whether the Voronoi circumflower needs recomputing, and
262 // keep track of the current circumflower and related information.
263 void ComputeCircumFlower();
269 std::vector<vtkTilePoint*> SortP; // Points sorted on radius**2
270 vtkSmartPointer<vtkDoubleArray> Petals; // Flower petals w/ radii > annular radius
271
272}; // vtkVoronoiTile
273
274//------------------------------------------------------------------------------
276{
277 // Compute the circumflower, and compute some info about
278 // the flower radii.
281
282 // Determine the circumflower and minimal sphere radius by
283 // checking against each of the flower petals.
284 for (const auto& p : this->Points)
285 {
286 double r2 = p.R2;
287 this->MinRadius2 = std::min(r2, this->MinRadius2);
288 this->MaxRadius2 = std::max(r2, this->MaxRadius2);
289 }
290 this->CircumFlower2 = (4.0 * this->MaxRadius2); // (2*(max petal radius))**2
291 this->RecomputeCircumFlower = false; // circumflower is up to date
292}
293
294//------------------------------------------------------------------------------
295inline bool vtkVoronoiTile::InFlower(const double x[2])
296{
297 // Check against the flower petals
298 for (const auto& p : this->Points)
299 {
300 double r2 = vtkMath::Distance2BetweenPoints2D(p.X, x);
301 if (r2 <= p.R2)
302 {
303 return true;
304 }
305 }
306
307 // Point not in the flower
308 return false;
309}
310
311VTK_ABI_NAMESPACE_END
312#endif
313// VTK-HeaderTest-Exclude: vtkVoronoiTile.h
RealT r2
Definition PyrC2Basis.h:20
dynamic, self-adjusting array of double
static double Distance2BetweenPoints2D(const double p1[2], const double p2[2])
Compute distance squared between two 2D points p1 and p2.
Definition vtkMath.h:2072
represent and manipulate 3D points
Definition vtkPoints.h:140
concrete dataset represents vertices, lines, polygons, and triangle strips
Hold a reference to a vtkObjectBase instance.
static vtkSmartPointer< T > New()
Create an instance of a VTK object.
implicit function for a set of spheres
Definition vtkSpheres.h:32
void ProducePolyData(vtkPolyData *pd)
double GetCircumFlower2()
Methods to determine whether a point x[2] is within the Voronoi flower, or Voronoi circumflower.
vtkVoronoiTile()
Constructor.
void Initialize(vtkIdType ptId, const double x[3], vtkPoints *pts, vtkIdType nPts, const vtkIdType *p)
Initialize with a convex polygon.
vtkSmartPointer< vtkDoubleArray > Petals
PointRingIterator Next(PointRingIterator &itr)
void Initialize(vtkIdType genPtId, const double genPt[3], double bds[4])
Method to initiate the construction of the polygon.
vtkDoubleArray * GetPetals()
vtkVoronoiTile(const vtkVoronoiTile &)
vtkSMPTools require a proper operator= and copy constructor.
void ComputeCircumFlower()
double * GetGeneratorPosition()
vtkVoronoiTile & operator=(const vtkVoronoiTile &)
vtkIdType GetNumberOfPoints()
void UpdatePetals(double cf2)
const PointRingType & GetPoints()
void ProducePolyData(vtkPolyData *pd, vtkSpheres *spheres)
Produce a vtkPolyData (and optional implicit function) from the current polygon.
ClipIntersectionStatus IntersectWithLine(double origin[2], double normal[2], vtkIdType neiPtId)
PointRingType Points
bool InFlower(const double x[2])
bool InCircumFlower(double r2)
ClipIntersectionStatus Clip(vtkIdType neiPtId, const double neiPt[2])
Method to clip the current convex tile with a plane defined by a neighboring point.
vtkIdType GetGeneratorPointId()
Obtain information about the generated tile.
PointRingType NewPoints
std::vector< vtkTilePoint * > SortP
vtkTilePoint(double tileX[2], double x[2], vtkIdType neiId)
vtkTilePoint(const vtkTilePoint &v)=default
vtkIdType NeiId
int vtkIdType
Definition vtkType.h:363
#define VTK_FLOAT_MIN
Definition vtkType.h:199
#define VTK_FLOAT_MAX
Definition vtkType.h:200
ClipIntersectionStatus
Classes, structs, and typedefs in support of Voronoi processing.
std::vector< vtkTilePoint > PointRingType
std::vector< vtkTilePoint >::iterator PointRingIterator