VTK  9.7.1
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
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 
56 VTK_ABI_NAMESPACE_BEGIN
57 
58 class vtkPolyData;
59 class 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.
88 using PointRingType = std::vector<vtkTilePoint>;
89 using PointRingIterator = std::vector<vtkTilePoint>::iterator;
90 
95 class VTKFILTERSMESHING_EXPORT vtkVoronoiTile
96 {
97 public:
103  : PtId(-1)
104  , X{ 0, 0, 0 } // z-component specifies location in z-plane
105  , NumClips(0)
106  , PruneTolerance(1.0e-13)
107  , RecomputeCircumFlower(true)
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);
119  this->Petals = vtkSmartPointer<vtkDoubleArray>::New();
120  this->Petals->SetNumberOfComponents(3); // x-y-R2
121  this->Petals->ReserveValues(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)
132  , RecomputeCircumFlower(true)
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);
144  this->Petals = vtkSmartPointer<vtkDoubleArray>::New();
145  this->Petals->SetNumberOfComponents(3); // x-y-R2
146  this->Petals->ReserveTuples(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 
163  void Initialize(
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  }
197  return (r2 <= this->CircumFlower2);
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 
215  void ProducePolyData(vtkPolyData* pd, vtkSpheres* spheres);
216  void ProducePolyData(vtkPolyData* pd) { this->ProducePolyData(pd, nullptr); }
217 
222  vtkIdType GetGeneratorPointId() { return this->PtId; }
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 
242 protected:
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();
267  double MinRadius2;
268  double MaxRadius2;
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.
279  this->MinRadius2 = VTK_FLOAT_MAX;
280  this->MaxRadius2 = VTK_FLOAT_MIN;
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 //------------------------------------------------------------------------------
295 inline 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 
311 VTK_ABI_NAMESPACE_END
312 #endif
313 // VTK-HeaderTest-Exclude: vtkVoronoiTile.h
RealT r2
Definition: PyrC2Basis.h:20
vtkVoronoiTile(const vtkVoronoiTile &)
vtkSMPTools require a proper operator= and copy constructor.
implicit function for a set of spheres
Definition: vtkSpheres.h:31
vtkIdType GetNumberOfPoints()
static double Distance2BetweenPoints2D(const double p1[2], const double p2[2])
Compute distance squared between two 2D points p1 and p2.
Definition: vtkMath.h:1963
double * GetGeneratorPosition()
std::vector< vtkTilePoint > PointRingType
bool InCircumFlower(double r2)
bool RecomputeCircumFlower
PointRingType Points
void ProducePolyData(vtkPolyData *pd)
double X[2]
int vtkIdType
Definition: vtkType.h:363
concrete dataset represents vertices, lines, polygons, and triangle strips
Definition: vtkPolyData.h:71
vtkIdType NumClips
static vtkSmartPointer< T > New()
Create an instance of a VTK object.
dynamic, self-adjusting array of double
The convex polygon tile class proper.
double GetCircumFlower2()
Methods to determine whether a point x[2] is within the Voronoi flower, or Voronoi circumflower...
#define VTK_FLOAT_MAX
Definition: vtkType.h:200
vtkSmartPointer< vtkDoubleArray > Petals
std::vector< vtkTilePoint >::iterator PointRingIterator
vtkVoronoiTile()
Constructor.
vtkIdType GetGeneratorPointId()
Obtain information about the generated tile.
PointRingType NewPoints
bool InFlower(const double x[2])
PointRingIterator Next(PointRingIterator &itr)
std::vector< vtkTilePoint * > SortP
ClipIntersectionStatus
Classes, structs, and typedefs in support of Voronoi processing.
vtkDoubleArray * GetPetals()
const PointRingType & GetPoints()
vtkIdType NeiId
void ComputeCircumFlower()
#define max(a, b)
represent and manipulate 3D points
Definition: vtkPoints.h:30
#define VTK_FLOAT_MIN
Definition: vtkType.h:199
vtkVoronoiTile & operator=(const vtkVoronoiTile &)
vtkTilePoint(double tileX[2], double x[2], vtkIdType neiId)