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  measure_w = std::max(measure_w, 0.01);
93  measure_h = std::max(measure_h, 0.01);
94  centeredness = measure_w * measure_h;
95 
96  double w = 2 * radius;
97  double h = 2 * radius;
98  if (screen_bounds[0] < 0.0)
99  {
100  w += screen_bounds[0];
101  }
102  if (screen_bounds[1] < 0.0)
103  {
104  w += screen_bounds[1];
105  }
106  if (screen_bounds[2] < 0.0)
107  {
108  h += screen_bounds[2];
109  }
110  if (screen_bounds[3] < 0.0)
111  {
112  h += screen_bounds[3];
113  }
114  itemCoverage = h * w / (4 * radius * radius);
115 
116  // Subtract from the full width to get the width of the square
117  // enclosing the circle slice from the sphere in the plane
118  // through the center of the sphere. If the screen bounds for
119  // the left and right planes (0,1) are greater than zero, then
120  // the edge of the sphere was a positive distance away from the
121  // plane, so there is a gap between the edge of the plane and
122  // the edge of the box.
123  double part_w = full_w;
124  if (screen_bounds[0] > 0.0)
125  {
126  part_w -= screen_bounds[0];
127  }
128  if (screen_bounds[1] > 0.0)
129  {
130  part_w -= screen_bounds[1];
131  }
132  // Do the same thing for the height with the top and bottom
133  // planes (2,3).
134  double part_h = full_h;
135  if (screen_bounds[2] > 0.0)
136  {
137  part_h -= screen_bounds[2];
138  }
139  if (screen_bounds[3] > 0.0)
140  {
141  part_h -= screen_bounds[3];
142  }
143 
144  // Compute the fraction of coverage
145  if ((full_w * full_h) != 0.0)
146  {
147  return (part_w * part_h) / (full_w * full_h);
148  }
149 
150  return 0;
151 }
152 }
153 
154 class VTK_WRAPEXCLUDE vtkStreamingPriorityQueueItem
155 {
156 public:
157  unsigned int Identifier; // this is used to identify this block when making a
158  // request.
159  double Refinement; // Where lower the Refinement cheaper is the
160  // processing for this block. 0 is considered as
161  // undefined.
162  double ScreenCoverage; // computed coverage for the block.
163  double Centeredness; // how centered the object is on the screen (1 is centered, 0.0001 is near
164  // the edge)
165  double Priority; // Computed priority for this block.
166  double Distance;
168  double ItemCoverage; // amount of the item that is onscreen (fraction, if whole item is onscreen
169  // it is 1)
170  vtkBoundingBox Bounds; // Bounds for the block.
171 
173  : Identifier(0)
174  , Refinement(0)
175  , ScreenCoverage(0)
176  , Priority(0)
177  , Distance(0)
178  , AmountOfDetail(-1)
179  {
180  }
181 };
182 
184 {
185 public:
187  const vtkStreamingPriorityQueueItem& me, const vtkStreamingPriorityQueueItem& other) const
188  {
189  return me.Priority < other.Priority;
190  }
191 };
192 
193 template <typename Comparator = vtkStreamingPriorityQueueItemComparator>
194 class VTK_WRAPEXCLUDE vtkStreamingPriorityQueue
195  : public std::priority_queue<vtkStreamingPriorityQueueItem,
196  std::vector<vtkStreamingPriorityQueueItem>, Comparator>
197 {
198 public:
200 
203  void UpdatePriorities(const double view_planes[24], const double clamp_bounds[6])
204  {
205  bool clamp_bounds_initialized =
206  (vtkMath::AreBoundsInitialized(const_cast<double*>(clamp_bounds)) != 0);
207  vtkBoundingBox clampBox(const_cast<double*>(clamp_bounds));
209 
210  vtkStreamingPriorityQueue current_queue;
211  std::swap(current_queue, *this);
212 
213  for (; !current_queue.empty(); current_queue.pop())
214  {
215  vtkStreamingPriorityQueueItem item = current_queue.top();
216  if (!item.Bounds.IsValid())
217  {
218  continue;
219  }
220 
221  double block_bounds[6];
222  item.Bounds.GetBounds(block_bounds);
223 
224  if (clamp_bounds_initialized)
225  {
226  if (!clampBox.ContainsPoint(block_bounds[0], block_bounds[2], block_bounds[4]) &&
227  !clampBox.ContainsPoint(block_bounds[1], block_bounds[3], block_bounds[5]))
228  {
229  // if the block_bounds is totally outside the clamp_bounds, skip it.
230  continue;
231  }
232  }
233 
234  double refinement2 = item.Refinement * item.Refinement;
235  double distance, centeredness, itemCoverage;
236  double coverage =
237  vtkComputeScreenCoverage(view_planes, block_bounds, distance, centeredness, itemCoverage);
238  item.ScreenCoverage = coverage;
239  item.Distance = distance;
240  item.Centeredness = centeredness;
241  item.ItemCoverage = itemCoverage;
242 
243  if (coverage > 0)
244  {
245  // item.Priority = coverage / (item.Refinement/* * distance*/) ;// / distance;
246  // //coverage * coverage / ( 1 + refinement2 + distance);
247  item.Priority = coverage * coverage * centeredness / (1 + refinement2 + distance);
248  }
249  else
250  {
251  item.Priority = 0;
252  }
253  this->push(item);
254  }
255  }
256 };
257 #endif
258 #endif
259 // 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])