]> Creatis software - clitk.git/blob - vv/vvGlyph2D.cxx
Merge branch 'master' into VTK6_Qt5
[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 #else
179     this->SetUpdateExtent(0, 1, 0);
180     this->SetSourceData(defaultSource);
181 #endif
182     defaultSource->Delete();
183     defaultSource = NULL;
184     defaultPoints->Delete();
185     defaultPoints = NULL;
186   }
187
188   if ( this->IndexMode != VTK_INDEXING_OFF ) {
189     pd = NULL;
190     haveNormals = 1;
191     for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++) {
192       source = this->GetSource(i, inputVector[1]);
193       if ( source != NULL ) {
194         if (source->GetNumberOfPoints() > numSourcePts) {
195           numSourcePts = source->GetNumberOfPoints();
196         }
197         if (source->GetNumberOfCells() > numSourceCells) {
198           numSourceCells = source->GetNumberOfCells();
199         }
200         if ( !(sourceNormals = source->GetPointData()->GetNormals()) ) {
201           haveNormals = 0;
202         }
203       }
204     }
205   } else {
206     source = this->GetSource(0, inputVector[1]);
207     sourcePts = source->GetPoints();
208     numSourcePts = sourcePts->GetNumberOfPoints();
209     numSourceCells = source->GetNumberOfCells();
210
211     sourceNormals = source->GetPointData()->GetNormals();
212     if ( sourceNormals ) {
213       haveNormals = 1;
214     } else {
215       haveNormals = 0;
216     }
217
218     sourceTCoords = source->GetPointData()->GetTCoords();
219     if (sourceTCoords) {
220       haveTCoords = 1;
221     } else {
222       haveTCoords = 0;
223     }
224
225     // Prepare to copy output.
226     pd = input->GetPointData();
227     outputPD->CopyAllocate(pd,numPts*numSourcePts);
228   }
229
230   newPts = vtkPoints::New();
231   newPts->Allocate(numPts*numSourcePts);
232   if ( this->GeneratePointIds ) {
233     pointIds = vtkIdTypeArray::New();
234     pointIds->SetName(this->PointIdsName);
235     pointIds->Allocate(numPts*numSourcePts);
236     outputPD->AddArray(pointIds);
237     pointIds->Delete();
238   }
239   if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars ) {
240     newScalars = inCScalars->NewInstance();
241     newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
242     newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
243     newScalars->SetName(inCScalars->GetName());
244   } else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars) {
245     newScalars = vtkFloatArray::New();
246     newScalars->Allocate(numPts*numSourcePts);
247     newScalars->SetName("GlyphScale");
248     if (this->ScaleMode == VTK_SCALE_BY_SCALAR) {
249       newScalars->SetName(inSScalars->GetName());
250     }
251   } else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) {
252     newScalars = vtkFloatArray::New();
253     newScalars->Allocate(numPts*numSourcePts);
254     newScalars->SetName("VectorMagnitude");
255   }
256   if ( haveVectors ) {
257     newVectors = vtkFloatArray::New();
258     newVectors->SetNumberOfComponents(3);
259     newVectors->Allocate(3*numPts*numSourcePts);
260     newVectors->SetName("GlyphVector");
261   }
262   if ( haveNormals ) {
263     newNormals = vtkFloatArray::New();
264     newNormals->SetNumberOfComponents(3);
265     newNormals->Allocate(3*numPts*numSourcePts);
266     newNormals->SetName("Normals");
267   }
268   if (haveTCoords) {
269     newTCoords = vtkFloatArray::New();
270     int numComps = sourceTCoords->GetNumberOfComponents();
271     newTCoords->SetNumberOfComponents(numComps);
272     newTCoords->Allocate(numComps*numPts*numSourcePts);
273     newTCoords->SetName("TCoords");
274   }
275
276   // Setting up for calls to PolyData::InsertNextCell()
277   if (this->IndexMode != VTK_INDEXING_OFF ) {
278     output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
279   } else {
280     output->Allocate(this->GetSource(0, inputVector[1]),
281                      3*numPts*numSourceCells, numPts*numSourceCells);
282   }
283
284   // Traverse all Input points, transforming Source points and copying
285   // point attributes.
286   //
287   ptIncr=0;
288   for (inPtId=0; inPtId < numPts; inPtId++) {
289     scalex = scaley = scalez = 1.0;
290     if ( ! (inPtId % 10000) ) {
291       this->UpdateProgress ((double)inPtId/numPts);
292       if (this->GetAbortExecute()) {
293         break;
294       }
295     }
296
297     // Get the scalar and vector data
298     if ( inSScalars ) {
299       s = inSScalars->GetComponent(inPtId, 0);
300       if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
301            this->ScaleMode == VTK_DATA_SCALING_OFF ) {
302         scalex = scaley = scalez = s;
303       }
304     }
305
306     if ( haveVectors ) {
307       if ( this->VectorMode == VTK_USE_NORMAL ) {
308         inNormals->GetTuple(inPtId, v);
309       } else {
310         inVectors->GetTuple(inPtId, v);
311       }
312
313       vMag = vtkMath::Norm(v);
314       if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) {
315         scalex = v[0];
316         scaley = v[1];
317         scalez = v[2];
318       } else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) {
319         scalex = scaley = scalez = vMag;
320       }
321     }
322
323     // Clamp data scale if enabled
324     if ( this->Clamping ) {
325       scalex = (scalex < this->Range[0] ? this->Range[0] :
326                 (scalex > this->Range[1] ? this->Range[1] : scalex));
327       scalex = (scalex - this->Range[0]) / den;
328       scaley = (scaley < this->Range[0] ? this->Range[0] :
329                 (scaley > this->Range[1] ? this->Range[1] : scaley));
330       scaley = (scaley - this->Range[0]) / den;
331       scalez = (scalez < this->Range[0] ? this->Range[0] :
332                 (scalez > this->Range[1] ? this->Range[1] : scalez));
333       scalez = (scalez - this->Range[0]) / den;
334     }
335
336     // Compute index into table of glyphs
337     if ( this->IndexMode == VTK_INDEXING_OFF ) {
338       index = 0;
339     } else {
340       if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) {
341         value = s;
342       } else {
343         value = vMag;
344       }
345
346       index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
347       index = (index < 0 ? 0 :
348                (index >= numberOfSources ? (numberOfSources-1) : index));
349
350       source = this->GetSource(index, inputVector[1]);
351       if ( source != NULL ) {
352         sourcePts = source->GetPoints();
353         sourceNormals = source->GetPointData()->GetNormals();
354         numSourcePts = sourcePts->GetNumberOfPoints();
355         numSourceCells = source->GetNumberOfCells();
356       }
357     }
358
359     // Make sure we're not indexing into empty glyph
360     if ( this->GetSource(index, inputVector[1]) == NULL ) {
361       continue;
362     }
363
364     // Check ghost points.
365     // If we are processing a piece, we do not want to duplicate
366     // glyphs on the borders.  The corrct check here is:
367     // ghostLevel > 0.  I am leaving this over glyphing here because
368     // it make a nice example (sphereGhost.tcl) to show the
369     // point ghost levels with the glyph filter.  I am not certain
370     // of the usefullness of point ghost levels over 1, but I will have
371     // to think about it.
372     if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel) {
373       continue;
374     }
375
376     if (!this->IsPointVisible(input, inPtId)) {
377       continue;
378     }
379
380     // Now begin copying/transforming glyph
381     trans->Identity();
382
383     // Copy all topology (transformation independent)
384     for (cellId=0; cellId < numSourceCells; cellId++) {
385       cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
386       cellPts = cell->GetPointIds();
387       npts = cellPts->GetNumberOfIds();
388       for (pts->Reset(), i=0; i < npts; i++) {
389         pts->InsertId(i,cellPts->GetId(i) + ptIncr);
390       }
391       output->InsertNextCell(cell->GetCellType(),pts);
392     }
393
394     // translate Source to Input point
395     input->GetPoint(inPtId, x);
396
397     //projection on the plane orthogonale to the camera
398     trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
399
400     trans->Translate(x[0], x[1], x[2]);
401
402     if ( haveVectors ) {
403       // Copy Input vector
404       for (i=0; i < numSourcePts; i++) {
405         newVectors->InsertTuple(i+ptIncr, v);
406       }
407       if (this->Orient && (vMag > 0.0)) {
408         // if there is no y or z component
409         if ( v[1] == 0.0 && v[2] == 0.0 ) {
410           if (v[0] < 0) { //just flip x if we need to
411             trans->RotateWXYZ(180.0,0,1,0);
412           }
413         } else {
414           vNew[0] = (v[0]+vMag) / 2.0;
415           vNew[1] = v[1] / 2.0;
416           vNew[2] = v[2] / 2.0;
417           trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]);
418         }
419       }
420     }
421
422     if (haveTCoords) {
423       for (i = 0; i < numSourcePts; i++) {
424         sourceTCoords->GetTuple(i, tc);
425         newTCoords->InsertTuple(i+ptIncr, tc);
426       }
427     }
428
429     // determine scale factor from scalars if appropriate
430     // Copy scalar value
431     if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE)) {
432       for (i=0; i < numSourcePts; i++) {
433         newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
434       }
435     } else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR)) {
436       for (i=0; i < numSourcePts; i++) {
437         outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
438       }
439     }
440     if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) {
441       double color = 1;
442       for (i=0; i < numSourcePts; i++) {
443         newScalars->InsertTuple(i+ptIncr, &color);
444       }
445     }
446
447     // scale data if appropriate
448     if ( this->Scaling ) {
449       if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) {
450         scalex = scaley = scalez = this->ScaleFactor;
451       } else {
452         scalex *= this->ScaleFactor;
453         scaley *= this->ScaleFactor;
454         scalez *= this->ScaleFactor;
455       }
456
457       if ( scalex == 0.0 ) {
458         scalex = 1.0e-10;
459       }
460       if ( scaley == 0.0 ) {
461         scaley = 1.0e-10;
462       }
463       if ( scalez == 0.0 ) {
464         scalez = 1.0e-10;
465       }
466       trans->Scale(scalex,scaley,scalez);
467     }
468     // multiply points and normals by resulting matrix
469     trans->TransformPoints(sourcePts,newPts);
470
471     if ( haveNormals ) {
472       trans->TransformNormals(sourceNormals,newNormals);
473     }
474
475     // Copy point data from source (if possible)
476     if ( pd ) {
477       for (i=0; i < numSourcePts; i++) {
478         outputPD->CopyData(pd,inPtId,ptIncr+i);
479       }
480     }
481
482     // If point ids are to be generated, do it here
483     if ( this->GeneratePointIds ) {
484       for (i=0; i < numSourcePts; i++) {
485         pointIds->InsertNextValue(inPtId);
486       }
487     }
488
489     ptIncr += numSourcePts;
490   }
491
492   // Update ourselves and release memory
493   //
494   output->SetPoints(newPts);
495   newPts->Delete();
496
497   if (newScalars) {
498     int idx = outputPD->AddArray(newScalars);
499     outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
500     newScalars->Delete();
501   }
502
503   if (newVectors) {
504     outputPD->SetVectors(newVectors);
505     newVectors->Delete();
506   }
507
508   if (newNormals) {
509     outputPD->SetNormals(newNormals);
510     newNormals->Delete();
511   }
512
513   if (newTCoords) {
514     outputPD->SetTCoords(newTCoords);
515     newTCoords->Delete();
516   }
517
518   output->Squeeze();
519   trans->Delete();
520   pts->Delete();
521
522   return 1;
523 }
524
525 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
526 {
527   this->Superclass::PrintSelf(os,indent);
528 }
529
530 void vvGlyph2D::SetOrientation(int x, int y, int z)
531 {
532   if (x == 0)
533     mOrientation[0] = 1.0e-10;
534   else
535     mOrientation[0] = 1.0;
536   if (y == 0)
537     mOrientation[1] = 1.0e-10;
538   else
539     mOrientation[1] = 1.0;
540   if (z == 0)
541     mOrientation[2] = 1.0e-10;
542   else
543     mOrientation[2] = 1.0;
544 }