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