]> Creatis software - clitk.git/blob - vv/vvGlyph2D.cxx
added the new headers
[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://oncora1.lyon.fnclcc.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     {
105         inCScalars = inSScalars;
106     }
107
108     vtkDataArray* temp = 0;
109     if (pd)
110     {
111         temp = pd->GetArray("vtkGhostLevels");
112     }
113     if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
114             || (temp->GetNumberOfComponents() != 1))
115     {
116         vtkDebugMacro("No appropriate ghost levels field available.");
117     }
118     else
119     {
120         inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
121     }
122
123     requestedGhostLevel =
124         outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
125
126     numPts = input->GetNumberOfPoints();
127     if (numPts < 1)
128     {
129         vtkDebugMacro(<<"No points to glyph!");
130         pts->Delete();
131         trans->Delete();
132         return 1;
133     }
134
135     // Check input for consistency
136     //
137     if ( (den = this->Range[1] - this->Range[0]) == 0.0 )
138     {
139         den = 1.0;
140     }
141     if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF &&
142             ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) ||
143              (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) )
144     {
145         haveVectors = 1;
146     }
147     else
148     {
149         haveVectors = 0;
150     }
151
152     if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) ||
153             (this->IndexMode == VTK_INDEXING_BY_VECTOR &&
154              ((!inVectors && this->VectorMode == VTK_USE_VECTOR) ||
155               (!inNormals && this->VectorMode == VTK_USE_NORMAL))) )
156     {
157         if ( this->GetSource(0, inputVector[1]) == NULL )
158         {
159             vtkErrorMacro(<<"Indexing on but don't have data to index with");
160             pts->Delete();
161             trans->Delete();
162             return 1;
163         }
164         else
165         {
166             vtkWarningMacro(<<"Turning indexing off: no data to index with");
167             this->IndexMode = VTK_INDEXING_OFF;
168         }
169     }
170
171     // Allocate storage for output PolyData
172     //
173     outputPD->CopyVectorsOff();
174     outputPD->CopyNormalsOff();
175     outputPD->CopyTCoordsOff();
176
177     if (!this->GetSource(0, inputVector[1]))
178     {
179         defaultSource = vtkPolyData::New();
180         defaultSource->Allocate();
181         vtkPoints *defaultPoints = vtkPoints::New();
182         defaultPoints->Allocate(6);
183         defaultPoints->InsertNextPoint(0, 0, 0);
184         defaultPoints->InsertNextPoint(1, 0, 0);
185         vtkIdType defaultPointIds[2];
186         defaultPointIds[0] = 0;
187         defaultPointIds[1] = 1;
188         defaultSource->SetPoints(defaultPoints);
189         defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
190         defaultSource->SetUpdateExtent(0, 1, 0);
191         this->SetSource(defaultSource);
192         defaultSource->Delete();
193         defaultSource = NULL;
194         defaultPoints->Delete();
195         defaultPoints = NULL;
196     }
197
198     if ( this->IndexMode != VTK_INDEXING_OFF )
199     {
200         pd = NULL;
201         haveNormals = 1;
202         for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++)
203         {
204             source = this->GetSource(i, inputVector[1]);
205             if ( source != NULL )
206             {
207                 if (source->GetNumberOfPoints() > numSourcePts)
208                 {
209                     numSourcePts = source->GetNumberOfPoints();
210                 }
211                 if (source->GetNumberOfCells() > numSourceCells)
212                 {
213                     numSourceCells = source->GetNumberOfCells();
214                 }
215                 if ( !(sourceNormals = source->GetPointData()->GetNormals()) )
216                 {
217                     haveNormals = 0;
218                 }
219             }
220         }
221     }
222     else
223     {
224         source = this->GetSource(0, inputVector[1]);
225         sourcePts = source->GetPoints();
226         numSourcePts = sourcePts->GetNumberOfPoints();
227         numSourceCells = source->GetNumberOfCells();
228
229         sourceNormals = source->GetPointData()->GetNormals();
230         if ( sourceNormals )
231         {
232             haveNormals = 1;
233         }
234         else
235         {
236             haveNormals = 0;
237         }
238
239         sourceTCoords = source->GetPointData()->GetTCoords();
240         if (sourceTCoords)
241         {
242             haveTCoords = 1;
243         }
244         else
245         {
246             haveTCoords = 0;
247         }
248
249         // Prepare to copy output.
250         pd = input->GetPointData();
251         outputPD->CopyAllocate(pd,numPts*numSourcePts);
252     }
253
254     newPts = vtkPoints::New();
255     newPts->Allocate(numPts*numSourcePts);
256     if ( this->GeneratePointIds )
257     {
258         pointIds = vtkIdTypeArray::New();
259         pointIds->SetName(this->PointIdsName);
260         pointIds->Allocate(numPts*numSourcePts);
261         outputPD->AddArray(pointIds);
262         pointIds->Delete();
263     }
264     if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars )
265     {
266         newScalars = inCScalars->NewInstance();
267         newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents());
268         newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts);
269         newScalars->SetName(inCScalars->GetName());
270     }
271     else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars)
272     {
273         newScalars = vtkFloatArray::New();
274         newScalars->Allocate(numPts*numSourcePts);
275         newScalars->SetName("GlyphScale");
276         if (this->ScaleMode == VTK_SCALE_BY_SCALAR)
277         {
278             newScalars->SetName(inSScalars->GetName());
279         }
280     }
281     else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors)
282     {
283         newScalars = vtkFloatArray::New();
284         newScalars->Allocate(numPts*numSourcePts);
285         newScalars->SetName("VectorMagnitude");
286     }
287     if ( haveVectors )
288     {
289         newVectors = vtkFloatArray::New();
290         newVectors->SetNumberOfComponents(3);
291         newVectors->Allocate(3*numPts*numSourcePts);
292         newVectors->SetName("GlyphVector");
293     }
294     if ( haveNormals )
295     {
296         newNormals = vtkFloatArray::New();
297         newNormals->SetNumberOfComponents(3);
298         newNormals->Allocate(3*numPts*numSourcePts);
299         newNormals->SetName("Normals");
300     }
301     if (haveTCoords)
302     {
303         newTCoords = vtkFloatArray::New();
304         int numComps = sourceTCoords->GetNumberOfComponents();
305         newTCoords->SetNumberOfComponents(numComps);
306         newTCoords->Allocate(numComps*numPts*numSourcePts);
307         newTCoords->SetName("TCoords");
308     }
309
310     // Setting up for calls to PolyData::InsertNextCell()
311     if (this->IndexMode != VTK_INDEXING_OFF )
312     {
313         output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells);
314     }
315     else
316     {
317         output->Allocate(this->GetSource(0, inputVector[1]),
318                          3*numPts*numSourceCells, numPts*numSourceCells);
319     }
320
321     // Traverse all Input points, transforming Source points and copying
322     // point attributes.
323     //
324     ptIncr=0;
325     for (inPtId=0; inPtId < numPts; inPtId++)
326     {
327         scalex = scaley = scalez = 1.0;
328         if ( ! (inPtId % 10000) )
329         {
330             this->UpdateProgress ((double)inPtId/numPts);
331             if (this->GetAbortExecute())
332             {
333                 break;
334             }
335         }
336
337         // Get the scalar and vector data
338         if ( inSScalars )
339         {
340             s = inSScalars->GetComponent(inPtId, 0);
341             if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ||
342                     this->ScaleMode == VTK_DATA_SCALING_OFF )
343             {
344                 scalex = scaley = scalez = s;
345             }
346         }
347
348         if ( haveVectors )
349         {
350             if ( this->VectorMode == VTK_USE_NORMAL )
351             {
352                 inNormals->GetTuple(inPtId, v);
353             }
354             else
355             {
356                 inVectors->GetTuple(inPtId, v);
357             }
358
359             vMag = vtkMath::Norm(v);
360             if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS )
361             {
362                 scalex = v[0];
363                 scaley = v[1];
364                 scalez = v[2];
365             }
366             else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR )
367             {
368                 scalex = scaley = scalez = vMag;
369             }
370         }
371
372         // Clamp data scale if enabled
373         if ( this->Clamping )
374         {
375             scalex = (scalex < this->Range[0] ? this->Range[0] :
376                       (scalex > this->Range[1] ? this->Range[1] : scalex));
377             scalex = (scalex - this->Range[0]) / den;
378             scaley = (scaley < this->Range[0] ? this->Range[0] :
379                       (scaley > this->Range[1] ? this->Range[1] : scaley));
380             scaley = (scaley - this->Range[0]) / den;
381             scalez = (scalez < this->Range[0] ? this->Range[0] :
382                       (scalez > this->Range[1] ? this->Range[1] : scalez));
383             scalez = (scalez - this->Range[0]) / den;
384         }
385
386         // Compute index into table of glyphs
387         if ( this->IndexMode == VTK_INDEXING_OFF )
388         {
389             index = 0;
390         }
391         else
392         {
393             if ( this->IndexMode == VTK_INDEXING_BY_SCALAR )
394             {
395                 value = s;
396             }
397             else
398             {
399                 value = vMag;
400             }
401
402             index = (int) ((double)(value - this->Range[0]) * numberOfSources / den);
403             index = (index < 0 ? 0 :
404                      (index >= numberOfSources ? (numberOfSources-1) : index));
405
406             source = this->GetSource(index, inputVector[1]);
407             if ( source != NULL )
408             {
409                 sourcePts = source->GetPoints();
410                 sourceNormals = source->GetPointData()->GetNormals();
411                 numSourcePts = sourcePts->GetNumberOfPoints();
412                 numSourceCells = source->GetNumberOfCells();
413             }
414         }
415
416         // Make sure we're not indexing into empty glyph
417         if ( this->GetSource(index, inputVector[1]) == NULL )
418         {
419             continue;
420         }
421
422         // Check ghost points.
423         // If we are processing a piece, we do not want to duplicate
424         // glyphs on the borders.  The corrct check here is:
425         // ghostLevel > 0.  I am leaving this over glyphing here because
426         // it make a nice example (sphereGhost.tcl) to show the
427         // point ghost levels with the glyph filter.  I am not certain
428         // of the usefullness of point ghost levels over 1, but I will have
429         // to think about it.
430         if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel)
431         {
432             continue;
433         }
434
435         if (!this->IsPointVisible(input, inPtId))
436         {
437             continue;
438         }
439
440         // Now begin copying/transforming glyph
441         trans->Identity();
442
443         // Copy all topology (transformation independent)
444         for (cellId=0; cellId < numSourceCells; cellId++)
445         {
446             cell = this->GetSource(index, inputVector[1])->GetCell(cellId);
447             cellPts = cell->GetPointIds();
448             npts = cellPts->GetNumberOfIds();
449             for (pts->Reset(), i=0; i < npts; i++)
450             {
451                 pts->InsertId(i,cellPts->GetId(i) + ptIncr);
452             }
453             output->InsertNextCell(cell->GetCellType(),pts);
454         }
455
456         // translate Source to Input point
457         input->GetPoint(inPtId, x);
458
459         //projection on the plane orthogonale to the camera
460         trans->Scale(mOrientation[0],mOrientation[1],mOrientation[2]);
461
462         trans->Translate(x[0], x[1], x[2]);
463
464         if ( haveVectors )
465         {
466             // Copy Input vector
467             for (i=0; i < numSourcePts; i++)
468             {
469                 newVectors->InsertTuple(i+ptIncr, v);
470             }
471             if (this->Orient && (vMag > 0.0))
472             {
473                 // if there is no y or z component
474                 if ( v[1] == 0.0 && v[2] == 0.0 )
475                 {
476                     if (v[0] < 0) //just flip x if we need to
477                     {
478                         trans->RotateWXYZ(180.0,0,1,0);
479                     }
480                 }
481                 else
482                 {
483                     vNew[0] = (v[0]+vMag) / 2.0;
484                     vNew[1] = v[1] / 2.0;
485                     vNew[2] = v[2] / 2.0;
486                     trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]);
487                 }
488             }
489         }
490
491         if (haveTCoords)
492         {
493             for (i = 0; i < numSourcePts; i++)
494             {
495                 sourceTCoords->GetTuple(i, tc);
496                 newTCoords->InsertTuple(i+ptIncr, tc);
497             }
498         }
499
500         // determine scale factor from scalars if appropriate
501         // Copy scalar value
502         if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE))
503         {
504             for (i=0; i < numSourcePts; i++)
505             {
506                 newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez
507             }
508         }
509         else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR))
510         {
511             for (i=0; i < numSourcePts; i++)
512             {
513                 outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i);
514             }
515         }
516         if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR)
517         {
518             double color = 1;
519             for (i=0; i < numSourcePts; i++)
520             {
521                 newScalars->InsertTuple(i+ptIncr, &color);
522             }
523         }
524
525         // scale data if appropriate
526         if ( this->Scaling )
527         {
528             if ( this->ScaleMode == VTK_DATA_SCALING_OFF )
529             {
530                 scalex = scaley = scalez = this->ScaleFactor;
531             }
532             else
533             {
534                 scalex *= this->ScaleFactor;
535                 scaley *= this->ScaleFactor;
536                 scalez *= this->ScaleFactor;
537             }
538
539             if ( scalex == 0.0 )
540             {
541                 scalex = 1.0e-10;
542             }
543             if ( scaley == 0.0 )
544             {
545                 scaley = 1.0e-10;
546             }
547             if ( scalez == 0.0 )
548             {
549                 scalez = 1.0e-10;
550             }
551             trans->Scale(scalex,scaley,scalez);
552         }
553         // multiply points and normals by resulting matrix
554         trans->TransformPoints(sourcePts,newPts);
555
556         if ( haveNormals )
557         {
558             trans->TransformNormals(sourceNormals,newNormals);
559         }
560
561         // Copy point data from source (if possible)
562         if ( pd )
563         {
564             for (i=0; i < numSourcePts; i++)
565             {
566                 outputPD->CopyData(pd,inPtId,ptIncr+i);
567             }
568         }
569
570         // If point ids are to be generated, do it here
571         if ( this->GeneratePointIds )
572         {
573             for (i=0; i < numSourcePts; i++)
574             {
575                 pointIds->InsertNextValue(inPtId);
576             }
577         }
578
579         ptIncr += numSourcePts;
580     }
581
582     // Update ourselves and release memory
583     //
584     output->SetPoints(newPts);
585     newPts->Delete();
586
587     if (newScalars)
588     {
589         int idx = outputPD->AddArray(newScalars);
590         outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
591         newScalars->Delete();
592     }
593
594     if (newVectors)
595     {
596         outputPD->SetVectors(newVectors);
597         newVectors->Delete();
598     }
599
600     if (newNormals)
601     {
602         outputPD->SetNormals(newNormals);
603         newNormals->Delete();
604     }
605
606     if (newTCoords)
607     {
608         outputPD->SetTCoords(newTCoords);
609         newTCoords->Delete();
610     }
611
612     output->Squeeze();
613     trans->Delete();
614     pts->Delete();
615
616     return 1;
617 }
618
619 void vvGlyph2D::PrintSelf(ostream& os, vtkIndent indent)
620 {
621     this->Superclass::PrintSelf(os,indent);
622 }
623
624 void vvGlyph2D::SetOrientation(int x, int y, int z)
625 {
626     if (x == 0)
627         mOrientation[0] = 1.0e-10;
628     else
629         mOrientation[0] = 1.0;
630     if (y == 0)
631         mOrientation[1] = 1.0e-10;
632     else
633         mOrientation[1] = 1.0;
634     if (z == 0)
635         mOrientation[2] = 1.0e-10;
636     else
637         mOrientation[2] = 1.0;
638 }