1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPolyData.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 "vtkPolyData.h"
16 
17 #include "vtkCellArray.h"
18 #include "vtkCellData.h"
19 #include "vtkCriticalSection.h"
20 #include "vtkEmptyCell.h"
21 #include "vtkGenericCell.h"
22 #include "vtkInformation.h"
23 #include "vtkInformationVector.h"
24 #include "vtkLine.h"
25 #include "vtkNew.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkPointData.h"
28 #include "vtkPointLocator.h"
29 #include "vtkPolyLine.h"
30 #include "vtkPolyVertex.h"
31 #include "vtkPolygon.h"
32 #include "vtkQuad.h"
33 #include "vtkTriangle.h"
34 #include "vtkTriangleStrip.h"
35 #include "vtkVertex.h"
36 
37 #include "vtkSmartPointer.h"
38 
39 vtkStandardNewMacro(vtkPolyData);
40 
41 //----------------------------------------------------------------------------
42 // Initialize static member.  This member is used to simplify traversal
43 // of verts, lines, polygons, and triangle strips lists.  It basically
44 // "marks" empty lists so that the traveral method "GetNextCell"
45 // works properly.
46 
47 struct vtkPolyDataDummyContainter
48 {
49   vtkSmartPointer<vtkCellArray> Dummy;
50 
vtkPolyDataDummyContaintervtkPolyDataDummyContainter51   vtkPolyDataDummyContainter()
52     {
53       this->Dummy.TakeReference(vtkCellArray::New());
54     }
55 };
56 
57 vtkPolyDataDummyContainter vtkPolyData::DummyContainer;
58 
vtkPolyData()59 vtkPolyData::vtkPolyData ()
60 {
61   // Create these guys only when needed. This saves a huge amount
62   // of memory and time spent in memory allocation.
63   this->Vertex = NULL;
64   this->PolyVertex = NULL;
65   this->Line = NULL;
66   this->PolyLine = NULL;
67   this->Triangle = NULL;
68   this->Quad = NULL;
69   this->Polygon = NULL;
70   this->TriangleStrip = NULL;
71   this->EmptyCell = NULL;
72 
73   this->Verts = NULL;
74   this->Lines = NULL;
75   this->Polys = NULL;
76   this->Strips = NULL;
77 
78   this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_PIECES_EXTENT);
79   this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1);
80   this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 1);
81   this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0);
82 
83   this->Cells = NULL;
84   this->Links = NULL;
85 }
86 
87 //----------------------------------------------------------------------------
~vtkPolyData()88 vtkPolyData::~vtkPolyData()
89 {
90   this->Cleanup();
91 
92   if (this->Vertex)
93     {
94     this->Vertex->Delete();
95     }
96 
97   if (this->PolyVertex)
98     {
99     this->PolyVertex->Delete();
100     }
101 
102   if (this->Line)
103     {
104     this->Line->Delete();
105     }
106 
107   if (this->PolyLine)
108     {
109     this->PolyLine->Delete();
110     }
111 
112   if (this->Triangle)
113     {
114     this->Triangle->Delete();
115     }
116 
117   if (this->Quad)
118     {
119     this->Quad->Delete();
120     }
121 
122   if (this->Polygon)
123     {
124     this->Polygon->Delete();
125     }
126 
127   if (this->TriangleStrip)
128     {
129     this->TriangleStrip->Delete();
130     }
131 
132   if (this->EmptyCell)
133     {
134     this->EmptyCell->Delete();
135     }
136 }
137 
138 //----------------------------------------------------------------------------
GetPiece()139 int vtkPolyData::GetPiece()
140 {
141   return this->Information->Get(vtkDataObject::DATA_PIECE_NUMBER());
142 }
143 
144 //----------------------------------------------------------------------------
GetNumberOfPieces()145 int vtkPolyData::GetNumberOfPieces()
146 {
147   return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_PIECES());
148 }
149 
150 //----------------------------------------------------------------------------
GetGhostLevel()151 int vtkPolyData::GetGhostLevel()
152 {
153   return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS());
154 }
155 
156 //----------------------------------------------------------------------------
157 // Copy the geometric and topological structure of an input poly data object.
CopyStructure(vtkDataSet * ds)158 void vtkPolyData::CopyStructure(vtkDataSet *ds)
159 {
160   vtkPolyData *pd=static_cast<vtkPolyData *>(ds);
161   vtkPointSet::CopyStructure(ds);
162 
163   if (this->Verts != pd->Verts)
164     {
165     if (this->Verts)
166       {
167       this->Verts->UnRegister(this);
168       }
169     this->Verts = pd->Verts;
170     if (this->Verts)
171       {
172       this->Verts->Register(this);
173       }
174     }
175 
176   if (this->Lines != pd->Lines)
177     {
178     if (this->Lines)
179       {
180       this->Lines->UnRegister(this);
181       }
182     this->Lines = pd->Lines;
183     if (this->Lines)
184       {
185       this->Lines->Register(this);
186       }
187     }
188 
189   if (this->Polys != pd->Polys)
190     {
191     if (this->Polys)
192       {
193       this->Polys->UnRegister(this);
194       }
195     this->Polys = pd->Polys;
196     if (this->Polys)
197       {
198       this->Polys->Register(this);
199       }
200     }
201 
202   if (this->Strips != pd->Strips)
203     {
204     if (this->Strips)
205       {
206       this->Strips->UnRegister(this);
207       }
208     this->Strips = pd->Strips;
209     if (this->Strips)
210       {
211       this->Strips->Register(this);
212       }
213     }
214 
215   if ( this->Cells )
216     {
217     this->Cells->UnRegister(this);
218     this->Cells = NULL;
219     }
220 
221   if ( this->Links )
222     {
223     this->Links->UnRegister(this);
224     this->Links = NULL;
225     }
226 }
227 
228 //----------------------------------------------------------------------------
GetCellType(vtkIdType cellId)229 int vtkPolyData::GetCellType(vtkIdType cellId)
230 {
231   if ( !this->Cells )
232     {
233     this->BuildCells();
234     }
235   return this->Cells->GetCellType(cellId);
236 }
237 
238 //----------------------------------------------------------------------------
GetCell(vtkIdType cellId)239 vtkCell *vtkPolyData::GetCell(vtkIdType cellId)
240 {
241   int i, loc;
242   vtkIdType *pts, numPts;
243   vtkCell *cell = NULL;
244   unsigned char type;
245 
246   if ( !this->Cells )
247     {
248     this->BuildCells();
249     }
250 
251   type = this->Cells->GetCellType(cellId);
252   loc = this->Cells->GetCellLocation(cellId);
253 
254   switch (type)
255     {
256     case VTK_VERTEX:
257       if (!this->Vertex)
258         {
259         this->Vertex = vtkVertex::New();
260         }
261       cell = this->Vertex;
262       this->Verts->GetCell(loc,numPts,pts);
263       break;
264 
265     case VTK_POLY_VERTEX:
266       if (! this->PolyVertex)
267         {
268         this->PolyVertex = vtkPolyVertex::New();
269         }
270       cell = this->PolyVertex;
271       this->Verts->GetCell(loc,numPts,pts);
272       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
273       cell->Points->SetNumberOfPoints(numPts);
274       break;
275 
276     case VTK_LINE:
277       if (! this->Line )
278         {
279         this->Line = vtkLine::New();
280         }
281       cell = this->Line;
282       this->Lines->GetCell(loc,numPts,pts);
283       break;
284 
285     case VTK_POLY_LINE:
286       if (!this->PolyLine)
287         {
288         this->PolyLine = vtkPolyLine::New();
289         }
290       cell = this->PolyLine;
291       this->Lines->GetCell(loc,numPts,pts);
292       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
293       cell->Points->SetNumberOfPoints(numPts);
294       break;
295 
296     case VTK_TRIANGLE:
297       if (!this->Triangle)
298         {
299         this->Triangle = vtkTriangle::New();
300         }
301       cell = this->Triangle;
302       this->Polys->GetCell(loc,numPts,pts);
303       break;
304 
305     case VTK_QUAD:
306       if (!this->Quad)
307         {
308         this->Quad = vtkQuad::New();
309         }
310       cell = this->Quad;
311       this->Polys->GetCell(loc,numPts,pts);
312       break;
313 
314     case VTK_POLYGON:
315       if (!this->Polygon)
316         {
317         this->Polygon = vtkPolygon::New();
318         }
319       cell = this->Polygon;
320       this->Polys->GetCell(loc,numPts,pts);
321       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
322       cell->Points->SetNumberOfPoints(numPts);
323       break;
324 
325     case VTK_TRIANGLE_STRIP:
326       if (!this->TriangleStrip)
327         {
328         this->TriangleStrip = vtkTriangleStrip::New();
329         }
330       cell = this->TriangleStrip;
331       this->Strips->GetCell(loc,numPts,pts);
332       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
333       cell->Points->SetNumberOfPoints(numPts);
334       break;
335 
336     default:
337       if (!this->EmptyCell)
338         {
339         this->EmptyCell = vtkEmptyCell::New();
340         }
341       cell = this->EmptyCell;
342       return cell;
343     }
344 
345   for (i=0; i < numPts; i++)
346     {
347     cell->PointIds->SetId(i,pts[i]);
348     cell->Points->SetPoint(i,this->Points->GetPoint(pts[i]));
349     }
350 
351   return cell;
352 }
353 
354 //----------------------------------------------------------------------------
GetCell(vtkIdType cellId,vtkGenericCell * cell)355 void vtkPolyData::GetCell(vtkIdType cellId, vtkGenericCell *cell)
356 {
357   int             i, loc;
358   vtkIdType       *pts=0;
359   vtkIdType       numPts;
360   unsigned char   type;
361   double           x[3];
362 
363   if ( !this->Cells )
364     {
365     this->BuildCells();
366     }
367 
368   type = this->Cells->GetCellType(cellId);
369   loc = this->Cells->GetCellLocation(cellId);
370 
371   switch (type)
372     {
373     case VTK_VERTEX:
374       cell->SetCellTypeToVertex();
375       this->Verts->GetCell(loc,numPts,pts);
376       break;
377 
378     case VTK_POLY_VERTEX:
379       cell->SetCellTypeToPolyVertex();
380       this->Verts->GetCell(loc,numPts,pts);
381       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
382       cell->Points->SetNumberOfPoints(numPts);
383       break;
384 
385     case VTK_LINE:
386       cell->SetCellTypeToLine();
387       this->Lines->GetCell(loc,numPts,pts);
388       break;
389 
390     case VTK_POLY_LINE:
391       cell->SetCellTypeToPolyLine();
392       this->Lines->GetCell(loc,numPts,pts);
393       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
394       cell->Points->SetNumberOfPoints(numPts);
395       break;
396 
397     case VTK_TRIANGLE:
398       cell->SetCellTypeToTriangle();
399       this->Polys->GetCell(loc,numPts,pts);
400       break;
401 
402     case VTK_QUAD:
403       cell->SetCellTypeToQuad();
404       this->Polys->GetCell(loc,numPts,pts);
405       break;
406 
407     case VTK_POLYGON:
408       cell->SetCellTypeToPolygon();
409       this->Polys->GetCell(loc,numPts,pts);
410       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
411       cell->Points->SetNumberOfPoints(numPts);
412       break;
413 
414     case VTK_TRIANGLE_STRIP:
415       cell->SetCellTypeToTriangleStrip();
416       this->Strips->GetCell(loc,numPts,pts);
417       cell->PointIds->SetNumberOfIds(numPts); //reset number of points
418       cell->Points->SetNumberOfPoints(numPts);
419       break;
420 
421     default:
422       cell->SetCellTypeToEmptyCell();
423       numPts = 0;
424     }
425 
426   for (i=0; i < numPts; i++)
427     {
428     cell->PointIds->SetId(i,pts[i]);
429     this->Points->GetPoint(pts[i], x);
430     cell->Points->SetPoint(i, x);
431     }
432 }
433 
434 //----------------------------------------------------------------------------
CopyCells(vtkPolyData * pd,vtkIdList * idList,vtkPointLocator * locator)435 void vtkPolyData::CopyCells(vtkPolyData *pd, vtkIdList *idList,
436                             vtkPointLocator *locator)
437 {
438   vtkIdType cellId, ptId, newId, newCellId, locatorPtId;
439   int numPts, numCellPts, i;
440   vtkPoints *newPoints;
441   vtkIdList *pointMap = vtkIdList::New(); //maps old pt ids into new
442   vtkIdList *cellPts, *newCellPts = vtkIdList::New();
443   vtkGenericCell *cell = vtkGenericCell::New();
444   double x[3];
445   vtkPointData *outPD = this->GetPointData();
446   vtkCellData *outCD = this->GetCellData();
447 
448   numPts = pd->GetNumberOfPoints();
449 
450   if (this->GetPoints() == NULL)
451     {
452     this->Points = vtkPoints::New();
453     }
454 
455   newPoints = this->GetPoints();
456 
457   pointMap->SetNumberOfIds(numPts);
458   for (i=0; i < numPts; i++)
459     {
460     pointMap->SetId(i,-1);
461     }
462 
463   // Filter the cells
464   for (cellId=0; cellId < idList->GetNumberOfIds(); cellId++)
465     {
466     pd->GetCell(idList->GetId(cellId), cell);
467     cellPts = cell->GetPointIds();
468     numCellPts = cell->GetNumberOfPoints();
469 
470     for (i=0; i < numCellPts; i++)
471       {
472       ptId = cellPts->GetId(i);
473       if ( (newId = pointMap->GetId(ptId)) < 0 )
474         {
475         pd->GetPoint(ptId, x);
476         if (locator != NULL)
477           {
478           if ((locatorPtId = locator->IsInsertedPoint(x)) == -1)
479             {
480             newId = newPoints->InsertNextPoint(x);
481             locator->InsertNextPoint(x);
482             pointMap->SetId(ptId, newId);
483             outPD->CopyData(pd->GetPointData(), ptId, newId);
484             }
485           else
486             {
487             newId = locatorPtId;
488             }
489           }
490         else
491           {
492           newId = newPoints->InsertNextPoint(x);
493           pointMap->SetId(ptId, newId);
494           outPD->CopyData(pd->GetPointData(), ptId, newId);
495           }
496         }
497       newCellPts->InsertId(i,newId);
498       }
499     newCellId = this->InsertNextCell(cell->GetCellType(), newCellPts);
500     outCD->CopyData(pd->GetCellData(), idList->GetId(cellId), newCellId);
501     newCellPts->Reset();
502     } // for all cells
503   newCellPts->Delete();
504   pointMap->Delete();
505   cell->Delete();
506 }
507 
508 //----------------------------------------------------------------------------
509 // Fast implementation of GetCellBounds().  Bounds are calculated without
510 // constructing a cell.
GetCellBounds(vtkIdType cellId,double bounds[6])511 void vtkPolyData::GetCellBounds(vtkIdType cellId, double bounds[6])
512 {
513   int i, loc;
514   vtkIdType *pts, numPts;
515   unsigned char type;
516   double x[3];
517 
518   if ( !this->Cells )
519     {
520     this->BuildCells();
521     }
522 
523   type = this->Cells->GetCellType(cellId);
524   loc = this->Cells->GetCellLocation(cellId);
525 
526   switch (type)
527     {
528     case VTK_VERTEX:
529     case VTK_POLY_VERTEX:
530       this->Verts->GetCell(loc,numPts,pts);
531       break;
532 
533     case VTK_LINE:
534     case VTK_POLY_LINE:
535       this->Lines->GetCell(loc,numPts,pts);
536       break;
537 
538     case VTK_TRIANGLE:
539     case VTK_QUAD:
540     case VTK_POLYGON:
541       this->Polys->GetCell(loc,numPts,pts);
542       break;
543 
544     case VTK_TRIANGLE_STRIP:
545       this->Strips->GetCell(loc,numPts,pts);
546       break;
547 
548     default:
549       bounds[0] = bounds[1] = bounds[2] = bounds[3] = bounds[4] = bounds[5]
550         = 0.0;
551       return;
552     }
553 
554   // carefully compute the bounds
555   if (numPts)
556     {
557     this->Points->GetPoint( pts[0], x );
558     bounds[0] = x[0];
559     bounds[2] = x[1];
560     bounds[4] = x[2];
561     bounds[1] = x[0];
562     bounds[3] = x[1];
563     bounds[5] = x[2];
564     for (i=1; i < numPts; i++)
565       {
566       this->Points->GetPoint( pts[i], x );
567       bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]);
568       bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]);
569       bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]);
570       bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]);
571       bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]);
572       bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]);
573       }
574     }
575   else
576     {
577     vtkMath::UninitializeBounds(bounds);
578     }
579 }
580 
581 
582 //----------------------------------------------------------------------------
ComputeBounds()583 void vtkPolyData::ComputeBounds()
584 {
585   if (this->GetMTime() > this->ComputeTime)
586     {
587     // If there are no cells, but there are points, back to the
588     // bounds of the points set.
589     if (this->GetNumberOfCells() == 0 && this->GetNumberOfPoints())
590       {
591       vtkPointSet::ComputeBounds();
592       return;
593       }
594 
595     int t, i;
596     vtkIdType *pts = 0;
597     vtkIdType npts = 0;
598     double x[3];
599 
600     vtkCellArray *cella[4];
601 
602     cella[0] = this->GetVerts();
603     cella[1] = this->GetLines();
604     cella[2] = this->GetPolys();
605     cella[3] = this->GetStrips();
606 
607     // carefully compute the bounds
608     int doneOne = 0;
609     this->Bounds[0] = this->Bounds[2] = this->Bounds[4] =  VTK_DOUBLE_MAX;
610     this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX;
611 
612     // Iterate over cells's points
613     for (t = 0; t < 4; t++)
614       {
615       for (cella[t]->InitTraversal(); cella[t]->GetNextCell(npts,pts); )
616         {
617         for (i = 0;  i < npts; i++)
618           {
619           this->Points->GetPoint( pts[i], x );
620           this->Bounds[0] = (x[0] < this->Bounds[0] ? x[0] : this->Bounds[0]);
621           this->Bounds[1] = (x[0] > this->Bounds[1] ? x[0] : this->Bounds[1]);
622           this->Bounds[2] = (x[1] < this->Bounds[2] ? x[1] : this->Bounds[2]);
623           this->Bounds[3] = (x[1] > this->Bounds[3] ? x[1] : this->Bounds[3]);
624           this->Bounds[4] = (x[2] < this->Bounds[4] ? x[2] : this->Bounds[4]);
625           this->Bounds[5] = (x[2] > this->Bounds[5] ? x[2] : this->Bounds[5]);
626           doneOne = 1;
627           }
628         }
629       }
630     if (!doneOne)
631       {
632       vtkMath::UninitializeBounds(this->Bounds);
633       }
634     this->ComputeTime.Modified();
635     }
636 }
637 
638 //----------------------------------------------------------------------------
639 // Set the cell array defining vertices.
SetVerts(vtkCellArray * v)640 void vtkPolyData::SetVerts (vtkCellArray* v)
641 {
642   if (v == this->DummyContainer.Dummy.GetPointer())
643     {
644     v = NULL;
645     }
646   if ( v != this->Verts)
647     {
648     if (this->Verts)
649       {
650       this->Verts->UnRegister(this);
651       }
652     this->Verts = v;
653     if (this->Verts)
654       {
655       this->Verts->Register(this);
656       }
657     this->Modified();
658     }
659 }
660 
661 //----------------------------------------------------------------------------
662 // Get the cell array defining vertices. If there are no vertices, an
663 // empty array will be returned (convenience to simplify traversal).
GetVerts()664 vtkCellArray* vtkPolyData::GetVerts()
665 {
666   if ( !this->Verts )
667     {
668     return this->DummyContainer.Dummy.GetPointer();
669     }
670   else
671     {
672     return this->Verts;
673     }
674 }
675 
676 //----------------------------------------------------------------------------
677 // Set the cell array defining lines.
SetLines(vtkCellArray * l)678 void vtkPolyData::SetLines (vtkCellArray* l)
679 {
680   if (l == this->DummyContainer.Dummy.GetPointer())
681     {
682     l = NULL;
683     }
684   if ( l != this->Lines)
685     {
686     if (this->Lines)
687       {
688       this->Lines->UnRegister(this);
689       }
690     this->Lines = l;
691     if (this->Lines)
692       {
693       this->Lines->Register(this);
694       }
695     this->Modified();
696     }
697 }
698 
699 //----------------------------------------------------------------------------
700 // Get the cell array defining lines. If there are no lines, an
701 // empty array will be returned (convenience to simplify traversal).
GetLines()702 vtkCellArray* vtkPolyData::GetLines()
703 {
704   if ( !this->Lines )
705     {
706     return this->DummyContainer.Dummy.GetPointer();
707     }
708   else
709     {
710     return this->Lines;
711     }
712 }
713 
714 //----------------------------------------------------------------------------
715 // Set the cell array defining polygons.
SetPolys(vtkCellArray * p)716 void vtkPolyData::SetPolys (vtkCellArray* p)
717 {
718   if(p == this->DummyContainer.Dummy.GetPointer())
719     {
720     p = NULL;
721     }
722   if ( p != this->Polys)
723     {
724     if (this->Polys)
725       {
726       this->Polys->UnRegister(this);
727       }
728     this->Polys = p;
729     if (this->Polys)
730       {
731       this->Polys->Register(this);
732       }
733     this->Modified();
734     }
735 }
736 
737 //----------------------------------------------------------------------------
738 // Get the cell array defining polygons. If there are no polygons, an
739 // empty array will be returned (convenience to simplify traversal).
GetPolys()740 vtkCellArray* vtkPolyData::GetPolys()
741 {
742   if ( !this->Polys )
743     {
744     return this->DummyContainer.Dummy.GetPointer();
745     }
746   else
747     {
748     return this->Polys;
749     }
750 }
751 
752 //----------------------------------------------------------------------------
753 // Set the cell array defining triangle strips.
SetStrips(vtkCellArray * s)754 void vtkPolyData::SetStrips (vtkCellArray* s)
755 {
756   if ( s == this->DummyContainer.Dummy.GetPointer())
757     {
758     s = NULL;
759     }
760   if ( s != this->Strips)
761     {
762     if (this->Strips)
763       {
764       this->Strips->UnRegister(this);
765       }
766     this->Strips = s;
767     if (this->Strips)
768       {
769       this->Strips->Register(this);
770       }
771     this->Modified();
772     }
773 }
774 
775 //----------------------------------------------------------------------------
776 // Get the cell array defining triangle strips. If there are no
777 // triangle strips, an empty array will be returned (convenience to
778 // simplify traversal).
GetStrips()779 vtkCellArray* vtkPolyData::GetStrips()
780 {
781   if ( !this->Strips )
782     {
783     return this->DummyContainer.Dummy.GetPointer();
784     }
785   else
786     {
787     return this->Strips;
788     }
789 }
790 
791 //----------------------------------------------------------------------------
Cleanup()792 void vtkPolyData::Cleanup()
793 {
794   if ( this->Verts )
795     {
796     this->Verts->UnRegister(this);
797     this->Verts = NULL;
798     }
799 
800   if ( this->Lines )
801     {
802     this->Lines->UnRegister(this);
803     this->Lines = NULL;
804     }
805 
806   if ( this->Polys )
807     {
808     this->Polys->UnRegister(this);
809     this->Polys = NULL;
810     }
811 
812   if ( this->Strips )
813     {
814     this->Strips->UnRegister(this);
815     this->Strips = NULL;
816     }
817 
818   if ( this->Cells )
819     {
820     this->Cells->UnRegister(this);
821     this->Cells = NULL;
822     }
823 
824   if ( this->Links )
825     {
826     this->Links->UnRegister(this);
827     this->Links = NULL;
828     }
829 }
830 
831 //----------------------------------------------------------------------------
832 // Restore object to initial state. Release memory back to system.
Initialize()833 void vtkPolyData::Initialize()
834 {
835   vtkPointSet::Initialize();
836 
837   this->Cleanup();
838 
839   if(this->Information)
840     {
841     this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1);
842     this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0);
843     this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0);
844     }
845 }
846 
847 //----------------------------------------------------------------------------
GetMaxCellSize()848 int vtkPolyData::GetMaxCellSize()
849 {
850   int maxCellSize=0, cellSize;
851 
852   if ( this->Verts )
853     {
854     cellSize = this->Verts->GetMaxCellSize();
855     if ( cellSize > maxCellSize )
856       {
857       maxCellSize = cellSize;
858       }
859     }
860 
861   if ( this->Lines )
862     {
863     cellSize = this->Lines->GetMaxCellSize();
864     if ( cellSize > maxCellSize )
865       {
866       maxCellSize = cellSize;
867       }
868     }
869 
870   if ( this->Polys )
871     {
872     cellSize = this->Polys->GetMaxCellSize();
873     if ( cellSize > maxCellSize )
874       {
875       maxCellSize = cellSize;
876       }
877     }
878 
879   if ( this->Strips )
880     {
881     cellSize = this->Strips->GetMaxCellSize();
882     if ( cellSize > maxCellSize )
883       {
884       maxCellSize = cellSize;
885       }
886     }
887 
888   return maxCellSize;
889 }
890 
891 //----------------------------------------------------------------------------
GetNumberOfCells()892 vtkIdType vtkPolyData::GetNumberOfCells()
893 {
894   return this->GetNumberOfVerts() + this->GetNumberOfLines() +
895          this->GetNumberOfPolys() + this->GetNumberOfStrips();
896 }
897 
898 //----------------------------------------------------------------------------
GetNumberOfVerts()899 vtkIdType vtkPolyData::GetNumberOfVerts()
900 {
901   return (this->Verts ? this->Verts->GetNumberOfCells() : 0);
902 }
903 
GetNumberOfLines()904 vtkIdType vtkPolyData::GetNumberOfLines()
905 {
906   return (this->Lines ? this->Lines->GetNumberOfCells() : 0);
907 }
908 
GetNumberOfPolys()909 vtkIdType vtkPolyData::GetNumberOfPolys()
910 {
911   return (this->Polys ? this->Polys->GetNumberOfCells() : 0);
912 }
913 
GetNumberOfStrips()914 vtkIdType vtkPolyData::GetNumberOfStrips()
915 {
916   return (this->Strips ? this->Strips->GetNumberOfCells() : 0);
917 }
918 
919 
920 //----------------------------------------------------------------------------
DeleteCells()921 void vtkPolyData::DeleteCells()
922 {
923   // if we have Links, we need to delete them (they are no longer valid)
924   if (this->Links)
925     {
926     this->Links->UnRegister( this );
927     this->Links = NULL;
928     }
929 
930   if (this->Cells)
931     {
932     this->Cells->UnRegister( this );
933     this->Cells = NULL;
934     }
935 }
936 
937 //----------------------------------------------------------------------------
938 // Create data structure that allows random access of cells.
BuildCells()939 void vtkPolyData::BuildCells()
940 {
941   vtkIdType numCells;
942   vtkCellArray *inVerts=this->GetVerts();
943   vtkCellArray *inLines=this->GetLines();
944   vtkCellArray *inPolys=this->GetPolys();
945   vtkCellArray *inStrips=this->GetStrips();
946   vtkIdType npts=0;
947   vtkIdType *pts=0;
948   vtkCellTypes *cells;
949 
950   vtkDebugMacro (<< "Building PolyData cells.");
951 
952   if ( (numCells = this->GetNumberOfCells()) < 1 )
953     {
954     numCells = 1000; //may be allocating empty list to begin with
955     }
956 
957   if (this->Cells)
958     {
959     this->DeleteCells();
960     }
961 
962   this->Cells = cells = vtkCellTypes::New();
963   this->Cells->Allocate(numCells,3*numCells);
964   this->Cells->Register(this);
965   cells->Delete();
966   //
967   // Traverse various lists to create cell array
968   //
969   for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); )
970     {
971     if ( npts > 1 )
972       {
973       cells->InsertNextCell(VTK_POLY_VERTEX,
974                             inVerts->GetTraversalLocation(npts));
975       }
976     else
977       {
978       cells->InsertNextCell(VTK_VERTEX,inVerts->GetTraversalLocation(npts));
979       }
980     }
981 
982   for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
983     {
984     if ( npts > 2 )
985       {
986       cells->InsertNextCell(VTK_POLY_LINE,inLines->GetTraversalLocation(npts));
987       }
988     else
989       {
990       cells->InsertNextCell(VTK_LINE,inLines->GetTraversalLocation(npts));
991       }
992     }
993 
994   for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); )
995     {
996     if ( npts == 3 )
997       {
998       cells->InsertNextCell(VTK_TRIANGLE,inPolys->GetTraversalLocation(npts));
999       }
1000     else if ( npts == 4 )
1001       {
1002       cells->InsertNextCell(VTK_QUAD,inPolys->GetTraversalLocation(npts));
1003       }
1004     else
1005       {
1006       cells->InsertNextCell(VTK_POLYGON,inPolys->GetTraversalLocation(npts));
1007       }
1008     }
1009 
1010   for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
1011     {
1012     cells->InsertNextCell(VTK_TRIANGLE_STRIP,
1013                           inStrips->GetTraversalLocation(npts));
1014     }
1015 }
1016 
1017 //----------------------------------------------------------------------------
DeleteLinks()1018 void vtkPolyData::DeleteLinks()
1019 {
1020   if (this->Links)
1021     {
1022     this->Links->UnRegister( this );
1023     this->Links = NULL;
1024     }
1025 }
1026 
1027 //----------------------------------------------------------------------------
1028 // Create upward links from points to cells that use each point. Enables
1029 // topologically complex queries.
BuildLinks(int initialSize)1030 void vtkPolyData::BuildLinks(int initialSize)
1031 {
1032   if ( this->Links )
1033     {
1034     this->DeleteLinks();
1035     }
1036 
1037   if ( this->Cells == NULL )
1038     {
1039     this->BuildCells();
1040     }
1041 
1042   this->Links = vtkCellLinks::New();
1043   if ( initialSize > 0 )
1044     {
1045     this->Links->Allocate(initialSize);
1046     }
1047   else
1048     {
1049     this->Links->Allocate(this->GetNumberOfPoints());
1050     }
1051   this->Links->Register(this);
1052   this->Links->Delete();
1053 
1054   this->Links->BuildLinks(this);
1055 }
1056 
1057 //----------------------------------------------------------------------------
1058 // Copy a cells point ids into list provided. (Less efficient.)
GetCellPoints(vtkIdType cellId,vtkIdList * ptIds)1059 void vtkPolyData::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds)
1060 {
1061   vtkIdType i;
1062   vtkIdType *pts, npts;
1063 
1064   ptIds->Reset();
1065   if ( this->Cells == NULL )
1066     {
1067     this->BuildCells();
1068     }
1069 
1070   this->vtkPolyData::GetCellPoints(cellId, npts, pts);
1071   ptIds->InsertId (npts-1,pts[npts-1]);
1072   for (i=0; i<npts-1; i++)
1073     {
1074     ptIds->SetId(i,pts[i]);
1075     }
1076 }
1077 
1078 //----------------------------------------------------------------------------
1079 // Return a pointer to a list of point ids defining cell. (More efficient.)
1080 // Assumes that cells have been built (with BuildCells()).
GetCellPoints(vtkIdType cellId,vtkIdType & npts,vtkIdType * & pts)1081 void vtkPolyData::GetCellPoints(vtkIdType cellId, vtkIdType& npts,
1082                                 vtkIdType* &pts)
1083 {
1084   int loc;
1085   unsigned char type;
1086 
1087   type = this->Cells->GetCellType(cellId);
1088   loc = this->Cells->GetCellLocation(cellId);
1089 
1090   switch (type)
1091     {
1092     case VTK_VERTEX: case VTK_POLY_VERTEX:
1093       this->Verts->GetCell(loc,npts,pts);
1094       break;
1095 
1096     case VTK_LINE: case VTK_POLY_LINE:
1097       this->Lines->GetCell(loc,npts,pts);
1098       break;
1099 
1100     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1101       this->Polys->GetCell(loc,npts,pts);
1102       break;
1103 
1104     case VTK_TRIANGLE_STRIP:
1105       this->Strips->GetCell(loc,npts,pts);
1106       break;
1107 
1108     default:
1109       npts = 0;
1110       pts = NULL;
1111     }
1112 }
1113 
1114 //----------------------------------------------------------------------------
GetPointCells(vtkIdType ptId,vtkIdList * cellIds)1115 void vtkPolyData::GetPointCells(vtkIdType ptId, vtkIdList *cellIds)
1116 {
1117   vtkIdType *cells;
1118   vtkIdType numCells;
1119   vtkIdType i;
1120 
1121   if ( ! this->Links )
1122     {
1123     this->BuildLinks();
1124     }
1125   cellIds->Reset();
1126 
1127   numCells = this->Links->GetNcells(ptId);
1128   cells = this->Links->GetCells(ptId);
1129 
1130   for (i=0; i < numCells; i++)
1131     {
1132     cellIds->InsertId(i,cells[i]);
1133     }
1134 }
1135 
1136 //----------------------------------------------------------------------------
1137 // Method allocates initial storage for vertex, line, polygon, and
1138 // triangle strip arrays. Use this method before the method
1139 // PolyData::InsertNextCell(). (Or, provide vertex, line, polygon, and
1140 // triangle strip cell arrays.)
Allocate(vtkIdType numCells,int extSize)1141 void vtkPolyData::Allocate(vtkIdType numCells, int extSize)
1142 {
1143   vtkCellArray *cells;
1144 
1145   if (!this->Cells)
1146     {
1147     this->Cells = vtkCellTypes::New();
1148     this->Cells->Allocate(numCells,3*numCells);
1149     // Consistent Register/UnRegister. (ShallowCopy).
1150     this->Cells->Register(this);
1151     this->Cells->Delete();
1152     }
1153 
1154   cells = vtkCellArray::New();
1155   cells->Allocate(numCells,extSize);
1156   this->SetVerts(cells);
1157   cells->Delete();
1158 
1159   cells = vtkCellArray::New();
1160   cells->Allocate(numCells,extSize);
1161   this->SetLines(cells);
1162   cells->Delete();
1163 
1164   cells = vtkCellArray::New();
1165   cells->Allocate(numCells,extSize);
1166   this->SetPolys(cells);
1167   cells->Delete();
1168 
1169   cells = vtkCellArray::New();
1170   cells->Allocate(numCells,extSize);
1171   this->SetStrips(cells);
1172   cells->Delete();
1173 }
1174 
Allocate(vtkPolyData * inPolyData,vtkIdType numCells,int extSize)1175 void vtkPolyData::Allocate(vtkPolyData *inPolyData, vtkIdType numCells,
1176                            int extSize)
1177 {
1178   vtkCellArray *cells;
1179   int numVerts=inPolyData->GetVerts()->GetNumberOfCells();
1180   int numLines=inPolyData->GetLines()->GetNumberOfCells();
1181   int numPolys=inPolyData->GetPolys()->GetNumberOfCells();
1182   int numStrips=inPolyData->GetStrips()->GetNumberOfCells();
1183   int total=numVerts+numLines+numPolys+numStrips;
1184 
1185   if ( total <= 0 )
1186     {
1187     return;
1188     }
1189 
1190   if (!this->Cells)
1191     {
1192     this->Cells = vtkCellTypes::New();
1193     this->Cells->Allocate(numCells,3*numCells);
1194     // Consistent Register/UnRegister. (ShallowCopy).
1195     this->Cells->Register(this);
1196     this->Cells->Delete();
1197     }
1198 
1199   if ( numVerts > 0 )
1200     {
1201     cells = vtkCellArray::New();
1202     cells->Allocate(
1203       static_cast<int>(static_cast<double>(numVerts)/total*numCells),extSize);
1204     this->SetVerts(cells);
1205     cells->Delete();
1206     }
1207   if ( numLines > 0 )
1208     {
1209     cells = vtkCellArray::New();
1210     cells->Allocate(
1211       static_cast<int>(static_cast<double>(numLines)/total*numCells),extSize);
1212     this->SetLines(cells);
1213     cells->Delete();
1214     }
1215   if ( numPolys > 0 )
1216     {
1217     cells = vtkCellArray::New();
1218     cells->Allocate(
1219       static_cast<int>(static_cast<double>(numPolys)/total*numCells),extSize);
1220     this->SetPolys(cells);
1221     cells->Delete();
1222     }
1223   if ( numStrips > 0 )
1224     {
1225     cells = vtkCellArray::New();
1226     cells->Allocate(
1227       static_cast<int>(static_cast<double>(numStrips)/total*numCells),extSize);
1228     this->SetStrips(cells);
1229     cells->Delete();
1230     }
1231 }
1232 
1233 //----------------------------------------------------------------------------
1234 // Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE,
1235 // VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP.  Make sure that
1236 // the PolyData::Allocate() function has been called first or that vertex,
1237 // line, polygon, and triangle strip arrays have been supplied.
1238 // Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD.
InsertNextCell(int type,int npts,vtkIdType * pts)1239 vtkIdType vtkPolyData::InsertNextCell(int type, int npts, vtkIdType *pts)
1240 {
1241   int id;
1242 
1243   if ( !this->Cells )
1244     {
1245     // if we get to this point, the user has not made any guess at the
1246     // number of cells, so this guess is as good as any
1247     this->Cells = vtkCellTypes::New();
1248     this->Cells->Allocate(5000,10000);
1249     }
1250 
1251   switch (type)
1252     {
1253     case VTK_VERTEX: case VTK_POLY_VERTEX:
1254       this->Verts->InsertNextCell(npts,pts);
1255       id = this->Cells->InsertNextCell(type,
1256                                        this->Verts->GetInsertLocation(npts));
1257       break;
1258 
1259     case VTK_LINE: case VTK_POLY_LINE:
1260       this->Lines->InsertNextCell(npts,pts);
1261       id = this->Cells->InsertNextCell(type,
1262                                        this->Lines->GetInsertLocation(npts));
1263       break;
1264 
1265     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1266       this->Polys->InsertNextCell(npts,pts);
1267       id = this->Cells->InsertNextCell(type,
1268                                        this->Polys->GetInsertLocation(npts));
1269       break;
1270 
1271     case VTK_PIXEL: //need to rearrange vertices
1272       {
1273       vtkIdType pixPts[4];
1274       pixPts[0] = pts[0];
1275       pixPts[1] = pts[1];
1276       pixPts[2] = pts[3];
1277       pixPts[3] = pts[2];
1278       this->Polys->InsertNextCell(npts,pixPts);
1279       id = this->Cells->InsertNextCell(VTK_QUAD,
1280                                        this->Polys->GetInsertLocation(npts));
1281       break;
1282       }
1283 
1284     case VTK_TRIANGLE_STRIP:
1285       this->Strips->InsertNextCell(npts,pts);
1286       id = this->Cells->InsertNextCell(type,
1287                                        this->Strips->GetInsertLocation(npts));
1288       break;
1289 
1290     default:
1291       id = -1;
1292       vtkErrorMacro(<<"Bad cell type! Can't insert!");
1293     }
1294   return id;
1295 }
1296 
1297 //----------------------------------------------------------------------------
1298 // Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE,
1299 // VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP.  Make sure that
1300 // the PolyData::Allocate() function has been called first or that vertex,
1301 // line, polygon, and triangle strip arrays have been supplied.
1302 // Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD.
InsertNextCell(int type,vtkIdList * pts)1303 vtkIdType vtkPolyData::InsertNextCell(int type, vtkIdList *pts)
1304 {
1305   vtkIdType id;
1306   vtkIdType npts = pts->GetNumberOfIds();
1307 
1308   if ( !this->Cells )
1309     {
1310     this->Cells = vtkCellTypes::New();
1311     this->Cells->Allocate(5000,10000);
1312     }
1313 
1314   switch (type)
1315     {
1316     case VTK_VERTEX: case VTK_POLY_VERTEX:
1317       this->Verts->InsertNextCell(pts);
1318       id = this->Cells->InsertNextCell(type, this->Verts->GetInsertLocation(npts));
1319       break;
1320 
1321     case VTK_LINE: case VTK_POLY_LINE:
1322       this->Lines->InsertNextCell(pts);
1323       id = this->Cells->InsertNextCell(type, this->Lines->GetInsertLocation(npts));
1324       break;
1325 
1326     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1327       this->Polys->InsertNextCell(pts);
1328       id = this->Cells->InsertNextCell(type, this->Polys->GetInsertLocation(npts));
1329       break;
1330 
1331     case VTK_PIXEL: //need to rearrange vertices
1332       {
1333       vtkIdType pixPts[4];
1334       pixPts[0] = pts->GetId(0);
1335       pixPts[1] = pts->GetId(1);
1336       pixPts[2] = pts->GetId(3);
1337       pixPts[3] = pts->GetId(2);
1338       this->Polys->InsertNextCell(4,pixPts);
1339       id = this->Cells->InsertNextCell(VTK_QUAD, this->Polys->GetInsertLocation(npts));
1340       break;
1341       }
1342 
1343     case VTK_TRIANGLE_STRIP:
1344       this->Strips->InsertNextCell(pts);
1345       id = this->Cells->InsertNextCell(type, this->Strips->GetInsertLocation(npts));
1346       break;
1347 
1348     case VTK_EMPTY_CELL:
1349       id = -1;
1350       // do nothing
1351       break;
1352 
1353     default:
1354       id = -1;
1355       vtkErrorMacro(<<"Bad cell type! Can't insert!");
1356     }
1357 
1358   return id;
1359 }
1360 
1361 //----------------------------------------------------------------------------
1362 // Recover extra allocated memory when creating data whose initial size
1363 // is unknown. Examples include using the InsertNextCell() method, or
1364 // when using the CellArray::EstimateSize() method to create vertices,
1365 // lines, polygons, or triangle strips.
Squeeze()1366 void vtkPolyData::Squeeze()
1367 {
1368   if ( this->Verts != NULL )
1369     {
1370     this->Verts->Squeeze();
1371     }
1372   if ( this->Lines != NULL )
1373     {
1374     this->Lines->Squeeze();
1375     }
1376   if ( this->Polys != NULL )
1377     {
1378     this->Polys->Squeeze();
1379     }
1380   if ( this->Strips != NULL )
1381     {
1382     this->Strips->Squeeze();
1383     }
1384 
1385   vtkPointSet::Squeeze();
1386 }
1387 
1388 //----------------------------------------------------------------------------
1389 // Begin inserting data all over again. Memory is not freed but otherwise
1390 // objects are returned to their initial state.
Reset()1391 void vtkPolyData::Reset()
1392 {
1393   if ( this->Verts != NULL )
1394     {
1395     this->Verts->Reset();
1396     }
1397   if ( this->Lines != NULL )
1398     {
1399     this->Lines->Reset();
1400     }
1401   if ( this->Polys != NULL )
1402     {
1403     this->Polys->Reset();
1404     }
1405   if ( this->Strips != NULL )
1406     {
1407     this->Strips->Reset();
1408     }
1409 }
1410 
1411 //----------------------------------------------------------------------------
1412 // Reverse the order of point ids defining the cell.
ReverseCell(vtkIdType cellId)1413 void vtkPolyData::ReverseCell(vtkIdType cellId)
1414 {
1415   int loc, type;
1416 
1417   if ( this->Cells == NULL )
1418     {
1419     this->BuildCells();
1420     }
1421   loc = this->Cells->GetCellLocation(cellId);
1422   type = this->Cells->GetCellType(cellId);
1423 
1424   switch (type)
1425     {
1426     case VTK_VERTEX: case VTK_POLY_VERTEX:
1427      this->Verts->ReverseCell(loc);
1428      break;
1429 
1430     case VTK_LINE: case VTK_POLY_LINE:
1431       this->Lines->ReverseCell(loc);
1432       break;
1433 
1434     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1435       this->Polys->ReverseCell(loc);
1436       break;
1437 
1438     case VTK_TRIANGLE_STRIP:
1439       this->Strips->ReverseCell(loc);
1440       break;
1441 
1442     default:
1443       break;
1444     }
1445 }
1446 
1447 //----------------------------------------------------------------------------
1448 // Add a point to the cell data structure (after cell pointers have been
1449 // built). This method allocates memory for the links to the cells.  (To
1450 // use this method, make sure points are available and BuildLinks() has been invoked.)
InsertNextLinkedPoint(int numLinks)1451 vtkIdType vtkPolyData::InsertNextLinkedPoint(int numLinks)
1452 {
1453   return this->Links->InsertNextPoint(numLinks);
1454 }
1455 
1456 //----------------------------------------------------------------------------
1457 // Add a point to the cell data structure (after cell pointers have been
1458 // built). This method adds the point and then allocates memory for the
1459 // links to the cells.  (To use this method, make sure points are available
1460 // and BuildLinks() has been invoked.)
InsertNextLinkedPoint(double x[3],int numLinks)1461 vtkIdType vtkPolyData::InsertNextLinkedPoint(double x[3], int numLinks)
1462 {
1463   this->Links->InsertNextPoint(numLinks);
1464   return this->Points->InsertNextPoint(x);
1465 }
1466 
1467 //----------------------------------------------------------------------------
1468 // Add a new cell to the cell data structure (after cell pointers have been
1469 // built). This method adds the cell and then updates the links from the points
1470 // to the cells. (Memory is allocated as necessary.)
InsertNextLinkedCell(int type,int npts,vtkIdType * pts)1471 vtkIdType vtkPolyData::InsertNextLinkedCell(int type, int npts, vtkIdType *pts)
1472 {
1473   vtkIdType i, id;
1474 
1475   id = this->InsertNextCell(type,npts,pts);
1476 
1477   for (i=0; i<npts; i++)
1478     {
1479     this->Links->ResizeCellList(pts[i],1);
1480     this->Links->AddCellReference(id,pts[i]);
1481     }
1482 
1483   return id;
1484 }
1485 
1486 //----------------------------------------------------------------------------
1487 // Remove a reference to a cell in a particular point's link list. You may also
1488 // consider using RemoveCellReference() to remove the references from all the
1489 // cell's points to the cell. This operator does not reallocate memory; use the
1490 // operator ResizeCellList() to do this if necessary.
RemoveReferenceToCell(vtkIdType ptId,vtkIdType cellId)1491 void vtkPolyData::RemoveReferenceToCell(vtkIdType ptId, vtkIdType cellId)
1492 {
1493   this->Links->RemoveCellReference(cellId, ptId);
1494 }
1495 
1496 //----------------------------------------------------------------------------
1497 // Add a reference to a cell in a particular point's link list. (You may also
1498 // consider using AddCellReference() to add the references from all the
1499 // cell's points to the cell.) This operator does not realloc memory; use the
1500 // operator ResizeCellList() to do this if necessary.
AddReferenceToCell(vtkIdType ptId,vtkIdType cellId)1501 void vtkPolyData::AddReferenceToCell(vtkIdType ptId, vtkIdType cellId)
1502 {
1503   this->Links->AddCellReference(cellId, ptId);
1504 }
1505 
1506 //----------------------------------------------------------------------------
1507 // Replace the points defining cell "cellId" with a new set of points. This
1508 // operator is (typically) used when links from points to cells have not been
1509 // built (i.e., BuildLinks() has not been executed). Use the operator
1510 // ReplaceLinkedCell() to replace a cell when cell structure has been built.
ReplaceCell(vtkIdType cellId,int npts,vtkIdType * pts)1511 void vtkPolyData::ReplaceCell(vtkIdType cellId, int npts, vtkIdType *pts)
1512 {
1513   int loc, type;
1514 
1515   if ( this->Cells == NULL )
1516     {
1517     this->BuildCells();
1518     }
1519   loc = this->Cells->GetCellLocation(cellId);
1520   type = this->Cells->GetCellType(cellId);
1521 
1522   switch (type)
1523     {
1524     case VTK_VERTEX: case VTK_POLY_VERTEX:
1525      this->Verts->ReplaceCell(loc,npts,pts);
1526      break;
1527 
1528     case VTK_LINE: case VTK_POLY_LINE:
1529       this->Lines->ReplaceCell(loc,npts,pts);
1530       break;
1531 
1532     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1533       this->Polys->ReplaceCell(loc,npts,pts);
1534       break;
1535 
1536     case VTK_TRIANGLE_STRIP:
1537       this->Strips->ReplaceCell(loc,npts,pts);
1538       break;
1539 
1540     default:
1541       break;
1542     }
1543 }
1544 
1545 //----------------------------------------------------------------------------
1546 // Replace one cell with another in cell structure. This operator updates the
1547 // connectivity list and the point's link list. It does not delete references
1548 // to the old cell in the point's link list. Use the operator
1549 // RemoveCellReference() to delete all references from points to (old) cell.
1550 // You may also want to consider using the operator ResizeCellList() if the
1551 // link list is changing size.
ReplaceLinkedCell(vtkIdType cellId,int npts,vtkIdType * pts)1552 void vtkPolyData::ReplaceLinkedCell(vtkIdType cellId, int npts, vtkIdType *pts)
1553 {
1554   int loc = this->Cells->GetCellLocation(cellId);
1555   int type = this->Cells->GetCellType(cellId);
1556 
1557   switch (type)
1558     {
1559     case VTK_VERTEX: case VTK_POLY_VERTEX:
1560      this->Verts->ReplaceCell(loc,npts,pts);
1561      break;
1562 
1563     case VTK_LINE: case VTK_POLY_LINE:
1564       this->Lines->ReplaceCell(loc,npts,pts);
1565       break;
1566 
1567     case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON:
1568       this->Polys->ReplaceCell(loc,npts,pts);
1569       break;
1570 
1571     case VTK_TRIANGLE_STRIP:
1572       this->Strips->ReplaceCell(loc,npts,pts);
1573       break;
1574 
1575     default:
1576       npts = 0;
1577     }
1578 
1579   for (int i=0; i < npts; i++)
1580     {
1581     this->Links->InsertNextCellReference(pts[i],cellId);
1582     }
1583 }
1584 
1585 //----------------------------------------------------------------------------
1586 // Get the neighbors at an edge. More efficient than the general
1587 // GetCellNeighbors(). Assumes links have been built (with BuildLinks()),
1588 // and looks specifically for edge neighbors.
GetCellEdgeNeighbors(vtkIdType cellId,vtkIdType p1,vtkIdType p2,vtkIdList * cellIds)1589 void vtkPolyData::GetCellEdgeNeighbors(vtkIdType cellId, vtkIdType p1,
1590                                        vtkIdType p2, vtkIdList *cellIds)
1591 {
1592   cellIds->Reset();
1593 
1594   const vtkCellLinks::Link &link1(this->Links->GetLink(p1));
1595   const vtkCellLinks::Link &link2(this->Links->GetLink(p2));
1596 
1597   const vtkIdType *cells1 = link1.cells;
1598   const vtkIdType *cells1End = cells1 + link1.ncells;
1599 
1600   const vtkIdType *cells2 = link2.cells;
1601   const vtkIdType *cells2End = cells2 + link2.ncells;
1602 
1603   while (cells1 != cells1End)
1604     {
1605     if (*cells1 != cellId)
1606       {
1607       const vtkIdType *cells2Cur(cells2);
1608       while (cells2Cur != cells2End)
1609         {
1610         if (*cells1 == *cells2Cur)
1611           {
1612           cellIds->InsertNextId(*cells1);
1613           break;
1614           }
1615         ++cells2Cur;
1616         }
1617       }
1618     ++cells1;
1619     }
1620 }
1621 
1622 //----------------------------------------------------------------------------
GetCellNeighbors(vtkIdType cellId,vtkIdList * ptIds,vtkIdList * cellIds)1623 void vtkPolyData::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds,
1624                                    vtkIdList *cellIds)
1625 {
1626   vtkIdType i, j, numPts, cellNum;
1627   int allFound, oneFound;
1628 
1629   if ( ! this->Links )
1630     {
1631     this->BuildLinks();
1632     }
1633 
1634   cellIds->Reset();
1635 
1636   // load list with candidate cells, remove current cell
1637   vtkIdType ptId = ptIds->GetId(0);
1638   int numPrime = this->Links->GetNcells(ptId);
1639   vtkIdType *primeCells = this->Links->GetCells(ptId);
1640   numPts = ptIds->GetNumberOfIds();
1641 
1642   // for each potential cell
1643   for (cellNum = 0; cellNum < numPrime; cellNum++)
1644     {
1645     // ignore the original cell
1646     if (primeCells[cellNum] != cellId)
1647       {
1648       // are all the remaining points in the cell ?
1649       for (allFound=1, i=1; i < numPts && allFound; i++)
1650         {
1651         ptId = ptIds->GetId(i);
1652         int numCurrent = this->Links->GetNcells(ptId);
1653         vtkIdType *currentCells = this->Links->GetCells(ptId);
1654         oneFound = 0;
1655         for (j = 0; j < numCurrent; j++)
1656           {
1657           if (primeCells[cellNum] == currentCells[j])
1658             {
1659             oneFound = 1;
1660             break;
1661             }
1662           }
1663         if (!oneFound)
1664           {
1665           allFound = 0;
1666           }
1667         }
1668       if (allFound)
1669         {
1670         cellIds->InsertNextId(primeCells[cellNum]);
1671         }
1672       }
1673     }
1674 }
1675 
IsEdge(vtkIdType p1,vtkIdType p2)1676 int vtkPolyData::IsEdge(vtkIdType p1, vtkIdType p2)
1677 {
1678   unsigned short int ncells;
1679   vtkIdType cellType;
1680   vtkIdType npts;
1681   vtkIdType i, j;
1682   vtkIdType *cells, *pts;
1683 
1684   this->GetPointCells(p1,ncells,cells);
1685   for (i=0; i<ncells; i++)
1686     {
1687     cellType = this->GetCellType(cells[i]);
1688     switch (cellType)
1689       {
1690       case VTK_EMPTY_CELL: case VTK_VERTEX: case VTK_POLY_VERTEX: case VTK_LINE: case VTK_POLY_LINE:
1691         break;
1692       case VTK_TRIANGLE:
1693         if ( this->IsPointUsedByCell(p2,cells[i]) )
1694           {
1695           return 1;
1696           }
1697         break;
1698       case VTK_QUAD:
1699         this->GetCellPoints(cells[i],npts,pts);
1700         for (j=0; j<npts-1; j++)
1701           {
1702           if (((pts[j]==p1)&&(pts[j+1]==p2))||((pts[j]==p2)&&(pts[j+1]==p1)))
1703             {
1704             return 1;
1705             }
1706           }
1707         if (((pts[0]==p1)&&(pts[npts-1]==p2))||((pts[0]==p2)&&(pts[npts-1]==p1)))
1708           {
1709           return 1;
1710           }
1711         break;
1712       case VTK_TRIANGLE_STRIP:
1713         this->GetCellPoints(cells[i],npts,pts);
1714         for (j=0; j<npts-2; j++)
1715           {
1716           if ((((pts[j]==p1)&&(pts[j+1]==p2))||((pts[j]==p2)&&(pts[j+1]==p1)))||
1717               (((pts[j]==p1)&&(pts[j+2]==p2))||((pts[j]==p2)&&(pts[j+2]==p1))))
1718             {
1719             return 1;
1720             }
1721           }
1722         if (((pts[npts-2]==p1)&&(pts[npts-1]==p2))||((pts[npts-2]==p2)&&(pts[npts-1]==p1)))
1723           {
1724           return 1;
1725           }
1726         break;
1727       default:
1728         this->GetCellPoints(cells[i],npts,pts);
1729         for (j=0; j<npts; j++)
1730           {
1731           if (p1==pts[j])
1732             {
1733             if ((pts[(j-1+npts)%npts]==p2)||(pts[(j+1)%npts]==p2))
1734               {
1735               return 1;
1736               }
1737             }
1738           }
1739       }
1740     }
1741   return 0;
1742 }
1743 
1744 //----------------------------------------------------------------------------
1745 
GetActualMemorySize()1746 unsigned long vtkPolyData::GetActualMemorySize()
1747 {
1748   unsigned long size=this->vtkPointSet::GetActualMemorySize();
1749   if ( this->Verts )
1750     {
1751     size += this->Verts->GetActualMemorySize();
1752     }
1753   if ( this->Lines )
1754     {
1755     size += this->Lines->GetActualMemorySize();
1756     }
1757   if ( this->Polys )
1758     {
1759     size += this->Polys->GetActualMemorySize();
1760     }
1761   if ( this->Strips )
1762     {
1763     size += this->Strips->GetActualMemorySize();
1764     }
1765   if ( this->Cells )
1766     {
1767     size += this->Cells->GetActualMemorySize();
1768     }
1769   if ( this->Links )
1770     {
1771     size += this->Links->GetActualMemorySize();
1772     }
1773   return size;
1774 }
1775 
1776 //----------------------------------------------------------------------------
ShallowCopy(vtkDataObject * dataObject)1777 void vtkPolyData::ShallowCopy(vtkDataObject *dataObject)
1778 {
1779   vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject);
1780   if (this == polyData)
1781      return;
1782 
1783   if ( polyData != NULL )
1784     {
1785     this->SetVerts(polyData->GetVerts());
1786     this->SetLines(polyData->GetLines());
1787     this->SetPolys(polyData->GetPolys());
1788     this->SetStrips(polyData->GetStrips());
1789 
1790     // I do not know if this is correct but.
1791     if (this->Cells)
1792       {
1793       this->Cells->UnRegister(this);
1794       }
1795     this->Cells = polyData->Cells;
1796     if (this->Cells)
1797       {
1798       this->Cells->Register(this);
1799       }
1800 
1801     if (this->Links)
1802       {
1803       this->Links->Delete();
1804       }
1805     this->Links = polyData->Links;
1806     if (this->Links)
1807       {
1808       this->Links->Register(this);
1809       }
1810     }
1811 
1812   // Do superclass
1813   this->vtkPointSet::ShallowCopy(dataObject);
1814 }
1815 
1816 //----------------------------------------------------------------------------
DeepCopy(vtkDataObject * dataObject)1817 void vtkPolyData::DeepCopy(vtkDataObject *dataObject)
1818 {
1819   // Do superclass
1820   // We have to do this BEFORE we call BuildLinks, else there are no points
1821   // to build the links on (the parent DeepCopy copies the points)
1822   this->vtkPointSet::DeepCopy(dataObject);
1823 
1824   vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject);
1825 
1826   if ( polyData != NULL )
1827     {
1828     vtkCellArray *ca;
1829     ca = vtkCellArray::New();
1830     ca->DeepCopy(polyData->GetVerts());
1831     this->SetVerts(ca);
1832     ca->Delete();
1833 
1834     ca = vtkCellArray::New();
1835     ca->DeepCopy(polyData->GetLines());
1836     this->SetLines(ca);
1837     ca->Delete();
1838 
1839     ca = vtkCellArray::New();
1840     ca->DeepCopy(polyData->GetPolys());
1841     this->SetPolys(ca);
1842     ca->Delete();
1843 
1844     ca = vtkCellArray::New();
1845     ca->DeepCopy(polyData->GetStrips());
1846     this->SetStrips(ca);
1847     ca->Delete();
1848 
1849     if ( this->Cells )
1850       {
1851       this->Cells->UnRegister(this);
1852       this->Cells = NULL;
1853       }
1854     if (polyData->Cells)
1855       {
1856       this->BuildCells();
1857       }
1858 
1859     if ( this->Links )
1860       {
1861       this->Links->UnRegister(this);
1862       this->Links = NULL;
1863       }
1864     if (polyData->Links)
1865       {
1866       this->BuildLinks();
1867       }
1868     }
1869 }
1870 
RemoveGhostCells(int level)1871 void vtkPolyData::RemoveGhostCells(int level)
1872 {
1873   // Get a pointer to the cell ghost level array.
1874   vtkUnsignedCharArray* temp = vtkUnsignedCharArray::SafeDownCast(
1875     this->CellData->GetArray("vtkGhostLevels"));
1876   if (temp == NULL)
1877     {
1878     vtkDebugMacro("Could not find cell ghost level array.");
1879     return;
1880     }
1881   if (temp->GetNumberOfComponents() != 1 ||
1882       temp->GetNumberOfTuples() < this->GetNumberOfCells())
1883     {
1884     vtkErrorMacro("Poorly formed ghost level array.");
1885     return;
1886     }
1887   unsigned char* cellGhostLevels = temp->GetPointer(0);
1888 
1889   vtkIdType numCells = this->GetNumberOfCells();
1890 
1891   vtkIntArray *types = vtkIntArray::New();
1892   types->SetNumberOfValues(numCells);
1893 
1894   for (vtkIdType i = 0; i < numCells; i++)
1895     {
1896     types->SetValue(i, this->GetCellType(i));
1897     }
1898 
1899   this->DeleteCells();
1900 
1901   // we have to make new copies of Verts, Lines, Polys
1902   // and Strips since they may be shared with other polydata
1903   vtkSmartPointer<vtkCellArray> verts;
1904   if(this->Verts)
1905     {
1906     verts = this->Verts;
1907     verts->InitTraversal();
1908     this->Verts->UnRegister(this);
1909     this->Verts = vtkCellArray::New();
1910     }
1911 
1912   vtkSmartPointer<vtkCellArray> lines;
1913   if(this->Lines)
1914     {
1915     lines = this->Lines;
1916     lines->InitTraversal();
1917     this->Lines->UnRegister(this);
1918     this->Lines = vtkCellArray::New();
1919     }
1920 
1921   vtkSmartPointer<vtkCellArray> polys;
1922   if(this->Polys)
1923     {
1924     polys = this->Polys;
1925     polys->InitTraversal();
1926     this->Polys->UnRegister(this);
1927     this->Polys = vtkCellArray::New();
1928     }
1929 
1930   vtkSmartPointer<vtkCellArray> strips;
1931   if(this->Strips)
1932     {
1933     strips = this->Strips;
1934     strips->InitTraversal();
1935     this->Strips->UnRegister(this);
1936     this->Strips = vtkCellArray::New();
1937     }
1938 
1939   vtkCellData *newCellData = vtkCellData::New();
1940   newCellData->CopyAllocate(this->CellData, numCells);
1941 
1942   vtkIdType *pts, n;
1943 
1944   int cellId;
1945 
1946   for (vtkIdType i = 0; i < numCells; i++)
1947     {
1948     int type = types->GetValue(i);
1949 
1950     if (type == VTK_VERTEX || type == VTK_POLY_VERTEX)
1951       {
1952       verts->GetNextCell(n, pts);
1953 
1954       if (int(cellGhostLevels[i]) < level)
1955         {
1956         cellId = this->InsertNextCell(type, n, pts);
1957         newCellData->CopyData(this->CellData, i, cellId);
1958         }
1959       }
1960     else if (type == VTK_LINE || type == VTK_POLY_LINE)
1961       {
1962       lines->GetNextCell(n, pts);
1963 
1964       if (int(cellGhostLevels[i]) < level)
1965         {
1966         cellId = this->InsertNextCell(type, n, pts);
1967         newCellData->CopyData(this->CellData, i, cellId);
1968         }
1969       }
1970     else if (type == VTK_POLYGON || type == VTK_TRIANGLE || type == VTK_QUAD)
1971       {
1972       polys->GetNextCell(n, pts);
1973 
1974       if (int(cellGhostLevels[i]) < level)
1975         {
1976         cellId = this->InsertNextCell(type, n, pts);
1977         newCellData->CopyData(this->CellData, i, cellId);
1978         }
1979       }
1980     else if (type == VTK_TRIANGLE_STRIP)
1981       {
1982       strips->GetNextCell(n, pts);
1983 
1984       if (int(cellGhostLevels[i]) < level)
1985         {
1986         cellId = this->InsertNextCell(type, n, pts);
1987         newCellData->CopyData(this->CellData, i, cellId);
1988         }
1989       }
1990     }
1991 
1992   newCellData->Squeeze();
1993 
1994   this->CellData->ShallowCopy(newCellData);
1995   newCellData->Delete();
1996 
1997   types->Delete();
1998 
1999   // If there are no more ghost levels, then remove all arrays.
2000   if (level <= 1)
2001     {
2002     this->CellData->RemoveArray("vtkGhostLevels");
2003     this->PointData->RemoveArray("vtkGhostLevels");
2004     }
2005 
2006   this->Squeeze();
2007 }
2008 //----------------------------------------------------------------------------
RemoveDeletedCells()2009 void vtkPolyData::RemoveDeletedCells()
2010 {
2011   if (!this->Cells)
2012     {
2013       return;
2014     }
2015 
2016   vtkNew<vtkPolyData> oldData;
2017   oldData->ShallowCopy(this);
2018   this->DeleteCells();
2019 
2020   if(this->Verts)
2021     {
2022     this->Verts->UnRegister(this);
2023     this->Verts = vtkCellArray::New();
2024     }
2025   if(this->Lines)
2026     {
2027     this->Lines->UnRegister(this);
2028     this->Lines = vtkCellArray::New();
2029     }
2030   if(this->Polys)
2031     {
2032     this->Polys->UnRegister(this);
2033     this->Polys = vtkCellArray::New();
2034     }
2035   if(this->Strips)
2036     {
2037     this->Strips->UnRegister(this);
2038     this->Strips = vtkCellArray::New();
2039     }
2040 
2041   this->CellData->CopyAllocate(oldData->GetCellData());
2042 
2043   const vtkIdType numCells = oldData->GetNumberOfCells();
2044   vtkCell *cell;
2045   vtkIdType cellId;
2046   vtkIdList *pointIds;
2047   int type;
2048   for (vtkIdType i = 0; i < numCells; i++)
2049     {
2050     type = oldData->GetCellType(i);
2051 
2052     if (type != VTK_EMPTY_CELL)
2053       {
2054       cell = oldData->GetCell(i);
2055       pointIds = cell->GetPointIds();
2056       cellId = this->InsertNextCell(type, pointIds);
2057       this->CellData->CopyData(oldData->GetCellData(), i, cellId);
2058       }
2059     }
2060 
2061   this->CellData->Squeeze();
2062 }
2063 //----------------------------------------------------------------------------
GetData(vtkInformation * info)2064 vtkPolyData* vtkPolyData::GetData(vtkInformation* info)
2065 {
2066   return info? vtkPolyData::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
2067 }
2068 
2069 //----------------------------------------------------------------------------
GetData(vtkInformationVector * v,int i)2070 vtkPolyData* vtkPolyData::GetData(vtkInformationVector* v, int i)
2071 {
2072   return vtkPolyData::GetData(v->GetInformationObject(i));
2073 }
2074 
2075 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)2076 void vtkPolyData::PrintSelf(ostream& os, vtkIndent indent)
2077 {
2078   this->Superclass::PrintSelf(os,indent);
2079 
2080   os << indent << "Number Of Vertices: " << this->GetNumberOfVerts() << "\n";
2081   os << indent << "Number Of Lines: " << this->GetNumberOfLines() << "\n";
2082   os << indent << "Number Of Polygons: " << this->GetNumberOfPolys() << "\n";
2083   os << indent << "Number Of Triangle Strips: " << this->GetNumberOfStrips() << "\n";
2084 
2085   os << indent << "Number Of Pieces: " << this->GetNumberOfPieces() << endl;
2086   os << indent << "Piece: " << this->GetPiece() << endl;
2087   os << indent << "Ghost Level: " << this->GetGhostLevel() << endl;
2088 }
2089 
2090 
2091 //----------------------------------------------------------------------------
GetScalarFieldCriticalIndex(vtkIdType pointId,vtkDataArray * scalarField)2092 int vtkPolyData::GetScalarFieldCriticalIndex (vtkIdType pointId,
2093                                               vtkDataArray *scalarField)
2094 {
2095   /*
2096    * implements scalar field critical point classification for manifold
2097    * 2D meshes.
2098    */
2099 
2100   /*
2101    * returned value:
2102    *   -4: no such field
2103    *   -3: attribute check failed
2104    *   -2: non 2-manifold star
2105    *   -1: regular point
2106    *   0: minimum
2107    *   1: saddle
2108    *   2: maximum
2109    */
2110 
2111   bool  is_min = true, is_max = true;
2112   vtkIdList *starTriangleList = vtkIdList::New(),
2113             *lowerLinkPointList = vtkIdList::New(),
2114             *upperLinkPointList = vtkIdList::New(),
2115             *pointList = NULL;
2116   double pointFieldValue = scalarField->GetComponent(pointId, 0),
2117          neighborFieldValue = 0;
2118 
2119   if(this->GetNumberOfPoints() != scalarField->GetSize())
2120     return vtkPolyData::ERR_INCORRECT_FIELD;
2121 
2122   /* make sure the connectivity is built */
2123   if(!this->Links) this->BuildLinks();
2124 
2125   /* build the lower and upper links */
2126   this->GetPointCells(pointId, starTriangleList);
2127   int starNb = starTriangleList->GetNumberOfIds();
2128   for(int i = 0; i < starNb; i++)
2129     {
2130     vtkCell *c = this->GetCell(starTriangleList->GetId(i));
2131     pointList = c->GetPointIds();
2132     int pointNb = pointList->GetNumberOfIds();
2133     if(pointNb != 3)
2134       {
2135       starTriangleList->Delete();
2136       lowerLinkPointList->Delete();
2137       upperLinkPointList->Delete();
2138       return vtkPolyData::ERR_NON_MANIFOLD_STAR;
2139       }
2140 
2141     for(int j = 0; j < pointNb; j++)
2142       {
2143       vtkIdType  currentPointId = pointList->GetId(j);
2144 
2145       /* quick check for extrema */
2146       neighborFieldValue = scalarField->GetComponent(currentPointId, 0);
2147       if((currentPointId != pointId)&&(neighborFieldValue == pointFieldValue))
2148         {
2149         /* simulation of simplicity (Edelsbrunner et al. ACM ToG 1990) */
2150         if(currentPointId > pointId)
2151           {
2152           is_max = false;
2153           upperLinkPointList->InsertUniqueId(currentPointId);
2154           }
2155         if(currentPointId < pointId)
2156           {
2157           is_min = false;
2158           lowerLinkPointList->InsertUniqueId(currentPointId);
2159           }
2160         }
2161       else
2162         {
2163         if(neighborFieldValue > pointFieldValue)
2164           {
2165           is_max = false;
2166           upperLinkPointList->InsertUniqueId(currentPointId);
2167           }
2168         if(neighborFieldValue < pointFieldValue)
2169           {
2170           is_min = false;
2171           lowerLinkPointList->InsertUniqueId(currentPointId);
2172           }
2173         }
2174       }
2175     }
2176 
2177   if((is_max)||(is_min))
2178     {
2179     starTriangleList->Delete();
2180     lowerLinkPointList->Delete();
2181     upperLinkPointList->Delete();
2182     if(is_max) return vtkPolyData::MAXIMUM;
2183     if(is_min) return vtkPolyData::MINIMUM;
2184     }
2185 
2186   /*
2187    * is the vertex really regular?
2188    * (lower and upper links are BOTH simply connected)
2189    */
2190   int visitedPointNb = 0, stackBottom = 0,
2191       lowerLinkPointNb = lowerLinkPointList->GetNumberOfIds(),
2192       upperLinkPointNb = upperLinkPointList->GetNumberOfIds();
2193 
2194   /* first, check lower link's simply connectedness */
2195   vtkIdList *stack = vtkIdList::New();
2196   stack->InsertUniqueId(lowerLinkPointList->GetId(0));
2197   vtkIdType currentPointId = stack->GetId(stackBottom), nextPointId = -1;
2198   do
2199     {
2200     stackBottom++;
2201     vtkIdList *triangleList = vtkIdList::New();
2202     this->GetPointCells(currentPointId, triangleList);
2203     int triangleNb = triangleList->GetNumberOfIds();
2204 
2205     for(int i = 0; i < triangleNb; i++)
2206       {
2207       vtkCell *c = this->GetCell(triangleList->GetId(i));
2208       pointList = c->GetPointIds();;
2209       int pointNb = pointList->GetNumberOfIds();
2210 
2211       if(pointList->IsId(pointId) >= 0)
2212         {
2213         // those two triangles are in the star of pointId
2214         int j = 0;
2215         do
2216           {
2217           nextPointId = pointList->GetId(j);
2218           j++;
2219           }while(((nextPointId == pointId)
2220           ||(nextPointId == currentPointId))&&(j < pointNb ));
2221         }
2222 
2223       if(lowerLinkPointList->IsId(nextPointId) >= 0)
2224         {
2225         stack->InsertUniqueId(nextPointId);
2226         }
2227 
2228       }
2229 
2230     triangleList->Delete();
2231     visitedPointNb++;
2232 
2233     currentPointId = stack->GetId(stackBottom), nextPointId = -1;
2234 
2235   }while(stackBottom < stack->GetNumberOfIds());
2236 
2237   if(visitedPointNb != lowerLinkPointNb)
2238     {
2239     // the lower link is not simply connected, then it's a saddle
2240     stack->Delete();
2241     starTriangleList->Delete();
2242     lowerLinkPointList->Delete();
2243     upperLinkPointList->Delete();
2244     return vtkPolyData::SADDLE;
2245     }
2246 
2247   /*
2248    * then, check upper link's simply connectedness.
2249    * BOTH need to be checked if the 2-manifold has boundary components.
2250    */
2251   stackBottom = 0;
2252   visitedPointNb = 0;
2253   stack->Delete();
2254   stack = vtkIdList::New();
2255   stack->InsertUniqueId(upperLinkPointList->GetId(0));
2256   currentPointId = stack->GetId(stackBottom), nextPointId = -1;
2257   do
2258     {
2259     stackBottom++;
2260     vtkIdList *triangleList = vtkIdList::New();
2261     this->GetPointCells(currentPointId, triangleList);
2262     int triangleNb = triangleList->GetNumberOfIds();
2263 
2264     for(int i = 0; i < triangleNb; i++)
2265       {
2266       vtkCell *c = this->GetCell(triangleList->GetId(i));
2267       pointList = c->GetPointIds();
2268       int pointNb = pointList->GetNumberOfIds();
2269 
2270       if(pointList->IsId(pointId) >= 0)
2271         {
2272         // those two triangles are in the star of pointId
2273         int j = 0;
2274         do
2275           {
2276           nextPointId = pointList->GetId(j);
2277           j++;
2278           }while(((nextPointId == pointId)
2279           ||(nextPointId == currentPointId))&&(j < pointNb));
2280         }
2281 
2282       if(upperLinkPointList->IsId(nextPointId) >= 0)
2283         {
2284         stack->InsertUniqueId(nextPointId);
2285         }
2286       }
2287 
2288     triangleList->Delete();
2289     visitedPointNb++;
2290 
2291     currentPointId = stack->GetId(stackBottom), nextPointId = -1;
2292     }while(stackBottom < stack->GetNumberOfIds());
2293 
2294   if(visitedPointNb != upperLinkPointNb)
2295     {
2296     // the upper link is not simply connected, then it's a saddle
2297     stack->Delete();
2298     starTriangleList->Delete();
2299     lowerLinkPointList->Delete();
2300     upperLinkPointList->Delete();
2301     return vtkPolyData::SADDLE;
2302     }
2303 
2304   /* else it's necessarily a regular point (only 4 cases in 2D)*/
2305   stack->Delete();
2306   starTriangleList->Delete();
2307   lowerLinkPointList->Delete();
2308   upperLinkPointList->Delete();
2309   return vtkPolyData::REGULAR_POINT;
2310 }
2311 
2312 //----------------------------------------------------------------------------
GetScalarFieldCriticalIndex(vtkIdType pointId,const char * fieldName)2313 int vtkPolyData::GetScalarFieldCriticalIndex (vtkIdType pointId,
2314                                               const char* fieldName)
2315 {
2316   /*
2317    * returned value:
2318    *   -4: no such field
2319    *   -3: attribute check failed
2320    *   -2: non 2-manifold star
2321    *   -1: regular point
2322    *   0: minimum
2323    *   1: saddle
2324    *   2: maximum
2325    */
2326 
2327   int fieldId = 0;
2328 
2329   vtkPointData *pointData = this->GetPointData();
2330   vtkDataArray *scalarField = pointData->GetArray(fieldName, fieldId);
2331 
2332   if(!scalarField) return vtkPolyData::ERR_NO_SUCH_FIELD;
2333 
2334   return this->GetScalarFieldCriticalIndex(pointId, scalarField);
2335 
2336 }
2337 
2338 //----------------------------------------------------------------------------
GetScalarFieldCriticalIndex(vtkIdType pointId,int fieldId)2339 int vtkPolyData::GetScalarFieldCriticalIndex (vtkIdType pointId, int fieldId)
2340 {
2341   /*
2342    * returned value:
2343    *   -4: no such field
2344    *   -3: attribute check failed
2345    *   -2: non 2-manifold star
2346    *   -1: regular point
2347    *   0: minimum
2348    *   1: saddle
2349    *   2: maximum
2350    */
2351 
2352   vtkPointData *pointData = this->GetPointData();
2353   vtkDataArray *scalarField = pointData->GetArray(fieldId);
2354 
2355   if(!scalarField) return vtkPolyData::ERR_NO_SUCH_FIELD;
2356 
2357   return this->GetScalarFieldCriticalIndex(pointId, scalarField);
2358 }
2359