1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkGlyph3D.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 "vtkGlyph3D.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkCell.h"
19 #include "vtkFloatArray.h"
20 #include "vtkIdList.h"
21 #include "vtkIdTypeArray.h"
22 #include "vtkInformation.h"
23 #include "vtkInformationVector.h"
24 #include "vtkMath.h"
25 #include "vtkNew.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkPointData.h"
28 #include "vtkPolyData.h"
29 #include "vtkSmartPointer.h"
30 #include "vtkStreamingDemandDrivenPipeline.h"
31 #include "vtkTransform.h"
32 #include "vtkTrivialProducer.h"
33 #include "vtkUniformGrid.h"
34 #include "vtkUnsignedCharArray.h"
35 
36 vtkStandardNewMacro(vtkGlyph3D);
37 vtkCxxSetObjectMacro(vtkGlyph3D, SourceTransform, vtkTransform);
38 
39 //----------------------------------------------------------------------------
40 // Construct object with scaling on, scaling mode is by scalar value,
41 // scale factor = 1.0, the range is (0,1), orient geometry is on, and
42 // orientation is by vector. Clamping and indexing are turned off. No
43 // initial sources are defined.
vtkGlyph3D()44 vtkGlyph3D::vtkGlyph3D()
45 {
46   this->Scaling = 1;
47   this->ColorMode = VTK_COLOR_BY_SCALE;
48   this->ScaleMode = VTK_SCALE_BY_SCALAR;
49   this->ScaleFactor = 1.0;
50   this->Range[0] = 0.0;
51   this->Range[1] = 1.0;
52   this->Orient = 1;
53   this->VectorMode = VTK_USE_VECTOR;
54   this->Clamping = 0;
55   this->IndexMode = VTK_INDEXING_OFF;
56   this->GeneratePointIds = 0;
57   this->PointIdsName = nullptr;
58   this->SetPointIdsName("InputPointIds");
59   this->SetNumberOfInputPorts(2);
60   this->FillCellData = 0;
61   this->SourceTransform = nullptr;
62   this->OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION;
63 
64   // by default process active point scalars
65   this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,
66                                vtkDataSetAttributes::SCALARS);
67   // by default process active point vectors
68   this->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,
69                                vtkDataSetAttributes::VECTORS);
70   // by default process active point normals
71   this->SetInputArrayToProcess(2,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,
72                                vtkDataSetAttributes::NORMALS);
73   // by default process active point scalars
74   this->SetInputArrayToProcess(3,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,
75                                vtkDataSetAttributes::SCALARS);
76 }
77 
78 //----------------------------------------------------------------------------
~vtkGlyph3D()79 vtkGlyph3D::~vtkGlyph3D()
80 {
81   delete [] PointIdsName;
82   this->SetSourceTransform(nullptr);
83 }
84 
85 //----------------------------------------------------------------------------
GetMTime()86 vtkMTimeType vtkGlyph3D::GetMTime()
87 {
88   vtkMTimeType mTime=this->Superclass::GetMTime();
89   vtkMTimeType time;
90   if ( this->SourceTransform != nullptr )
91   {
92     time = this->SourceTransform ->GetMTime();
93     mTime = ( time > mTime ? time : mTime );
94   }
95   return mTime;
96 }
97 
98 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)99 int vtkGlyph3D::RequestData(
100   vtkInformation *vtkNotUsed(request),
101   vtkInformationVector **inputVector,
102   vtkInformationVector *outputVector)
103 {
104   // get the info objects
105   vtkDataSet* input = vtkDataSet::GetData(inputVector[0], 0);
106   vtkPolyData* output = vtkPolyData::GetData(outputVector, 0);
107 
108   return this->Execute(input, inputVector[1], output)? 1 : 0;
109 }
110 
111 //----------------------------------------------------------------------------
Execute(vtkDataSet * input,vtkInformationVector * sourceVector,vtkPolyData * output)112 bool vtkGlyph3D::Execute(
113   vtkDataSet* input,
114   vtkInformationVector* sourceVector,
115   vtkPolyData* output)
116 {
117   vtkDataArray *inSScalars = this->GetInputArrayToProcess(0, input);
118   vtkDataArray *inVectors = this->GetInputArrayToProcess(1, input);
119   return this->Execute(input, sourceVector, output, inSScalars, inVectors);
120 }
121 
122 //----------------------------------------------------------------------------
Execute(vtkDataSet * input,vtkInformationVector * sourceVector,vtkPolyData * output,vtkDataArray * inSScalars,vtkDataArray * inVectors)123 bool vtkGlyph3D::Execute(
124   vtkDataSet* input,
125   vtkInformationVector* sourceVector,
126   vtkPolyData* output,
127   vtkDataArray *inSScalars,
128   vtkDataArray *inVectors)
129 {
130   assert(input && output);
131   if (input == nullptr || output == nullptr)
132   {
133     // nothing to do.
134     return true;
135   }
136 
137   // this is used to respect blanking specified on uniform grids.
138   vtkUniformGrid* inputUG = vtkUniformGrid::SafeDownCast(input);
139 
140   vtkPointData *pd;
141   vtkDataArray *inCScalars; // Scalars for Coloring
142   unsigned char* inGhostLevels=nullptr;
143   vtkDataArray *inNormals, *sourceNormals = nullptr;
144   vtkDataArray *sourceTCoords = nullptr;
145   vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
146   vtkPoints *sourcePts = nullptr;
147   vtkSmartPointer<vtkPoints> transformedSourcePts = vtkSmartPointer<vtkPoints>::New();
148   vtkPoints *newPts;
149   vtkDataArray *newScalars=nullptr;
150   vtkDataArray *newVectors=nullptr;
151   vtkDataArray *newNormals=nullptr;
152   vtkDataArray *newTCoords = nullptr;
153   double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value, tc[3];
154   vtkTransform *trans = vtkTransform::New();
155   vtkNew<vtkIdList> pointIdList;
156   vtkIdList *cellPts;
157   int npts;
158   vtkIdList *pts;
159   vtkIdType ptIncr, cellIncr, cellId;
160   int haveVectors, haveNormals, haveTCoords = 0;
161   double scalex,scaley,scalez, den;
162   vtkPointData* outputPD = output->GetPointData();
163   vtkCellData* outputCD = output->GetCellData();
164   int numberOfSources = this->GetNumberOfInputConnections(1);
165   vtkIdTypeArray *pointIds=nullptr;
166   vtkSmartPointer<vtkPolyData> source = this->GetSource(0, sourceVector);
167   vtkNew<vtkIdList> srcPointIdList;
168   vtkNew<vtkIdList> dstPointIdList;
169   vtkNew<vtkIdList> srcCellIdList;
170   vtkNew<vtkIdList> dstCellIdList;
171 
172   vtkDebugMacro(<<"Generating glyphs");
173 
174   pts = vtkIdList::New();
175   pts->Allocate(VTK_CELL_SIZE);
176 
177   pd = input->GetPointData();
178   inNormals = this->GetInputArrayToProcess(2, input);
179   inCScalars = this->GetInputArrayToProcess(3, input);
180   if (inCScalars == nullptr)
181   {
182     inCScalars = inSScalars;
183   }
184 
185   vtkDataArray* temp = nullptr;
186   if (pd)
187   {
188     temp = pd->GetArray(vtkDataSetAttributes::GhostArrayName());
189   }
190   if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
191     || (temp->GetNumberOfComponents() != 1))
192   {
193     vtkDebugMacro("No appropriate ghost levels field available.");
194   }
195   else
196   {
197     inGhostLevels =static_cast<vtkUnsignedCharArray *>(temp)->GetPointer(0);
198   }
199 
200 
201   numPts = input->GetNumberOfPoints();
202   if (numPts < 1)
203   {
204     vtkDebugMacro(<<"No points to glyph!");
205     pts->Delete();
206     trans->Delete();
207     return 1;
208   }
209 
210   // Check input for consistency
211   //
212   if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
213   {
214     den = 1.0;
215   }
216   if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
217        ((this->VectorMode == VTK_USE_VECTOR && inVectors != nullptr) ||
218         (this->VectorMode == VTK_USE_NORMAL && inNormals != nullptr)) )
219   {
220     haveVectors = 1;
221   }
222   else
223   {
224     haveVectors = 0;
225   }
226 
227   if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) ||
228        (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
229        ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
230         (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
231   {
232     if ( source == nullptr )
233     {
234       vtkErrorMacro(<<"Indexing on but don't have data to index with");
235       pts->Delete();
236       trans->Delete();
237       return true;
238     }
239     else
240     {
241       vtkWarningMacro(<<"Turning indexing off: no data to index with");
242       this->IndexMode = VTK_INDEXING_OFF;
243     }
244   }
245 
246   // Allocate storage for output PolyData
247   //
248   outputPD->CopyVectorsOff();
249   outputPD->CopyNormalsOff();
250   outputPD->CopyTCoordsOff();
251 
252   if ( source == nullptr )
253   {
254     vtkNew<vtkPolyData> defaultSource;
255     defaultSource->Allocate();
256     vtkNew<vtkPoints> defaultPoints;
257     defaultPoints->Allocate(6);
258     defaultPoints->InsertNextPoint(0, 0, 0);
259     defaultPoints->InsertNextPoint(1, 0, 0);
260     vtkIdType defaultPointIds[2];
261     defaultPointIds[0] = 0;
262     defaultPointIds[1] = 1;
263     defaultSource->SetPoints(defaultPoints);
264     defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
265     source = defaultSource;
266   }
267 
268   if ( this->IndexMode != VTK_INDEXING_OFF )
269   {
270     pd = nullptr;
271     haveNormals = 1;
272     for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
273     {
274       source = this->GetSource(i, sourceVector);
275       if ( source != nullptr )
276       {
277         if (source->GetNumberOfPoints() > numSourcePts)
278         {
279           numSourcePts = source->GetNumberOfPoints();
280         }
281         if (source->GetNumberOfCells() > numSourceCells)
282         {
283           numSourceCells = source->GetNumberOfCells();
284         }
285         if ( !(sourceNormals = source->GetPointData()->GetNormals()) )
286         {
287           haveNormals = 0;
288         }
289       }
290     }
291   }
292   else
293   {
294     sourcePts = source->GetPoints();
295     numSourcePts = sourcePts->GetNumberOfPoints();
296     numSourceCells = source->GetNumberOfCells();
297 
298     sourceNormals = source->GetPointData()->GetNormals();
299     if ( sourceNormals )
300     {
301       haveNormals = 1;
302     }
303     else
304     {
305       haveNormals = 0;
306     }
307 
308     sourceTCoords = source->GetPointData()->GetTCoords();
309     if (sourceTCoords)
310     {
311       haveTCoords = 1;
312     }
313     else
314     {
315       haveTCoords = 0;
316     }
317 
318     // Prepare to copy output.
319     pd = input->GetPointData();
320     outputPD->CopyAllocate(pd,numPts*numSourcePts);
321     if (this->FillCellData)
322     {
323       outputCD->CopyAllocate(pd,numPts*numSourceCells);
324     }
325   }
326 
327   srcPointIdList->SetNumberOfIds(numSourcePts);
328   dstPointIdList->SetNumberOfIds(numSourcePts);
329   srcCellIdList->SetNumberOfIds(numSourceCells);
330   dstCellIdList->SetNumberOfIds(numSourceCells);
331 
332   newPts = vtkPoints::New();
333 
334   // Set the desired precision for the points in the output.
335   if(this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
336   {
337     newPts->SetDataType(VTK_FLOAT);
338   }
339   else if(this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
340   {
341     newPts->SetDataType(VTK_FLOAT);
342   }
343   else if(this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
344   {
345     newPts->SetDataType(VTK_DOUBLE);
346   }
347 
348   newPts->Allocate(numPts*numSourcePts);
349   if ( this->GeneratePointIds )
350   {
351     pointIds = vtkIdTypeArray::New();
352     pointIds->SetName(this->PointIdsName);
353     pointIds->Allocate(numPts*numSourcePts);
354     outputPD->AddArray(pointIds);
355     pointIds->Delete();
356   }
357   if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars )
358   {
359     newScalars = inCScalars->NewInstance();
360     newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
361     newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
362     newScalars->SetName(inCScalars->GetName());
363   }
364   else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars)
365   {
366     newScalars = vtkFloatArray::New();
367     newScalars->Allocate(numPts*numSourcePts);
368     newScalars->SetName("GlyphScale");
369     if (this->ScaleMode == VTK_SCALE_BY_SCALAR)
370     {
371       newScalars->SetName(inSScalars->GetName());
372     }
373   }
374   else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
375   {
376     newScalars = vtkFloatArray::New();
377     newScalars->Allocate(numPts*numSourcePts);
378     newScalars->SetName("VectorMagnitude");
379   }
380   if ( haveVectors )
381   {
382     newVectors = vtkFloatArray::New();
383     newVectors->SetNumberOfComponents(3);
384     newVectors->Allocate(3*numPts*numSourcePts);
385     newVectors->SetName("GlyphVector");
386   }
387   if ( haveNormals )
388   {
389     newNormals = vtkFloatArray::New();
390     newNormals->SetNumberOfComponents(3);
391     newNormals->Allocate(3*numPts*numSourcePts);
392     newNormals->SetName("Normals");
393   }
394   if (haveTCoords)
395   {
396     newTCoords = vtkFloatArray::New();
397     int numComps = sourceTCoords->GetNumberOfComponents();
398     newTCoords->SetNumberOfComponents(numComps);
399     newTCoords->Allocate(numComps*numPts*numSourcePts);
400     newTCoords->SetName("TCoords");
401   }
402 
403   // Setting up for calls to PolyData::InsertNextCell()
404   if (this->IndexMode != VTK_INDEXING_OFF )
405   {
406     output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
407   }
408   else
409   {
410     output->Allocate(source,
411                      3*numPts*numSourceCells, numPts*numSourceCells);
412   }
413 
414   transformedSourcePts->SetDataTypeToDouble();
415   transformedSourcePts->Allocate(numSourcePts);
416 
417   // Traverse all Input points, transforming Source points and copying
418   // point attributes.
419   //
420   ptIncr=0;
421   cellIncr=0;
422   for (inPtId=0; inPtId < numPts; inPtId++)
423   {
424     scalex = scaley = scalez = 1.0;
425     if ( ! (inPtId % 10000) )
426     {
427       this->UpdateProgress(static_cast<double>(inPtId)/numPts);
428       if (this->GetAbortExecute())
429       {
430         break;
431       }
432     }
433 
434     // Get the scalar and vector data
435     if ( inSScalars )
436     {
437       s = inSScalars->GetComponent(inPtId, 0);
438       if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
439            this->ScaleMode == VTK_DATA_SCALING_OFF )
440       {
441         scalex = scaley = scalez = s;
442       }
443     }
444 
445     if ( haveVectors )
446     {
447       vtkDataArray *array3D = this->VectorMode == VTK_USE_NORMAL? inNormals : inVectors;
448       if(array3D->GetNumberOfComponents()>3)
449       {
450         vtkErrorMacro(<<"vtkDataArray "<<array3D->GetName()<<" has more than 3 components.\n");
451         pts->Delete();
452         trans->Delete();
453         if(newPts)
454         {
455           newPts->Delete();
456         }
457         if(newVectors)
458         {
459           newVectors->Delete();
460         }
461         return false;
462       }
463 
464       v[0] = 0;
465       v[1] = 0;
466       v[2] = 0;
467       array3D->GetTuple(inPtId, v);
468       vMag = vtkMath::Norm(v);
469       if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
470       {
471         scalex = v[0];
472         scaley = v[1];
473         scalez = v[2];
474       }
475       else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
476       {
477         scalex = scaley = scalez = vMag;
478       }
479     }
480 
481     // Clamp data scale if enabled
482     if ( this->Clamping )
483     {
484       scalex = (scalex < this->Range[0] ? this->Range[0] :
485                 (scalex > this->Range[1] ? this->Range[1] : scalex));
486       scalex = (scalex - this->Range[0]) / den;
487       scaley = (scaley < this->Range[0] ? this->Range[0] :
488                 (scaley > this->Range[1] ? this->Range[1] : scaley));
489       scaley = (scaley - this->Range[0]) / den;
490       scalez = (scalez < this->Range[0] ? this->Range[0] :
491                 (scalez > this->Range[1] ? this->Range[1] : scalez));
492       scalez = (scalez - this->Range[0]) / den;
493     }
494 
495     // Compute index into table of glyphs
496     if ( this->IndexMode != VTK_INDEXING_OFF )
497     {
498       if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
499       {
500         value = s;
501       }
502       else
503       {
504         value = vMag;
505       }
506 
507       int index = static_cast<int>((value - this->Range[0])*numberOfSources / den);
508       index = (index < 0 ? 0 :
509               (index >= numberOfSources ? (numberOfSources-1) : index));
510 
511       source = this->GetSource(index, sourceVector);
512       if ( source != nullptr )
513       {
514         sourcePts = source->GetPoints();
515         sourceNormals = source->GetPointData()->GetNormals();
516         numSourcePts = sourcePts->GetNumberOfPoints();
517         numSourceCells = source->GetNumberOfCells();
518       }
519     }
520 
521     // Make sure we're not indexing into empty glyph
522     if ( source == nullptr )
523     {
524       continue;
525     }
526 
527     // Check ghost points.
528     // If we are processing a piece, we do not want to duplicate
529     // glyphs on the borders.
530     if (inGhostLevels &&
531         inGhostLevels[inPtId] & vtkDataSetAttributes::DUPLICATEPOINT)
532     {
533       continue;
534     }
535 
536     if (inputUG && !inputUG->IsPointVisible(inPtId))
537     {
538       // input is a vtkUniformGrid and the current point is blanked. Don't glyph
539       // it.
540       continue;
541     }
542 
543     if (!this->IsPointVisible(input, inPtId))
544     {
545       continue;
546     }
547 
548     // Now begin copying/transforming glyph
549     trans->Identity();
550 
551     // Copy all topology (transformation independent)
552     for (cellId=0; cellId < numSourceCells; cellId++)
553     {
554       source->GetCellPoints(cellId, pointIdList);
555       cellPts = pointIdList;
556       npts = cellPts->GetNumberOfIds();
557       for (pts->Reset(), i=0; i < npts; i++)
558       {
559         pts->InsertId(i, cellPts->GetId(i) + ptIncr);
560       }
561       output->InsertNextCell(source->GetCellType(cellId), pts);
562     }
563 
564     // translate Source to Input point
565     input->GetPoint(inPtId, x);
566     trans->Translate(x[0], x[1], x[2]);
567 
568     if ( haveVectors )
569     {
570       // Copy Input vector
571       for (i=0; i < numSourcePts; i++)
572       {
573         newVectors->InsertTuple(i+ptIncr, v);
574       }
575       if (this->Orient && (vMag > 0.0))
576       {
577         // if there is no y or z component
578         if ( v[1] == 0.0 && v[2] == 0.0 )
579         {
580           if (v[0] < 0) //just flip x if we need to
581           {
582             trans->RotateWXYZ(180.0,0,1,0);
583           }
584         }
585         else
586         {
587           vNew[0] = (v[0]+vMag) / 2.0;
588           vNew[1] = v[1] / 2.0;
589           vNew[2] = v[2] / 2.0;
590           trans->RotateWXYZ(180.0,vNew[0],vNew[1],vNew[2]);
591         }
592       }
593     }
594 
595     if (haveTCoords)
596     {
597       for (i = 0; i < numSourcePts; i++)
598       {
599         sourceTCoords->GetTuple(i, tc);
600         newTCoords->InsertTuple(i+ptIncr, tc);
601       }
602     }
603 
604     // determine scale factor from scalars if appropriate
605     // Copy scalar value
606     if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE))
607     {
608       for (i=0; i < numSourcePts; i++)
609       {
610         newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
611       }
612     }
613     else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR))
614     {
615       for (i=0; i < numSourcePts; i++)
616       {
617         outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
618       }
619     }
620     if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
621     {
622       for (i=0; i < numSourcePts; i++)
623       {
624         newScalars->InsertTuple(i+ptIncr, &vMag);
625       }
626     }
627 
628     // scale data if appropriate
629     if ( this->Scaling )
630     {
631       if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
632       {
633         scalex = scaley = scalez = this->ScaleFactor;
634       }
635       else
636       {
637         scalex *= this->ScaleFactor;
638         scaley *= this->ScaleFactor;
639         scalez *= this->ScaleFactor;
640       }
641 
642       if ( scalex == 0.0 )
643       {
644         scalex = 1.0e-10;
645       }
646       if ( scaley == 0.0 )
647       {
648         scaley = 1.0e-10;
649       }
650       if ( scalez == 0.0 )
651       {
652         scalez = 1.0e-10;
653       }
654       trans->Scale(scalex,scaley,scalez);
655     }
656 
657     // multiply points and normals by resulting matrix
658     if (this->SourceTransform)
659     {
660       transformedSourcePts->Reset();
661       this->SourceTransform->TransformPoints(sourcePts, transformedSourcePts);
662       trans->TransformPoints(transformedSourcePts, newPts);
663     }
664     else
665     {
666       trans->TransformPoints(sourcePts,newPts);
667     }
668 
669     if ( haveNormals )
670     {
671       trans->TransformNormals(sourceNormals,newNormals);
672     }
673 
674     // Copy point data from source (if possible)
675     if ( pd )
676     {
677       for (i = 0; i < numSourcePts; ++i)
678       {
679         srcPointIdList->SetId(i, inPtId);
680         dstPointIdList->SetId(i, ptIncr + i);
681       }
682       outputPD->CopyData(pd, srcPointIdList, dstPointIdList);
683       if (this->FillCellData)
684       {
685         for (i = 0; i < numSourceCells; ++i)
686         {
687           srcCellIdList->SetId(i, inPtId);
688           dstCellIdList->SetId(i, cellIncr + i);
689         }
690         outputCD->CopyData(pd, srcCellIdList, dstCellIdList);
691       }
692     }
693 
694     // If point ids are to be generated, do it here
695     if ( this->GeneratePointIds )
696     {
697       for (i=0; i < numSourcePts; i++)
698       {
699         pointIds->InsertNextValue(inPtId);
700       }
701     }
702 
703     ptIncr += numSourcePts;
704     cellIncr += numSourceCells;
705   }
706 
707   // Update ourselves and release memory
708   //
709   output->SetPoints(newPts);
710   newPts->Delete();
711 
712   if (newScalars)
713   {
714     int idx = outputPD->AddArray(newScalars);
715     outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
716     newScalars->Delete();
717   }
718 
719   if (newVectors)
720   {
721     outputPD->SetVectors(newVectors);
722     newVectors->Delete();
723   }
724 
725   if (newNormals)
726   {
727     outputPD->SetNormals(newNormals);
728     newNormals->Delete();
729   }
730 
731   if (newTCoords)
732   {
733     outputPD->SetTCoords(newTCoords);
734     newTCoords->Delete();
735   }
736 
737   output->Squeeze();
738   trans->Delete();
739   pts->Delete();
740 
741   return true;
742 }
743 
744 //----------------------------------------------------------------------------
745 // Specify a source object at a specified table location.
SetSourceConnection(int id,vtkAlgorithmOutput * algOutput)746 void vtkGlyph3D::SetSourceConnection(int id, vtkAlgorithmOutput* algOutput)
747 {
748   if (id < 0)
749   {
750     vtkErrorMacro("Bad index " << id << " for source.");
751     return;
752   }
753 
754   int numConnections = this->GetNumberOfInputConnections(1);
755   if (id < numConnections)
756   {
757     this->SetNthInputConnection(1, id, algOutput);
758   }
759   else if (id == numConnections && algOutput)
760   {
761     this->AddInputConnection(1, algOutput);
762   }
763   else if (algOutput)
764   {
765     vtkWarningMacro("The source id provided is larger than the maximum "
766                     "source id, using " << numConnections << " instead.");
767     this->AddInputConnection(1, algOutput);
768   }
769 }
770 
771 //----------------------------------------------------------------------------
772 // Specify a source object at a specified table location.
SetSourceData(int id,vtkPolyData * pd)773 void vtkGlyph3D::SetSourceData(int id, vtkPolyData *pd)
774 {
775   int numConnections = this->GetNumberOfInputConnections(1);
776 
777   if (id < 0 || id > numConnections)
778   {
779     vtkErrorMacro("Bad index " << id << " for source.");
780     return;
781   }
782 
783   vtkTrivialProducer* tp = nullptr;
784   if (pd)
785   {
786     tp = vtkTrivialProducer::New();
787     tp->SetOutput(pd);
788   }
789 
790   if (id < numConnections)
791   {
792     if (tp)
793     {
794       this->SetNthInputConnection(1, id, tp->GetOutputPort());
795     }
796     else
797     {
798       this->SetNthInputConnection(1, id, nullptr);
799     }
800   }
801   else if (id == numConnections && tp)
802   {
803     this->AddInputConnection(1, tp->GetOutputPort());
804   }
805 
806   if (tp)
807   {
808     tp->Delete();
809   }
810 }
811 
812 //----------------------------------------------------------------------------
813 // Get a pointer to a source object at a specified table location.
GetSource(int id)814 vtkPolyData *vtkGlyph3D::GetSource(int id)
815 {
816   if ( id < 0 || id >= this->GetNumberOfInputConnections(1) )
817   {
818     return nullptr;
819   }
820 
821   return vtkPolyData::SafeDownCast(
822     this->GetExecutive()->GetInputData(1, id));
823 }
824 
825 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)826 void vtkGlyph3D::PrintSelf(ostream& os, vtkIndent indent)
827 {
828   this->Superclass::PrintSelf(os,indent);
829 
830   os << indent << "Generate Point Ids "
831      << (this->GeneratePointIds ? "On\n" : "Off\n");
832 
833   os << indent << "PointIdsName: " << (this->PointIdsName ? this->PointIdsName
834        : "(none)") << "\n";
835 
836   os << indent << "Output Points Precision: " << this->OutputPointsPrecision
837      << "\n";
838 
839   os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;
840 
841   if ( this->GetNumberOfInputConnections(1) < 2 )
842   {
843     if ( this->GetSource(0) != nullptr )
844     {
845       os << indent << "Source: (" << this->GetSource(0) << ")\n";
846     }
847     else
848     {
849       os << indent << "Source: (none)\n";
850     }
851   }
852   else
853   {
854     os << indent << "A table of " << this->GetNumberOfInputConnections(1) << " glyphs has been defined\n";
855   }
856 
857   os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n");
858 
859   os << indent << "Scale Mode: ";
860   if ( this->ScaleMode == VTK_SCALE_BY_SCALAR )
861   {
862     os << "Scale by scalar\n";
863   }
864   else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
865   {
866     os << "Scale by vector\n";
867   }
868   else
869   {
870     os << "Data scaling is turned off\n";
871   }
872 
873   os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
874   os << indent << "Clamping: " << (this->Clamping ? "On\n" : "Off\n");
875   os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1] << ")\n";
876   os << indent << "Orient: " << (this->Orient ? "On\n" : "Off\n");
877   os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ?
878                                        "Orient by vector\n" : "Orient by normal\n");
879   os << indent << "Index Mode: ";
880   if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
881   {
882     os << "Index by scalar value\n";
883   }
884   else if ( this->IndexMode == VTK_INDEXING_BY_VECTOR )
885   {
886     os << "Index by vector value\n";
887   }
888   else
889   {
890     os << "Indexing off\n";
891   }
892 
893   os << indent << "Fill Cell Data: " << (this->FillCellData ? "On\n" : "Off\n");
894 
895   os << indent << "SourceTransform: ";
896   if (this->SourceTransform)
897   {
898     os << endl;
899     this->SourceTransform->PrintSelf(os, indent.GetNextIndent());
900   }
901   else
902   {
903     os << "(none)" << endl;
904   }
905 }
906 
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)907 int vtkGlyph3D::RequestUpdateExtent(
908   vtkInformation *vtkNotUsed(request),
909   vtkInformationVector **inputVector,
910   vtkInformationVector *outputVector)
911 {
912   // get the info objects
913   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
914   vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0);
915   vtkInformation *outInfo = outputVector->GetInformationObject(0);
916 
917   if (sourceInfo)
918   {
919     sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
920                     0);
921     sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
922                     1);
923     sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
924                     0);
925   }
926   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
927               outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()));
928   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
929               outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()));
930   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
931               outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()));
932   inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1);
933 
934   return 1;
935 }
936 
937 //----------------------------------------------------------------------------
GetSource(int idx,vtkInformationVector * sourceInfo)938 vtkPolyData* vtkGlyph3D::GetSource(int idx, vtkInformationVector *sourceInfo)
939 {
940   vtkInformation *info = sourceInfo->GetInformationObject(idx);
941   if (!info)
942   {
943     return nullptr;
944   }
945   return vtkPolyData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
946 }
947 
948 //----------------------------------------------------------------------------
FillInputPortInformation(int port,vtkInformation * info)949 int vtkGlyph3D::FillInputPortInformation(int port, vtkInformation *info)
950 {
951   if (port == 0)
952   {
953     info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
954     return 1;
955   }
956   else if (port == 1)
957   {
958     info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
959     info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
960     info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
961     return 1;
962   }
963   return 0;
964 }
965