]> Creatis software - clitk.git/blob - vv/vvGlyph2D.cxx
Debug RTStruct conversion with empty struc
[clitk.git] / vv / vvGlyph2D.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
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
8
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.
12
13   It is distributed under dual licence
14
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"
19
20 #include <vtkVersion.h>
21 #include "vtkCell.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"
28 #include "vtkMath.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"
35
36 vtkStandardNewMacro(vvGlyph2D);
37
38 vvGlyph2D::vvGlyph2D()
39 {
40   mOrientation[0] = 1;
41   mOrientation[1] = 1;
42   mOrientation[2] = 1;
43   mUseLog = 0;
44 }
45
46 //----------------------------------------------------------------------------
47 int vvGlyph2D::RequestData(
48   vtkInformation *vtkNotUsed(request),
49   vtkInformationVector **inputVector,
50   vtkInformationVector *outputVector)
51 {
52   // get the info objects
53   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
54   vtkInformation *outInfo = outputVector->GetInformationObject(0);
55
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()));
61
62   vtkPointData *pd;
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;
71   int index;
72   vtkPoints *sourcePts = NULL;
73   vtkPoints *newPts;
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();
80   vtkCell *cell;
81   vtkIdList *cellPts;
82   int npts;
83   vtkIdList *pts;
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;
92
93   vtkDebugMacro(<<"Generating glyphs");
94
95   pts = vtkIdList::New();
96   pts->Allocate(VTK_CELL_SIZE);
97
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;
105   }
106
107   vtkDataArray* temp = 0;
108   if (pd) {
109     temp = pd->GetArray("vtkGhostLevels");
110   }
111   if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
112        || (temp->GetNumberOfComponents() != 1)) {
113     vtkDebugMacro("No appropriate ghost levels field available.");
114   } else {
115     inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
116   }
117
118   requestedGhostLevel =
119     outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
120
121   numPts = input->GetNumberOfPoints();
122   if (numPts < 1) {
123     vtkDebugMacro(<<"No points to glyph!");
124     pts->Delete();
125     trans->Delete();
126     return 1;
127   }
128
129   // Check input for consistency
130   //
131   if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) {
132     den = 1.0;
133   }
134   if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
135        ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
136         (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) ) {
137     haveVectors = 1;
138   } else {
139     haveVectors = 0;
140   }
141
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");
148       pts->Delete();
149       trans->Delete();
150       return 1;
151     } else {
152       vtkWarningMacro(<<"Turning indexing off: no data to index with");
153       this->IndexMode = VTK_INDEXING_OFF;
154     }
155   }
156
157   // Allocate storage for output PolyData
158   //
159   outputPD->CopyVectorsOff();
160   outputPD->CopyNormalsOff();
161   outputPD->CopyTCoordsOff();
162
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 >= 8 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1)
179     int extentTemp[3] = {0, 1, 0};
180     this->UpdateExtent(extentTemp);
181     this->SetSourceData(defaultSource);
182 #else
183     this->SetUpdateExtent(0, 1, 0);
184     this->SetSourceData(defaultSource);
185 #endif
186     defaultSource->Delete();
187     defaultSource = NULL;
188     defaultPoints->Delete();
189     defaultPoints = NULL;
190   }
191
192   if ( this->IndexMode != VTK_INDEXING_OFF ) {
193     pd = NULL;
194     haveNormals = 1;
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();
200         }
201         if (source->GetNumberOfCells() > numSourceCells) {
202           numSourceCells = source->GetNumberOfCells();
203         }
204         if ( !(sourceNormals = source->GetPointData()->GetNormals()) ) {
205           haveNormals = 0;
206         }
207       }
208     }
209   } else {
210     source = this->GetSource(0, inputVector[1]);
211     sourcePts = source->GetPoints();
212     numSourcePts = sourcePts->GetNumberOfPoints();
213     numSourceCells = source->GetNumberOfCells();
214
215     sourceNormals = source->GetPointData()->GetNormals();
216     if ( sourceNormals ) {
217       haveNormals = 1;
218     } else {
219       haveNormals = 0;
220     }
221
222     sourceTCoords = source->GetPointData()->GetTCoords();
223     if (sourceTCoords) {
224       haveTCoords = 1;
225     } else {
226       haveTCoords = 0;
227     }
228
229     // Prepare to copy output.
230     pd = input->GetPointData();
231     outputPD->CopyAllocate(pd,numPts*numSourcePts);
232   }
233
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);
241     pointIds->Delete();
242   }
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());
254     }
255   } else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) {
256     newScalars = vtkFloatArray::New();
257     newScalars->Allocate(numPts*numSourcePts);
258     newScalars->SetName("VectorMagnitude");
259   }
260   if ( haveVectors ) {
261     newVectors = vtkFloatArray::New();
262     newVectors->SetNumberOfComponents(3);
263     newVectors->Allocate(3*numPts*numSourcePts);
264     newVectors->SetName("GlyphVector");
265   }
266   if ( haveNormals ) {
267     newNormals = vtkFloatArray::New();
268     newNormals->SetNumberOfComponents(3);
269     newNormals->Allocate(3*numPts*numSourcePts);
270     newNormals->SetName("Normals");
271   }
272   if (haveTCoords) {
273     newTCoords = vtkFloatArray::New();
274     int numComps = sourceTCoords->GetNumberOfComponents();
275     newTCoords->SetNumberOfComponents(numComps);
276     newTCoords->Allocate(numComps*numPts*numSourcePts);
277     newTCoords->SetName("TCoords");
278   }
279
280   // Setting up for calls to PolyData::InsertNextCell()
281   if (this->IndexMode != VTK_INDEXING_OFF ) {
282     output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
283   } else {
284     output->Allocate(this->GetSource(0, inputVector[1]),
285                      3*numPts*numSourceCells, numPts*numSourceCells);
286   }
287
288   // Traverse all Input points, transforming Source points and copying
289   // point attributes.
290   //
291   ptIncr=0;
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()) {
297         break;
298       }
299     }
300
301     // Get the scalar and vector data
302     if ( inSScalars ) {
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;
307       }
308     }
309
310     if ( haveVectors ) {
311       if ( this->VectorMode == VTK_USE_NORMAL ) {
312         inNormals->GetTuple(inPtId, v);
313       } else {
314         inVectors->GetTuple(inPtId, v);
315       }
316
317       vMag = vtkMath::Norm(v);
318       if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) {
319         scalex = v[0];
320         scaley = v[1];
321         scalez = v[2];
322       } else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) {
323         scalex = scaley = scalez = vMag;
324       }
325     }
326
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;
338     }
339
340     // Compute index into table of glyphs
341     if ( this->IndexMode == VTK_INDEXING_OFF ) {
342       index = 0;
343     } else {
344       if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) {
345         value = s;
346       } else {
347         value = vMag;
348       }
349
350       index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
351       index = (index < 0 ? 0 :
352                (index >= numberOfSources ? (numberOfSources-1) : index));
353
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();
360       }
361     }
362
363     // Make sure we're not indexing into empty glyph
364     if ( this->GetSource(index, inputVector[1]) == NULL ) {
365       continue;
366     }
367
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) {
377       continue;
378     }
379
380     if (!this->IsPointVisible(input, inPtId)) {
381       continue;
382     }
383
384     // Now begin copying/transforming glyph
385     trans->Identity();
386
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);
394       }
395       output->InsertNextCell(cell->GetCellType(),pts);
396     }
397
398     // translate Source to Input point
399     input->GetPoint(inPtId, x);
400
401     //projection on the plane orthogonale to the camera
402     trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
403
404     trans->Translate(x[0], x[1], x[2]);
405
406     if ( haveVectors ) {
407       // Copy Input vector
408       for (i=0; i < numSourcePts; i++) {
409         newVectors->InsertTuple(i+ptIncr, v);
410       }
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);
416           }
417         } else {
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]);
422         }
423       }
424     }
425
426     if (haveTCoords) {
427       for (i = 0; i < numSourcePts; i++) {
428         sourceTCoords->GetTuple(i, tc);
429         newTCoords->InsertTuple(i+ptIncr, tc);
430       }
431     }
432
433     // determine scale factor from scalars if appropriate
434     // Copy scalar value
435     if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE)) {
436       for (i=0; i < numSourcePts; i++) {
437         newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
438       }
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);
442       }
443     }
444     if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) {
445       double color = 1;
446       for (i=0; i < numSourcePts; i++) {
447         newScalars->InsertTuple(i+ptIncr, &color);
448       }
449     }
450
451     // scale data if appropriate
452     if ( this->Scaling ) {
453       if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) {
454         scalex = scaley = scalez = this->ScaleFactor;
455       } else {
456         scalex *= this->ScaleFactor;
457         scaley *= this->ScaleFactor;
458         scalez *= this->ScaleFactor;
459       }
460
461       if ( scalex == 0.0 ) {
462         scalex = 1.0e-10;
463       }
464       if ( scaley == 0.0 ) {
465         scaley = 1.0e-10;
466       }
467       if ( scalez == 0.0 ) {
468         scalez = 1.0e-10;
469       }
470       trans->Scale(scalex,scaley,scalez);
471     }
472     // multiply points and normals by resulting matrix
473     trans->TransformPoints(sourcePts,newPts);
474
475     if ( haveNormals ) {
476       trans->TransformNormals(sourceNormals,newNormals);
477     }
478
479     // Copy point data from source (if possible)
480     if ( pd ) {
481       for (i=0; i < numSourcePts; i++) {
482         outputPD->CopyData(pd,inPtId,ptIncr+i);
483       }
484     }
485
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);
490       }
491     }
492
493     ptIncr += numSourcePts;
494   }
495
496   // Update ourselves and release memory
497   //
498   output->SetPoints(newPts);
499   newPts->Delete();
500
501   if (newScalars) {
502     int idx = outputPD->AddArray(newScalars);
503     outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
504     newScalars->Delete();
505   }
506
507   if (newVectors) {
508     outputPD->SetVectors(newVectors);
509     newVectors->Delete();
510   }
511
512   if (newNormals) {
513     outputPD->SetNormals(newNormals);
514     newNormals->Delete();
515   }
516
517   if (newTCoords) {
518     outputPD->SetTCoords(newTCoords);
519     newTCoords->Delete();
520   }
521
522   output->Squeeze();
523   trans->Delete();
524   pts->Delete();
525
526   return 1;
527 }
528
529 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
530 {
531   this->Superclass::PrintSelf(os,indent);
532 }
533
534 void vvGlyph2D::SetOrientation(int x, int y, int z)
535 {
536   if (x == 0)
537     mOrientation[0] = 1.0e-10;
538   else
539     mOrientation[0] = 1.0;
540   if (y == 0)
541     mOrientation[1] = 1.0e-10;
542   else
543     mOrientation[1] = 1.0;
544   if (z == 0)
545     mOrientation[2] = 1.0e-10;
546   else
547     mOrientation[2] = 1.0;
548 }