1 /*=========================================================================
5 Author : Pierre Seroul (pierre.seroul@gmail.com)
8 Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
9 CREATIS-LRMN http://www.creatis.insa-lyon.fr
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, version 3 of the License.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 =========================================================================*/
24 #include "vvGlyph2D.h"
27 #include "vtkDataSet.h"
28 #include "vtkFloatArray.h"
29 #include "vtkIdList.h"
30 #include "vtkIdTypeArray.h"
31 #include "vtkInformation.h"
32 #include "vtkInformationVector.h"
34 #include "vtkObjectFactory.h"
35 #include "vtkPointData.h"
36 #include "vtkPolyData.h"
37 #include "vtkStreamingDemandDrivenPipeline.h"
38 #include "vtkTransform.h"
39 #include "vtkUnsignedCharArray.h"
41 vtkCxxRevisionMacro(vvGlyph2D, "DummyRevision");
42 vtkStandardNewMacro(vvGlyph2D);
44 vvGlyph2D::vvGlyph2D()
52 //----------------------------------------------------------------------------
53 int vvGlyph2D::RequestData(
54 vtkInformation *vtkNotUsed(request),
55 vtkInformationVector **inputVector,
56 vtkInformationVector *outputVector)
58 // get the info objects
59 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
60 vtkInformation *outInfo = outputVector->GetInformationObject(0);
62 // get the input and ouptut
63 vtkDataSet *input = vtkDataSet::SafeDownCast(
64 inInfo->Get(vtkDataObject::DATA_OBJECT()));
65 vtkPolyData *output = vtkPolyData::SafeDownCast(
66 outInfo->Get(vtkDataObject::DATA_OBJECT()));
69 vtkDataArray *inSScalars; // Scalars for Scaling
70 vtkDataArray *inCScalars; // Scalars for Coloring
71 vtkDataArray *inVectors;
72 int requestedGhostLevel;
73 unsigned char* inGhostLevels=0;
74 vtkDataArray *inNormals, *sourceNormals = NULL;
75 vtkDataArray *sourceTCoords = NULL;
76 vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
78 vtkPoints *sourcePts = NULL;
80 vtkDataArray *newScalars=NULL;
81 vtkDataArray *newVectors=NULL;
82 vtkDataArray *newNormals=NULL;
83 vtkDataArray *newTCoords = NULL;
84 double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value, tc[3];
85 vtkTransform *trans = vtkTransform::New();
90 vtkIdType ptIncr, cellId;
91 int haveVectors, haveNormals, haveTCoords = 0;
92 double scalex,scaley,scalez, den;
93 vtkPointData *outputPD = output->GetPointData();
94 int numberOfSources = this->GetNumberOfInputConnections(1);
95 vtkPolyData *defaultSource = NULL;
96 vtkIdTypeArray *pointIds=0;
97 vtkPolyData *source = 0;
99 vtkDebugMacro(<<"Generating glyphs");
101 pts = vtkIdList::New();
102 pts->Allocate(VTK_CELL_SIZE);
104 pd = input->GetPointData();
105 inSScalars = this->GetInputArrayToProcess(0,inputVector);
106 inVectors = this->GetInputArrayToProcess(1,inputVector);
107 inNormals = this->GetInputArrayToProcess(2,inputVector);
108 inCScalars = this->GetInputArrayToProcess(3,inputVector);
109 if (inCScalars == NULL)
111 inCScalars = inSScalars;
114 vtkDataArray* temp = 0;
117 temp = pd->GetArray("vtkGhostLevels");
119 if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
120 || (temp->GetNumberOfComponents() != 1))
122 vtkDebugMacro("No appropriate ghost levels field available.");
126 inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
129 requestedGhostLevel =
130 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
132 numPts = input->GetNumberOfPoints();
135 vtkDebugMacro(<<"No points to glyph!");
141 // Check input for consistency
143 if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
147 if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
148 ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
149 (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) )
158 if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) ||
159 (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
160 ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
161 (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
163 if ( this->GetSource(0, inputVector[1]) == NULL )
165 vtkErrorMacro(<<"Indexing on but don't have data to index with");
172 vtkWarningMacro(<<"Turning indexing off: no data to index with");
173 this->IndexMode = VTK_INDEXING_OFF;
177 // Allocate storage for output PolyData
179 outputPD->CopyVectorsOff();
180 outputPD->CopyNormalsOff();
181 outputPD->CopyTCoordsOff();
183 if (!this->GetSource(0, inputVector[1]))
185 defaultSource = vtkPolyData::New();
186 defaultSource->Allocate();
187 vtkPoints *defaultPoints = vtkPoints::New();
188 defaultPoints->Allocate(6);
189 defaultPoints->InsertNextPoint(0, 0, 0);
190 defaultPoints->InsertNextPoint(1, 0, 0);
191 vtkIdType defaultPointIds[2];
192 defaultPointIds[0] = 0;
193 defaultPointIds[1] = 1;
194 defaultSource->SetPoints(defaultPoints);
195 defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
196 defaultSource->SetUpdateExtent(0, 1, 0);
197 this->SetSource(defaultSource);
198 defaultSource->Delete();
199 defaultSource = NULL;
200 defaultPoints->Delete();
201 defaultPoints = NULL;
204 if ( this->IndexMode != VTK_INDEXING_OFF )
208 for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
210 source = this->GetSource(i, inputVector[1]);
211 if ( source != NULL )
213 if (source->GetNumberOfPoints() > numSourcePts)
215 numSourcePts = source->GetNumberOfPoints();
217 if (source->GetNumberOfCells() > numSourceCells)
219 numSourceCells = source->GetNumberOfCells();
221 if ( !(sourceNormals = source->GetPointData()->GetNormals()) )
230 source = this->GetSource(0, inputVector[1]);
231 sourcePts = source->GetPoints();
232 numSourcePts = sourcePts->GetNumberOfPoints();
233 numSourceCells = source->GetNumberOfCells();
235 sourceNormals = source->GetPointData()->GetNormals();
245 sourceTCoords = source->GetPointData()->GetTCoords();
255 // Prepare to copy output.
256 pd = input->GetPointData();
257 outputPD->CopyAllocate(pd,numPts*numSourcePts);
260 newPts = vtkPoints::New();
261 newPts->Allocate(numPts*numSourcePts);
262 if ( this->GeneratePointIds )
264 pointIds = vtkIdTypeArray::New();
265 pointIds->SetName(this->PointIdsName);
266 pointIds->Allocate(numPts*numSourcePts);
267 outputPD->AddArray(pointIds);
270 if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars )
272 newScalars = inCScalars->NewInstance();
273 newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
274 newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
275 newScalars->SetName(inCScalars->GetName());
277 else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars)
279 newScalars = vtkFloatArray::New();
280 newScalars->Allocate(numPts*numSourcePts);
281 newScalars->SetName("GlyphScale");
282 if (this->ScaleMode == VTK_SCALE_BY_SCALAR)
284 newScalars->SetName(inSScalars->GetName());
287 else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
289 newScalars = vtkFloatArray::New();
290 newScalars->Allocate(numPts*numSourcePts);
291 newScalars->SetName("VectorMagnitude");
295 newVectors = vtkFloatArray::New();
296 newVectors->SetNumberOfComponents(3);
297 newVectors->Allocate(3*numPts*numSourcePts);
298 newVectors->SetName("GlyphVector");
302 newNormals = vtkFloatArray::New();
303 newNormals->SetNumberOfComponents(3);
304 newNormals->Allocate(3*numPts*numSourcePts);
305 newNormals->SetName("Normals");
309 newTCoords = vtkFloatArray::New();
310 int numComps = sourceTCoords->GetNumberOfComponents();
311 newTCoords->SetNumberOfComponents(numComps);
312 newTCoords->Allocate(numComps*numPts*numSourcePts);
313 newTCoords->SetName("TCoords");
316 // Setting up for calls to PolyData::InsertNextCell()
317 if (this->IndexMode != VTK_INDEXING_OFF )
319 output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
323 output->Allocate(this->GetSource(0, inputVector[1]),
324 3*numPts*numSourceCells, numPts*numSourceCells);
327 // Traverse all Input points, transforming Source points and copying
331 for (inPtId=0; inPtId < numPts; inPtId++)
333 scalex = scaley = scalez = 1.0;
334 if ( ! (inPtId % 10000) )
336 this->UpdateProgress ((double)inPtId/numPts);
337 if (this->GetAbortExecute())
343 // Get the scalar and vector data
346 s = inSScalars->GetComponent(inPtId, 0);
347 if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
348 this->ScaleMode == VTK_DATA_SCALING_OFF )
350 scalex = scaley = scalez = s;
356 if ( this->VectorMode == VTK_USE_NORMAL )
358 inNormals->GetTuple(inPtId, v);
362 inVectors->GetTuple(inPtId, v);
365 vMag = vtkMath::Norm(v);
366 if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
372 else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
374 scalex = scaley = scalez = vMag;
378 // Clamp data scale if enabled
379 if ( this->Clamping )
381 scalex = (scalex < this->Range[0] ? this->Range[0] :
382 (scalex > this->Range[1] ? this->Range[1] : scalex));
383 scalex = (scalex - this->Range[0]) / den;
384 scaley = (scaley < this->Range[0] ? this->Range[0] :
385 (scaley > this->Range[1] ? this->Range[1] : scaley));
386 scaley = (scaley - this->Range[0]) / den;
387 scalez = (scalez < this->Range[0] ? this->Range[0] :
388 (scalez > this->Range[1] ? this->Range[1] : scalez));
389 scalez = (scalez - this->Range[0]) / den;
392 // Compute index into table of glyphs
393 if ( this->IndexMode == VTK_INDEXING_OFF )
399 if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
408 index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
409 index = (index < 0 ? 0 :
410 (index >= numberOfSources ? (numberOfSources-1) : index));
412 source = this->GetSource(index, inputVector[1]);
413 if ( source != NULL )
415 sourcePts = source->GetPoints();
416 sourceNormals = source->GetPointData()->GetNormals();
417 numSourcePts = sourcePts->GetNumberOfPoints();
418 numSourceCells = source->GetNumberOfCells();
422 // Make sure we're not indexing into empty glyph
423 if ( this->GetSource(index, inputVector[1]) == NULL )
428 // Check ghost points.
429 // If we are processing a piece, we do not want to duplicate
430 // glyphs on the borders. The corrct check here is:
431 // ghostLevel > 0. I am leaving this over glyphing here because
432 // it make a nice example (sphereGhost.tcl) to show the
433 // point ghost levels with the glyph filter. I am not certain
434 // of the usefullness of point ghost levels over 1, but I will have
435 // to think about it.
436 if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel)
441 if (!this->IsPointVisible(input, inPtId))
446 // Now begin copying/transforming glyph
449 // Copy all topology (transformation independent)
450 for (cellId=0; cellId < numSourceCells; cellId++)
452 cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
453 cellPts = cell->GetPointIds();
454 npts = cellPts->GetNumberOfIds();
455 for (pts->Reset(), i=0; i < npts; i++)
457 pts->InsertId(i,cellPts->GetId(i) + ptIncr);
459 output->InsertNextCell(cell->GetCellType(),pts);
462 // translate Source to Input point
463 input->GetPoint(inPtId, x);
465 //projection on the plane orthogonale to the camera
466 trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
468 trans->Translate(x[0], x[1], x[2]);
473 for (i=0; i < numSourcePts; i++)
475 newVectors->InsertTuple(i+ptIncr, v);
477 if (this->Orient && (vMag > 0.0))
479 // if there is no y or z component
480 if ( v[1] == 0.0 && v[2] == 0.0 )
482 if (v[0] < 0) //just flip x if we need to
484 trans->RotateWXYZ(180.0,0,1,0);
489 vNew[0] = (v[0]+vMag) / 2.0;
490 vNew[1] = v[1] / 2.0;
491 vNew[2] = v[2] / 2.0;
492 trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]);
499 for (i = 0; i < numSourcePts; i++)
501 sourceTCoords->GetTuple(i, tc);
502 newTCoords->InsertTuple(i+ptIncr, tc);
506 // determine scale factor from scalars if appropriate
508 if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE))
510 for (i=0; i < numSourcePts; i++)
512 newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
515 else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR))
517 for (i=0; i < numSourcePts; i++)
519 outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
522 if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
525 for (i=0; i < numSourcePts; i++)
527 newScalars->InsertTuple(i+ptIncr, &color);
531 // scale data if appropriate
534 if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
536 scalex = scaley = scalez = this->ScaleFactor;
540 scalex *= this->ScaleFactor;
541 scaley *= this->ScaleFactor;
542 scalez *= this->ScaleFactor;
557 trans->Scale(scalex,scaley,scalez);
559 // multiply points and normals by resulting matrix
560 trans->TransformPoints(sourcePts,newPts);
564 trans->TransformNormals(sourceNormals,newNormals);
567 // Copy point data from source (if possible)
570 for (i=0; i < numSourcePts; i++)
572 outputPD->CopyData(pd,inPtId,ptIncr+i);
576 // If point ids are to be generated, do it here
577 if ( this->GeneratePointIds )
579 for (i=0; i < numSourcePts; i++)
581 pointIds->InsertNextValue(inPtId);
585 ptIncr += numSourcePts;
588 // Update ourselves and release memory
590 output->SetPoints(newPts);
595 int idx = outputPD->AddArray(newScalars);
596 outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
597 newScalars->Delete();
602 outputPD->SetVectors(newVectors);
603 newVectors->Delete();
608 outputPD->SetNormals(newNormals);
609 newNormals->Delete();
614 outputPD->SetTCoords(newTCoords);
615 newTCoords->Delete();
625 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
627 this->Superclass::PrintSelf(os,indent);
630 void vvGlyph2D::SetOrientation(int x, int y, int z)
633 mOrientation[0] = 1.0e-10;
635 mOrientation[0] = 1.0;
637 mOrientation[1] = 1.0e-10;
639 mOrientation[1] = 1.0;
641 mOrientation[2] = 1.0e-10;
643 mOrientation[2] = 1.0;