1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #include "vvGlyph2D.h"
20 #include <vtkVersion.h>
22 #include "vtkDataSet.h"
23 #include "vtkFloatArray.h"
24 #include "vtkIdList.h"
25 #include "vtkIdTypeArray.h"
26 #include "vtkInformation.h"
27 #include "vtkInformationVector.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkPointData.h"
31 #include "vtkPolyData.h"
32 #include "vtkStreamingDemandDrivenPipeline.h"
33 #include "vtkTransform.h"
34 #include "vtkUnsignedCharArray.h"
36 vtkStandardNewMacro(vvGlyph2D);
38 vvGlyph2D::vvGlyph2D()
46 //----------------------------------------------------------------------------
47 int vvGlyph2D::RequestData(
48 vtkInformation *vtkNotUsed(request),
49 vtkInformationVector **inputVector,
50 vtkInformationVector *outputVector)
52 // get the info objects
53 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
54 vtkInformation *outInfo = outputVector->GetInformationObject(0);
56 // get the input and ouptut
57 vtkDataSet *input = vtkDataSet::SafeDownCast(
58 inInfo->Get(vtkDataObject::DATA_OBJECT()));
59 vtkPolyData *output = vtkPolyData::SafeDownCast(
60 outInfo->Get(vtkDataObject::DATA_OBJECT()));
63 vtkDataArray *inSScalars; // Scalars for Scaling
64 vtkDataArray *inCScalars; // Scalars for Coloring
65 vtkDataArray *inVectors;
66 int requestedGhostLevel;
67 unsigned char* inGhostLevels=0;
68 vtkDataArray *inNormals, *sourceNormals = NULL;
69 vtkDataArray *sourceTCoords = NULL;
70 vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
72 vtkPoints *sourcePts = NULL;
74 vtkDataArray *newScalars=NULL;
75 vtkDataArray *newVectors=NULL;
76 vtkDataArray *newNormals=NULL;
77 vtkDataArray *newTCoords = NULL;
78 double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value, tc[3];
79 vtkTransform *trans = vtkTransform::New();
84 vtkIdType ptIncr, cellId;
85 int haveVectors, haveNormals, haveTCoords = 0;
86 double scalex,scaley,scalez, den;
87 vtkPointData *outputPD = output->GetPointData();
88 int numberOfSources = this->GetNumberOfInputConnections(1);
89 vtkPolyData *defaultSource = NULL;
90 vtkIdTypeArray *pointIds=0;
91 vtkPolyData *source = 0;
93 vtkDebugMacro(<<"Generating glyphs");
95 pts = vtkIdList::New();
96 pts->Allocate(VTK_CELL_SIZE);
98 pd = input->GetPointData();
99 inSScalars = this->GetInputArrayToProcess(0,inputVector);
100 inVectors = this->GetInputArrayToProcess(1,inputVector);
101 inNormals = this->GetInputArrayToProcess(2,inputVector);
102 inCScalars = this->GetInputArrayToProcess(3,inputVector);
103 if (inCScalars == NULL) {
104 inCScalars = inSScalars;
107 vtkDataArray* temp = 0;
109 temp = pd->GetArray("vtkGhostLevels");
111 if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
112 || (temp->GetNumberOfComponents() != 1)) {
113 vtkDebugMacro("No appropriate ghost levels field available.");
115 inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
118 requestedGhostLevel =
119 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
121 numPts = input->GetNumberOfPoints();
123 vtkDebugMacro(<<"No points to glyph!");
129 // Check input for consistency
131 if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) {
134 if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
135 ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
136 (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) ) {
142 if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) ||
143 (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
144 ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
145 (!inNormals && this->VectorMode == VTK_USE_NORMAL))) ) {
146 if ( this->GetSource(0, inputVector[1]) == NULL ) {
147 vtkErrorMacro(<<"Indexing on but don't have data to index with");
152 vtkWarningMacro(<<"Turning indexing off: no data to index with");
153 this->IndexMode = VTK_INDEXING_OFF;
157 // Allocate storage for output PolyData
159 outputPD->CopyVectorsOff();
160 outputPD->CopyNormalsOff();
161 outputPD->CopyTCoordsOff();
163 if (!this->GetSource(0, inputVector[1])) {
164 defaultSource = vtkPolyData::New();
165 defaultSource->Allocate();
166 vtkPoints *defaultPoints = vtkPoints::New();
167 defaultPoints->Allocate(6);
168 defaultPoints->InsertNextPoint(0, 0, 0);
169 defaultPoints->InsertNextPoint(1, 0, 0);
170 vtkIdType defaultPointIds[2];
171 defaultPointIds[0] = 0;
172 defaultPointIds[1] = 1;
173 defaultSource->SetPoints(defaultPoints);
174 defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
175 #if VTK_MAJOR_VERSION <= 5
176 defaultSource->SetUpdateExtent(0, 1, 0);
177 this->SetSource(defaultSource);
178 #elif VTK_MAJOR_VERSION >= 7 && VTK_MINOR_VERSION >= 1
179 int extentTemp[3] = {0, 1, 0};
180 this->UpdateExtent(extentTemp);
181 this->SetSourceData(defaultSource);
183 this->SetUpdateExtent(0, 1, 0);
184 this->SetSourceData(defaultSource);
186 defaultSource->Delete();
187 defaultSource = NULL;
188 defaultPoints->Delete();
189 defaultPoints = NULL;
192 if ( this->IndexMode != VTK_INDEXING_OFF ) {
195 for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++) {
196 source = this->GetSource(i, inputVector[1]);
197 if ( source != NULL ) {
198 if (source->GetNumberOfPoints() > numSourcePts) {
199 numSourcePts = source->GetNumberOfPoints();
201 if (source->GetNumberOfCells() > numSourceCells) {
202 numSourceCells = source->GetNumberOfCells();
204 if ( !(sourceNormals = source->GetPointData()->GetNormals()) ) {
210 source = this->GetSource(0, inputVector[1]);
211 sourcePts = source->GetPoints();
212 numSourcePts = sourcePts->GetNumberOfPoints();
213 numSourceCells = source->GetNumberOfCells();
215 sourceNormals = source->GetPointData()->GetNormals();
216 if ( sourceNormals ) {
222 sourceTCoords = source->GetPointData()->GetTCoords();
229 // Prepare to copy output.
230 pd = input->GetPointData();
231 outputPD->CopyAllocate(pd,numPts*numSourcePts);
234 newPts = vtkPoints::New();
235 newPts->Allocate(numPts*numSourcePts);
236 if ( this->GeneratePointIds ) {
237 pointIds = vtkIdTypeArray::New();
238 pointIds->SetName(this->PointIdsName);
239 pointIds->Allocate(numPts*numSourcePts);
240 outputPD->AddArray(pointIds);
243 if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars ) {
244 newScalars = inCScalars->NewInstance();
245 newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
246 newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
247 newScalars->SetName(inCScalars->GetName());
248 } else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars) {
249 newScalars = vtkFloatArray::New();
250 newScalars->Allocate(numPts*numSourcePts);
251 newScalars->SetName("GlyphScale");
252 if (this->ScaleMode == VTK_SCALE_BY_SCALAR) {
253 newScalars->SetName(inSScalars->GetName());
255 } else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) {
256 newScalars = vtkFloatArray::New();
257 newScalars->Allocate(numPts*numSourcePts);
258 newScalars->SetName("VectorMagnitude");
261 newVectors = vtkFloatArray::New();
262 newVectors->SetNumberOfComponents(3);
263 newVectors->Allocate(3*numPts*numSourcePts);
264 newVectors->SetName("GlyphVector");
267 newNormals = vtkFloatArray::New();
268 newNormals->SetNumberOfComponents(3);
269 newNormals->Allocate(3*numPts*numSourcePts);
270 newNormals->SetName("Normals");
273 newTCoords = vtkFloatArray::New();
274 int numComps = sourceTCoords->GetNumberOfComponents();
275 newTCoords->SetNumberOfComponents(numComps);
276 newTCoords->Allocate(numComps*numPts*numSourcePts);
277 newTCoords->SetName("TCoords");
280 // Setting up for calls to PolyData::InsertNextCell()
281 if (this->IndexMode != VTK_INDEXING_OFF ) {
282 output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
284 output->Allocate(this->GetSource(0, inputVector[1]),
285 3*numPts*numSourceCells, numPts*numSourceCells);
288 // Traverse all Input points, transforming Source points and copying
292 for (inPtId=0; inPtId < numPts; inPtId++) {
293 scalex = scaley = scalez = 1.0;
294 if ( ! (inPtId % 10000) ) {
295 this->UpdateProgress ((double)inPtId/numPts);
296 if (this->GetAbortExecute()) {
301 // Get the scalar and vector data
303 s = inSScalars->GetComponent(inPtId, 0);
304 if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
305 this->ScaleMode == VTK_DATA_SCALING_OFF ) {
306 scalex = scaley = scalez = s;
311 if ( this->VectorMode == VTK_USE_NORMAL ) {
312 inNormals->GetTuple(inPtId, v);
314 inVectors->GetTuple(inPtId, v);
317 vMag = vtkMath::Norm(v);
318 if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) {
322 } else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) {
323 scalex = scaley = scalez = vMag;
327 // Clamp data scale if enabled
328 if ( this->Clamping ) {
329 scalex = (scalex < this->Range[0] ? this->Range[0] :
330 (scalex > this->Range[1] ? this->Range[1] : scalex));
331 scalex = (scalex - this->Range[0]) / den;
332 scaley = (scaley < this->Range[0] ? this->Range[0] :
333 (scaley > this->Range[1] ? this->Range[1] : scaley));
334 scaley = (scaley - this->Range[0]) / den;
335 scalez = (scalez < this->Range[0] ? this->Range[0] :
336 (scalez > this->Range[1] ? this->Range[1] : scalez));
337 scalez = (scalez - this->Range[0]) / den;
340 // Compute index into table of glyphs
341 if ( this->IndexMode == VTK_INDEXING_OFF ) {
344 if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) {
350 index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
351 index = (index < 0 ? 0 :
352 (index >= numberOfSources ? (numberOfSources-1) : index));
354 source = this->GetSource(index, inputVector[1]);
355 if ( source != NULL ) {
356 sourcePts = source->GetPoints();
357 sourceNormals = source->GetPointData()->GetNormals();
358 numSourcePts = sourcePts->GetNumberOfPoints();
359 numSourceCells = source->GetNumberOfCells();
363 // Make sure we're not indexing into empty glyph
364 if ( this->GetSource(index, inputVector[1]) == NULL ) {
368 // Check ghost points.
369 // If we are processing a piece, we do not want to duplicate
370 // glyphs on the borders. The corrct check here is:
371 // ghostLevel > 0. I am leaving this over glyphing here because
372 // it make a nice example (sphereGhost.tcl) to show the
373 // point ghost levels with the glyph filter. I am not certain
374 // of the usefullness of point ghost levels over 1, but I will have
375 // to think about it.
376 if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel) {
380 if (!this->IsPointVisible(input, inPtId)) {
384 // Now begin copying/transforming glyph
387 // Copy all topology (transformation independent)
388 for (cellId=0; cellId < numSourceCells; cellId++) {
389 cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
390 cellPts = cell->GetPointIds();
391 npts = cellPts->GetNumberOfIds();
392 for (pts->Reset(), i=0; i < npts; i++) {
393 pts->InsertId(i,cellPts->GetId(i) + ptIncr);
395 output->InsertNextCell(cell->GetCellType(),pts);
398 // translate Source to Input point
399 input->GetPoint(inPtId, x);
401 //projection on the plane orthogonale to the camera
402 trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
404 trans->Translate(x[0], x[1], x[2]);
408 for (i=0; i < numSourcePts; i++) {
409 newVectors->InsertTuple(i+ptIncr, v);
411 if (this->Orient && (vMag > 0.0)) {
412 // if there is no y or z component
413 if ( v[1] == 0.0 && v[2] == 0.0 ) {
414 if (v[0] < 0) { //just flip x if we need to
415 trans->RotateWXYZ(180.0,0,1,0);
418 vNew[0] = (v[0]+vMag) / 2.0;
419 vNew[1] = v[1] / 2.0;
420 vNew[2] = v[2] / 2.0;
421 trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]);
427 for (i = 0; i < numSourcePts; i++) {
428 sourceTCoords->GetTuple(i, tc);
429 newTCoords->InsertTuple(i+ptIncr, tc);
433 // determine scale factor from scalars if appropriate
435 if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE)) {
436 for (i=0; i < numSourcePts; i++) {
437 newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
439 } else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR)) {
440 for (i=0; i < numSourcePts; i++) {
441 outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
444 if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) {
446 for (i=0; i < numSourcePts; i++) {
447 newScalars->InsertTuple(i+ptIncr, &color);
451 // scale data if appropriate
452 if ( this->Scaling ) {
453 if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) {
454 scalex = scaley = scalez = this->ScaleFactor;
456 scalex *= this->ScaleFactor;
457 scaley *= this->ScaleFactor;
458 scalez *= this->ScaleFactor;
461 if ( scalex == 0.0 ) {
464 if ( scaley == 0.0 ) {
467 if ( scalez == 0.0 ) {
470 trans->Scale(scalex,scaley,scalez);
472 // multiply points and normals by resulting matrix
473 trans->TransformPoints(sourcePts,newPts);
476 trans->TransformNormals(sourceNormals,newNormals);
479 // Copy point data from source (if possible)
481 for (i=0; i < numSourcePts; i++) {
482 outputPD->CopyData(pd,inPtId,ptIncr+i);
486 // If point ids are to be generated, do it here
487 if ( this->GeneratePointIds ) {
488 for (i=0; i < numSourcePts; i++) {
489 pointIds->InsertNextValue(inPtId);
493 ptIncr += numSourcePts;
496 // Update ourselves and release memory
498 output->SetPoints(newPts);
502 int idx = outputPD->AddArray(newScalars);
503 outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
504 newScalars->Delete();
508 outputPD->SetVectors(newVectors);
509 newVectors->Delete();
513 outputPD->SetNormals(newNormals);
514 newNormals->Delete();
518 outputPD->SetTCoords(newTCoords);
519 newTCoords->Delete();
529 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
531 this->Superclass::PrintSelf(os,indent);
534 void vvGlyph2D::SetOrientation(int x, int y, int z)
537 mOrientation[0] = 1.0e-10;
539 mOrientation[0] = 1.0;
541 mOrientation[1] = 1.0e-10;
543 mOrientation[1] = 1.0;
545 mOrientation[2] = 1.0e-10;
547 mOrientation[2] = 1.0;