vtkStreamingPriorityQueue.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
2 // SPDX-License-Identifier: BSD-3-Clause
13 #ifndef vtkStreamingPriorityQueue_h
14 #define vtkStreamingPriorityQueue_h
15 #ifndef VTK_WRAPPING_CXX
16 
17 #include "vtkBoundingBox.h" // for vtkBoundingBox
18 #include "vtkMath.h" // for vtkMath
19 #include "vtkWrappingHints.h" // for wrapping attributes
20 
21 #include <queue> // for std::priority_queue
22 
23 //*****************************************************************************
24 namespace
25 {
26 // this code is stolen from vtkFrustumCoverageCuller.
27 inline double vtkComputeScreenCoverage(const double planes[24], const double bounds[6],
28  double& distance, double& centeredness, double& itemCoverage)
29 {
30  distance = 0.0;
31  centeredness = 0.0;
32  itemCoverage = 0.0;
33 
34  // a duff dataset like a polydata with no cells will have bad bounds
35  if (!vtkMath::AreBoundsInitialized(const_cast<double*>(bounds)))
36  {
37  return 0.0;
38  }
39  double screen_bounds[4];
40 
41  double center[3];
42  center[0] = (bounds[0] + bounds[1]) / 2.0;
43  center[1] = (bounds[2] + bounds[3]) / 2.0;
44  center[2] = (bounds[4] + bounds[5]) / 2.0;
45  double radius = 0.5 *
46  sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
47  (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
48  (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
49  for (int i = 0; i < 6; i++)
50  {
51  // Compute how far the center of the sphere is from this plane
52  double d = planes[i * 4 + 0] * center[0] + planes[i * 4 + 1] * center[1] +
53  planes[i * 4 + 2] * center[2] + planes[i * 4 + 3];
54  // If d < -radius the prop is not within the view frustum
55  if (d < -radius)
56  {
57  return 0.0;
58  }
59 
60  // The first four planes are the ones bounding the edges of the
61  // view plane (the last two are the near and far planes) The
62  // distance from the edge of the sphere to these planes is stored
63  // to compute coverage.
64  if (i < 4)
65  {
66  screen_bounds[i] = d - radius;
67  }
68  // The fifth plane is the near plane - use the distance to
69  // the center (d) as the value to sort by
70  if (i == 4)
71  {
72  distance = d;
73  }
74  }
75 
76  // If the prop wasn't culled during the plane tests...
77  // Compute the width and height of this slice through the
78  // view frustum that contains the center of the sphere
79  double full_w = screen_bounds[0] + screen_bounds[1] + 2.0 * radius;
80  double full_h = screen_bounds[2] + screen_bounds[3] + 2.0 * radius;
81 
82  // Multiply the distances from each side to get a measure of how centered
83  // the sphere is on the screen (divide by half the length in that dimension
84  // squared to get a measure of how centered the object is in that dimension).
85  double measure_w =
86  (screen_bounds[0] + radius) * (screen_bounds[1] + radius) / (full_w * full_w / 4.0);
87  double measure_h =
88  (screen_bounds[2] + radius) * (screen_bounds[3] + radius) / (full_h * full_h / 4.0);
89 
90  // If the object is off the edge of the screen, treat it as if it is just
91  // inside the edge (which we know it is since it wasn't culled)
92  if (measure_w < 0.01)
93  {
94  measure_w = 0.01;
95  }
96  if (measure_h < 0.01)
97  {
98  measure_h = 0.01;
99  }
100  centeredness = measure_w * measure_h;
101 
102  double w = 2 * radius;
103  double h = 2 * radius;
104  if (screen_bounds[0] < 0.0)
105  {
106  w += screen_bounds[0];
107  }
108  if (screen_bounds[1] < 0.0)
109  {
110  w += screen_bounds[1];
111  }
112  if (screen_bounds[2] < 0.0)
113  {
114  h += screen_bounds[2];
115  }
116  if (screen_bounds[3] < 0.0)
117  {
118  h += screen_bounds[3];
119  }
120  itemCoverage = h * w / (4 * radius * radius);
121 
122  // Subtract from the full width to get the width of the square
123  // enclosing the circle slice from the sphere in the plane
124  // through the center of the sphere. If the screen bounds for
125  // the left and right planes (0,1) are greater than zero, then
126  // the edge of the sphere was a positive distance away from the
127  // plane, so there is a gap between the edge of the plane and
128  // the edge of the box.
129  double part_w = full_w;
130  if (screen_bounds[0] > 0.0)
131  {
132  part_w -= screen_bounds[0];
133  }
134  if (screen_bounds[1] > 0.0)
135  {
136  part_w -= screen_bounds[1];
137  }
138  // Do the same thing for the height with the top and bottom
139  // planes (2,3).
140  double part_h = full_h;
141  if (screen_bounds[2] > 0.0)
142  {
143  part_h -= screen_bounds[2];
144  }
145  if (screen_bounds[3] > 0.0)
146  {
147  part_h -= screen_bounds[3];
148  }
149 
150  // Compute the fraction of coverage
151  if ((full_w * full_h) != 0.0)
152  {
153  return (part_w * part_h) / (full_w * full_h);
154  }
155 
156  return 0;
157 }
158 }
159 
160 class VTK_WRAPEXCLUDE vtkStreamingPriorityQueueItem
161 {
162 public:
163  unsigned int Identifier; // this is used to identify this block when making a
164  // request.
165  double Refinement; // Where lower the Refinement cheaper is the
166  // processing for this block. 0 is considered as
167  // undefined.
168  double ScreenCoverage; // computed coverage for the block.
169  double Centeredness; // how centered the object is on the screen (1 is centered, 0.0001 is near
170  // the edge)
171  double Priority; // Computed priority for this block.
172  double Distance;
174  double ItemCoverage; // amount of the item that is onscreen (fraction, if whole item is onscreen
175  // it is 1)
176  vtkBoundingBox Bounds; // Bounds for the block.
177 
179  : Identifier(0)
180  , Refinement(0)
181  , ScreenCoverage(0)
182  , Priority(0)
183  , Distance(0)
184  , AmountOfDetail(-1)
185  {
186  }
187 };
188 
190 {
191 public:
193  const vtkStreamingPriorityQueueItem& me, const vtkStreamingPriorityQueueItem& other) const
194  {
195  return me.Priority < other.Priority;
196  }
197 };
198 
199 template <typename Comparator = vtkStreamingPriorityQueueItemComparator>
200 class VTK_WRAPEXCLUDE vtkStreamingPriorityQueue
201  : public std::priority_queue<vtkStreamingPriorityQueueItem,
202  std::vector<vtkStreamingPriorityQueueItem>, Comparator>
203 {
204 public:
206 
209  void UpdatePriorities(const double view_planes[24], const double clamp_bounds[6])
210  {
211  bool clamp_bounds_initialized =
212  (vtkMath::AreBoundsInitialized(const_cast<double*>(clamp_bounds)) != 0);
213  vtkBoundingBox clampBox(const_cast<double*>(clamp_bounds));
215 
216  vtkStreamingPriorityQueue current_queue;
217  std::swap(current_queue, *this);
218 
219  for (; !current_queue.empty(); current_queue.pop())
220  {
221  vtkStreamingPriorityQueueItem item = current_queue.top();
222  if (!item.Bounds.IsValid())
223  {
224  continue;
225  }
226 
227  double block_bounds[6];
228  item.Bounds.GetBounds(block_bounds);
229 
230  if (clamp_bounds_initialized)
231  {
232  if (!clampBox.ContainsPoint(block_bounds[0], block_bounds[2], block_bounds[4]) &&
233  !clampBox.ContainsPoint(block_bounds[1], block_bounds[3], block_bounds[5]))
234  {
235  // if the block_bounds is totally outside the clamp_bounds, skip it.
236  continue;
237  }
238  }
239 
240  double refinement2 = item.Refinement * item.Refinement;
241  double distance, centeredness, itemCoverage;
242  double coverage =
243  vtkComputeScreenCoverage(view_planes, block_bounds, distance, centeredness, itemCoverage);
244  item.ScreenCoverage = coverage;
245  item.Distance = distance;
246  item.Centeredness = centeredness;
247  item.ItemCoverage = itemCoverage;
248 
249  if (coverage > 0)
250  {
251  // item.Priority = coverage / (item.Refinement/* * distance*/) ;// / distance;
252  // //coverage * coverage / ( 1 + refinement2 + distance);
253  item.Priority = coverage * coverage * centeredness / (1 + refinement2 + distance);
254  }
255  else
256  {
257  item.Priority = 0;
258  }
259  this->push(item);
260  }
261  }
262 };
263 #endif
264 #endif
265 // VTK-HeaderTest-Exclude: vtkStreamingPriorityQueue.h
void GetBounds(double bounds[6]) const
int ContainsPoint(double p[3]) const
int IsValid() const
void UpdatePriorities(const double view_planes[24], const double clamp_bounds[6])
Updates the priorities of items in the queue.
bool operator()(const vtkStreamingPriorityQueueItem &me, const vtkStreamingPriorityQueueItem &other) const
center
radius
provides a datastructure for building priority queues.
static vtkTypeBool AreBoundsInitialized(double bounds[6])