1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkUnstructuredGridVolumeZSweepMapper.cxx
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 "vtkUnstructuredGridVolumeZSweepMapper.h"
16 
17 #include "vtkObjectFactory.h"
18 #include "vtkUnstructuredGrid.h"
19 #include "vtkTimerLog.h"
20 #include "vtkVolume.h"
21 #include "vtkRenderer.h"
22 #include "vtkRenderWindow.h"
23 #include "vtkRayCastImageDisplayHelper.h"
24 #include "vtkTransform.h"
25 #include "vtkCamera.h"
26 #include "vtkCellIterator.h"
27 #include "vtkGenericCell.h"
28 #include "vtkPriorityQueue.h"
29 #include "vtkIdList.h"
30 #include "vtkVolumeProperty.h"
31 #include "vtkColorTransferFunction.h"
32 #include "vtkPiecewiseFunction.h"
33 #include "vtkSmartPointer.h"
34 #include "vtkUnstructuredGridPreIntegration.h"
35 #include "vtkUnstructuredGridPartialPreIntegration.h"
36 #include "vtkUnstructuredGridHomogeneousRayIntegrator.h"
37 #include "vtkDoubleArray.h"
38 #include "vtkDataArray.h"
39 
40 #include "vtkPolyData.h"
41 #include "vtkCellArray.h"
42 //#include "vtkXMLPolyDataWriter.h"
43 #include "vtkPointData.h"
44 
45 #include <cassert>
46 #include <cstring> // memset()
47 #include <vector>
48 #include <list>
49 
50 // do not remove the following line:
51 //#define BACK_TO_FRONT
52 
53 // Put the internal classes in a namespace to avoid potential naming conflicts.
54 namespace vtkUnstructuredGridVolumeZSweepMapperNamespace
55 {
56 
57 enum
58 {
59   VTK_VALUES_X_INDEX=0, //  world coordinate
60   VTK_VALUES_Y_INDEX, //  world coordinate
61   VTK_VALUES_Z_INDEX, //  world coordinate
62   VTK_VALUES_SCALAR_INDEX,
63   VTK_VALUES_SIZE // size of a value array
64 };
65 
66 // Internal classes
67 //-----------------------------------------------------------------------------
68 // Store the result of the scan conversion at some pixel.
69 class vtkPixelListEntry
70 {
71 public:
72   vtkPixelListEntry() = default;
73 
Init(double values[VTK_VALUES_SIZE],double zView,bool exitFace)74   void Init(double values[VTK_VALUES_SIZE],
75             double zView,
76             bool exitFace)
77   {
78       this->Zview=zView;
79       int i=0;
80       while(i<VTK_VALUES_SIZE)
81       {
82         this->Values[i]=values[i];
83         ++i;
84       }
85       this->ExitFace = exitFace;
86   }
87 
88 
89   // Return the interpolated values at this pixel.
GetValues()90   inline double *GetValues() { return this->Values; }
91   // Return the interpolated z coordinate in view space at this pixel.
GetZview() const92   inline double GetZview() const { return this->Zview; }
93   // Return whether the fragment comes from an external face.
GetExitFace() const94   inline bool GetExitFace() const { return this->ExitFace; }
95 
GetPrevious()96   vtkPixelListEntry *GetPrevious() { return this->Previous; }
GetNext()97   vtkPixelListEntry *GetNext() { return this->Next; }
98 
SetPrevious(vtkPixelListEntry * e)99   void SetPrevious(vtkPixelListEntry *e) { this->Previous=e; }
SetNext(vtkPixelListEntry * e)100   void SetNext(vtkPixelListEntry *e) { this->Next=e; }
101 
102 protected:
103   double Values[VTK_VALUES_SIZE];
104   double Zview;
105   bool ExitFace;
106 
107   // List structure: both for the free block list (one-way) and any
108   // pixel list (two-way)
109   vtkPixelListEntry *Next;
110   // List structure: only for the pixel list (two-way)
111   vtkPixelListEntry *Previous;
112 private:
113   vtkPixelListEntry(const vtkPixelListEntry &other) = delete;
114   vtkPixelListEntry &operator=(const vtkPixelListEntry &other) = delete;
115 };
116 
117 //-----------------------------------------------------------------------------
118 // Cache the projection of a vertex
119 class vtkVertexEntry
120 {
121 public:
122   vtkVertexEntry() = default;
123 
vtkVertexEntry(int screenX,int screenY,double xWorld,double yWorld,double zWorld,double zView,double scalar,double invW)124   vtkVertexEntry(int screenX,
125                  int screenY,
126                  double xWorld,
127                  double yWorld,
128                  double zWorld,
129                  double zView,
130                  double scalar,
131                  double invW)
132     :ScreenX(screenX),ScreenY(screenY),Zview(zView),InvW(invW)
133   {
134       this->Values[VTK_VALUES_X_INDEX]=xWorld;
135       this->Values[VTK_VALUES_Y_INDEX]=yWorld;
136       this->Values[VTK_VALUES_Z_INDEX]=zWorld;
137       this->Values[VTK_VALUES_SCALAR_INDEX]=scalar;
138   }
139 
Set(int screenX,int screenY,double xWorld,double yWorld,double zWorld,double zView,double scalar,double invW)140   void Set(int screenX,
141            int screenY,
142            double xWorld,
143            double yWorld,
144            double zWorld,
145            double zView,
146            double scalar,
147            double invW)
148   {
149       this->ScreenX=screenX;
150       this->ScreenY=screenY;
151       this->Zview=zView;
152       this->Values[VTK_VALUES_X_INDEX]=xWorld;
153       this->Values[VTK_VALUES_Y_INDEX]=yWorld;
154       this->Values[VTK_VALUES_Z_INDEX]=zWorld;
155       this->Values[VTK_VALUES_SCALAR_INDEX]=scalar;
156       this->InvW=invW;
157   }
158 
GetScreenX()159   int GetScreenX()
160   {
161       return this->ScreenX;
162   }
GetScreenY()163   int GetScreenY()
164   {
165       return this->ScreenY;
166   }
GetValues()167   double *GetValues()
168   {
169       return this->Values;
170   }
GetZview()171   double GetZview()
172   {
173       return this->Zview;
174   }
GetInvW()175   double GetInvW()
176   {
177       return this->InvW;
178   }
179 
operator =(const vtkVertexEntry & other)180   vtkVertexEntry &operator=(const vtkVertexEntry &other) {
181     ScreenX = other.ScreenX;
182     ScreenY = other.ScreenY;
183     memcpy(Values, other.Values, sizeof(double)*VTK_VALUES_SIZE);
184     Zview = other.Zview;
185     InvW = other.InvW;
186     return *this;
187   }
vtkVertexEntry(const vtkVertexEntry & other)188   vtkVertexEntry(const vtkVertexEntry &other) {
189     if( this != &other)
190     {
191       *this = other;
192     }
193   }
194 
195 protected:
196   int ScreenX;
197   int ScreenY;
198   double Values[VTK_VALUES_SIZE];
199   double Zview;
200   double InvW;
201 };
202 
203 
204 //-----------------------------------------------------------------------------
205 // Abstract interface for an edge of a triangle in the screen space.
206 // Used during scan-conversion.
207 class vtkScreenEdge
208 {
209 public:
210   // If the edge is a composite edge (top+bottom) switch to the bottom edge.
211   // Otherwise, do nothing.
OnBottom(int skipped,int y)212   virtual void OnBottom(int skipped, int y)
213   {
214       if(!skipped)
215       {
216         this->NextLine(y);
217       }
218   }
219   // Increment edge state to the next line.
220   virtual void NextLine(int y)=0;
221   // Increment edge state to the next deltaY line.
222   virtual void SkipLines(int deltaY,
223                          int y)=0;
224   // Return the abscissa for the current line.
225   virtual int GetX()=0;
226   // Return the projected values for the current line. They are linearly
227   // incrementally interpolated in view space. The actual values are
228   // given by projectedValue/InvW. This is the way the values in world space
229   // are incrementally (not linearly) interpolated in view space.
230   virtual double *GetPValues()=0;
231   // Return 1/W, linearly interpolated in view space.
232   virtual double GetInvW()=0;
233   // Return Z in view coordinates, linearly interpolated in view space.
234   virtual double GetZview()=0;
235 protected:
236   // Destructor.
237   virtual ~vtkScreenEdge() = default;
238 };
239 
240 //-----------------------------------------------------------------------------
241 // Do an incremental traversing of an edge based on an Y increment.
242 enum
243 {
244   VTK_CASE_VERTICAL=0,
245   VTK_CASE_MOSTLY_VERTICAL,
246   VTK_CASE_DIAGONAL,
247   VTK_CASE_HORIZONTAL_BEGIN,
248   VTK_CASE_HORIZONTAL_END,
249   VTK_CASE_HORIZONTAL_MS, // most significant pixel
250   VTK_CASE_VERTICAL_IN_TO_OUT, // with edge equation
251   VTK_CASE_VERTICAL_OUT_TO_IN,
252   VTK_CASE_HORIZONTAL_IN_TO_OUT,
253   VTK_CASE_HORIZONTAL_OUT_TO_IN,
254   VTK_CASE_UNDEFINED
255 };
256 
257 // We use an edge equation as described in:
258 // Juan Pineda
259 // A Parallel Algorithm for Polygon Rasterization
260 // In Computer Graphics, Volume 22, Number 4, August 1988
261 // SIGGRAPH'88, Atlanta, August 1-5, 1988.
262 // pages 17--20.
263 
264 // or in:
265 
266 // Marc Olano and Trey Greer
267 // Triangle Scan Conversion using 2D Homogeneous Coordinates
268 // In 1997 SIGGRAPH/Eurographics Workshop
269 // pages 89--95.
270 // http://www.cs.unc.edu/~olano/papers/2dh-tri/2dh-tri.pdf
271 
272 #define MOST_SIGNIFICANT
273 #define EDGE_EQUATION
274 #define HORI_EDGE_EQUATION
275 //#define STRICTLY_INSIDE
276 
277 class vtkSimpleScreenEdge
278   : public vtkScreenEdge
279 {
280 public:
vtkSimpleScreenEdge()281   vtkSimpleScreenEdge()
282   {
283     this->Case = VTK_CASE_UNDEFINED;
284   }
285   // Initialize the edge by the vertices v0 and v2 (ordered in y)
286   // `onRight' is true if the edge in on the right side of the triangle.
Init(vtkVertexEntry * v0,vtkVertexEntry * v2,int dx20,int dy20,int onRight)287   void Init(vtkVertexEntry *v0,
288             vtkVertexEntry *v2,
289             int dx20,
290             int dy20,
291             int onRight)
292   {
293       double z0=v0->GetZview();
294       double z2=v2->GetZview();
295 
296       double invW0=v0->GetInvW();
297       double invW2=v2->GetInvW();
298 
299       double pv0[VTK_VALUES_SIZE];
300       double pv2[VTK_VALUES_SIZE];
301       int i=0;
302       while(i<VTK_VALUES_SIZE)
303       {
304         pv0[i]=v0->GetValues()[i]*invW0;
305         this->PValues[i]=pv0[i];
306         pv2[i]=v2->GetValues()[i]*invW2;
307         ++i;
308       }
309 
310       this->InvW=invW0;
311       this->Zview=z0;
312 
313       int x0=v0->GetScreenX();
314       int x2=v2->GetScreenX();
315 
316       this->X0=x0;
317       this->X2=x2;
318 
319       this->V2=v2;
320 
321       this->X=x0;
322 
323       if(dx20==0)
324       {
325         this->Case=VTK_CASE_VERTICAL;
326         double invDy20=1.0/dy20;
327         i=0;
328         while(i<VTK_VALUES_SIZE)
329         {
330           this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
331           ++i;
332         }
333         this->DinvW=(invW2-invW0)*invDy20;
334         this->Dz=(z2-z0)*invDy20;
335       }
336       else
337       {
338         if(dx20>0)
339         {
340           this->IncX=1;
341           if(dx20>dy20)
342           {
343             // Mostly horizontal
344 #ifdef HORI_EDGE_EQUATION
345             if(onRight)
346             {
347               this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT;
348             }
349             else
350             {
351               this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN;
352             }
353             this->Error=0;
354             this->SDy=dy20;
355             this->XStep=dx20/dy20; // integral division
356             this->Dx=dx20-this->XStep*this->SDy;
357 
358             double invDy20=1.0/dy20;
359             i=0;
360             while(i<VTK_VALUES_SIZE)
361             {
362               this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
363               ++i;
364             }
365             this->DinvW=(invW2-invW0)*invDy20;
366             this->Dz=(z2-z0)*invDy20;
367 #else
368 #ifdef MOST_SIGNIFICANT
369             this->Case=VTK_CASE_HORIZONTAL_MS;
370             this->XStep=dx20/dy20; // integral division
371             this->Dy=dy20;
372             this->Dy2=dy20<<1; // *2
373             this->Error=0;
374             this->ErrorStep=(dx20-this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, r<dy
375             double invDx20=1.0/dx20;
376             i=0;
377             while(i<VTK_VALUES_SIZE)
378             {
379               this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
380               this->PValuesStep[i]=this->Dpv[i]*this->XStep;
381               ++i;
382             }
383             this->DinvW=(invW2-invW0)*invDx20;
384             this->Dz=(z2-z0)*invDx20;
385             this->InvWStep=this->DinvW*this->XStep;
386             this->ZStep=this->Dz*this->XStep;
387 
388 #else
389             if(!onRight)
390             {
391               this->Case=VTK_CASE_HORIZONTAL_BEGIN;
392               this->First=1;
393               this->Dy2=dy20<<1; // *2
394               this->Dx2=dx20<<1; // *2
395               this->Error=dx20;
396 
397               this->XStep=dx20/dy20; // integral division
398 
399               this->ErrorStep=this->XStep*this->Dy2;
400 
401               double invDx20=1.0/dx20;
402               i=0;
403               while(i<VTK_VALUES_SIZE)
404               {
405                 this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
406                 this->PValuesStep[i]=this->Dpv[i]*this->XStep;
407                 ++i;
408               }
409               this->DinvW=(invW2-invW0)*invDx20;
410               this->Dz=(z2-z0)*invDx20;
411               this->InvWStep=this->DinvW*this->XStep;
412               this->ZStep=this->Dz*this->XStep;
413             }
414             else
415             {
416               this->Case=VTK_CASE_HORIZONTAL_END;
417 
418               this->InvW2=invW2;
419               i=0;
420               while(i<VTK_VALUES_SIZE)
421               {
422                 this->PValues2[i]=pv2[i];
423                 ++i;
424               }
425 
426               this->Zview2=z2;
427 
428               this->Dy2=dy20<<1; // *2
429               this->Dx2=dx20<<1; // *2
430               this->Error=dx20;
431               this->XStep=dx20/dy20;
432               this->ErrorStep=this->XStep*this->Dy2;
433 
434               double invDx20=1.0/dx20;
435               i=0;
436               while(i<VTK_VALUES_SIZE)
437               {
438                 this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
439                 this->PValuesStep[i]=this->Dpv[i]*this->XStep;
440                 ++i;
441               }
442               this->DinvW=(invW2-invW0)*invDx20;
443               this->Dz=(z2-z0)*invDx20;
444               this->InvWStep=this->DinvW*this->XStep;
445               this->ZStep=this->Dz*this->XStep;
446 
447               while(this->Error<this->Dx2)
448               {
449                 this->X+=this->IncX;
450                 this->InvW+= this->DinvW;
451                 i=0;
452                 while(i<VTK_VALUES_SIZE)
453                 {
454                   this->PValues[i]+=this->Dpv[i];
455                   ++i;
456                 }
457                 this->Zview+=this->Dz;
458 
459                 this->Error+=this->Dy2;
460               }
461               this->Error-=this->Dx2;
462               this->X-=this->IncX;
463               this->InvW-= this->DinvW;
464               i=0;
465               while(i<VTK_VALUES_SIZE)
466               {
467                 this->PValues[i]-=this->Dpv[i];
468                 ++i;
469               }
470               this->Zview-=this->Dz;
471             }
472 #endif
473 #endif // EDGE_EQUATION
474           }
475           else
476           {
477             if(dx20==dy20)
478             {
479               this->Case=VTK_CASE_DIAGONAL;
480 
481               double invDy20=1.0/dy20;
482               i=0;
483               while(i<VTK_VALUES_SIZE)
484               {
485                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
486                 ++i;
487               }
488               this->DinvW=(invW2-invW0)*invDy20;
489               this->Dz=(z2-z0)*invDy20;
490             }
491             else
492             {
493 #ifdef EDGE_EQUATION
494               if(onRight)
495               {
496                 this->Case=VTK_CASE_VERTICAL_IN_TO_OUT;
497               }
498               else
499               {
500                 this->Case=VTK_CASE_VERTICAL_OUT_TO_IN;
501               }
502               this->Error=0;
503               this->SDy=dy20;
504               this->Dx=dx20;
505 
506               double invDy20=1.0/dy20;
507               i=0;
508               while(i<VTK_VALUES_SIZE)
509               {
510                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
511                 ++i;
512               }
513               this->DinvW=(invW2-invW0)*invDy20;
514               this->Dz=(z2-z0)*invDy20;
515 #else
516               this->Case=VTK_CASE_MOSTLY_VERTICAL;
517               this->Dx2=dx20<<1; // *2
518               this->Dy2=dy20<<1; // *2
519               this->Error=dy20;
520 
521               double invDy20=1.0/dy20;
522               i=0;
523               while(i<VTK_VALUES_SIZE)
524               {
525                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
526                 ++i;
527               }
528               this->DinvW=(invW2-invW0)*invDy20;
529               this->Dz=(z2-z0)*invDy20;
530 #endif
531             }
532           }
533         }
534         else
535         {
536           this->IncX=-1;
537           if(-dx20>dy20)
538           {
539              // Mostly horizontal
540 #ifdef HORI_EDGE_EQUATION
541             if(onRight)
542             {
543               this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN;
544             }
545             else
546             {
547               this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT;
548             }
549             this->Error=0;
550             this->SDy=-dy20;
551             this->XStep=dx20/dy20; // integral division
552             this->Dx=dx20+this->XStep*this->SDy;
553 
554             double invDy20=1.0/dy20;
555             i=0;
556             while(i<VTK_VALUES_SIZE)
557             {
558               this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
559               ++i;
560             }
561             this->DinvW=(invW2-invW0)*invDy20;
562             this->Dz=(z2-z0)*invDy20;
563 #else
564 #ifdef MOST_SIGNIFICANT
565             this->Case=VTK_CASE_HORIZONTAL_MS;
566             this->XStep=dx20/dy20; // integral division
567             this->Dy=dy20;
568             this->Dy2=dy20<<1; // *2
569             this->Error=0;
570             this->ErrorStep=(dx20+this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, r<dy
571             double invDx20=-1.0/dx20;
572             i=0;
573             while(i<VTK_VALUES_SIZE)
574             {
575               this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
576               this->PValuesStep[i]=-this->Dpv[i]*this->XStep;
577               ++i;
578             }
579             this->DinvW=(invW2-invW0)*invDx20;
580             this->Dz=(z2-z0)*invDx20;
581             this->InvWStep=-this->DinvW*this->XStep;
582             this->ZStep=-this->Dz*this->XStep;
583 
584 
585 #else
586             if(onRight)
587             {
588               this->Case=VTK_CASE_HORIZONTAL_BEGIN;
589               this->First=1;
590               this->Dy2=dy20<<1; // *2
591               this->Dx2=(-dx20)<<1; // *2
592               this->Error=-dx20;
593               this->XStep=dx20/dy20;
594               this->ErrorStep=-this->XStep*this->Dy2;
595 
596               double invDx20=-1.0/dx20;
597 
598               i=0;
599               while(i<VTK_VALUES_SIZE)
600               {
601                 this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
602                 this->PValuesStep[i]=-this->Dpv[i]*this->XStep;
603                 ++i;
604               }
605               this->DinvW=(invW2-invW0)*invDx20;
606               this->Dz=(z2-z0)*invDx20;
607               this->InvWStep=-this->DinvW*this->XStep;
608               this->ZStep=-this->Dz*this->XStep;
609             }
610             else
611             {
612               this->Case=VTK_CASE_HORIZONTAL_END;
613 
614               this->InvW2=invW2;
615               i=0;
616               while(i<VTK_VALUES_SIZE)
617               {
618                 this->PValues2[i]=pv2[i];
619                 ++i;
620               }
621               this->Zview2=z2;
622 
623               this->Dy2=dy20<<1; // *2
624               this->Dx2=(-dx20)<<1; // *2
625               this->Error=-dx20;
626               this->XStep=dx20/dy20;
627               this->ErrorStep=-this->XStep*this->Dy2;
628 
629               double invDx20=-1.0/dx20;
630 
631               i=0;
632               while(i<VTK_VALUES_SIZE)
633               {
634                 this->Dpv[i]=(pv2[i]-pv0[i])*invDx20;
635                 this->PValuesStep[i]=-this->Dpv[i]*this->XStep;
636                 ++i;
637               }
638               this->DinvW=(invW2-invW0)*invDx20;
639               this->Dz=(z2-z0)*invDx20;
640               this->InvWStep=-this->DinvW*this->XStep;
641               this->ZStep=-this->Dz*this->XStep;
642 
643               while(this->Error<this->Dx2)
644               {
645                 this->X+=this->IncX;
646                 this->InvW+= this->DinvW;
647                 i=0;
648                 while(i<VTK_VALUES_SIZE)
649                 {
650                   this->PValues[i]+=this->Dpv[i];
651                   ++i;
652                 }
653                 this->Zview+=this->Dz;
654 
655                 this->Error+=this->Dy2;
656               }
657               this->Error-=this->Dx2;
658               this->X-=this->IncX;
659 
660               this->InvW-= this->DinvW;
661               i=0;
662               while(i<VTK_VALUES_SIZE)
663               {
664                 this->PValues[i]-=this->Dpv[i];
665                 ++i;
666               }
667               this->Zview-=this->Dz;
668             }
669 #endif
670 #endif // EDGE_EQUATION
671           }
672           else
673           {
674             if(dx20==-dy20)
675             {
676               this->Case=VTK_CASE_DIAGONAL;
677 
678               double invDy20=1.0/dy20;
679               i=0;
680               while(i<VTK_VALUES_SIZE)
681               {
682                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
683                 ++i;
684               }
685               this->DinvW=(invW2-invW0)*invDy20;
686               this->Dz=(z2-z0)*invDy20;
687             }
688             else
689             {
690 #ifdef EDGE_EQUATION
691               if(onRight)
692               {
693                 this->Case=VTK_CASE_VERTICAL_OUT_TO_IN;
694               }
695               else
696               {
697                 this->Case=VTK_CASE_VERTICAL_IN_TO_OUT;
698               }
699               this->Error=0;
700               this->SDy=-dy20;
701               this->Dx=dx20;
702 
703               double invDy20=1.0/dy20;
704               i=0;
705               while(i<VTK_VALUES_SIZE)
706               {
707                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
708                 ++i;
709               }
710               this->DinvW=(invW2-invW0)*invDy20;
711               this->Dz=(z2-z0)*invDy20;
712 #else
713               this->Case=VTK_CASE_MOSTLY_VERTICAL;
714               this->Dx2=(-dx20)<<1; // *2
715               this->Dy2=dy20<<1; // *2
716               this->Error=dy20;
717 
718               double invDy20=1.0/dy20;
719               i=0;
720               while(i<VTK_VALUES_SIZE)
721               {
722                 this->Dpv[i]=(pv2[i]-pv0[i])*invDy20;
723                 ++i;
724               }
725               this->DinvW=(invW2-invW0)*invDy20;
726               this->Dz=(z2-z0)*invDy20;
727 #endif
728             }
729           }
730         }
731       }
732   }
733 
734   // Check that the current abscissa is in the range given by the vertices.
ValidXRange()735   int ValidXRange()
736   {
737       if(this->X0<=this->X2)
738       {
739         return (this->X>=this->X0) && (this->X<=this->X2);
740       }
741       else
742       {
743         return (this->X>=this->X2) && (this->X<=this->X0);
744       }
745   }
GetX()746   int GetX() override
747   {
748       // assert("pre: valid_range" && ValidXRange() );
749       return this->X;
750   }
GetInvW()751   double GetInvW() override { return this->InvW; }
GetPValues()752   double *GetPValues() override { return this->PValues; }
GetZview()753   double GetZview() override { return this->Zview; }
754 
NextLine(int y)755   void NextLine(int y) override
756   {
757       int i;
758       switch(this->Case)
759       {
760         case VTK_CASE_VERTICAL:
761           // nothing to do with X
762           this->InvW+=this->DinvW;
763           i=0;
764           while(i<VTK_VALUES_SIZE)
765           {
766             this->PValues[i]+=this->Dpv[i];
767             ++i;
768           }
769           this->Zview+=this->Dz;
770           break;
771         case VTK_CASE_DIAGONAL:
772           // X
773           this->X+=this->IncX;
774           this->InvW+=this->DinvW;
775           i=0;
776           while(i<VTK_VALUES_SIZE)
777           {
778             this->PValues[i]+=this->Dpv[i];
779             ++i;
780           }
781           this->Zview+=this->Dz;
782           break;
783         case VTK_CASE_MOSTLY_VERTICAL:
784           // X
785           this->Error+=this->Dx2;
786           if(this->Error>=this->Dy2)
787           {
788             this->Error-=this->Dy2;
789             this->X+=this->IncX;
790           }
791           this->InvW+=this->DinvW;
792           i=0;
793           while(i<VTK_VALUES_SIZE)
794           {
795             this->PValues[i]+=this->Dpv[i];
796             ++i;
797           }
798           this->Zview+=this->Dz;
799           break;
800         case VTK_CASE_VERTICAL_OUT_TO_IN:
801           this->Error-=this->Dx;
802           if(this->SDy>0)
803           {
804 #ifdef STRICTLY_INSIDE
805             if(this->Error<=0)
806 #else
807             if(this->Error<0) // we are no more on the right side
808 #endif
809             {
810               this->Error+=this->SDy;
811 #ifdef STRICTLY_INSIDE
812               assert("check: positive_equation" && this->Error>0);
813 #else
814               assert("check: positive_equation" && this->Error>=0);
815 #endif
816               this->X+=this->IncX;
817             }
818           }
819           else
820           {
821 #ifdef STRICTLY_INSIDE
822             if(this->Error>=0) // we are no more on the left side
823 #else
824             if(this->Error>0) // we are no more on the left side
825 #endif
826             {
827               this->Error+=this->SDy;
828 #ifdef STRICTLY_INSIDE
829 //              assert("check: negative_equation" && this->Error>0);
830 #else
831               assert("check: negative_equation" && this->Error<=0);
832 #endif
833               this->X+=this->IncX;
834             }
835           }
836           // Interpolate the values on inc y
837           this->InvW+=this->DinvW;
838           i=0;
839           while(i<VTK_VALUES_SIZE)
840           {
841             this->PValues[i]+=this->Dpv[i];
842             ++i;
843           }
844           this->Zview+=this->Dz;
845           break;
846         case  VTK_CASE_VERTICAL_IN_TO_OUT:
847           this->Error+=this->SDy-this->Dx;
848           if(this->SDy<0)
849           {
850 #ifdef STRICTLY_INSIDE
851             if(this->Error<=0) // out: too far on left
852 #else
853             if(this->Error<0) // out: too far on left
854 #endif
855             {
856               this->Error-=this->SDy;
857 #ifdef STRICTLY_INSIDE
858               assert("check: positive_equation" && this->Error>0);
859 #else
860               assert("check: positive_equation" && this->Error>=0);
861 #endif
862             }
863             else
864             {
865               this->X+=this->IncX;
866             }
867           }
868           else
869           {
870 #ifdef STRICTLY_INSIDE
871             if(this->Error>=0) // out: too far on right
872 #else
873             if(this->Error>0) // out: too far on right
874 #endif
875             {
876               this->Error-=this->SDy;
877 #ifdef STRICTLY_INSIDE
878               assert("check: negative_equation" && this->Error<0);
879 #else
880               assert("check: negative_equation" && this->Error<=0);
881 #endif
882             }
883             else
884             {
885               this->X+=this->IncX;
886             }
887           }
888           // Interpolate the values on inc y
889           this->InvW+=this->DinvW;
890           i=0;
891           while(i<VTK_VALUES_SIZE)
892           {
893             this->PValues[i]+=this->Dpv[i];
894             ++i;
895           }
896           this->Zview+=this->Dz;
897           break;
898 
899         case VTK_CASE_HORIZONTAL_OUT_TO_IN:
900           this->Error-=this->Dx;
901           this->X+=this->XStep;
902           if(this->SDy>0)
903           {
904 #ifdef STRICTLY_INSIDE
905             if(this->Error<=0) // we are no more on the right side
906 #else
907             if(this->Error<0) // we are no more on the right side
908 #endif
909             {
910               this->Error+=this->SDy;
911 #ifdef STRICTLY_INSIDE
912               assert("check: positive_equation" && this->Error>0);
913 #else
914               assert("check: positive_equation" && this->Error>=0);
915 #endif
916               this->X+=this->IncX;
917             }
918           }
919           else
920           {
921 #ifdef STRICTLY_INSIDE
922             if(this->Error>=0) // we are no more on the left side
923 #else
924             if(this->Error>0) // we are no more on the left side
925 #endif
926             {
927               this->Error+=this->SDy;
928 #ifdef STRICTLY_INSIDE
929               assert("check: negative_equation" && this->Error<0);
930 #else
931               assert("check: negative_equation" && this->Error<=0);
932 #endif
933               this->X+=this->IncX;
934             }
935           }
936           // Interpolate the values on inc y
937           this->InvW+=this->DinvW;
938           i=0;
939           while(i<VTK_VALUES_SIZE)
940           {
941             this->PValues[i]+=this->Dpv[i];
942             ++i;
943           }
944           this->Zview+=this->Dz;
945           break;
946 
947         case  VTK_CASE_HORIZONTAL_IN_TO_OUT:
948           this->Error+=this->SDy-this->Dx;
949           this->X+=this->XStep;
950           if(this->SDy<0)
951           {
952 #ifdef STRICTLY_INSIDE
953             if(this->Error<=0) // out: too far on left
954 #else
955             if(this->Error<0) // out: too far on left
956 #endif
957             {
958               this->Error-=this->SDy;
959 #ifdef STRICTLY_INSIDE
960 //              assert("check: positive_equation" && this->Error>0);
961 #else
962               assert("check: positive_equation" && this->Error>=0);
963 #endif
964             }
965             else
966             {
967               this->X+=this->IncX;
968             }
969           }
970           else
971           {
972 #ifdef STRICTLY_INSIDE
973             if(this->Error>=0) // out: too far on right
974 #else
975             if(this->Error>0) // out: too far on right
976 #endif
977             {
978               this->Error-=this->SDy;
979 #ifdef STRICTLY_INSIDE
980 //            assert("check: negative_equation" && this->Error<0);
981 #else
982               assert("check: negative_equation" && this->Error<=0);
983 #endif
984             }
985             else
986             {
987               this->X+=this->IncX;
988             }
989           }
990           // Interpolate the values on inc y
991           this->InvW+=this->DinvW;
992           i=0;
993           while(i<VTK_VALUES_SIZE)
994           {
995             this->PValues[i]+=this->Dpv[i];
996             ++i;
997           }
998           this->Zview+=this->Dz;
999           break;
1000 
1001         case VTK_CASE_HORIZONTAL_BEGIN:
1002           if(this->First)
1003           {
1004             this->First=0;
1005           }
1006           else
1007           {
1008             this->X+=this->XStep;
1009 
1010             this->InvW+=this->InvWStep;
1011             i=0;
1012             while(i<VTK_VALUES_SIZE)
1013             {
1014               this->PValues[i]+=this->PValuesStep[i];
1015               ++i;
1016             }
1017             this->Zview+=this->ZStep;
1018             this->Error+=this->ErrorStep;
1019           }
1020           while(this->Error<this->Dx2)
1021           {
1022             this->X+=this->IncX;
1023             this->InvW+=this->DinvW;
1024             i=0;
1025             while(i<VTK_VALUES_SIZE)
1026             {
1027               this->PValues[i]+=this->Dpv[i];
1028               ++i;
1029             }
1030             this->Zview+=this->Dz;
1031 
1032             this->Error+=this->Dy2;
1033           }
1034           this->Error-=this->Dx2;
1035           break;
1036         case VTK_CASE_HORIZONTAL_END:
1037           if(y==this->V2->GetScreenY())
1038           {
1039             this->X=this->V2->GetScreenX();
1040             i=0;
1041             while(i<VTK_VALUES_SIZE)
1042             {
1043               this->PValues[i]=this->PValues2[i];
1044               ++i;
1045             }
1046             this->Zview=this->Zview2;
1047             this->InvW=this->InvW2;
1048           }
1049           else
1050           {
1051             this->X+=this->XStep;
1052 
1053             this->InvW+=this->InvWStep;
1054             i=0;
1055             while(i<VTK_VALUES_SIZE)
1056             {
1057               this->PValues[i]+=this->PValuesStep[i];
1058               ++i;
1059             }
1060             this->Zview+=this->ZStep;
1061 
1062             this->Error+=this->ErrorStep;
1063 
1064             while(this->Error<this->Dx2)
1065             {
1066               this->X+=this->IncX;
1067               this->InvW+=this->DinvW;
1068               i=0;
1069               while(i<VTK_VALUES_SIZE)
1070               {
1071                 this->PValues[i]+=this->Dpv[i];
1072                 ++i;
1073               }
1074               this->Zview+=this->Dz;
1075 
1076               this->Error+=this->Dy2;
1077             }
1078             this->Error-=this->Dx2;
1079           }
1080           break;
1081         case VTK_CASE_HORIZONTAL_MS:
1082           this->Error+=this->ErrorStep;
1083           if(this->Error>=this->Dy)
1084           {
1085             this->Error-=this->Dy2;
1086             this->X+=this->XStep+this->IncX;
1087             this->InvW+=this->InvWStep+this->DinvW;
1088             i=0;
1089             while(i<VTK_VALUES_SIZE)
1090             {
1091               this->PValues[i]+=this->PValuesStep[i]+this->Dpv[i];
1092               ++i;
1093             }
1094             this->Zview+=this->ZStep+this->Dz;
1095           }
1096           else
1097           {
1098             this->X+=this->XStep;
1099             this->InvW+=this->InvWStep;
1100             i=0;
1101             while(i<VTK_VALUES_SIZE)
1102             {
1103               this->PValues[i]+=this->PValuesStep[i];
1104               ++i;
1105             }
1106             this->Zview+=this->ZStep;
1107           }
1108           break;
1109         default:
1110           vtkGenericWarningMacro(<< "Undefined edge case");
1111       }
1112   }
1113 
SkipLines(int deltaY,int y)1114   void SkipLines(int deltaY,
1115                  int y) override
1116   {
1117       if(deltaY==1)
1118       {
1119         this->NextLine(0);
1120         return;
1121       }
1122 
1123       int firstDeltaY;
1124       int i;
1125       switch(this->Case)
1126       {
1127         case VTK_CASE_VERTICAL:
1128           // nothing to do with X
1129           this->InvW+=this->DinvW*deltaY;
1130           i=0;
1131           while(i<VTK_VALUES_SIZE)
1132           {
1133             this->PValues[i]+=this->Dpv[i]*deltaY;
1134             ++i;
1135           }
1136           this->Zview+=this->Dz*deltaY;
1137           break;
1138         case VTK_CASE_DIAGONAL:
1139           // X
1140           this->X+=this->IncX*deltaY;
1141           this->InvW+=this->DinvW*deltaY;
1142           i=0;
1143           while(i<VTK_VALUES_SIZE)
1144           {
1145             this->PValues[i]+=this->Dpv[i]*deltaY;
1146             ++i;
1147           }
1148           this->Zview+=this->Dz*deltaY;
1149           break;
1150         case VTK_CASE_MOSTLY_VERTICAL:
1151           // X
1152           this->Error+=this->Dx2*deltaY;
1153           while(this->Error>=this->Dy2)
1154           {
1155             this->Error-=this->Dy2;
1156             this->X+=this->IncX;
1157           }
1158           this->InvW+=this->DinvW*deltaY;
1159           i=0;
1160           while(i<VTK_VALUES_SIZE)
1161           {
1162             this->PValues[i]+=this->Dpv[i]*deltaY;
1163             ++i;
1164           }
1165           this->Zview+=this->Dz*deltaY;
1166           break;
1167         case VTK_CASE_VERTICAL_OUT_TO_IN:
1168           this->Error-=this->Dx*deltaY;
1169           if(this->SDy>0)
1170           {
1171 #ifdef STRICTLY_INSIDE
1172             while(this->Error<=0) // we are no more on the right side
1173 #else
1174             while(this->Error<0) // we are no more on the right side
1175 #endif
1176             {
1177               this->Error+=this->SDy;
1178               this->X+=this->IncX;
1179             }
1180           }
1181           else
1182           {
1183 #ifdef STRICTLY_INSIDE
1184             while(this->Error>=0) // we are no more on the left side
1185 #else
1186             while(this->Error>0) // we are no more on the left side
1187 #endif
1188             {
1189               this->Error+=this->SDy;
1190               this->X+=this->IncX;
1191             }
1192           }
1193           // Interpolate the values on inc y
1194           this->InvW+=this->DinvW*deltaY;
1195           i=0;
1196           while(i<VTK_VALUES_SIZE)
1197           {
1198             this->PValues[i]+=this->Dpv[i]*deltaY;
1199             ++i;
1200           }
1201           this->Zview+=this->Dz*deltaY;
1202           break;
1203         case  VTK_CASE_VERTICAL_IN_TO_OUT:
1204           this->Error+=(this->SDy-this->Dx)*deltaY;
1205           this->X+=this->IncX*deltaY;
1206            if(this->SDy<0)
1207            {
1208 #ifdef STRICTLY_INSIDE
1209              while(this->Error<=0) // out: too far on left
1210 #else
1211              while(this->Error<0) // out: too far on left
1212 #endif
1213              {
1214                this->Error-=this->SDy;
1215                this->X-=this->IncX;
1216              }
1217            }
1218            else
1219            {
1220 #ifdef STRICTLY_INSIDE
1221              while(this->Error>=0) // out: too far on right
1222 #else
1223              while(this->Error>0) // out: too far on right
1224 #endif
1225              {
1226                this->Error-=this->SDy;
1227                this->X-=this->IncX;
1228              }
1229            }
1230           // Interpolate the values on inc y
1231           this->InvW+=this->DinvW*deltaY;
1232           i=0;
1233           while(i<VTK_VALUES_SIZE)
1234           {
1235             this->PValues[i]+=this->Dpv[i]*deltaY;
1236             ++i;
1237           }
1238           this->Zview+=this->Dz*deltaY;
1239           break;
1240 
1241         case VTK_CASE_HORIZONTAL_OUT_TO_IN:
1242           this->Error-=this->Dx*deltaY;
1243           this->X+=this->XStep*deltaY;
1244           if(this->SDy>0)
1245           {
1246 #ifdef STRICTLY_INSIDE
1247             while(this->Error<=0) // we are no more on the right side
1248 #else
1249             while(this->Error<0) // we are no more on the right side
1250 #endif
1251             {
1252               this->Error+=this->SDy;
1253               this->X+=this->IncX;
1254             }
1255           }
1256           else
1257           {
1258 #ifdef STRICTLY_INSIDE
1259             while(this->Error>=0) // we are no more on the left side
1260 #else
1261             while(this->Error>0) // we are no more on the left side
1262 #endif
1263             {
1264               this->Error+=this->SDy;
1265               this->X+=this->IncX;
1266             }
1267           }
1268           // Interpolate the values on inc y
1269           this->InvW+=this->DinvW*deltaY;
1270           i=0;
1271           while(i<VTK_VALUES_SIZE)
1272           {
1273             this->PValues[i]+=this->Dpv[i]*deltaY;
1274             ++i;
1275           }
1276           this->Zview+=this->Dz*deltaY;
1277           break;
1278         case  VTK_CASE_HORIZONTAL_IN_TO_OUT:
1279           this->Error+=(this->SDy-this->Dx)*deltaY;
1280           this->X+=(this->XStep+this->IncX)*deltaY;
1281 //          this->X+=this->IncX*deltaY;
1282            if(this->SDy<0)
1283            {
1284 #ifdef STRICTLY_INSIDE
1285              while(this->Error<=0) // out: too far on left
1286 #else
1287              while(this->Error<0) // out: too far on left
1288 #endif
1289              {
1290                this->Error-=this->SDy;
1291                this->X-=this->IncX;
1292              }
1293            }
1294            else
1295            {
1296 #ifdef STRICTLY_INSIDE
1297              while(this->Error>=0) // out: too far on right
1298 #else
1299              while(this->Error>0) // out: too far on right
1300 #endif
1301              {
1302                this->Error-=this->SDy;
1303                this->X-=this->IncX;
1304              }
1305            }
1306           // Interpolate the values on inc y
1307           this->InvW+=this->DinvW*deltaY;
1308           i=0;
1309           while(i<VTK_VALUES_SIZE)
1310           {
1311             this->PValues[i]+=this->Dpv[i]*deltaY;
1312             ++i;
1313           }
1314           this->Zview+=this->Dz*deltaY;
1315           break;
1316 
1317         case VTK_CASE_HORIZONTAL_BEGIN:
1318 
1319           if(this->First)
1320           {
1321             this->First=0;
1322             firstDeltaY=deltaY-1;
1323           }
1324           else
1325           {
1326             firstDeltaY=deltaY;
1327           }
1328 
1329           this->X+=this->XStep*firstDeltaY;
1330 
1331           this->InvW+=this->InvWStep*firstDeltaY;
1332           i=0;
1333           while(i<VTK_VALUES_SIZE)
1334           {
1335             this->PValues[i]+=this->PValuesStep[i]*firstDeltaY;
1336             ++i;
1337           }
1338           this->Zview+=this->ZStep*firstDeltaY;
1339           this->Error+=this->ErrorStep*firstDeltaY;
1340 
1341           while(this->Error<this->Dx2)
1342           {
1343             this->X+=this->IncX;
1344             this->InvW+=this->DinvW;
1345             i=0;
1346             while(i<VTK_VALUES_SIZE)
1347             {
1348               this->PValues[i]+=this->Dpv[i];
1349               ++i;
1350             }
1351             this->Zview+=this->Dz;
1352 
1353             this->Error+=this->Dy2;
1354           }
1355           this->Error-=this->Dx2;
1356           break;
1357         case VTK_CASE_HORIZONTAL_END:
1358           if(y==this->V2->GetScreenY())
1359           {
1360             this->X=this->V2->GetScreenX();
1361             i=0;
1362             while(i<VTK_VALUES_SIZE)
1363             {
1364               this->PValues[i]=this->PValues2[i];
1365               ++i;
1366             }
1367             this->Zview=this->Zview2;
1368             this->InvW=this->InvW2;
1369           }
1370           else
1371           {
1372             this->X+=this->XStep*deltaY;
1373 
1374             this->InvW+=this->InvWStep*deltaY;
1375             i=0;
1376             while(i<VTK_VALUES_SIZE)
1377             {
1378               this->PValues[i]+=this->PValuesStep[i]*deltaY;
1379               ++i;
1380             }
1381             this->Zview+=this->ZStep*deltaY;
1382 
1383             this->Error+=this->ErrorStep*deltaY;
1384 
1385             while(this->Error<this->Dx2)
1386             {
1387               this->X+=this->IncX;
1388               this->InvW+=this->DinvW;
1389               i=0;
1390               while(i<VTK_VALUES_SIZE)
1391               {
1392                 this->PValues[i]+=this->Dpv[i];
1393                 ++i;
1394               }
1395               this->Zview+=this->Dz;
1396 
1397               this->Error+=this->Dy2;
1398             }
1399             this->Error-=this->Dx2;
1400           }
1401           break;
1402         case VTK_CASE_HORIZONTAL_MS:
1403           this->Error+=this->ErrorStep*deltaY;
1404           this->X+=this->XStep*deltaY;
1405           this->InvW+=this->InvWStep*deltaY;
1406           i=0;
1407           while(i<VTK_VALUES_SIZE)
1408           {
1409             this->PValues[i]+=this->PValuesStep[i]*deltaY;
1410             ++i;
1411           }
1412           this->Zview+=this->ZStep*deltaY;
1413 
1414           while(this->Error>=this->Dy)
1415           {
1416             this->Error-=this->Dy2;
1417             this->X+=this->IncX;
1418             this->InvW+=this->DinvW;
1419             i=0;
1420             while(i<VTK_VALUES_SIZE)
1421             {
1422               this->PValues[i]+=this->Dpv[i];
1423               ++i;
1424             }
1425             this->Zview+=this->Dz;
1426           }
1427           break;
1428       }
1429   }
1430 
1431 protected:
1432   int Case;
1433   int Error; // error to the mid-point
1434   int Dx2; // 2*dx
1435   int Dy2; // 2*dy
1436   int First; // use only with VTK_CASE_HORIZONTAL_BEGIN case
1437   int XStep; // dx/dy
1438   int ErrorStep; // XStep*Dy2
1439 
1440   vtkVertexEntry *V2;
1441 
1442   int IncX; // -1 or 1
1443 
1444   int X; // Current abscissa
1445 
1446   int X0; // for debugging
1447   int X2; // for debugging
1448 
1449   // Slope of 1/w
1450   double DinvW;
1451   // Current 1/W
1452   double InvW;
1453   // DinvW*XStep
1454   double InvWStep;
1455   // 1/W at the end vertex
1456   double InvW2;
1457 
1458   // Slope of the z coordinate in view space
1459   double Dz;
1460   // current z in view space
1461   double Zview;
1462   // Dz*XStep
1463   double ZStep;
1464   // z coordinate in view space at the end vertex
1465   double Zview2;
1466 
1467   // Slope of each projected values on the edge
1468   double Dpv[VTK_VALUES_SIZE];
1469 
1470 
1471   // Current projected values
1472   double PValues[VTK_VALUES_SIZE];
1473   // Dpv*XStep
1474   double PValuesStep[VTK_VALUES_SIZE];
1475   // Values at the end vertex.
1476   double PValues2[VTK_VALUES_SIZE];
1477 
1478   int Dy; // VTK_HORIZONTAL_MS
1479   int SDy; // VTK_VERTICAL_LEFT/RIGHT
1480   int Dx; // VTK_VERTICAL_LEFT/RIGHT
1481 };
1482 
1483 //-----------------------------------------------------------------------------
1484 // During rasterization of a triangle, there is always one side with two
1485 // edges and the other side with a single edge.
1486 // This class manages the side with the two edges called top and bottom edges.
1487 class vtkDoubleScreenEdge
1488   :public vtkScreenEdge
1489 {
1490 public:
Init(vtkVertexEntry * v0,vtkVertexEntry * v1,vtkVertexEntry * v2,int dx10,int dy10,int onRight)1491   void Init(vtkVertexEntry *v0,
1492             vtkVertexEntry *v1,
1493             vtkVertexEntry *v2,
1494             int dx10,
1495             int dy10,
1496             int onRight)
1497   {
1498       this->Current=nullptr;
1499       if(dy10!=0)
1500       {
1501         this->Top.Init(v0,v1,dx10,dy10,onRight);
1502         this->Current=&this->Top;
1503       }
1504 
1505       int dx21=v2->GetScreenX()-v1->GetScreenX();
1506       int dy21=v2->GetScreenY()-v1->GetScreenY();
1507 
1508       if(dy21!=0)
1509       {
1510         this->Bottom.Init(v1,v2,dx21,dy21,onRight);
1511         if(this->Current==nullptr)
1512         {
1513           this->Current=&this->Bottom;
1514         }
1515       }
1516   }
1517 
GetX()1518   int GetX() override { return this->Current->GetX(); }
GetInvW()1519   double GetInvW() override { return this->Current->GetInvW(); }
GetZview()1520   double GetZview() override { return this->Current->GetZview(); }
GetPValues()1521   double *GetPValues() override { return this->Current->GetPValues(); }
1522 
OnBottom(int skipped,int y)1523   void OnBottom(int skipped, int y) override
1524   {
1525       this->Current=&this->Bottom;
1526       this->Current->OnBottom(skipped,y);
1527   }
1528 
NextLine(int y)1529   void NextLine(int y) override
1530   {
1531       this->Current->NextLine(y);
1532   }
SkipLines(int deltaY,int y)1533   void SkipLines(int deltaY,
1534                  int y) override
1535   {
1536       this->Current->SkipLines(deltaY,y);
1537   }
1538 
1539 protected:
1540   vtkSimpleScreenEdge Top;
1541   vtkSimpleScreenEdge Bottom;
1542   vtkScreenEdge *Current;
1543 };
1544 
1545 //-----------------------------------------------------------------------------
1546 // Horizontal span between two points of two edges.
1547 // Used during scan-conversion.
1548 // It interpolates the values along the span.
1549 
1550 class vtkSpan
1551 {
1552 public:
1553   // Initialize the span from the left abcissa x0 and the right absissa x1 and
1554   // from 1/W, the projected values and the z coordinate in view space at
1555   // those points. Set the current state to the left point.
Init(int x0,double invW0,double pValues0[VTK_VALUES_SIZE],double zView0,int x1,double invW1,double pValues1[VTK_VALUES_SIZE],double zView1)1556   void Init(int x0,
1557             double invW0,
1558             double pValues0[VTK_VALUES_SIZE], // projected values
1559             double zView0,
1560             int x1,
1561             double invW1,
1562             double pValues1[VTK_VALUES_SIZE], // projected values
1563             double zView1)
1564   {
1565 //      assert("pre: dx>=0" && x1-x0>=0);
1566       // x0=x1: the span is just a point
1567 
1568       int i;
1569       if(x0!=x1)
1570       {
1571 
1572         double invDx10=1.0/(x1-x0);
1573         i=0;
1574         while(i<VTK_VALUES_SIZE)
1575         {
1576           this->Dpv[i]=(pValues1[i]-pValues0[i])*invDx10;
1577           ++i;
1578         }
1579         this->DinvW=(invW1-invW0)*invDx10;
1580         this->Dz=(zView1-zView0)*invDx10;
1581       }
1582       else
1583       {
1584         i=0;
1585         while(i<VTK_VALUES_SIZE)
1586         {
1587           this->Dpv[i]=0;
1588           ++i;
1589         }
1590         this->DinvW=0;
1591         this->Dz=0;
1592       }
1593 
1594       this->Zview=zView0;
1595       this->InvW=invW0;
1596       i=0;
1597       double w=1/this->InvW;
1598       while(i<VTK_VALUES_SIZE)
1599       {
1600         this->PValues[i]=pValues0[i];
1601         this->Values[i]=this->PValues[i]*w;
1602         ++i;
1603       }
1604       this->X=x0;
1605       this->X1=x1;
1606   }
1607 
1608   // Is the current state after the right point?
IsAtEnd()1609   vtkTypeBool IsAtEnd()
1610   {
1611       return this->X>this->X1;
1612   }
1613 
1614   // Current abscissa.
GetX()1615   int GetX() { return this->X; }
1616   // Current values.
GetValues()1617   double *GetValues() { return this->Values; }
1618   // Current z coordinate in view space.
GetZview()1619   double GetZview() { return this->Zview; }
1620 
1621   // Go the next abscissa from left to right.
NextPixel()1622   void NextPixel()
1623   {
1624       ++this->X;
1625 
1626        this->InvW+=this->DinvW;
1627        int i=0;
1628        double w=1/this->InvW;
1629        while(i<VTK_VALUES_SIZE)
1630        {
1631          this->PValues[i]+=this->Dpv[i];
1632          this->Values[i]=this->PValues[i]*w;
1633          ++i;
1634        }
1635        this->Zview+=this->Dz;
1636   }
1637 
1638 protected:
1639   int X1; // abscissa at the right point.
1640 
1641   int X; // current abscissa
1642 
1643   // Slope of 1/w
1644   double DinvW;
1645   // current 1/W
1646   double InvW;
1647 
1648   // Slope of the z coordinate in view space
1649   double Dz;
1650   // current z coordinate in view space
1651   double Zview;
1652 
1653   // Slope of each projected values on the span
1654   double Dpv[VTK_VALUES_SIZE];
1655   // Current projected values
1656   double PValues[VTK_VALUES_SIZE];
1657 
1658   // Current values: Values=PValues/InvW
1659   double Values[VTK_VALUES_SIZE];
1660 };
1661 
1662 
1663 // Pimpl (i.e. private implementation) idiom
1664 
1665 //typedef std::list<vtkPixelListEntry *> vtkPixelList;
1666 
1667 class vtkPixelListEntryBlock
1668 {
1669 public:
vtkPixelListEntryBlock(vtkIdType size)1670   vtkPixelListEntryBlock(vtkIdType size)
1671   {
1672       assert("pre: positive_size" && size>0);
1673       this->Size=size;
1674       this->Next=nullptr;
1675       this->Array=new vtkPixelListEntry[size];
1676       this->Last=this->Array+size-1;
1677       // link each entry to the next one
1678       vtkPixelListEntry *p;
1679       vtkPixelListEntry *q;
1680       p=this->Array;
1681       q=p+1;
1682       vtkIdType i=1;
1683       while(i<size)
1684       {
1685         p->SetNext(q);
1686         ++i;
1687         p=q;
1688         ++q;
1689       }
1690       p->SetNext(nullptr);
1691   }
~vtkPixelListEntryBlock()1692   ~vtkPixelListEntryBlock()
1693   {
1694       delete[] this->Array;
1695   }
GetSize()1696   vtkIdType GetSize() { return this->Size; }
GetNext()1697   vtkPixelListEntryBlock *GetNext() { return this->Next; }
GetFirst()1698   vtkPixelListEntry *GetFirst() { return this->Array; }
GetLast()1699   vtkPixelListEntry *GetLast() { return this->Last; }
SetNext(vtkPixelListEntryBlock * other)1700   void SetNext(vtkPixelListEntryBlock *other) { this->Next=other; }
1701 
1702 protected:
1703   vtkIdType Size;
1704   vtkPixelListEntryBlock *Next;
1705   vtkPixelListEntry *Array;
1706   vtkPixelListEntry *Last;
1707 };
1708 
1709 const vtkIdType VTK_PIXEL_BLOCK_SIZE=64;
1710 
1711 class vtkPixelListEntryMemory
1712 {
1713 public:
vtkPixelListEntryMemory()1714   vtkPixelListEntryMemory()
1715   {
1716       this->FirstBlock=new vtkPixelListEntryBlock(VTK_PIXEL_BLOCK_SIZE);
1717       this->FirstFreeElement=this->FirstBlock->GetFirst();
1718       this->Size=VTK_PIXEL_BLOCK_SIZE;
1719   }
~vtkPixelListEntryMemory()1720   ~vtkPixelListEntryMemory()
1721   {
1722       vtkPixelListEntryBlock *p=this->FirstBlock;
1723       vtkPixelListEntryBlock *q;
1724       while(p!=nullptr)
1725       {
1726         q=p->GetNext();
1727         delete p;
1728         p=q;
1729       }
1730   }
AllocateEntry()1731   vtkPixelListEntry *AllocateEntry()
1732   {
1733       if(this->FirstFreeElement==nullptr)
1734       {
1735         this->AllocateBlock(this->Size<<1);
1736 //        this->AllocateBlock(BLOCK_SIZE);
1737       }
1738       vtkPixelListEntry *result=this->FirstFreeElement;
1739       this->FirstFreeElement=result->GetNext();
1740       assert("post: result_exists" && result!=nullptr);
1741       return result;
1742   }
FreeEntry(vtkPixelListEntry * e)1743   void FreeEntry(vtkPixelListEntry *e)
1744   {
1745       assert("pre: e_exists" && e!=nullptr);
1746 
1747       // the following line works even if this->FirstFreeElement==0
1748       e->SetNext(this->FirstFreeElement);
1749       this->FirstFreeElement=e;
1750   }
FreeSubList(vtkPixelListEntry * first,vtkPixelListEntry * last)1751   void FreeSubList(vtkPixelListEntry *first,
1752                    vtkPixelListEntry *last)
1753   {
1754       assert("pre: first_exists" && first!=nullptr);
1755       assert("pre: last_exists" && last!=nullptr);
1756       // pre: first==last can be true
1757       // the following line works even if this->FirstFreeElement==0
1758       last->SetNext(this->FirstFreeElement);
1759       this->FirstFreeElement=first;
1760   }
1761 protected:
1762 
AllocateBlock(vtkIdType size)1763   void AllocateBlock(vtkIdType size)
1764   {
1765       assert("pre: positive_size" && size>0);
1766       vtkPixelListEntryBlock *b=new vtkPixelListEntryBlock(size);
1767       this->Size+=size;
1768       // Update the block linked list: starts with the new block
1769       b->SetNext(this->FirstBlock);
1770       this->FirstBlock=b;
1771 
1772       // Update the free element linked list.
1773       // It works even if this->FirstFreeElement==0
1774       b->GetLast()->SetNext(this->FirstFreeElement);
1775       this->FirstFreeElement=b->GetFirst();
1776   }
1777 
1778   vtkPixelListEntryBlock *FirstBlock;
1779   vtkPixelListEntry *FirstFreeElement;
1780   vtkIdType Size; // overall size, in number of elements, not in bytes
1781 };
1782 
1783 
1784 class vtkPixelList
1785 {
1786 public:
vtkPixelList()1787   vtkPixelList()
1788   {
1789       this->Size=0;
1790   }
GetFirst()1791   vtkPixelListEntry *GetFirst()
1792   {
1793       assert("pre: not_empty" && this->Size>0);
1794       return this->First;
1795   }
GetSize()1796   vtkIdType GetSize() { return this->Size; }
1797 
AddAndSort(vtkPixelListEntry * p)1798   void AddAndSort(vtkPixelListEntry *p)
1799   {
1800       assert("pre: p_exists" && p!=nullptr);
1801       if(this->Size==0)
1802       {
1803         p->SetPrevious(nullptr);
1804         p->SetNext(nullptr);
1805         this->First=p;
1806         this->Last=p;
1807       }
1808       else
1809       {
1810         vtkPixelListEntry *it=this->Last;
1811         int sorted=0;
1812         double z=p->GetZview();
1813         while(!sorted && it!=nullptr)
1814         {
1815           // It is not uncommon for an external face and internal face to meet.
1816           // On the edge where this happens, an exit fragment and non-exit
1817           // fragment could be generated at the same point.  In this case, it is
1818           // very important that the exit fragment be last in the list.
1819           // Otherwise, the ray exit may be improperly marked as between the two
1820           // overlapping fragments. (Note that if you start to see "speckling"
1821           // in the image from filled spaces, we may need to add adjust the
1822           // tolerance to this calculation.)
1823           const double tolerance = 1.0e-8;
1824           if (p->GetExitFace())
1825           {
1826 #ifdef BACK_TO_FRONT
1827             sorted=it->GetZview() >= z-tolerance;
1828 #else
1829             sorted=it->GetZview() <= z+tolerance;
1830 #endif
1831           }
1832           else
1833           {
1834 #ifdef BACK_TO_FRONT
1835             sorted=it->GetZview() > z+tolerance;
1836 #else
1837             sorted=it->GetZview() < z-tolerance;
1838 #endif
1839           }
1840           if(!sorted)
1841           {
1842             it=it->GetPrevious();
1843           }
1844         }
1845         if(it==nullptr) // first element
1846         {
1847           p->SetPrevious(nullptr);
1848           p->SetNext(this->First);
1849           // this->First==0 is handled by case size==0
1850           this->First->SetPrevious(p);
1851           this->First=p;
1852         }
1853         else
1854         {
1855           if(it->GetNext()==nullptr) // last element
1856           {
1857             it->SetNext(p);
1858             p->SetPrevious(it);
1859             p->SetNext(nullptr);
1860             this->Last=p;
1861           }
1862           else // general case
1863           {
1864             vtkPixelListEntry *q=it->GetNext();
1865             q->SetPrevious(p);
1866             p->SetNext(q);
1867             p->SetPrevious(it);
1868             it->SetNext(p);
1869           }
1870         }
1871       }
1872       ++this->Size;
1873   }
1874 
1875   // the return pointer is used by the memory manager.
RemoveFirst(vtkPixelListEntryMemory * mm)1876   void RemoveFirst(vtkPixelListEntryMemory *mm)
1877   {
1878       assert("pre: not_empty" && this->Size>0);
1879       assert("pre: mm_exists" && mm!=nullptr);
1880 
1881       vtkPixelListEntry *p=this->First;
1882       if(this->Size>1)
1883       {
1884         this->First=p->GetNext();
1885         this->First->SetPrevious(nullptr);
1886       }
1887       --this->Size;
1888       mm->FreeEntry(p);
1889   }
1890 
1891   // the return pointer on the first element is used by the memory manager.
Clear(vtkPixelListEntryMemory * mm)1892   void Clear(vtkPixelListEntryMemory *mm)
1893   {
1894       assert("pre: mm_exists" && mm!=nullptr);
1895       if(this->Size>0)
1896       {
1897         // it works even if first==last
1898         mm->FreeSubList(this->First,this->Last);
1899         this->Size=0;
1900       }
1901   }
1902 
1903 protected:
1904   vtkIdType Size;
1905   vtkPixelListEntry *First;
1906   vtkPixelListEntry *Last;
1907 };
1908 
1909 //-----------------------------------------------------------------------------
1910 // Store the pixel lists for all the frame.
1911 class vtkPixelListFrame
1912 {
1913 public:
1914   typedef std::vector<vtkPixelList> VectorType;
1915 
vtkPixelListFrame(int size)1916   vtkPixelListFrame(int size)
1917     :Vector(size)
1918   {
1919   }
1920 
1921   // Return width*height
GetSize()1922   vtkIdType GetSize() { return static_cast<vtkIdType>(this->Vector.size()); }
1923 
1924   // Return the size of the list at pixel `i'.
GetListSize(int i)1925   vtkIdType GetListSize(int i)
1926   {
1927       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1928       return this->Vector[i].GetSize();
1929   }
1930 
1931   // Add a value the pixel list of pixel `i' and sort it in the list.
AddAndSort(int i,vtkPixelListEntry * pixelEntry)1932   void AddAndSort(int i,
1933                   vtkPixelListEntry *pixelEntry)
1934   {
1935       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1936       assert("pre: pixelEntry_exists" &&  pixelEntry!=nullptr);
1937 
1938       this->Vector[i].AddAndSort(pixelEntry);
1939   }
1940 
1941   // Return the first entry for pixel `i'.
GetFront(int i)1942   vtkPixelListEntry *GetFront(int i)
1943   {
1944       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1945       assert("pre: not_empty" && this->GetListSize(i)>0);
1946       return this->Vector[i].GetFirst();
1947   }
1948 
1949   // Remove the first entry for pixel `i'.
PopFront(int i,vtkPixelListEntryMemory * mm)1950   void PopFront(int i,
1951                 vtkPixelListEntryMemory *mm)
1952   {
1953       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1954       assert("pre: not_empty" && this->GetListSize(i)>0);
1955       assert("pre: mm_exists" && mm!=nullptr);
1956       this->Vector[i].RemoveFirst(mm);
1957   }
1958 
1959   // Return the begin iterator for pixel `i'.
GetFirst(int i)1960   vtkPixelListEntry *GetFirst(int i)
1961   {
1962       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1963       return this->Vector[i].GetFirst();
1964   }
1965 #if 0
1966   // Return the end iterator for pixel `i'.
1967   std::list<vtkPixelListEntry *>::iterator GetEndIterator(int i)
1968   {
1969       assert("pre: valid_i" && i>=0 && i<this->GetSize());
1970       return this->Vector[i].end();
1971   }
1972 #endif
1973   // Clear the list of each pixel of the frame.
Clean(vtkPixelListEntryMemory * mm)1974   void Clean(vtkPixelListEntryMemory *mm)
1975   {
1976       assert("pre: mm_exists" && mm!=nullptr);
1977       vtkIdType i=0;
1978       vtkIdType c = static_cast<vtkIdType>(this->Vector.size());
1979       while(i<c)
1980       {
1981         vtkPixelList *l=&(Vector[i]);
1982         l->Clear(mm);
1983         ++i;
1984       }
1985   }
1986 
1987   // Destructor.
~vtkPixelListFrame()1988   ~vtkPixelListFrame()
1989   {
1990 #if 0
1991       vtkIdType i=0;
1992       vtkIdType c=this->Vector.size();
1993       while(i<c)
1994       {
1995         vtkPixelList *l=&(Vector[i]);
1996         while(!l->empty())
1997         {
1998           delete l->front();
1999           l->pop_front();
2000         }
2001         ++i;
2002       }
2003 #endif
2004   }
2005 
GetList(int i)2006   vtkPixelList *GetList(int i)
2007   {
2008       assert("pre: valid_i" && i>=0 && i<this->GetSize());
2009       return &(this->Vector[i]);
2010   }
2011 
2012 protected:
2013   VectorType Vector;
2014 
2015   // the STL specification claims that
2016   // size() on a std: :list is permitted to be O(n)!!!!
2017 //  std::vector<vtkIdType> Sizes;
2018 
2019 //  std::list<vtkPixelListEntry *>::iterator It;
2020 //  std::list<vtkPixelListEntry *>::iterator PreviousIt;
2021 //  std::list<vtkPixelListEntry *>::iterator ItEnd;
2022 };
2023 
2024 //-----------------------------------------------------------------------------
2025 // Store a triangle face. Ids are in increasing order. Orientation does not
2026 // matter for the algorithm.
2027 class vtkFace
2028 {
2029 public:
2030   enum {
2031     NOT_EXTERNAL,
2032     FRONT_FACE,
2033     BACK_FACE
2034   };
2035 
2036   // Initialization from face ids in increasing order.
vtkFace(vtkIdType faceIds[3],int externalSide)2037   vtkFace(vtkIdType faceIds[3], int externalSide)
2038   {
2039       assert("pre: ordered ids" && faceIds[0]<faceIds[1]
2040              && faceIds[1]<faceIds[2]);
2041       this->FaceIds[0]=faceIds[0];
2042       this->FaceIds[1]=faceIds[1];
2043       this->FaceIds[2]=faceIds[2];
2044       this->Count=0;
2045       this->Rendered = 0;
2046       this->ExternalSide = externalSide;
2047   }
2048 
2049   // Return the 3 face ids.
GetFaceIds()2050   inline vtkIdType *GetFaceIds() { return this->FaceIds; }
2051 
2052   // Return whether this face is external.
GetExternalSide()2053   inline int GetExternalSide() { return this->ExternalSide; }
2054 
2055   // Are `this' and faceIds equal?
IsEqual(vtkIdType faceIds[3])2056   int IsEqual(vtkIdType faceIds[3])
2057   {
2058       return (this->FaceIds[0]==faceIds[0])&&(this->FaceIds[1]==faceIds[1])
2059         &&(this->FaceIds[2]==faceIds[2]);
2060   }
2061 
Ref()2062   void Ref() { ++this->Count; }
Unref()2063   void Unref()
2064   {
2065       --this->Count;
2066       if(this->Count==0)
2067       {
2068         delete this;
2069       }
2070   }
2071 
GetRendered()2072   int GetRendered() { return this->Rendered; }
SetRendered(int value)2073   void SetRendered(int value) { this->Rendered=value; }
2074 
GetScalar(int index)2075   double GetScalar(int index)
2076   {
2077       assert("pre: valid_index" && index>=0 && index<=1);
2078       return this->Scalar[index];
2079   }
2080 
SetScalar(int index,double value)2081   void SetScalar(int index,
2082                  double value)
2083   {
2084       assert("pre: valid_index" && index>=0 && index<=1);
2085       this->Scalar[index]=value;
2086       assert("post: is_set" && this->GetScalar(index)==value);
2087   }
2088 
2089 protected:
2090   vtkIdType FaceIds[3];
2091   int Count;
2092   int Rendered;
2093   int ExternalSide;
2094 
2095   double Scalar[2]; // 0: value for positive orientation,
2096   // 1: value for negative orientation.
2097 
2098 private:
2099   vtkFace() = delete;
2100   vtkFace(const vtkFace &other) = delete;
2101   vtkFace &operator=(const vtkFace &other) = delete;
2102 };
2103 
2104 //-----------------------------------------------------------------------------
2105 // For each vertex, store the list of faces incident on this vertex.
2106 // It is view independent.
2107 class vtkUseSet
2108 {
2109 public:
2110   typedef std::vector<std::list<vtkFace *> *> VectorType;
2111   VectorType Vector;
2112 
2113   std::list<vtkFace *> AllFaces; // to set up rendering to false.
2114 
2115   // Initialize with the number of vertices.
vtkUseSet(int size)2116   vtkUseSet(int size)
2117     :Vector(size)
2118   {
2119       vtkIdType i=0;
2120       vtkIdType c = static_cast<vtkIdType>(this->Vector.size());
2121       while(i<c)
2122       {
2123         this->Vector[i]=nullptr;
2124         ++i;
2125       }
2126       this->CellScalars=0;
2127       this->NumberOfComponents=0;
2128   }
2129 
2130   // Destructor.
~vtkUseSet()2131   ~vtkUseSet()
2132   {
2133       vtkIdType i=0;
2134       vtkIdType c = static_cast<vtkIdType>(this->Vector.size());
2135       while(i<c)
2136       {
2137         if(this->Vector[i]!=nullptr)
2138         {
2139           while(!this->Vector[i]->empty())
2140           {
2141             (*this->Vector[i]->begin())->Unref();
2142             this->Vector[i]->pop_front();
2143           }
2144           delete this->Vector[i];
2145         }
2146         ++i;
2147       }
2148       while(!this->AllFaces.empty())
2149       {
2150         (*this->AllFaces.begin())->Unref();
2151         this->AllFaces.pop_front();
2152       }
2153   }
2154 
SetCellScalars(int cellScalars)2155   void SetCellScalars(int cellScalars)
2156   {
2157       this->CellScalars=cellScalars;
2158   }
SetNumberOfComponents(int numberOfComponents)2159   void SetNumberOfComponents(int numberOfComponents)
2160   {
2161       assert("pre: cell_mode" && this->CellScalars);
2162       this->NumberOfComponents=numberOfComponents;
2163   }
2164 
2165   // For each vertex, clear the list of faces incident to it.
2166   // also set number of cells per vertex to 0.
Clear()2167   void Clear()
2168   {
2169       vtkIdType i=0;
2170       vtkIdType c = static_cast<vtkIdType>(this->Vector.size());
2171       while(i<c)
2172       {
2173         if(this->Vector[i]!=nullptr)
2174         {
2175           while(!this->Vector[i]->empty())
2176           {
2177             (*this->Vector[i]->begin())->Unref();
2178             this->Vector[i]->pop_front();
2179           }
2180           delete this->Vector[i];
2181           this->Vector[i]=nullptr;
2182         }
2183         ++i;
2184       }
2185       while(!this->AllFaces.empty())
2186       {
2187         (*this->AllFaces.begin())->Unref();
2188         this->AllFaces.pop_front();
2189       }
2190   }
2191 
2192   // Add face to each vertex only if the useset does not have the face yet.
AddFace(vtkIdType faceIds[3],vtkDataArray * scalars,vtkIdType cellIdx,int orientationChanged,bool external)2193   void AddFace(vtkIdType faceIds[3],
2194                vtkDataArray *scalars,
2195                vtkIdType cellIdx,
2196                int orientationChanged,
2197                bool external)
2198   {
2199       // Ignore degenerate faces.
2200       if ((faceIds[0] == faceIds[1]) || (faceIds[1] == faceIds[2])) return;
2201 
2202       assert("pre: ordered ids" && faceIds[0]<faceIds[1]
2203              && faceIds[1]<faceIds[2]);
2204 
2205       vtkFace *f=this->GetFace(faceIds);
2206       if(f==nullptr)
2207       {
2208         int externalSide;
2209         if (external)
2210         {
2211           if (orientationChanged)
2212           {
2213             externalSide = vtkFace::BACK_FACE;
2214           }
2215           else
2216           {
2217             externalSide = vtkFace::FRONT_FACE;
2218           }
2219         }
2220         else
2221         {
2222           externalSide = vtkFace::NOT_EXTERNAL;
2223         }
2224         f=new vtkFace(faceIds, externalSide);
2225         this->AllFaces.push_back(f);
2226         f->Ref();
2227         // All the vertices of this face need to be fed
2228         int i=0;
2229         while(i<3)
2230         {
2231           std::list<vtkFace *> *p=this->Vector[faceIds[i]];
2232           if(p==nullptr)
2233           {
2234             p=new std::list<vtkFace *>;
2235             this->Vector[faceIds[i]]=p;
2236           }
2237           p->push_back(f);
2238           f->Ref();
2239           ++i;
2240         }
2241         if(this->CellScalars)
2242         {
2243           int c=this->NumberOfComponents;
2244           int scalarNumber;
2245           if(orientationChanged)
2246           {
2247             scalarNumber=1;
2248           }
2249           else
2250           {
2251             scalarNumber=0;
2252           }
2253           if(c==1)
2254           {
2255             f->SetScalar(scalarNumber,scalars->GetComponent(cellIdx,0));
2256           }
2257           else
2258           {
2259             double tmp=0;
2260             double tmp2;
2261             i=0;
2262             while(i<c)
2263             {
2264               tmp2=scalars->GetComponent(cellIdx,i);
2265               tmp+=tmp2*tmp2;
2266               ++i;
2267             }
2268             f->SetScalar(scalarNumber,sqrt(tmp));
2269           }
2270         }
2271       }
2272       else
2273       {
2274         if(this->CellScalars)
2275         {
2276           int scalarNumber;
2277           if(orientationChanged)
2278           {
2279             scalarNumber=1;
2280           }
2281           else
2282           {
2283             scalarNumber=0;
2284           }
2285           int c=this->NumberOfComponents;
2286           if(c==1)
2287           {
2288             f->SetScalar(scalarNumber,scalars->GetComponent(cellIdx,0));
2289           }
2290           else
2291           {
2292             double tmp=0;
2293             double tmp2;
2294             int i=0;
2295             while(i<c)
2296             {
2297               tmp2=scalars->GetComponent(cellIdx,i);
2298               tmp+=tmp2*tmp2;
2299               ++i;
2300             }
2301             f->SetScalar(scalarNumber,sqrt(tmp));
2302           }
2303         }
2304       }
2305   }
2306 
2307 
SetNotRendered()2308   void SetNotRendered()
2309   {
2310       std::list<vtkFace *>::iterator it;
2311       std::list<vtkFace *>::iterator end;
2312       it=this->AllFaces.begin();
2313       end=this->AllFaces.end();
2314       while(it!=end)
2315       {
2316         (*it)->SetRendered(0);
2317         ++it;
2318       }
2319   }
2320 
2321 protected:
2322   // Return pointer to face faceIds if the use set of vertex faceIds[0] have
2323   // this face, otherwise return null.
GetFace(vtkIdType faceIds[3])2324   vtkFace *GetFace(vtkIdType faceIds[3])
2325   {
2326       std::list<vtkFace *> *useSet=this->Vector[faceIds[0]];
2327       vtkFace *result=nullptr;
2328 
2329       if(useSet!=nullptr)
2330       {
2331         this->It=(*useSet).begin();
2332         this->ItEnd=(*useSet).end();
2333         int found=0;
2334         while(!found && this->It!=this->ItEnd)
2335         {
2336           result=*this->It;
2337           found=result->IsEqual(faceIds);
2338           ++this->It;
2339         }
2340         if(!found)
2341         {
2342           result=nullptr;
2343         }
2344       }
2345       return result;
2346   }
2347 
2348   int CellScalars;
2349   int NumberOfComponents;
2350 
2351 
2352   // Used in GetFace()
2353   std::list<vtkFace *>::iterator It;
2354   std::list<vtkFace *>::iterator ItEnd;
2355 };
2356 
2357 // For each vertex, store its projection. It is view-dependent.
2358 class vtkVertices
2359 {
2360 public:
2361   typedef std::vector<vtkVertexEntry> VectorType;
2362   VectorType Vector;
2363 
2364   // Initialize with the number of vertices.
vtkVertices(int size)2365   vtkVertices(int size)
2366     :Vector(size)
2367   {
2368   }
2369 };
2370 
2371 };
2372 
2373 using namespace vtkUnstructuredGridVolumeZSweepMapperNamespace;
2374 
2375 //-----------------------------------------------------------------------------
2376 // Implementation of the public class.
2377 
2378 vtkStandardNewMacro(vtkUnstructuredGridVolumeZSweepMapper);
2379 
2380 vtkCxxSetObjectMacro(vtkUnstructuredGridVolumeZSweepMapper, RayIntegrator,
2381                      vtkUnstructuredGridVolumeRayIntegrator);
2382 
2383 
2384 //-----------------------------------------------------------------------------
2385 // Description:
2386 // Set MaxPixelListSize to 32.
vtkUnstructuredGridVolumeZSweepMapper()2387 vtkUnstructuredGridVolumeZSweepMapper::vtkUnstructuredGridVolumeZSweepMapper()
2388 {
2389   this->MaxPixelListSize=64; // default value.
2390 
2391   this->ImageSampleDistance        =  1.0;
2392   this->MinimumImageSampleDistance =  1.0;
2393   this->MaximumImageSampleDistance = 10.0;
2394   this->AutoAdjustSampleDistances  =  1;
2395 
2396   this->ImageMemorySize[0]     = 0;
2397   this->ImageMemorySize[1]     = 0;
2398 
2399   this->Image                  = nullptr;
2400   this->RealRGBAImage=nullptr;
2401 
2402   this->RenderTimeTable        = nullptr;
2403   this->RenderVolumeTable      = nullptr;
2404   this->RenderRendererTable    = nullptr;
2405   this->RenderTableSize        = 0;
2406   this->RenderTableEntries     = 0;
2407 
2408   this->ZBuffer                = nullptr;
2409   this->ZBufferSize[0]         = 0;
2410   this->ZBufferSize[1]         = 0;
2411   this->ZBufferOrigin[0]       = 0;
2412   this->ZBufferOrigin[1]       = 0;
2413 
2414   this->IntermixIntersectingGeometry = 1;
2415 
2416   this->ImageDisplayHelper     = vtkRayCastImageDisplayHelper::New();
2417 
2418   this->PixelListFrame=nullptr;
2419 
2420   this->Cell=vtkGenericCell::New();
2421 
2422   this->EventList=vtkPriorityQueue::New();
2423 
2424   this->UseSet=nullptr;
2425   this->Vertices=nullptr;
2426 
2427   this->PerspectiveTransform = vtkTransform::New();
2428   this->PerspectiveMatrix = vtkMatrix4x4::New();
2429 
2430   this->SimpleEdge=new vtkSimpleScreenEdge;
2431   this->DoubleEdge=new vtkDoubleScreenEdge;
2432 
2433   this->Span=new vtkSpan;
2434 
2435   this->RayIntegrator = nullptr;
2436   this->RealRayIntegrator = nullptr;
2437 
2438   this->IntersectionLengths=vtkDoubleArray::New();
2439   this->IntersectionLengths->SetNumberOfValues(1);
2440   this->NearIntersections=vtkDoubleArray::New();
2441   this->NearIntersections->SetNumberOfValues(1);
2442   this->FarIntersections=vtkDoubleArray::New();
2443   this->FarIntersections->SetNumberOfValues(1);
2444 
2445   this->MemoryManager=nullptr;
2446 }
2447 
2448 //-----------------------------------------------------------------------------
~vtkUnstructuredGridVolumeZSweepMapper()2449 vtkUnstructuredGridVolumeZSweepMapper::~vtkUnstructuredGridVolumeZSweepMapper()
2450 {
2451   delete this->MemoryManager;
2452   delete this->PixelListFrame;
2453   this->Cell->Delete();
2454   this->EventList->Delete();
2455 
2456   this->ImageDisplayHelper->Delete();
2457 
2458   delete this->UseSet;
2459   delete this->Vertices;
2460 
2461   this->PerspectiveTransform->Delete();
2462   this->PerspectiveMatrix->Delete();
2463 
2464   delete this->SimpleEdge;
2465   delete this->DoubleEdge;
2466   delete this->Span;
2467 
2468   if ( this->Image )
2469   {
2470     delete [] this->Image;
2471     delete [] this->RealRGBAImage;
2472   }
2473 
2474   if ( this->RenderTableSize )
2475   {
2476     delete [] this->RenderTimeTable;
2477     delete [] this->RenderVolumeTable;
2478     delete [] this->RenderRendererTable;
2479   }
2480 
2481   this->SetRayIntegrator(nullptr);
2482   if (this->RealRayIntegrator)
2483   {
2484     this->RealRayIntegrator->UnRegister(this);
2485   }
2486 
2487   this->IntersectionLengths->Delete();
2488   this->NearIntersections->Delete();
2489   this->FarIntersections->Delete();
2490 }
2491 
2492 //-----------------------------------------------------------------------------
RetrieveRenderTime(vtkRenderer * ren,vtkVolume * vol)2493 float vtkUnstructuredGridVolumeZSweepMapper::RetrieveRenderTime(
2494   vtkRenderer *ren,
2495   vtkVolume   *vol )
2496 {
2497   int i;
2498 
2499   for ( i = 0; i < this->RenderTableEntries; i++ )
2500   {
2501     if ( this->RenderVolumeTable[i] == vol &&
2502          this->RenderRendererTable[i] == ren )
2503     {
2504       return this->RenderTimeTable[i];
2505     }
2506   }
2507 
2508   return 0.0;
2509 }
2510 
2511 //-----------------------------------------------------------------------------
StoreRenderTime(vtkRenderer * ren,vtkVolume * vol,float time)2512 void vtkUnstructuredGridVolumeZSweepMapper::StoreRenderTime(
2513   vtkRenderer *ren,
2514   vtkVolume   *vol,
2515   float       time )
2516 {
2517   int i;
2518   for ( i = 0; i < this->RenderTableEntries; i++ )
2519   {
2520     if ( this->RenderVolumeTable[i] == vol &&
2521          this->RenderRendererTable[i] == ren )
2522     {
2523       this->RenderTimeTable[i] = time;
2524       return;
2525     }
2526   }
2527 
2528 
2529   // Need to increase size
2530   if ( this->RenderTableEntries >= this->RenderTableSize )
2531   {
2532     if ( this->RenderTableSize == 0 )
2533     {
2534       this->RenderTableSize = 10;
2535     }
2536     else
2537     {
2538       this->RenderTableSize *= 2;
2539     }
2540 
2541     float       *oldTimePtr     = this->RenderTimeTable;
2542     vtkVolume   **oldVolumePtr   = this->RenderVolumeTable;
2543     vtkRenderer **oldRendererPtr = this->RenderRendererTable;
2544 
2545     this->RenderTimeTable     = new float [this->RenderTableSize];
2546     this->RenderVolumeTable   = new vtkVolume *[this->RenderTableSize];
2547     this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize];
2548 
2549     for (i = 0; i < this->RenderTableEntries; i++ )
2550     {
2551       this->RenderTimeTable[i] = oldTimePtr[i];
2552       this->RenderVolumeTable[i] = oldVolumePtr[i];
2553       this->RenderRendererTable[i] = oldRendererPtr[i];
2554     }
2555 
2556     delete [] oldTimePtr;
2557     delete [] oldVolumePtr;
2558     delete [] oldRendererPtr;
2559   }
2560 
2561   this->RenderTimeTable[this->RenderTableEntries] = time;
2562   this->RenderVolumeTable[this->RenderTableEntries] = vol;
2563   this->RenderRendererTable[this->RenderTableEntries] = ren;
2564 
2565   this->RenderTableEntries++;
2566 }
2567 
2568 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)2569 void vtkUnstructuredGridVolumeZSweepMapper::PrintSelf(ostream& os,
2570                                                       vtkIndent indent)
2571 {
2572   this->Superclass::PrintSelf(os,indent);
2573 
2574   os << indent << "Max Pixel List Size: " << this->MaxPixelListSize << "\n";
2575 
2576   os << indent << "Image Sample Distance: "
2577      << this->ImageSampleDistance << "\n";
2578   os << indent << "Minimum Image Sample Distance: "
2579      << this->MinimumImageSampleDistance << "\n";
2580   os << indent << "Maximum Image Sample Distance: "
2581      << this->MaximumImageSampleDistance << "\n";
2582   os << indent << "Auto Adjust Sample Distances: "
2583      << this->AutoAdjustSampleDistances << "\n";
2584   os << indent << "Intermix Intersecting Geometry: "
2585     << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n");
2586 
2587   // The PrintSelf test just search for words in the PrintSelf function
2588   // We add here the internal variable we don't want to display:
2589   // this->ImageViewportSize this->ImageOrigin this->ImageInUseSize
2590 
2591   if (this->RayIntegrator)
2592   {
2593     os << indent << "RayIntegrator: "
2594        << this->RayIntegrator->GetClassName() << endl;
2595   }
2596   else
2597   {
2598     os << indent << "RayIntegrator: (automatic)" << endl;
2599   }
2600 }
2601 
2602 //-----------------------------------------------------------------------------
2603 // Description:
2604 // Maximum size allowed for a pixel list. Default is 32.
2605 // During the rendering, if a list of pixel is full, incremental compositing
2606 // is performed. Even if it is a user setting, it is an advanced parameter.
2607 // You have to understand how the algorithm works to change this value.
GetMaxPixelListSize()2608 int vtkUnstructuredGridVolumeZSweepMapper::GetMaxPixelListSize()
2609 {
2610   return this->MaxPixelListSize;
2611 }
2612 
2613 //-----------------------------------------------------------------------------
2614 // Description:
2615 // Change the maximum size allowed for a pixel list. It is an advanced
2616 // parameter.
SetMaxPixelListSize(int size)2617 void vtkUnstructuredGridVolumeZSweepMapper::SetMaxPixelListSize(int size)
2618 {
2619   assert("pre: positive_size" && size>1);
2620   this->MaxPixelListSize=size;
2621 }
2622 
2623 //-----------------------------------------------------------------------------
2624 #define ESTABLISH_INTEGRATOR(classname)                                 \
2625   if (   !this->RealRayIntegrator                                       \
2626          || (!this->RealRayIntegrator->IsA(#classname)) )               \
2627   {                                                                   \
2628     if (this->RealRayIntegrator) this->RealRayIntegrator->UnRegister(this); \
2629     this->RealRayIntegrator = classname::New();                         \
2630     this->RealRayIntegrator->Register(this);                            \
2631     this->RealRayIntegrator->Delete();                                  \
2632   }                                                                   \
2633 
2634 //-----------------------------------------------------------------------------
2635 // Description:
2636 // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
2637 // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS
2638 // Render the volume
Render(vtkRenderer * ren,vtkVolume * vol)2639 void vtkUnstructuredGridVolumeZSweepMapper::Render(vtkRenderer *ren,
2640                                                    vtkVolume *vol)
2641 {
2642   vtkDebugMacro(<<"Render");
2643 
2644   // Check for input
2645   if(this->GetInput()==nullptr)
2646   {
2647     vtkErrorMacro(<< "No Input!");
2648     return;
2649   }
2650 
2651   int inputAlgPort;
2652   vtkAlgorithm* inputAlg = this->GetInputAlgorithm(0, 0, inputAlgPort);
2653   inputAlg->UpdateWholeExtent();
2654 
2655   this->Scalars = this->GetScalars(this->GetInput(), this->ScalarMode,
2656                                    this->ArrayAccessMode,
2657                                    this->ArrayId, this->ArrayName,
2658                                    this->CellScalars);
2659 
2660   if(this->Scalars==nullptr)
2661   {
2662     vtkErrorMacro("Can't use the ZSweep mapper without scalars!");
2663     return;
2664   }
2665 
2666    // Check to make sure we have an appropriate integrator.
2667   if (this->RayIntegrator)
2668   {
2669     if (this->RealRayIntegrator != this->RayIntegrator)
2670     {
2671       if (this->RealRayIntegrator)
2672       {
2673         this->RealRayIntegrator->UnRegister(this);
2674       }
2675       this->RealRayIntegrator = this->RayIntegrator;
2676       this->RealRayIntegrator->Register(this);
2677     }
2678   }
2679   else
2680   {
2681     if (this->CellScalars)
2682     {
2683       ESTABLISH_INTEGRATOR(vtkUnstructuredGridHomogeneousRayIntegrator);
2684     }
2685     else
2686     {
2687       if (vol->GetProperty()->GetIndependentComponents())
2688       {
2689         ESTABLISH_INTEGRATOR(vtkUnstructuredGridPreIntegration);
2690       }
2691       else
2692       {
2693         ESTABLISH_INTEGRATOR(vtkUnstructuredGridPartialPreIntegration);
2694       }
2695     }
2696   }
2697   // Start timing now. We didn't want to capture the update of the
2698   // input data in the times
2699   this->Timer->StartTimer();
2700 
2701   int oldImageMemorySize[2];
2702   oldImageMemorySize[0] = this->ImageMemorySize[0];
2703   oldImageMemorySize[1] = this->ImageMemorySize[1];
2704 
2705   // If we are automatically adjusting the size to achieve a desired frame
2706   // rate, then do that adjustment here. Base the new image sample distance
2707   // on the previous one and the previous render time. Don't let
2708   // the adjusted image sample distance be less than the minimum image sample
2709   // distance or more than the maximum image sample distance.
2710   float oldImageSampleDistance = this->ImageSampleDistance;
2711   if ( this->AutoAdjustSampleDistances )
2712   {
2713     float oldTime = this->RetrieveRenderTime( ren, vol );
2714     float newTime = vol->GetAllocatedRenderTime();
2715     this->ImageSampleDistance *= sqrt(oldTime / newTime);
2716     this->ImageSampleDistance =
2717       (this->ImageSampleDistance>this->MaximumImageSampleDistance)?
2718       (this->MaximumImageSampleDistance):(this->ImageSampleDistance);
2719     this->ImageSampleDistance =
2720       (this->ImageSampleDistance<this->MinimumImageSampleDistance)?
2721       (this->MinimumImageSampleDistance):(this->ImageSampleDistance);
2722   }
2723 
2724   // The full image fills the viewport. First, compute the actual viewport
2725   // size, then divide by the ImageSampleDistance to find the full image
2726   // size in pixels
2727   int width, height;
2728   ren->GetTiledSize(&width, &height);
2729   this->ImageViewportSize[0] =
2730     static_cast<int>(width/this->ImageSampleDistance);
2731   this->ImageViewportSize[1] =
2732     static_cast<int>(height/this->ImageSampleDistance);
2733 
2734   this->ImageInUseSize[0] = this->ImageViewportSize[0];
2735   this->ImageInUseSize[1] = this->ImageViewportSize[1];
2736   this->ImageOrigin[0] = 0;
2737   this->ImageOrigin[1] = 0;
2738 
2739   // What is a power of 2 size big enough to fit this image?
2740   this->ImageMemorySize[0] = 32;
2741   this->ImageMemorySize[1] = 32;
2742   while ( this->ImageMemorySize[0] < this->ImageInUseSize[0] )
2743   {
2744     this->ImageMemorySize[0] *= 2;
2745   }
2746   while ( this->ImageMemorySize[1] < this->ImageInUseSize[1] )
2747   {
2748     this->ImageMemorySize[1] *= 2;
2749   }
2750 
2751   // If the old image size is much too big (more than twice in
2752   // either direction) then set the old width to 0 which will
2753   // cause the image to be recreated
2754   if ( oldImageMemorySize[0] > 2*this->ImageMemorySize[0] ||
2755        oldImageMemorySize[1] > 2*this->ImageMemorySize[1] )
2756   {
2757     oldImageMemorySize[0] = 0;
2758   }
2759 
2760   // If the old image is big enough (but not too big - we handled
2761   // that above) then we'll bump up our required size to the
2762   // previous one. This will keep us from thrashing.
2763   if ( oldImageMemorySize[0] >= this->ImageMemorySize[0] &&
2764        oldImageMemorySize[1] >= this->ImageMemorySize[1] )
2765   {
2766     this->ImageMemorySize[0] = oldImageMemorySize[0];
2767     this->ImageMemorySize[1] = oldImageMemorySize[1];
2768   }
2769 
2770   int bufferSize=this->ImageMemorySize[0] * this->ImageMemorySize[1] * 4;
2771 
2772   // Do we already have a texture big enough? If not, create a new one and
2773   // clear it.
2774   if ( !this->Image ||
2775        this->ImageMemorySize[0] > oldImageMemorySize[0] ||
2776        this->ImageMemorySize[1] > oldImageMemorySize[1] )
2777   {
2778     // If there is an image there must be row bounds
2779     if ( this->Image )
2780     {
2781       delete [] this->Image;
2782       delete [] this->RealRGBAImage;
2783     }
2784     this->Image = new unsigned char[bufferSize];
2785     this->RealRGBAImage=new float[bufferSize];
2786   }
2787 
2788   // We have to clear the image, each time:
2789   memset(this->Image,0,bufferSize);
2790 
2791   vtkIdType j=0;
2792   while(j<bufferSize)
2793   {
2794     this->RealRGBAImage[j]=0;
2795     this->RealRGBAImage[j+1]=0;
2796     this->RealRGBAImage[j+2]=0;
2797     this->RealRGBAImage[j+3]=0;
2798     j+=4;
2799   }
2800 
2801   // Capture the zbuffer if necessary
2802   if ( this->IntermixIntersectingGeometry &&
2803        ren->GetNumberOfPropsRendered() )
2804   {
2805     int x1, x2, y1, y2;
2806     double *viewport   =  ren->GetViewport();
2807     int *renWinSize   =  ren->GetRenderWindow()->GetSize();
2808 
2809     // turn this->ImageOrigin into (x1,y1) in window (not viewport!)
2810     // coordinates.
2811     x1 = static_cast<int> (
2812       viewport[0] * static_cast<float>(renWinSize[0]) +
2813       static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance );
2814     y1 = static_cast<int> (
2815       viewport[1] * static_cast<float>(renWinSize[1]) +
2816       static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance);
2817 
2818     // compute z buffer size
2819     this->ZBufferSize[0] = static_cast<int>(
2820       static_cast<float>(this->ImageInUseSize[0]) * this->ImageSampleDistance);
2821     this->ZBufferSize[1] = static_cast<int>(
2822       static_cast<float>(this->ImageInUseSize[1]) * this->ImageSampleDistance);
2823 
2824     // Use the size to compute (x2,y2) in window coordinates
2825     x2 = x1 + this->ZBufferSize[0] - 1;
2826     y2 = y1 + this->ZBufferSize[1] - 1;
2827 
2828     // This is the z buffer origin (in viewport coordinates)
2829     this->ZBufferOrigin[0] = static_cast<int>(
2830       static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance);
2831     this->ZBufferOrigin[1] = static_cast<int>(
2832       static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance);
2833 
2834     // Capture the z buffer
2835     this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(x1,y1,x2,y2);
2836   }
2837 
2838   this->RealRayIntegrator->Initialize(vol, this->Scalars);
2839 
2840   // Here is the Zsweep algorithm:
2841 
2842   // 1. For each vertex, find the list of incident faces (the "use set") (3.1)
2843   // In the original paper, it deals with incident cells but the chapter about
2844   // the parallel version in the dissertation deals with faces, which makes
2845   // more sense. Hence, there is no need for the sparsification step (3.5.1)
2846   // It is view-independent, so it can be reused for the next call to Render()
2847   // if the dataset did not change.
2848   vtkDebugMacro(<<"BuildUseSets: start");
2849   this->BuildUseSets();
2850   vtkDebugMacro(<<"BuildUseSets: done");
2851 
2852   // 2. Sort the vertices by z-coordinates (view-dependent) in view space.
2853   // For each vertex, compute its camera coordinates and sort it
2854   // by z in an heap. The heap is called the "event list".
2855   // The heap stores the Id of the vertices.
2856   // It is view-dependent.
2857   vtkDebugMacro(<<"ProjectAndSortVertices: start");
2858   this->ProjectAndSortVertices(ren,vol);
2859   vtkDebugMacro(<<"ProjectAndSortVertices: done");
2860 
2861   // 3. Create an empty "pixel list" (two way linked list) for each pixel of
2862   //    the screen.
2863   vtkDebugMacro(<<"CreateAndCleanPixelList: start");
2864   this->CreateAndCleanPixelList();
2865   vtkDebugMacro(<<"CreateAndCleanPixelList: done");
2866 
2867   // 4. Main loop
2868   // (section 2 paragraph 11)
2869   vtkDebugMacro(<<"MainLoop: start");
2870   this->MainLoop(ren->GetRenderWindow());
2871   vtkDebugMacro(<<"MainLoop: done");
2872 
2873   // The algorithm is done: send to result to the final image.
2874   if ( !ren->GetRenderWindow()->GetAbortRender() )
2875   {
2876     float depth;
2877     if ( this->IntermixIntersectingGeometry )
2878     {
2879       depth = this->GetMinimumBoundsDepth( ren, vol );
2880     }
2881     else
2882     {
2883       depth = -1;
2884     }
2885 
2886     // copy the double image into the unsigned char image:
2887 
2888     j=0;
2889     while(j<bufferSize)
2890     {
2891       float alpha=this->RealRGBAImage[j+3];
2892       if(alpha!=0)
2893       {
2894         this->Image[j+0]=this->ColorComponentRealToByte(this->RealRGBAImage[j+0]);
2895         this->Image[j+1]=this->ColorComponentRealToByte(this->RealRGBAImage[j+1]);
2896         this->Image[j+2]=this->ColorComponentRealToByte(this->RealRGBAImage[j+2]);
2897         this->Image[j+3]=this->ColorComponentRealToByte(alpha);
2898       }
2899       else
2900       {
2901         this->Image[j+0]=0;
2902         this->Image[j+1]=0;
2903         this->Image[j+2]=0;
2904         this->Image[j+3]=0;
2905       }
2906       j+=4;
2907     }
2908     this->ImageDisplayHelper->
2909       RenderTexture( vol, ren,
2910                      this->ImageMemorySize,
2911                      this->ImageViewportSize,
2912                      this->ImageInUseSize,
2913                      this->ImageOrigin,
2914                      depth,
2915                      this->Image );
2916 
2917     this->Timer->StopTimer();
2918     this->TimeToDraw = this->Timer->GetElapsedTime();
2919     this->StoreRenderTime( ren, vol, this->TimeToDraw );
2920   }
2921   else
2922   {
2923     this->ImageSampleDistance = oldImageSampleDistance;
2924   }
2925 
2926   delete [] this->ZBuffer;
2927   this->ZBuffer = nullptr;
2928 
2929   this->UpdateProgress(1.0);
2930 }
2931 
2932 //-----------------------------------------------------------------------------
AllocateUseSet(vtkIdType size)2933 void vtkUnstructuredGridVolumeZSweepMapper::AllocateUseSet(vtkIdType size)
2934 {
2935   if(this->UseSet!=nullptr)
2936   {
2937     if(size>static_cast<vtkIdType>(this->UseSet->Vector.size()))
2938     {
2939       delete this->UseSet;
2940       this->UseSet=new vtkUseSet(size);
2941     }
2942     else
2943     {
2944       this->UseSet->Clear();
2945     }
2946   }
2947   else
2948   {
2949     this->UseSet=new vtkUseSet(size);
2950   }
2951 }
2952 
2953 //-----------------------------------------------------------------------------
AllocateVertices(vtkIdType size)2954 void vtkUnstructuredGridVolumeZSweepMapper::AllocateVertices(vtkIdType size)
2955 {
2956   if(this->Vertices!=nullptr)
2957   {
2958     if(size>static_cast<vtkIdType>(this->Vertices->Vector.size()))
2959     {
2960       delete this->Vertices;
2961       this->Vertices=new vtkVertices(size);
2962     }
2963   }
2964   else
2965   {
2966     this->Vertices=new vtkVertices(size);
2967   }
2968 }
2969 
2970 //-----------------------------------------------------------------------------
BuildUseSets()2971 void vtkUnstructuredGridVolumeZSweepMapper::BuildUseSets()
2972 {
2973   int needsUpdate = 0;
2974 
2975   // If we have never created the list, we need updating
2976   if (this->UseSet==nullptr )
2977   {
2978     needsUpdate = 1;
2979   }
2980 
2981   // If the data has changed in some way then we need to update
2982   vtkUnstructuredGridBase *input = this->GetInput();
2983   if ( input->GetMTime() > this->SavedTriangleListMTime.GetMTime() )
2984   {
2985     needsUpdate = 1;
2986   }
2987 
2988   if(this->CellScalars &&
2989      this->GetMTime() > this->SavedTriangleListMTime.GetMTime())
2990   {
2991     needsUpdate=1;
2992   }
2993 
2994   // If we don't need updating, return
2995   if ( !needsUpdate )
2996   {
2997     return;
2998   }
2999 
3000   vtkIdType numberOfPoints=input->GetNumberOfPoints();
3001 
3002   vtkIdList *cellNeighbors = vtkIdList::New();
3003 
3004   // init the use set of each vertex
3005   this->AllocateUseSet(numberOfPoints);
3006 
3007   this->UseSet->SetCellScalars(this->CellScalars);
3008   if(this->CellScalars)
3009   {
3010     this->UseSet->SetNumberOfComponents(
3011       this->Scalars->GetNumberOfComponents());
3012   }
3013   // for each cell
3014   vtkSmartPointer<vtkCellIterator> cellIter =
3015       vtkSmartPointer<vtkCellIterator>::Take(input->NewCellIterator());
3016   for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
3017        cellIter->GoToNextCell())
3018   {
3019     cellIter->GetCell(this->Cell);
3020     vtkIdType faces = this->Cell->GetNumberOfFaces();
3021     if (faces > 0)
3022     {
3023       vtkIdType faceidx=0;
3024       vtkCell *face;
3025       vtkIdType faceIds[3];
3026       vtkIdType orderedFaceIds[3];
3027       // for each face
3028       while(faceidx<faces)
3029       {
3030         face=this->Cell->GetFace(faceidx);
3031         faceIds[0]=face->GetPointId(0);
3032         faceIds[1]=face->GetPointId(1);
3033         faceIds[2]=face->GetPointId(2);
3034         int orientationChanged=this->ReorderTriangle(faceIds,orderedFaceIds);
3035         input->GetCellNeighbors(cellIter->GetCellId(), face->GetPointIds(),
3036                                 cellNeighbors);
3037         bool external = (cellNeighbors->GetNumberOfIds() == 0);
3038 
3039         // Add face only if it is not already in the useset.
3040         this->UseSet->AddFace(orderedFaceIds, this->Scalars,
3041                               cellIter->GetCellId(), orientationChanged,
3042                               external);
3043 
3044         ++faceidx;
3045       }
3046     }
3047   }
3048   cellNeighbors->Delete();
3049   this->SavedTriangleListMTime.Modified();
3050 }
3051 
3052 //-----------------------------------------------------------------------------
3053 // Description:
3054 // Reorder vertices `v' in increasing order in `w'. Return if the orientation
3055 // has changed.
ReorderTriangle(vtkIdType v[3],vtkIdType w[3])3056 int vtkUnstructuredGridVolumeZSweepMapper::ReorderTriangle(vtkIdType v[3],
3057                                                            vtkIdType w[3])
3058 {
3059   if(v[0]>v[1])
3060   {
3061     if(v[1]>v[2])
3062     {
3063       // v[2] is the min
3064       w[0]=v[2];
3065       w[1]=v[0];
3066       w[2]=v[1];
3067     }
3068     else
3069     {
3070       // v[1] is the min
3071       w[0]=v[1];
3072       w[1]=v[2];
3073       w[2]=v[0];
3074     }
3075   }
3076   else
3077   {
3078     if(v[0]>v[2])
3079     {
3080       // v[2] is the min
3081       w[0]=v[2];
3082       w[1]=v[0];
3083       w[2]=v[1];
3084     }
3085     else
3086     {
3087       // v[0] is the min
3088       w[0]=v[0];
3089       w[1]=v[1];
3090       w[2]=v[2];
3091     }
3092   }
3093   // At this point the triangle start with the min id and the
3094   // order did not change
3095   // Now, ensure that the two last id are in increasing order
3096   int result=w[1]>w[2];
3097   if(result)
3098   {
3099     vtkIdType tmp=w[1];
3100     w[1]=w[2];
3101     w[2]=tmp;
3102   }
3103   return result;
3104 }
3105 
3106 //-----------------------------------------------------------------------------
ProjectAndSortVertices(vtkRenderer * ren,vtkVolume * vol)3107 void vtkUnstructuredGridVolumeZSweepMapper::ProjectAndSortVertices(
3108   vtkRenderer *ren,
3109   vtkVolume *vol)
3110 {
3111   assert("pre: empty list" && this->EventList->GetNumberOfItems()==0);
3112 
3113   vtkUnstructuredGridBase *input = this->GetInput();
3114   vtkIdType numberOfPoints=input->GetNumberOfPoints();
3115 
3116   vtkIdType pointId=0;
3117   vtkVertexEntry *vertex=nullptr;
3118   // Pre-computation for the projection.
3119 
3120   ren->ComputeAspect();
3121   double *aspect = ren->GetAspect();
3122 
3123   // Get the view matrix in two steps - there is a one step method in camera
3124   // but it turns off stereo so we do not want to use that one
3125   vtkCamera *cam = ren->GetActiveCamera();
3126   this->PerspectiveTransform->Identity();
3127   this->PerspectiveTransform->Concatenate(
3128     cam->GetProjectionTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 ));
3129   this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix());
3130   this->PerspectiveTransform->Concatenate(vol->GetMatrix());
3131   this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix());
3132 
3133   this->AllocateVertices(numberOfPoints);
3134 
3135   while(pointId<numberOfPoints)
3136   {
3137     vertex=&(this->Vertices->Vector[pointId]);
3138 
3139     // Projection
3140     //
3141     double inPoint[4];
3142     input->GetPoint(pointId,inPoint);
3143     inPoint[3] = 1.0;
3144 
3145     double outPoint[4];
3146     this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint );
3147     assert("outPoint[3]" && outPoint[3]!=0.0);
3148 
3149     double invW=1/outPoint[3];
3150     double zView = outPoint[2]*invW;
3151 
3152     int xScreen=static_cast<int>((outPoint[0]*invW+1)*0.5*this->ImageViewportSize[0]-this->ImageOrigin[0]);
3153     int yScreen=static_cast<int>((outPoint[1]*invW+1)*0.5*this->ImageViewportSize[1]-this->ImageOrigin[1]);
3154 
3155     double outWorldPoint[4];
3156 
3157     vol->GetMatrix()->MultiplyPoint( inPoint, outWorldPoint );
3158 
3159     assert("check: vol no projection" && outWorldPoint[3]==1);
3160 
3161     double scalar;
3162     if(this->CellScalars) // cell attribute
3163     {
3164       scalar=0; // ignored
3165     }
3166     else // point attribute
3167     {
3168       int numComp=this->Scalars->GetNumberOfComponents();
3169       if(numComp==1)
3170       {
3171         scalar=this->Scalars->GetComponent(pointId,0);
3172       }
3173       else
3174       {
3175         int comp=0;
3176         scalar=0;
3177         while(comp<numComp)
3178         {
3179           double value=this->Scalars->GetComponent(pointId,comp);
3180           scalar+=value*value;
3181           ++comp;
3182         }
3183         scalar=sqrt(scalar);
3184       }
3185     }
3186 
3187     vertex->Set(xScreen,yScreen,outWorldPoint[0]/outWorldPoint[3],
3188                 outWorldPoint[1]/outWorldPoint[3],
3189                 outWorldPoint[2]/outWorldPoint[3],zView,scalar,invW);
3190 
3191     // Sorting
3192     //
3193     // we store -z because the top of the priority list is the
3194     // smallest value
3195 #ifdef BACK_TO_FRONT
3196     this->EventList->Insert(-zView,pointId);
3197 #else
3198     this->EventList->Insert(zView,pointId);
3199 #endif
3200     ++pointId;
3201   }
3202 }
3203 
3204 //-----------------------------------------------------------------------------
CreateAndCleanPixelList()3205 void vtkUnstructuredGridVolumeZSweepMapper::CreateAndCleanPixelList()
3206 {
3207   // paper: a "pixel list" is a double linked list. We put that in a queue.
3208   vtkIdType size=this->ImageInUseSize[0]*this->ImageInUseSize[1];
3209   if(this->PixelListFrame!=nullptr)
3210   {
3211     if(this->PixelListFrame->GetSize()<size)
3212     {
3213       delete this->PixelListFrame;
3214       this->PixelListFrame=nullptr;
3215     }
3216   }
3217 
3218   if(this->PixelListFrame==nullptr)
3219   {
3220     this->PixelListFrame=new vtkPixelListFrame(size);
3221   }
3222 }
3223 
3224 //-----------------------------------------------------------------------------
MainLoop(vtkRenderWindow * renWin)3225 void vtkUnstructuredGridVolumeZSweepMapper::MainLoop(vtkRenderWindow *renWin)
3226 {
3227 // used to know if the next vertex is on the same plane
3228   double currentZ; // than the previous one. If so, the z-target has to be
3229   // updated (without calling the compositing function)
3230   if(this->EventList->GetNumberOfItems()==0)
3231   {
3232     return; // we are done.
3233   }
3234 
3235   // initialize the "previous z-target" to the z-coordinate of the first
3236   // vertex.
3237   double previousZTarget=0.0;
3238   vtkIdType vertex=this->EventList->Peek(0,previousZTarget);
3239 
3240 #ifdef BACK_TO_FRONT
3241   previousZTarget=-previousZTarget; // because the EventList store -z
3242 #endif
3243 
3244   // (section 2 paragraph 11)
3245   // initialize the "z-target" with the maximum z-coordinate of the adjacent
3246   // vertices to the first vertex. The adjacent vertices can be found
3247   // indirectly by using the "use set" of the first vertex (cells), and
3248   // by taking the vertices of all those cells.
3249   //
3250   double zTarget=previousZTarget;
3251   std::list<vtkFace *>::iterator it;
3252   std::list<vtkFace *>::iterator itEnd;
3253 
3254 //  this->MaxRecordedPixelListSize=0;
3255   this->MaxPixelListSizeReached=0;
3256   this->XBounds[0]=this->ImageInUseSize[0];
3257   this->XBounds[1]=0;
3258   this->YBounds[0]=this->ImageInUseSize[1];
3259   this->YBounds[1]=0;
3260 
3261   vtkIdType progressCount=0;
3262   vtkIdType sum=this->EventList->GetNumberOfItems();
3263 
3264   if(this->MemoryManager==nullptr)
3265   {
3266     this->MemoryManager=new vtkPixelListEntryMemory;
3267   }
3268 
3269   this->UseSet->SetNotRendered();
3270 
3271   int aborded=0;
3272   // for each vertex of the "event list"
3273   while(this->EventList->GetNumberOfItems()>0)
3274   {
3275     this->UpdateProgress(static_cast<double>(progressCount)/sum);
3276 
3277     aborded=renWin->CheckAbortStatus();
3278     if(aborded)
3279     {
3280       break;
3281     }
3282     ++progressCount;
3283     //  the z coordinate of the current vertex defines the "sweep plane".
3284     vertex=this->EventList->Pop(0,currentZ);
3285 
3286     if(this->UseSet->Vector[vertex]!=nullptr)
3287     { // otherwise the vertex is not useful, basically this is the
3288       // end we reached the last ztarget
3289 
3290 #ifdef BACK_TO_FRONT
3291     currentZ=-currentZ; // because the EventList store -z
3292 #endif
3293 
3294     if(previousZTarget==currentZ)
3295     {
3296       // the new vertex is on the same sweep plane than the previous vertex
3297       // that defined a z target
3298       // => the z target has to be updated accordingly
3299       // This is also the case for the first vertex.
3300       it=this->UseSet->Vector[vertex]->begin();
3301       itEnd=this->UseSet->Vector[vertex]->end();
3302 
3303       // for each face incident with the vertex
3304       while(it!=itEnd)
3305       {
3306         vtkFace *face=(*it);
3307         // for each point of the face, get the closest z
3308         vtkIdType *vids=face->GetFaceIds();
3309         vtkIdType i=0;
3310         while(i<3)
3311         {
3312           double z=this->Vertices->Vector[vids[i]].GetZview();
3313 #ifdef BACK_TO_FRONT
3314           if(z<zTarget)
3315 #else
3316             if(z>zTarget)
3317 #endif
3318             {
3319             zTarget=z;
3320             }
3321           ++i;
3322         }
3323         ++it;
3324       }
3325     }
3326 
3327     // Time to call the composite function?
3328 #ifdef BACK_TO_FRONT
3329     if(currentZ<zTarget)
3330 #else
3331     if(currentZ>zTarget)
3332 #endif
3333     {
3334       this->CompositeFunction(zTarget);
3335 
3336       // Update the zTarget
3337       previousZTarget=zTarget;
3338 
3339       it=this->UseSet->Vector[vertex]->begin();
3340       itEnd=this->UseSet->Vector[vertex]->end();
3341       // for each cell incident with the vertex
3342       while(it!=itEnd)
3343       {
3344         vtkFace *face=(*it);
3345         // for each point of the face, get the closest z
3346         vtkIdType *vids=face->GetFaceIds();
3347         vtkIdType i=0;
3348         while(i<3)
3349         {
3350           double z=this->Vertices->Vector[vids[i]].GetZview();
3351 #ifdef BACK_TO_FRONT
3352           if(z<zTarget)
3353 #else
3354             if(z>zTarget)
3355 #endif
3356             {
3357             zTarget=z;
3358             }
3359           ++i;
3360         }
3361         ++it;
3362       }
3363     }
3364     else
3365     {
3366       if(this->MaxPixelListSizeReached)
3367       {
3368         this->CompositeFunction(currentZ);
3369         // We do not update the zTarget in this case.
3370       }
3371     }
3372 
3373     //  use the "use set" (cells) of the vertex to get the cells that are
3374     //  incident on the vertex, and that have this vertex as
3375     //  minimal z-coordinate,
3376 
3377     it=this->UseSet->Vector[vertex]->begin();
3378     itEnd=this->UseSet->Vector[vertex]->end();
3379 
3380     while(it!=itEnd)
3381     {
3382       vtkFace *face=(*it);
3383       if(!face->GetRendered())
3384       {
3385         vtkIdType *vids=face->GetFaceIds();
3386         if(this->CellScalars)
3387         {
3388           this->FaceScalars[0]=face->GetScalar(0);
3389           this->FaceScalars[1]=face->GetScalar(1);
3390         }
3391         this->RasterizeFace(vids, face->GetExternalSide());
3392         face->SetRendered(1);
3393       }
3394 #if 0 // face search
3395       // for each point of the face, get the closest z
3396       vtkIdType *vids=face->GetFaceIds();
3397       vtkIdType minVertex=vids[0];
3398       double farestZ=this->Vertices->Vector[vids[0]].GetZview();
3399 
3400       vtkIdType i=1;
3401       while(i<3)
3402       {
3403         double z=this->Vertices->Vector[vids[i]].GetZview();
3404 #ifdef BACK_TO_FRONT
3405         if(z>farestZ)
3406 #else
3407           if(z<farestZ)
3408 #endif
3409           {
3410           farestZ=z;
3411           minVertex=vids[i];
3412           }
3413         ++i;
3414       }
3415       if(minVertex==vertex)
3416       {
3417 //        if(face->GetRendered())
3418 //          {
3419 //          cout<<"FACE ALREADY RENDERED!!!!"<<endl;
3420 //          }
3421         this->RasterizeFace(vids);
3422 //        face->SetRendered(1);
3423       }
3424 #endif // face search
3425       ++it;
3426     }
3427     } // if useset of vertex is not null
3428   } // while(eventList->GetNumberOfItems()>0)
3429 
3430   if(!aborded)
3431   {
3432     // Here a final compositing
3433     vtkDebugMacro(<<"Flush Compositing");
3434 //   this->SavePixelListFrame();
3435 #ifdef BACK_TO_FRONT
3436     this->CompositeFunction(-2);
3437 #else
3438     this->CompositeFunction(2);
3439 #endif
3440   }
3441   else
3442   {
3443     this->EventList->Reset();
3444   }
3445   this->PixelListFrame->Clean(this->MemoryManager);
3446 //  vtkDebugMacro(<<"MaxRecordedPixelListSize="<<this->MaxRecordedPixelListSize);
3447 
3448   assert("post: empty_list" && this->EventList->GetNumberOfItems()==0);
3449 }
3450 
3451 //-----------------------------------------------------------------------------
SavePixelListFrame()3452 void vtkUnstructuredGridVolumeZSweepMapper::SavePixelListFrame()
3453 {
3454   vtkPolyData *dataset=vtkPolyData::New();
3455 
3456   vtkIdType height=this->ImageInUseSize[1];
3457   vtkIdType width=this->ImageInUseSize[0];
3458   vtkPixelListEntry *current;
3459   vtkIdType i;
3460 
3461   vtkPoints *pts=vtkPoints::New();
3462   pts->SetDataTypeToDouble();
3463 
3464   vtkDoubleArray *dataArray=vtkDoubleArray::New();
3465   vtkCellArray *vertices=vtkCellArray::New();
3466   vtkIdType pointId=0;
3467 
3468 //  height=151;
3469 //  width=151;
3470 
3471   vtkIdType y=0; //150;
3472   while(y<height)
3473   {
3474     vtkIdType x=0; //150;
3475     while(x<width)
3476     {
3477       i=y*this->ImageInUseSize[0]+x;
3478       current=this->PixelListFrame->GetFirst(i);
3479       while(current!=nullptr)
3480       {
3481         double *values=current->GetValues();
3482 
3483         double point[3];
3484         point[0]=x;
3485         point[1]=y;
3486         point[2]=values[2]; // zWorld
3487 
3488         pts->InsertNextPoint(point);
3489         dataArray->InsertNextValue(values[3]);
3490         vertices->InsertNextCell(1,&pointId);
3491         current=current->GetNext();
3492         ++pointId;
3493       }
3494       ++x;
3495     }
3496     ++y;
3497   }
3498   dataset->SetPoints(pts);
3499   pts->Delete();
3500   dataset->SetVerts(vertices);
3501   vertices->Delete();
3502   dataset->GetPointData()->SetScalars(dataArray);
3503   dataArray->Delete();
3504 
3505   /*
3506   vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New();
3507   writer->SetFileName("pixellistframe.vtp");
3508   writer->SetInputData(dataset);
3509   writer->SetIdTypeToInt32();
3510   dataset->Delete();
3511   writer->Write();
3512   writer->Delete();
3513   */
3514 }
3515 
3516 //-----------------------------------------------------------------------------
3517 // Description:
3518 // Perform a scan conversion of a triangle, interpolating z and the scalar.
RasterizeFace(vtkIdType faceIds[3],int externalSide)3519 void vtkUnstructuredGridVolumeZSweepMapper::RasterizeFace(vtkIdType faceIds[3],
3520                                                           int externalSide)
3521 {
3522   // The triangle is split by a horizontal line passing through the
3523   // second vertex v1 (y-order)
3524   // Hence, on one side there's one edge (v0v2), on the other side there are two
3525   // edges (v0v1 and v1v2).
3526 
3527   vtkVertexEntry *v0=&(this->Vertices->Vector[faceIds[0]]);
3528   vtkVertexEntry *v1=&(this->Vertices->Vector[faceIds[1]]);
3529   vtkVertexEntry *v2=&(this->Vertices->Vector[faceIds[2]]);
3530 
3531   bool exitFace = false;
3532 
3533   // Find the orientation of the triangle on the screen to get the right
3534   // scalar
3535   if((externalSide != vtkFace::NOT_EXTERNAL) || this->CellScalars)
3536   {
3537     // To find the "winding" of the triangle as projected in screen space, we
3538     // perform the cross section.  The result trivially points along the Z axis.
3539     // Its magnitude is proportional to the triangle area and its direction
3540     // points away from the "front" face (what we are really interested in).
3541     // Since we know the cross product points in the Z direction, we only need
3542     // the Z component.
3543     int vec0[2], vec1[2];
3544     vec0[0] = v1->GetScreenX() - v0->GetScreenX();
3545     vec0[1] = v1->GetScreenY() - v0->GetScreenY();
3546     vec1[0] = v2->GetScreenX() - v0->GetScreenX();
3547     vec1[1] = v2->GetScreenY() - v0->GetScreenY();
3548     int zcross= vec0[0]*vec1[1] - vec0[1]*vec1[0];
3549     if(zcross<0)
3550     {
3551       this->FaceSide=1;
3552     }
3553     else
3554     {
3555       this->FaceSide=0;
3556     }
3557 
3558     // When determining the exit face, be conservative.  If the triangle is too
3559     // small to determine the orientation, it is better to assume that it is
3560     // exit than not exit.  This is because if it is misclassified as exit, then
3561     // we simply will not fill a rather small tet.  If it is misclassified as
3562     // not exit when it is, it could potential cause the filling of a large
3563     // space.
3564     if (externalSide == vtkFace::FRONT_FACE)
3565     {
3566 #ifdef BACK_TO_FRONT
3567       exitFace = (zcross >= 0);
3568 #else
3569       exitFace = (zcross <= 0);
3570 #endif
3571     }
3572     else if (externalSide == vtkFace::BACK_FACE)
3573     {
3574 #ifdef BACK_TO_FRONT
3575       exitFace = (zcross <= 0);
3576 #else
3577       exitFace = (zcross >= 0);
3578 #endif
3579     }
3580   }
3581 
3582   this->RasterizeTriangle(v0,v1,v2,exitFace);
3583 }
3584 
3585 //-----------------------------------------------------------------------------
3586 // Description:
3587 // Perform a scan conversion of a triangle, interpolating z and the scalar.
RasterizeTriangle(vtkVertexEntry * ve0,vtkVertexEntry * ve1,vtkVertexEntry * ve2,bool externalFace)3588 void  vtkUnstructuredGridVolumeZSweepMapper::RasterizeTriangle(
3589                                                             vtkVertexEntry *ve0,
3590                                                             vtkVertexEntry *ve1,
3591                                                             vtkVertexEntry *ve2,
3592                                                             bool externalFace)
3593 {
3594   assert("pre: ve0_exists" && ve0!=nullptr);
3595   assert("pre: ve1_exists" && ve1!=nullptr);
3596   assert("pre: ve2_exists" && ve2!=nullptr);
3597 
3598   vtkVertexEntry *v0=ve0;
3599   vtkVertexEntry *v1=ve1;
3600   vtkVertexEntry *v2=ve2;
3601 
3602   // The triangle is split by a horizontal line passing through the
3603   // second vertex v1 (y-order)
3604   // Hence, on one side there's one edge (v0v2), on the other side there are two
3605   // edges (v0v1 and v1v2).
3606 
3607   // Order vertices by y screen.
3608 
3609   vtkVertexEntry *tmp;
3610 
3611   if(v0->GetScreenY()>v1->GetScreenY())
3612   {
3613     tmp=v0;
3614     v0=v1;
3615     v1=tmp;
3616   }
3617   if(v0->GetScreenY()>v2->GetScreenY())
3618   {
3619     tmp=v1;
3620     v1=v0;
3621     v0=v2;
3622     v2=tmp;
3623   }
3624   else
3625   {
3626     if(v1->GetScreenY()>v2->GetScreenY())
3627     {
3628       tmp=v1;
3629       v1=v2;
3630       v2=tmp;
3631     }
3632   }
3633 
3634   if(v0->GetScreenY()<this->YBounds[0])
3635   {
3636     if(v0->GetScreenY()>=0)
3637     {
3638       this->YBounds[0]=v0->GetScreenY();
3639     }
3640     else
3641     {
3642       this->YBounds[0]=0;
3643     }
3644   }
3645   if(v2->GetScreenY()>this->YBounds[1])
3646   {
3647     if(v2->GetScreenY()<this->ImageInUseSize[1])
3648     {
3649       this->YBounds[1]=v2->GetScreenY();
3650     }
3651     else
3652     {
3653       this->YBounds[1]=this->ImageInUseSize[1]-1;
3654     }
3655   }
3656 
3657   int x=v0->GetScreenX();
3658 
3659   if(x<this->XBounds[0])
3660   {
3661     if(x>=0)
3662     {
3663       this->XBounds[0]=x;
3664     }
3665     else
3666     {
3667       this->XBounds[0]=0;
3668     }
3669   }
3670   else
3671   {
3672     if(x>this->XBounds[1])
3673     {
3674       if(x<this->ImageInUseSize[0])
3675       {
3676         this->XBounds[1]=x;
3677       }
3678       else
3679       {
3680         this->XBounds[1]=this->ImageInUseSize[0]-1;
3681       }
3682     }
3683   }
3684   x=v1->GetScreenX();
3685 
3686   if(x<this->XBounds[0])
3687   {
3688     if(x>=0)
3689     {
3690       this->XBounds[0]=x;
3691     }
3692     else
3693     {
3694       this->XBounds[0]=0;
3695     }
3696   }
3697   else
3698   {
3699     if(x>this->XBounds[1])
3700     {
3701       if(x<this->ImageInUseSize[0])
3702       {
3703         this->XBounds[1]=x;
3704       }
3705       else
3706       {
3707         this->XBounds[1]=this->ImageInUseSize[0]-1;
3708       }
3709     }
3710   }
3711 
3712   x=v2->GetScreenX();
3713 
3714   if(x<this->XBounds[0])
3715   {
3716     if(x>=0)
3717     {
3718       this->XBounds[0]=x;
3719     }
3720     else
3721     {
3722       this->XBounds[0]=0;
3723     }
3724   }
3725   else
3726   {
3727     if(x>this->XBounds[1])
3728     {
3729       if(x<this->ImageInUseSize[0])
3730       {
3731         this->XBounds[1]=x;
3732       }
3733       else
3734       {
3735         this->XBounds[1]=this->ImageInUseSize[0]-1;
3736       }
3737     }
3738   }
3739 
3740   int dy20=v2->GetScreenY()-v0->GetScreenY();
3741   int dx10=v1->GetScreenX()-v0->GetScreenX();
3742   int dx20=v2->GetScreenX()-v0->GetScreenX();
3743   int dy10=v1->GetScreenY()-v0->GetScreenY();
3744 
3745   int det=dy20*dx10-dx20*dy10;
3746 
3747   vtkScreenEdge *leftEdge=nullptr;
3748   vtkScreenEdge *rightEdge=nullptr;
3749 
3750   if(det==0) //v0v1v2 aligned or v0=v1=v2
3751   {
3752     // easy case: v0=v1=v2 render the 3 points
3753     if(v0->GetScreenX()==v1->GetScreenX() && v0->GetScreenX()==v2->GetScreenX()
3754        && v0->GetScreenY()==v1->GetScreenY()
3755        && v0->GetScreenY()==v2->GetScreenY())
3756     {
3757       x=v0->GetScreenX();
3758       int y=v0->GetScreenY();
3759       if(x>=0 && x<this->ImageInUseSize[0] && y>=0 &&
3760          y<this->ImageInUseSize[1])
3761       {
3762         vtkIdType i=y*this->ImageInUseSize[0]+x;
3763         // Write the pixel
3764         vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry();
3765         p0->Init(v0->GetValues(),v0->GetZview(), externalFace);
3766         if(this->CellScalars)
3767         {
3768           p0->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
3769         }
3770         this->PixelListFrame->AddAndSort(i,p0);
3771 
3772         vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry();
3773         p1->Init(v1->GetValues(),v1->GetZview(), externalFace);
3774         if(this->CellScalars)
3775         {
3776           p1->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
3777         }
3778         this->PixelListFrame->AddAndSort(i,p1);
3779 
3780         vtkPixelListEntry *p2=this->MemoryManager->AllocateEntry();
3781         p2->Init(v2->GetValues(),v2->GetZview(), externalFace);
3782         if(this->CellScalars)
3783         {
3784           p2->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
3785         }
3786         this->PixelListFrame->AddAndSort(i,p2);
3787 
3788 
3789 //        if(this->PixelListFrame->GetListSize(i)>this->MaxRecordedPixelListSize)
3790 //          {
3791 //          this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(i);
3792 //          }
3793 
3794         if(!this->MaxPixelListSizeReached)
3795         {
3796           this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(i)>
3797             this->MaxPixelListSize;
3798         }
3799       }
3800     }
3801     else // line
3802     {
3803       this->RasterizeLine(v0,v1,externalFace);
3804       this->RasterizeLine(v1,v2,externalFace);
3805       this->RasterizeLine(v0,v2,externalFace);
3806     }
3807     return;
3808   }
3809   else
3810   {
3811     if(det>0) //v0v1 on right
3812     {
3813        this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,1); // true=on right
3814        rightEdge=this->DoubleEdge;
3815        this->SimpleEdge->Init(v0,v2,dx20,dy20,0);
3816        leftEdge=this->SimpleEdge;
3817     }
3818     else
3819     {
3820        // v0v1 on left
3821        this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,0); // true=on right
3822        leftEdge=this->DoubleEdge;
3823        this->SimpleEdge->Init(v0,v2,dx20,dy20,1);
3824        rightEdge=this->SimpleEdge;
3825     }
3826   }
3827 
3828   int y=v0->GetScreenY();
3829   int y1=v1->GetScreenY();
3830   int y2=v2->GetScreenY();
3831 
3832   int skipped=0;
3833 
3834   if(y1>=0) // clipping
3835   {
3836 
3837     if(y1>=this->ImageInUseSize[1]) // clipping
3838     {
3839       y1=this->ImageInUseSize[1]-1;
3840     }
3841 
3842     while(y<=y1)
3843     {
3844       if(y>=0 && y<this->ImageInUseSize[1]) // clipping
3845       {
3846         this->RasterizeSpan(y,leftEdge,rightEdge,externalFace);
3847       }
3848       ++y;
3849       if(y<=y1)
3850       {
3851         leftEdge->NextLine(y);
3852         rightEdge->NextLine(y);
3853       }
3854     }
3855   }
3856   else
3857   {
3858     leftEdge->SkipLines(y1-y,y1);
3859     rightEdge->SkipLines(y1-y,y1);
3860     y=y1;
3861     skipped=1;
3862   }
3863 
3864   if(y<this->ImageInUseSize[1]) // clipping
3865   {
3866     leftEdge->OnBottom(skipped,y);
3867     rightEdge->OnBottom(skipped,y);
3868 
3869     if(y2>=this->ImageInUseSize[1]) // clipping
3870     {
3871       y2=this->ImageInUseSize[1]-1;
3872     }
3873 
3874     while(y<=y2)
3875     {
3876       if(y>=0) // clipping, needed in case of no top
3877       {
3878         this->RasterizeSpan(y,leftEdge,rightEdge,externalFace);
3879       }
3880       ++y;
3881       leftEdge->NextLine(y);
3882       rightEdge->NextLine(y);
3883     }
3884   }
3885 }
3886 
3887 //-----------------------------------------------------------------------------
RasterizeSpan(int y,vtkScreenEdge * left,vtkScreenEdge * right,bool exitFace)3888 void vtkUnstructuredGridVolumeZSweepMapper::RasterizeSpan(int y,
3889                                                           vtkScreenEdge *left,
3890                                                           vtkScreenEdge *right,
3891                                                           bool exitFace)
3892 {
3893   assert("pre: left_exists" && left!=nullptr);
3894   assert("pre: right_exists" && right!=nullptr);
3895 
3896   vtkIdType i=y*this->ImageInUseSize[0];
3897 
3898   this->Span->Init(left->GetX(),
3899                    left->GetInvW(),
3900                    left->GetPValues(),
3901                    left->GetZview(),
3902                    right->GetX(),
3903                    right->GetInvW(),
3904                    right->GetPValues(),
3905                    right->GetZview());
3906 
3907   while(!this->Span->IsAtEnd())
3908   {
3909     int x=this->Span->GetX();
3910     if(x>=0 && x<this->ImageInUseSize[0]) // clipping
3911     {
3912       vtkIdType j=i+x;
3913       // Write the pixel
3914       vtkPixelListEntry *p=this->MemoryManager->AllocateEntry();
3915       p->Init(this->Span->GetValues(),this->Span->GetZview(), exitFace);
3916 
3917       if(this->CellScalars)
3918       {
3919         p->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
3920       }
3921       this->PixelListFrame->AddAndSort(j,p);
3922 
3923 
3924 //      if(this->PixelListFrame->GetListSize(j)>this->MaxRecordedPixelListSize)
3925 //        {
3926 //        this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(j);
3927 //        }
3928 
3929       if(!this->MaxPixelListSizeReached)
3930       {
3931         this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)>
3932           this->MaxPixelListSize;
3933       }
3934     }
3935     this->Span->NextPixel();
3936   }
3937 }
3938 
3939 enum
3940 {
3941   VTK_LINE_CONSTANT=0,
3942   VTK_LINE_BRESENHAM,
3943   VTK_LINE_DIAGONAL
3944 };
3945 
3946 //-----------------------------------------------------------------------------
RasterizeLine(vtkVertexEntry * v0,vtkVertexEntry * v1,bool exitFace)3947 void vtkUnstructuredGridVolumeZSweepMapper::RasterizeLine(vtkVertexEntry *v0,
3948                                                           vtkVertexEntry *v1,
3949                                                           bool exitFace)
3950 {
3951   assert("pre: v0_exists" && v0!=nullptr);
3952   assert("pre: v1_exists" && v1!=nullptr);
3953   assert("pre: y_ordered" && v0->GetScreenY()<=v1->GetScreenY());
3954 
3955   int lineCase;
3956   int xIncrement; // if true increment x, if false increment y
3957   int dx;
3958   int dy;
3959   int xSign;
3960 
3961   // initialization is not useful, it is just to remove compiler warnings
3962   int dx2=0;
3963   int dy2=0;
3964   int e=0;
3965 
3966   double values[VTK_VALUES_SIZE];
3967   double pValues[VTK_VALUES_SIZE];
3968 
3969   double dPv[VTK_VALUES_SIZE];
3970   double dInvW;
3971   double dZ;
3972 
3973   double zView;
3974   double invW;
3975 
3976   int i;
3977 
3978   int x=v0->GetScreenX();
3979   int y=v0->GetScreenY();
3980 
3981   // 1. Find the case
3982   dx=v1->GetScreenX()-v0->GetScreenX();
3983   if(dx<0)
3984   {
3985     dx=-dx;
3986     xSign=-1;
3987   }
3988   else
3989   {
3990     xSign=1;
3991   }
3992   dy=v1->GetScreenY()-v0->GetScreenY();
3993   xIncrement=dx>dy;
3994   if(xIncrement)
3995   {
3996     if(dy==0)
3997     {
3998       lineCase=VTK_LINE_CONSTANT;
3999     }
4000     else
4001     {
4002       lineCase=VTK_LINE_BRESENHAM;
4003       dx2=dx<<1;
4004       dy2=dy<<1;
4005       e=dx;
4006     }
4007 
4008     double invDx=1.0/dx;
4009     i=0;
4010     invW=v0->GetInvW();
4011     double invW1=v1->GetInvW();
4012     double *val0=v0->GetValues();
4013     double *val1=v1->GetValues();
4014     while(i<VTK_VALUES_SIZE)
4015     {
4016       values[i]=val0[i];
4017       pValues[i]=values[i]*invW;
4018       dPv[i]=(val1[i]*invW1-pValues[i])*invDx;
4019       ++i;
4020     }
4021     dInvW=(invW1-invW)*invDx;
4022     zView=v0->GetZview();
4023     dZ=(v1->GetZview()-zView)*invDx;
4024   }
4025   else
4026   {
4027     if(dx==0)
4028     {
4029       if(dy==0)
4030       {
4031         // render both points and return
4032         // write pixel
4033         if(x>=0 && x<this->ImageInUseSize[0] && y>=0 &&
4034            y<this->ImageInUseSize[1]) // clipping
4035         {
4036           vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!!
4037           // Write the pixel
4038           vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry();
4039           p0->Init(v0->GetValues(),v0->GetZview(), exitFace);
4040 
4041           if(this->CellScalars)
4042           {
4043             p0->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
4044           }
4045           this->PixelListFrame->AddAndSort(j,p0);
4046 
4047           // Write the pixel
4048           vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry();
4049           p1->Init(v1->GetValues(),v1->GetZview(), exitFace);
4050 
4051           if(this->CellScalars)
4052           {
4053             p1->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
4054           }
4055           this->PixelListFrame->AddAndSort(j,p1);
4056 
4057           if(!this->MaxPixelListSizeReached)
4058           {
4059             this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)>
4060               this->MaxPixelListSize;
4061           }
4062         }
4063         return;
4064       }
4065       else
4066       {
4067         lineCase=VTK_LINE_CONSTANT;
4068       }
4069     }
4070     else
4071     {
4072       if(dy==dx)
4073       {
4074         lineCase=VTK_LINE_DIAGONAL;
4075       }
4076       else
4077       {
4078         lineCase=VTK_LINE_BRESENHAM;
4079         dx2=dx<<1;
4080         dy2=dy<<1;
4081         e=dy;
4082       }
4083     }
4084     double invDy=1.0/dy;
4085     i=0;
4086     invW=v0->GetInvW();
4087     double invW1=v1->GetInvW();
4088     double *val0=v0->GetValues();
4089     double *val1=v1->GetValues();
4090     while(i<VTK_VALUES_SIZE)
4091     {
4092       values[i]=val0[i];
4093       pValues[i]=values[i]*invW;
4094       dPv[i]=(val1[i]*invW1-pValues[i])*invDy;
4095       ++i;
4096     }
4097     dInvW=(invW1-invW)*invDy;
4098     zView=v0->GetZview();
4099     dZ=(v1->GetZview()-zView)*invDy;
4100   }
4101 
4102   // 2. Iterate over each pixel of the straight line.
4103   int done=0;
4104   while(!done)
4105   {
4106     // write pixel
4107     if(x>=0 && x<this->ImageInUseSize[0] && y>=0 &&
4108        y<this->ImageInUseSize[1]) // clipping
4109     {
4110       vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!!
4111       // Write the pixel
4112       vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry();
4113       p0->Init(values,zView,exitFace);
4114 
4115       if(this->CellScalars)
4116       {
4117         p0->GetValues()[VTK_VALUES_SCALAR_INDEX]=this->FaceScalars[this->FaceSide];
4118       }
4119       this->PixelListFrame->AddAndSort(j,p0);
4120 
4121       if(!this->MaxPixelListSizeReached)
4122       {
4123         this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)>
4124           this->MaxPixelListSize;
4125       }
4126     }
4127 
4128     // next pixel
4129     switch(lineCase)
4130     {
4131       case VTK_LINE_CONSTANT:
4132         if(xIncrement)
4133         {
4134           x+=xSign;
4135           if(xSign>0)
4136           {
4137             done=x>v1->GetScreenX();
4138           }
4139           else
4140           {
4141             done=x<v1->GetScreenX();
4142           }
4143         }
4144         else
4145         {
4146           ++y;
4147           done=y>v1->GetScreenY();
4148         }
4149         //values, invw, zview
4150         break;
4151       case VTK_LINE_DIAGONAL:
4152         ++y;
4153         x+=xSign;
4154         done=y>v1->GetScreenY();
4155         //values, invw, zview
4156         break;
4157       case VTK_LINE_BRESENHAM:
4158         if(xIncrement)
4159         {
4160           x+=xSign;
4161           e+=dy2;
4162           if(e>=dx2)
4163           {
4164             e-=dx2;
4165             ++y;
4166           }
4167           if(xSign>0)
4168           {
4169             done=x>v1->GetScreenX();
4170           }
4171           else
4172           {
4173             done=x<v1->GetScreenX();
4174           }
4175         }
4176         else
4177         {
4178           ++y;
4179           e+=dx2;
4180           if(e>=dy2)
4181           {
4182             e-=dy2;
4183             x+=xSign;
4184           }
4185           done=y>v1->GetScreenY();
4186         }
4187         // values, invw, zview
4188         break;
4189     }
4190     if(!done)
4191     {
4192       invW+=dInvW;
4193       i=0;
4194       double w=1.0/invW;
4195       while(i<VTK_VALUES_SIZE)
4196       {
4197         pValues[i]+=dPv[i];
4198         values[i]=pValues[i]*w;
4199         ++i;
4200       }
4201       zView+=dZ;
4202     }
4203   }
4204 }
4205 
4206 //-----------------------------------------------------------------------------
CompositeFunction(double zTarget)4207 void vtkUnstructuredGridVolumeZSweepMapper::CompositeFunction(double zTarget)
4208 {
4209   int y=this->YBounds[0];
4210   vtkIdType i=y*this->ImageInUseSize[0]+this->XBounds[0];
4211 
4212   vtkIdType index=(y*this->ImageMemorySize[0]+this->XBounds[0])<< 2; // *4
4213   vtkIdType indexStep=this->ImageMemorySize[0]<<2; // *4
4214 
4215   vtkPixelListEntry *current;
4216   vtkPixelListEntry *next;
4217   double zBuffer=0;
4218 
4219   int newXBounds[2];
4220   int newYBounds[2];
4221 
4222   newXBounds[0]=this->ImageInUseSize[0];
4223   newXBounds[1]=0;
4224   newYBounds[0]=this->ImageInUseSize[1];
4225   newYBounds[1]=0;
4226 
4227   int xMin=this->XBounds[0];
4228   int xMax=this->XBounds[1];
4229   int yMax=this->YBounds[1];
4230 
4231   vtkPixelList *pixel;
4232   int x;
4233   vtkIdType j;
4234   vtkIdType index2;
4235   int done;
4236   int doIntegration;
4237   double length;
4238   float *color;
4239 
4240   // for each pixel in the bounding box
4241   while(y<=yMax)
4242   {
4243     x=xMin;
4244     j=i;
4245     index2=index;
4246     while(x<=xMax)
4247     {
4248       pixel=this->PixelListFrame->GetList(j);
4249       // we need at least two entries per pixel to perform compositing
4250       if(pixel->GetSize()>=2)
4251       {
4252         current=pixel->GetFirst();
4253         next=current->GetNext();
4254 #ifdef BACK_TO_FRONT
4255         done=current->GetZview()<=zTarget || next->GetZview()<=zTarget;
4256 #else
4257         done=current->GetZview()>=zTarget || next->GetZview()>=zTarget;
4258 #endif
4259 
4260         if(!done && this->ZBuffer!=nullptr)
4261         {
4262           // value of the z buffer at the current pixel.
4263           zBuffer=this->GetZBufferValue(x,y);
4264         }
4265 
4266         while(!done)
4267         {
4268           if (current->GetExitFace())
4269           {
4270             // Do not do the integration if the current face is an exit face.
4271             // The space between current and next should be empty.
4272             doIntegration = 0;
4273           }
4274           else
4275           {
4276             if(this->ZBuffer!=nullptr)
4277             {
4278               // check that current and next are in front of the z-buffer value
4279               doIntegration=current->GetZview()<zBuffer
4280                 && next->GetZview()<zBuffer;
4281             }
4282             else
4283             {
4284               doIntegration=1;
4285             }
4286           }
4287 
4288           if(doIntegration)
4289           {
4290             if(current->GetZview()!=next->GetZview())
4291             {
4292               // length in world coordinates
4293               length=sqrt(vtkMath::Distance2BetweenPoints(
4294                             current->GetValues(),next->GetValues()));
4295               if(length!=0)
4296 //              if(length>=0.4)
4297               {
4298                 color=this->RealRGBAImage+index2;
4299                 this->IntersectionLengths->SetValue(0,length);
4300 
4301                 if(this->CellScalars)
4302                 {
4303                   // same value for near and far intersection
4304                   this->NearIntersections->SetValue(0,current->GetValues()[VTK_VALUES_SCALAR_INDEX]);
4305                   this->FarIntersections->SetValue(0,current->GetValues()[VTK_VALUES_SCALAR_INDEX]);
4306                 }
4307                 else
4308                 {
4309                   this->NearIntersections->SetValue(0,current->GetValues()[VTK_VALUES_SCALAR_INDEX]);
4310                   this->FarIntersections->SetValue(0,next->GetValues()[VTK_VALUES_SCALAR_INDEX]);
4311                 }
4312 #ifdef BACK_TO_FRONT
4313                 this->RealRayIntegrator->Integrate(this->IntersectionLengths,
4314                                                    this->FarIntersections,
4315                                                    this->NearIntersections,
4316                                                    color);
4317 #else
4318                 this->RealRayIntegrator->Integrate(this->IntersectionLengths,
4319                                                    this->NearIntersections,
4320                                                    this->FarIntersections,
4321                                                    color);
4322 #endif
4323               } // length!=0
4324             } // current->GetZview()!=next->GetZview()
4325           } // doIntegration
4326 
4327           // Next entry
4328           pixel->RemoveFirst(this->MemoryManager); // remove current
4329           done=pixel->GetSize()<2; // empty queue?
4330           if(!done)
4331           {
4332             current=next;
4333             next=current->GetNext();
4334 #ifdef BACK_TO_FRONT
4335             done=next->GetZview()<=zTarget;
4336 #else
4337             done=next->GetZview()>=zTarget;
4338 #endif
4339           }
4340         } // while(!done)
4341       }
4342       if(pixel->GetSize()>=2)
4343       {
4344         if(x<newXBounds[0])
4345         {
4346           newXBounds[0]=x;
4347         }
4348         else
4349         {
4350           if(x>newXBounds[1])
4351           {
4352             newXBounds[1]=x;
4353           }
4354         }
4355         if(y<newYBounds[0])
4356         {
4357           newYBounds[0]=y;
4358         }
4359         else
4360         {
4361           if(y>newYBounds[1])
4362           {
4363             newYBounds[1]=y;
4364           }
4365         }
4366       }
4367 
4368       // next abscissa
4369       ++j;
4370       index2+=4;
4371       ++x;
4372     }
4373     // next ordinate
4374     i=i+this->ImageInUseSize[0];
4375     index+=indexStep;
4376     ++y;
4377   }
4378 
4379   // Update the bounding box. Useful for the delayed compositing
4380 
4381   this->XBounds[0]=newXBounds[0];
4382   this->XBounds[1]=newXBounds[1];
4383   this->YBounds[0]=newYBounds[0];
4384   this->YBounds[1]=newYBounds[1];
4385 
4386   this->MaxPixelListSizeReached=0;
4387 }
4388 
4389 //-----------------------------------------------------------------------------
4390 // Description:
4391 // Convert and clamp a float color component into an unsigned char.
ColorComponentRealToByte(float color)4392 unsigned char vtkUnstructuredGridVolumeZSweepMapper::ColorComponentRealToByte(
4393   float color)
4394 {
4395   int val=static_cast<int>(color*255.0);
4396   if(val>255)
4397   {
4398     val=255;
4399   }
4400   else
4401   {
4402     if(val<0)
4403     {
4404       val=0;
4405     }
4406   }
4407   return static_cast<unsigned char>(val);
4408 }
4409 
4410 //-----------------------------------------------------------------------------
GetZBufferValue(int x,int y)4411 double vtkUnstructuredGridVolumeZSweepMapper::GetZBufferValue(int x,
4412                                                               int y)
4413 {
4414   int xPos, yPos;
4415 
4416   xPos = static_cast<int>(static_cast<float>(x) * this->ImageSampleDistance);
4417   yPos = static_cast<int>(static_cast<float>(y) * this->ImageSampleDistance);
4418 
4419   xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos);
4420   yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos);
4421 
4422   return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos);
4423 }
4424 
4425 //-----------------------------------------------------------------------------
GetMinimumBoundsDepth(vtkRenderer * ren,vtkVolume * vol)4426 double vtkUnstructuredGridVolumeZSweepMapper::GetMinimumBoundsDepth(
4427   vtkRenderer *ren,
4428   vtkVolume   *vol )
4429 {
4430   double bounds[6];
4431   vol->GetBounds( bounds );
4432 
4433   ren->ComputeAspect();
4434   double *aspect = ren->GetAspect();
4435 
4436   // Get the view matrix in two steps - there is a one step method in camera
4437   // but it turns off stereo so we do not want to use that one
4438   vtkCamera *cam = ren->GetActiveCamera();
4439   this->PerspectiveTransform->Identity();
4440   this->PerspectiveTransform->Concatenate(
4441     cam->GetProjectionTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 ));
4442   this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix());
4443   this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix());
4444 
4445   double minZ = 1.0;
4446 
4447   for ( int k = 0; k < 2; k++ )
4448   {
4449     for ( int j = 0; j < 2; j++ )
4450     {
4451       for ( int i = 0; i < 2; i++ )
4452       {
4453         double inPoint[4];
4454         inPoint[0] = bounds[  i];
4455         inPoint[1] = bounds[2+j];
4456         inPoint[2] = bounds[4+k];
4457         inPoint[3] = 1.0;
4458 
4459         double outPoint[4];
4460         this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint );
4461         double testZ = outPoint[2] / outPoint[3];
4462         minZ = ( testZ < minZ ) ? (testZ) : (minZ);
4463       }
4464     }
4465   }
4466 
4467   return minZ;
4468 }
4469