1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPixelExtenth.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkPixelExtent.h"
16 
17 using std::deque;
18 using std::ostream;
19 
20 //-----------------------------------------------------------------------------
Grow(const vtkPixelExtent & inputExt,const vtkPixelExtent & problemDomain,int n)21 vtkPixelExtent vtkPixelExtent::Grow(
22       const vtkPixelExtent &inputExt,
23       const vtkPixelExtent &problemDomain,
24       int n)
25 {
26   vtkPixelExtent outputExt = vtkPixelExtent::Grow(inputExt, n);
27   outputExt &= problemDomain;
28   return outputExt;
29 }
30 
31 //-----------------------------------------------------------------------------
Grow(const vtkPixelExtent & inputExt,int n)32 vtkPixelExtent vtkPixelExtent::Grow(
33       const vtkPixelExtent &inputExt,
34       int n)
35 {
36   vtkPixelExtent outputExt(inputExt);
37   outputExt.Grow(0, n);
38   outputExt.Grow(1, n);
39   return outputExt;
40 }
41 
42 //-----------------------------------------------------------------------------
GrowLow(const vtkPixelExtent & inputExt,int q,int n)43 vtkPixelExtent vtkPixelExtent::GrowLow(
44       const vtkPixelExtent &inputExt,
45       int q,
46       int n)
47 {
48   vtkPixelExtent outputExt(inputExt);
49   outputExt[2*q] -= n;
50   return outputExt;
51 }
52 
53 //-----------------------------------------------------------------------------
GrowHigh(const vtkPixelExtent & inputExt,int q,int n)54 vtkPixelExtent vtkPixelExtent::GrowHigh(
55       const vtkPixelExtent &inputExt,
56       int q,
57       int n)
58 {
59   vtkPixelExtent outputExt(inputExt);
60   outputExt[2*q+1] += n;
61   return outputExt;
62 }
63 
64 //-----------------------------------------------------------------------------
Shrink(const vtkPixelExtent & inputExt,int n)65 vtkPixelExtent vtkPixelExtent::Shrink(
66       const vtkPixelExtent &inputExt,
67       int n)
68 {
69   return vtkPixelExtent::Grow(inputExt, -n);
70 }
71 
72 //-----------------------------------------------------------------------------
Shrink(const vtkPixelExtent & inputExt,const vtkPixelExtent & problemDomain,int n)73 vtkPixelExtent vtkPixelExtent::Shrink(
74       const vtkPixelExtent &inputExt,
75       const vtkPixelExtent &problemDomain,
76       int n)
77 {
78   vtkPixelExtent outputExt(inputExt);
79 
80   outputExt.Grow(0, -n);
81   outputExt.Grow(1, -n);
82 
83   // don't shrink at the problem domain
84   // because you don't grow outside the problem domain.
85   for (int i=0; i<4; ++i)
86     {
87     if (inputExt[i] == problemDomain[i])
88       {
89       outputExt[i] = problemDomain[i];
90       }
91     }
92 
93   return outputExt;
94 }
95 
96 //-----------------------------------------------------------------------------
CellToNode(const vtkPixelExtent & inputExt)97 vtkPixelExtent vtkPixelExtent::CellToNode(
98       const vtkPixelExtent &inputExt)
99 {
100   vtkPixelExtent outputExt(inputExt);
101   ++outputExt[1];
102   ++outputExt[3];
103   return outputExt;
104 }
105 
106 //-----------------------------------------------------------------------------
NodeToCell(const vtkPixelExtent & inputExt)107 vtkPixelExtent vtkPixelExtent::NodeToCell(const vtkPixelExtent &inputExt)
108 {
109   vtkPixelExtent outputExt(inputExt);
110   --outputExt[1];
111   --outputExt[3];
112   return outputExt;
113 }
114 
115 //-----------------------------------------------------------------------------
Shift(int * ij,int n)116 void vtkPixelExtent::Shift(
117       int *ij,
118       int n)
119 {
120   ij[0] += n;
121   ij[1] += n;
122 }
123 
124 //-----------------------------------------------------------------------------
Shift(int * ij,int * n)125 void vtkPixelExtent::Shift(
126       int *ij,
127       int *n)
128 {
129   ij[0] += n[0];
130   ij[1] += n[1];
131 }
132 
133 //-----------------------------------------------------------------------------
Split(int i1,int j1,const vtkPixelExtent & ext,deque<vtkPixelExtent> & newExts)134 void vtkPixelExtent::Split(
135       int i1,
136       int j1,
137       const vtkPixelExtent &ext,
138       deque<vtkPixelExtent> &newExts)
139 {
140   // cell is inside, split results in as many as
141   // 4 new extents. check for each one.
142   int i0 = i1 - 1;
143   int j0 = j1 - 1;
144 
145   int outside = 1;
146 
147   // lower left
148   if (ext.Contains(i0, j0))
149     {
150     newExts.push_back(vtkPixelExtent(ext[0], i0, ext[2], j0));
151     outside = 0;
152     }
153   // lower right
154   if (ext.Contains(i1, j0))
155     {
156     newExts.push_back(vtkPixelExtent(i1, ext[1], ext[2], j0));
157     outside = 0;
158     }
159   // upper left
160   if (ext.Contains(i0, j1))
161     {
162     newExts.push_back(vtkPixelExtent(ext[0], i0, j1, ext[3]));
163     outside = 0;
164     }
165   // upper right
166   if (ext.Contains(i1, j1))
167     {
168     newExts.push_back(vtkPixelExtent(i1, ext[1], j1, ext[3]));
169     outside = 0;
170     }
171 
172   // split cell is outside, pass through
173   if (outside)
174     {
175     newExts.push_back(ext);
176     return;
177     }
178 }
179 
180 //-----------------------------------------------------------------------------
Subtract(const vtkPixelExtent & A,vtkPixelExtent B,deque<vtkPixelExtent> & C)181 void vtkPixelExtent::Subtract(
182       const vtkPixelExtent &A,
183       vtkPixelExtent B,
184       deque<vtkPixelExtent> &C)
185 {
186   // split method requires split point inside the extent
187   vtkPixelExtent I(A);
188   I &= B;
189 
190   if (I.Empty())
191     {
192     // do nothing if disjoint
193     C.push_back(A);
194     return;
195     }
196   if (B.Contains(A))
197     {
198     // if A is covered by B then remove A
199     return;
200     }
201 
202   // split left and bellow this cells
203   I.CellToNode();
204 
205   deque<vtkPixelExtent> tmpA0;
206   tmpA0.push_back(A);
207   for (int q=0; q<4; ++q)
208     {
209     const int ids[8] = {0,2, 1,2, 1,3, 0,3};
210     int qq = 2*q;
211     int i = I[ids[qq]];
212     int j = I[ids[qq+1]];
213     deque<vtkPixelExtent> tmpA1;
214     while ( !tmpA0.empty() )
215       {
216       vtkPixelExtent ext = tmpA0.back();
217       tmpA0.pop_back();
218       vtkPixelExtent::Split(i,j, ext, tmpA1);
219       }
220     tmpA0 = tmpA1;
221     }
222 
223   // remove anything covered by B
224   size_t n = tmpA0.size();
225   for (size_t q=0; q<n; ++q)
226     {
227     const vtkPixelExtent &ext = tmpA0[q];
228     if (!B.Contains(ext))
229       {
230       C.push_back(ext);
231       }
232     }
233 }
234 
235 // ----------------------------------------------------------------------------
Merge(deque<vtkPixelExtent> & exts)236 void vtkPixelExtent::Merge(deque<vtkPixelExtent> &exts)
237 {
238   size_t ne = exts.size();
239 
240   // working in point space simplifies things because
241   // points overlap in adjacent extents while cells do not
242   deque<vtkPixelExtent> tmpExts(ne);
243   for (size_t t=0; t<ne; ++t)
244     {
245     vtkPixelExtent ext(exts[t]);
246     ext.CellToNode();
247     tmpExts[t] = ext;
248     }
249 
250   // one pass for each direction
251   for (int q=0; q<2; ++q)
252     {
253     int qq = 2*q;
254     // consider each extent as a target to be merged
255     for (size_t t=0; t<ne; ++t)
256       {
257       // if a merger occurs the merged extent is added
258       // as a new target with the constituents marked empty
259       // and the current pass is terminated early
260       bool nextPass = false;
261 
262       // current target
263       vtkPixelExtent &ext0 = tmpExts[t];
264       if (ext0.Empty())
265         {
266         // was merged in preceeding pass
267         continue;
268         }
269 
270       for (size_t c=0; c<ne; ++c)
271         {
272         if (c == t)
273           {
274           // don't attempt merge with self
275           continue;
276           }
277 
278         // candidate
279         vtkPixelExtent &ext1 = tmpExts[c];
280         if (ext1.Empty())
281           {
282           // was merged in preceeding pass
283           continue;
284           }
285 
286         // must be same size and coordinate in merge dir
287         if ( (ext0[qq] == ext1[qq]) && (ext0[qq+1] == ext1[qq+1]) )
288           {
289           // must overlap overlap
290           vtkPixelExtent ext2(ext0);
291           ext2 &= ext1;
292           if (!ext2.Empty())
293             {
294             // merge and add as new target
295             // in a later pass
296             vtkPixelExtent ext3(ext0);
297             ext3 |= ext1;
298             tmpExts.push_back(ext3);
299             ++ne;
300 
301             // mark the merged extents empty
302             ext0.Clear();
303             ext1.Clear();
304 
305             // move to next target
306             nextPass = true;
307             }
308           }
309         if (nextPass)
310           {
311           break;
312           }
313         }
314       }
315     }
316   // discard merged targets copy to output
317   exts.clear();
318   for (size_t t=0; t<ne; ++t)
319     {
320     vtkPixelExtent &ext = tmpExts[t];
321     if (!ext.Empty())
322       {
323       ext.NodeToCell();
324       exts.push_back(ext);
325       }
326     }
327 }
328 
329 //*****************************************************************************
operator <<(ostream & os,const vtkPixelExtent & ext)330 ostream &operator<<(ostream &os, const vtkPixelExtent &ext)
331 {
332   if (ext.Empty())
333     {
334     os << "(empty)";
335     }
336   else
337     {
338     os
339       << "("
340       << ext[0] << ", "
341       << ext[1] << ", "
342       << ext[2] << ", "
343       << ext[3] << ")";
344     }
345   return os;
346 }
347