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