1 /*=========================================================================
4 Module: $RCSfile: vvGlyph2D.cxx,v $
6 Date: $Date: 2010/01/06 13:31:57 $
7 Version: $Revision: 1.1 $
8 Author : Pierre Seroul (pierre.seroul@gmail.com)
11 Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
12 CREATIS-LRMN http://www.creatis.insa-lyon.fr
14 This program is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, version 3 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 =========================================================================*/
27 #include "vvGlyph2D.h"
30 #include "vtkDataSet.h"
31 #include "vtkFloatArray.h"
32 #include "vtkIdList.h"
33 #include "vtkIdTypeArray.h"
34 #include "vtkInformation.h"
35 #include "vtkInformationVector.h"
37 #include "vtkObjectFactory.h"
38 #include "vtkPointData.h"
39 #include "vtkPolyData.h"
40 #include "vtkStreamingDemandDrivenPipeline.h"
41 #include "vtkTransform.h"
42 #include "vtkUnsignedCharArray.h"
44 vtkCxxRevisionMacro(vvGlyph2D, "$Revision: 1.1 $");
45 vtkStandardNewMacro(vvGlyph2D);
47 vvGlyph2D::vvGlyph2D()
55 //----------------------------------------------------------------------------
56 int vvGlyph2D::RequestData(
57 vtkInformation *vtkNotUsed(request),
58 vtkInformationVector **inputVector,
59 vtkInformationVector *outputVector)
61 // get the info objects
62 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
63 vtkInformation *outInfo = outputVector->GetInformationObject(0);
65 // get the input and ouptut
66 vtkDataSet *input = vtkDataSet::SafeDownCast(
67 inInfo->Get(vtkDataObject::DATA_OBJECT()));
68 vtkPolyData *output = vtkPolyData::SafeDownCast(
69 outInfo->Get(vtkDataObject::DATA_OBJECT()));
72 vtkDataArray *inSScalars; // Scalars for Scaling
73 vtkDataArray *inCScalars; // Scalars for Coloring
74 vtkDataArray *inVectors;
75 int requestedGhostLevel;
76 unsigned char* inGhostLevels=0;
77 vtkDataArray *inNormals, *sourceNormals = NULL;
78 vtkDataArray *sourceTCoords = NULL;
79 vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
81 vtkPoints *sourcePts = NULL;
83 vtkDataArray *newScalars=NULL;
84 vtkDataArray *newVectors=NULL;
85 vtkDataArray *newNormals=NULL;
86 vtkDataArray *newTCoords = NULL;
87 double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value, tc[3];
88 vtkTransform *trans = vtkTransform::New();
93 vtkIdType ptIncr, cellId;
94 int haveVectors, haveNormals, haveTCoords = 0;
95 double scalex,scaley,scalez, den;
96 vtkPointData *outputPD = output->GetPointData();
97 int numberOfSources = this->GetNumberOfInputConnections(1);
98 vtkPolyData *defaultSource = NULL;
99 vtkIdTypeArray *pointIds=0;
100 vtkPolyData *source = 0;
102 vtkDebugMacro(<<"Generating glyphs");
104 pts = vtkIdList::New();
105 pts->Allocate(VTK_CELL_SIZE);
107 pd = input->GetPointData();
108 inSScalars = this->GetInputArrayToProcess(0,inputVector);
109 inVectors = this->GetInputArrayToProcess(1,inputVector);
110 inNormals = this->GetInputArrayToProcess(2,inputVector);
111 inCScalars = this->GetInputArrayToProcess(3,inputVector);
112 if (inCScalars == NULL)
114 inCScalars = inSScalars;
117 vtkDataArray* temp = 0;
120 temp = pd->GetArray("vtkGhostLevels");
122 if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
123 || (temp->GetNumberOfComponents() != 1))
125 vtkDebugMacro("No appropriate ghost levels field available.");
129 inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
132 requestedGhostLevel =
133 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
135 numPts = input->GetNumberOfPoints();
138 vtkDebugMacro(<<"No points to glyph!");
144 // Check input for consistency
146 if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
150 if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
151 ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
152 (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) )
161 if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) ||
162 (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
163 ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
164 (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
166 if ( this->GetSource(0, inputVector[1]) == NULL )
168 vtkErrorMacro(<<"Indexing on but don't have data to index with");
175 vtkWarningMacro(<<"Turning indexing off: no data to index with");
176 this->IndexMode = VTK_INDEXING_OFF;
180 // Allocate storage for output PolyData
182 outputPD->CopyVectorsOff();
183 outputPD->CopyNormalsOff();
184 outputPD->CopyTCoordsOff();
186 if (!this->GetSource(0, inputVector[1]))
188 defaultSource = vtkPolyData::New();
189 defaultSource->Allocate();
190 vtkPoints *defaultPoints = vtkPoints::New();
191 defaultPoints->Allocate(6);
192 defaultPoints->InsertNextPoint(0, 0, 0);
193 defaultPoints->InsertNextPoint(1, 0, 0);
194 vtkIdType defaultPointIds[2];
195 defaultPointIds[0] = 0;
196 defaultPointIds[1] = 1;
197 defaultSource->SetPoints(defaultPoints);
198 defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
199 defaultSource->SetUpdateExtent(0, 1, 0);
200 this->SetSource(defaultSource);
201 defaultSource->Delete();
202 defaultSource = NULL;
203 defaultPoints->Delete();
204 defaultPoints = NULL;
207 if ( this->IndexMode != VTK_INDEXING_OFF )
211 for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
213 source = this->GetSource(i, inputVector[1]);
214 if ( source != NULL )
216 if (source->GetNumberOfPoints() > numSourcePts)
218 numSourcePts = source->GetNumberOfPoints();
220 if (source->GetNumberOfCells() > numSourceCells)
222 numSourceCells = source->GetNumberOfCells();
224 if ( !(sourceNormals = source->GetPointData()->GetNormals()) )
233 source = this->GetSource(0, inputVector[1]);
234 sourcePts = source->GetPoints();
235 numSourcePts = sourcePts->GetNumberOfPoints();
236 numSourceCells = source->GetNumberOfCells();
238 sourceNormals = source->GetPointData()->GetNormals();
248 sourceTCoords = source->GetPointData()->GetTCoords();
258 // Prepare to copy output.
259 pd = input->GetPointData();
260 outputPD->CopyAllocate(pd,numPts*numSourcePts);
263 newPts = vtkPoints::New();
264 newPts->Allocate(numPts*numSourcePts);
265 if ( this->GeneratePointIds )
267 pointIds = vtkIdTypeArray::New();
268 pointIds->SetName(this->PointIdsName);
269 pointIds->Allocate(numPts*numSourcePts);
270 outputPD->AddArray(pointIds);
273 if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars )
275 newScalars = inCScalars->NewInstance();
276 newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
277 newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
278 newScalars->SetName(inCScalars->GetName());
280 else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars)
282 newScalars = vtkFloatArray::New();
283 newScalars->Allocate(numPts*numSourcePts);
284 newScalars->SetName("GlyphScale");
285 if (this->ScaleMode == VTK_SCALE_BY_SCALAR)
287 newScalars->SetName(inSScalars->GetName());
290 else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
292 newScalars = vtkFloatArray::New();
293 newScalars->Allocate(numPts*numSourcePts);
294 newScalars->SetName("VectorMagnitude");
298 newVectors = vtkFloatArray::New();
299 newVectors->SetNumberOfComponents(3);
300 newVectors->Allocate(3*numPts*numSourcePts);
301 newVectors->SetName("GlyphVector");
305 newNormals = vtkFloatArray::New();
306 newNormals->SetNumberOfComponents(3);
307 newNormals->Allocate(3*numPts*numSourcePts);
308 newNormals->SetName("Normals");
312 newTCoords = vtkFloatArray::New();
313 int numComps = sourceTCoords->GetNumberOfComponents();
314 newTCoords->SetNumberOfComponents(numComps);
315 newTCoords->Allocate(numComps*numPts*numSourcePts);
316 newTCoords->SetName("TCoords");
319 // Setting up for calls to PolyData::InsertNextCell()
320 if (this->IndexMode != VTK_INDEXING_OFF )
322 output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
326 output->Allocate(this->GetSource(0, inputVector[1]),
327 3*numPts*numSourceCells, numPts*numSourceCells);
330 // Traverse all Input points, transforming Source points and copying
334 for (inPtId=0; inPtId < numPts; inPtId++)
336 scalex = scaley = scalez = 1.0;
337 if ( ! (inPtId % 10000) )
339 this->UpdateProgress ((double)inPtId/numPts);
340 if (this->GetAbortExecute())
346 // Get the scalar and vector data
349 s = inSScalars->GetComponent(inPtId, 0);
350 if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
351 this->ScaleMode == VTK_DATA_SCALING_OFF )
353 scalex = scaley = scalez = s;
359 if ( this->VectorMode == VTK_USE_NORMAL )
361 inNormals->GetTuple(inPtId, v);
365 inVectors->GetTuple(inPtId, v);
368 vMag = vtkMath::Norm(v);
369 if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
375 else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
377 scalex = scaley = scalez = vMag;
381 // Clamp data scale if enabled
382 if ( this->Clamping )
384 scalex = (scalex < this->Range[0] ? this->Range[0] :
385 (scalex > this->Range[1] ? this->Range[1] : scalex));
386 scalex = (scalex - this->Range[0]) / den;
387 scaley = (scaley < this->Range[0] ? this->Range[0] :
388 (scaley > this->Range[1] ? this->Range[1] : scaley));
389 scaley = (scaley - this->Range[0]) / den;
390 scalez = (scalez < this->Range[0] ? this->Range[0] :
391 (scalez > this->Range[1] ? this->Range[1] : scalez));
392 scalez = (scalez - this->Range[0]) / den;
395 // Compute index into table of glyphs
396 if ( this->IndexMode == VTK_INDEXING_OFF )
402 if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
411 index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
412 index = (index < 0 ? 0 :
413 (index >= numberOfSources ? (numberOfSources-1) : index));
415 source = this->GetSource(index, inputVector[1]);
416 if ( source != NULL )
418 sourcePts = source->GetPoints();
419 sourceNormals = source->GetPointData()->GetNormals();
420 numSourcePts = sourcePts->GetNumberOfPoints();
421 numSourceCells = source->GetNumberOfCells();
425 // Make sure we're not indexing into empty glyph
426 if ( this->GetSource(index, inputVector[1]) == NULL )
431 // Check ghost points.
432 // If we are processing a piece, we do not want to duplicate
433 // glyphs on the borders. The corrct check here is:
434 // ghostLevel > 0. I am leaving this over glyphing here because
435 // it make a nice example (sphereGhost.tcl) to show the
436 // point ghost levels with the glyph filter. I am not certain
437 // of the usefullness of point ghost levels over 1, but I will have
438 // to think about it.
439 if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel)
444 if (!this->IsPointVisible(input, inPtId))
449 // Now begin copying/transforming glyph
452 // Copy all topology (transformation independent)
453 for (cellId=0; cellId < numSourceCells; cellId++)
455 cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
456 cellPts = cell->GetPointIds();
457 npts = cellPts->GetNumberOfIds();
458 for (pts->Reset(), i=0; i < npts; i++)
460 pts->InsertId(i,cellPts->GetId(i) + ptIncr);
462 output->InsertNextCell(cell->GetCellType(),pts);
465 // translate Source to Input point
466 input->GetPoint(inPtId, x);
468 //projection on the plane orthogonale to the camera
469 trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
471 trans->Translate(x[0], x[1], x[2]);
476 for (i=0; i < numSourcePts; i++)
478 newVectors->InsertTuple(i+ptIncr, v);
480 if (this->Orient && (vMag > 0.0))
482 // if there is no y or z component
483 if ( v[1] == 0.0 && v[2] == 0.0 )
485 if (v[0] < 0) //just flip x if we need to
487 trans->RotateWXYZ(180.0,0,1,0);
492 vNew[0] = (v[0]+vMag) / 2.0;
493 vNew[1] = v[1] / 2.0;
494 vNew[2] = v[2] / 2.0;
495 trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]);
502 for (i = 0; i < numSourcePts; i++)
504 sourceTCoords->GetTuple(i, tc);
505 newTCoords->InsertTuple(i+ptIncr, tc);
509 // determine scale factor from scalars if appropriate
511 if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE))
513 for (i=0; i < numSourcePts; i++)
515 newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
518 else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR))
520 for (i=0; i < numSourcePts; i++)
522 outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
525 if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
528 for (i=0; i < numSourcePts; i++)
530 newScalars->InsertTuple(i+ptIncr, &color);
534 // scale data if appropriate
537 if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
539 scalex = scaley = scalez = this->ScaleFactor;
543 scalex *= this->ScaleFactor;
544 scaley *= this->ScaleFactor;
545 scalez *= this->ScaleFactor;
560 trans->Scale(scalex,scaley,scalez);
562 // multiply points and normals by resulting matrix
563 trans->TransformPoints(sourcePts,newPts);
567 trans->TransformNormals(sourceNormals,newNormals);
570 // Copy point data from source (if possible)
573 for (i=0; i < numSourcePts; i++)
575 outputPD->CopyData(pd,inPtId,ptIncr+i);
579 // If point ids are to be generated, do it here
580 if ( this->GeneratePointIds )
582 for (i=0; i < numSourcePts; i++)
584 pointIds->InsertNextValue(inPtId);
588 ptIncr += numSourcePts;
591 // Update ourselves and release memory
593 output->SetPoints(newPts);
598 int idx = outputPD->AddArray(newScalars);
599 outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
600 newScalars->Delete();
605 outputPD->SetVectors(newVectors);
606 newVectors->Delete();
611 outputPD->SetNormals(newNormals);
612 newNormals->Delete();
617 outputPD->SetTCoords(newTCoords);
618 newTCoords->Delete();
628 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
630 this->Superclass::PrintSelf(os,indent);
633 void vvGlyph2D::SetOrientation(int x, int y, int z)
636 mOrientation[0] = 1.0e-10;
638 mOrientation[0] = 1.0;
640 mOrientation[1] = 1.0e-10;
642 mOrientation[1] = 1.0;
644 mOrientation[2] = 1.0e-10;
646 mOrientation[2] = 1.0;