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