]> SALOME platform Git repositories - modules/visu.git/blob - src/PIPELINE/VISU_LookupTable.cxx
Salome HOME
Merge from OCC_development_generic_2006
[modules/visu.git] / src / PIPELINE / VISU_LookupTable.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //  File   : VISU_LookupTable.cxx
24 //  Author : Vitaliy Smetannikov
25 //  Module : VISU
26
27 #include "VISU_LookupTable.hxx"
28
29 #include <vtkObjectFactory.h>
30 #include <vtkBitArray.h>
31 #include <math.h>
32
33 using namespace std;
34
35 VISU_LookupTable *VISU_LookupTable::New() {
36   vtkObject* ret = vtkObjectFactory::CreateInstance("VISU_LookupTable");
37   if(ret)
38     return (VISU_LookupTable*)ret;
39   return new VISU_LookupTable;
40 }
41
42 VISU_LookupTable::VISU_LookupTable(int sze, int ext)
43   : vtkLookupTable(sze, ext), myScale(1.0), myBicolor(false) {}
44
45 void VISU_LookupTable::SetMapScale(float theScale)
46 {
47   if( myScale != theScale )
48   {
49     myScale = theScale;
50     Modified();
51   }
52 }
53
54 void VISU_LookupTable::SetBicolor( bool theBicolor )
55 {
56   if( myBicolor != theBicolor )
57   {
58     myBicolor = theBicolor;
59     Modified();
60   }
61 }
62
63
64 int VISU_LookupTable::ComputeLogRange(float inRange[2], float outRange[2]){
65   if(inRange[0] >= inRange[1])
66     return -1;
67   if(0.0 <= inRange[0] && 0.0 < inRange[1]){
68     if(inRange[0] != 0.0)
69       outRange[0] = log10((double)inRange[0]);
70     else
71       outRange[0] = log10((double)inRange[1]*1.0E-6);
72     outRange[1] = log10((double)inRange[1]);
73     return 0;
74   }else if(inRange[0] < 0.0 && inRange[1] <= 0.0){
75     outRange[0] = log10((double)-inRange[0]);
76     outRange[1] = log10((double)-inRange[1]);
77     return 1;
78   }else
79     return -1;
80 }
81
82 unsigned char* VISU_LookupTable::MapValue(float v) {
83   if(GetScale() == VTK_SCALE_LOG10) {
84     float aLowBound = log10(this->TableRange[0]);
85     v = pow(10.0f,aLowBound + (v - aLowBound)*myScale);
86     return vtkLookupTable::MapValue(v);
87   } else if (!myBicolor) {
88     v = this->TableRange[0] + (v - this->TableRange[0])*myScale;
89     return vtkLookupTable::MapValue(v);
90   } else {
91     unsigned char* table = this->Table->GetPointer(0);
92     int index = v > 0 ? 4*static_cast<int>(this->GetNumberOfColors()-1) : 0;
93     return &table[index];
94   }
95 }
96
97 // Apply log to value, with appropriate constraints.
98 inline float VISU_ApplyLogScale(float v, float range[2], 
99                                 float logRange[2])
100 {
101   // is the range set for negative numbers?
102   if (range[0] < 0)
103     {
104     if (v < 0)
105       {
106       v = log10(-static_cast<double>(v));
107       }
108     else if (range[0] > range[1])
109       {
110       v = logRange[0];
111       }
112     else
113       {
114       v = logRange[1];
115       }
116     }
117   else
118     {
119     if (v > 0)
120       {
121       v = log10(static_cast<double>(v));
122       }
123     else if (range[0] < range[1])
124       {
125       v = logRange[0];
126       }
127     else
128       {
129       v = logRange[1];
130       }
131     }
132   return v;
133 }                 
134
135 // Apply shift/scale to the scalar value v and do table lookup.
136 inline unsigned char *VISU_LinearLookup(float v,   
137                                         unsigned char *table,
138                                         float maxIndex,
139                                         float shift, float scale,
140                                         bool bicolor)
141 {
142   if( !bicolor )
143   {
144     float findx = (v + shift)*scale;
145     if (findx < 0)
146       findx = 0;
147     if (findx > maxIndex)
148       findx = maxIndex;
149
150     return &table[4*static_cast<int>(findx)];
151     // round
152     //return &table[4*(int)(findx + 0.5f)];
153   }
154   else
155   {
156     int index = v > 0 ? 4*static_cast<int>(maxIndex) : 0;
157     return &table[index];
158   }
159 }
160
161 // accelerate the mapping by copying the data in 32-bit chunks instead
162 // of 8-bit chunks
163 template<class T>
164 void VISU_LookupTableMapData(vtkLookupTable *self, T *input, 
165                              unsigned char *output, int length, 
166                              int inIncr, int outFormat,
167                              float theMapScale, bool bicolor)
168 {
169   int i = length;
170   float *range = self->GetTableRange();
171   float maxIndex = self->GetNumberOfColors() - 1;
172   float shift, scale;
173   unsigned char *table = self->GetPointer(0);
174   unsigned char *cptr;
175   float alpha;
176
177   if ( (alpha=self->GetAlpha()) >= 1.0 ) //no blending required 
178     {
179     if (self->GetScale() == VTK_SCALE_LOG10)
180       {
181       float val;
182       float logRange[2];
183       VISU_LookupTable::ComputeLogRange(range, logRange);
184       shift = -logRange[0];
185       if (logRange[1] <= logRange[0])
186         {
187         scale = VTK_LARGE_FLOAT;
188         }
189       else
190         {
191         scale = (maxIndex + 1)/(logRange[1] - logRange[0]);
192         }
193       /* correct scale
194       scale = maxIndex/(logRange[1] - logRange[0]);
195       */
196       if (outFormat == VTK_RGBA)
197         {
198         while (--i >= 0) 
199           {
200           val = VISU_ApplyLogScale(*input, range, logRange);
201           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
202           *output++ = *cptr++;
203           *output++ = *cptr++;
204           *output++ = *cptr++;
205           *output++ = *cptr++;     
206           input += inIncr;
207           }
208         }
209       else if (outFormat == VTK_RGB)
210         {
211         while (--i >= 0) 
212           {
213           val = VISU_ApplyLogScale(*input, range, logRange);
214           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
215           *output++ = *cptr++;
216           *output++ = *cptr++;
217           *output++ = *cptr++;
218           input += inIncr;
219           }
220         }
221       else if (outFormat == VTK_LUMINANCE_ALPHA)
222         {
223         while (--i >= 0) 
224           {
225           val = VISU_ApplyLogScale(*input, range, logRange);
226           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
227           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
228                                                  cptr[2]*0.11 + 0.5);
229           *output++ = cptr[3];
230           input += inIncr;
231           }
232         }
233       else // outFormat == VTK_LUMINANCE
234         {
235         while (--i >= 0) 
236           {
237           val = VISU_ApplyLogScale(*input, range, logRange);
238           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
239           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
240                                                  cptr[2]*0.11 + 0.5);
241           input += inIncr;
242           }
243         }
244       }//if log scale
245
246     else //not log scale
247       {
248       shift = -range[0];
249       if (range[1] <= range[0])
250         {
251         scale = VTK_LARGE_FLOAT;
252         }
253       else
254         {
255         scale = (maxIndex + 1)/(range[1] - range[0]);
256         }
257       /* correct scale
258       scale = maxIndex/(range[1] - range[0]);
259       */
260
261       if (outFormat == VTK_RGBA)
262         {
263         while (--i >= 0) 
264           {
265           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale, bicolor); 
266           *output++ = *cptr++;
267           *output++ = *cptr++;
268           *output++ = *cptr++;
269           *output++ = *cptr++;     
270           input += inIncr;
271           }
272         }
273       else if (outFormat == VTK_RGB)
274         {
275         while (--i >= 0) 
276           {
277           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale, bicolor); 
278           *output++ = *cptr++;
279           *output++ = *cptr++;
280           *output++ = *cptr++;
281           input += inIncr;
282           }
283         }
284       else if (outFormat == VTK_LUMINANCE_ALPHA)
285         {
286         while (--i >= 0) 
287           {
288           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale, bicolor); 
289           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
290                                                  cptr[2]*0.11 + 0.5);
291           *output++ = cptr[3];
292           input += inIncr;
293           }
294         }
295       else // outFormat == VTK_LUMINANCE
296         {
297         while (--i >= 0) 
298           {
299           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale, bicolor); 
300           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
301                                                  cptr[2]*0.11 + 0.5);
302           input += inIncr;
303           }
304         }
305       }//if not log lookup
306     }//if blending not needed
307
308   else //blend with the specified alpha
309     {
310     if (self->GetScale() == VTK_SCALE_LOG10)
311       {
312       float val;
313       float logRange[2];
314       VISU_LookupTable::ComputeLogRange(range, logRange);
315       shift = -logRange[0];
316       if (logRange[1] <= logRange[0])
317         {
318         scale = VTK_LARGE_FLOAT;
319         }
320       else
321         {
322         scale = (maxIndex + 1)/(logRange[1] - logRange[0]);
323         }
324       /* correct scale
325       scale = maxIndex/(logRange[1] - logRange[0]);
326       */
327       if (outFormat == VTK_RGBA)
328         {
329         while (--i >= 0) 
330           {
331           val = VISU_ApplyLogScale(*input, range, logRange);
332           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
333           *output++ = *cptr++;
334           *output++ = *cptr++;
335           *output++ = *cptr++;
336           *output++ = static_cast<unsigned char>((*cptr)*alpha); cptr++;
337           input += inIncr;
338           }
339         }
340       else if (outFormat == VTK_RGB)
341         {
342         while (--i >= 0) 
343           {
344           val = VISU_ApplyLogScale(*input, range, logRange);
345           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
346           *output++ = *cptr++;
347           *output++ = *cptr++;
348           *output++ = *cptr++;
349           input += inIncr;
350           }
351         }
352       else if (outFormat == VTK_LUMINANCE_ALPHA)
353         {
354         while (--i >= 0) 
355           {
356           val = VISU_ApplyLogScale(*input, range, logRange);
357           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
358           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
359                                                  cptr[2]*0.11 + 0.5);
360           *output++ = static_cast<unsigned char>(alpha*cptr[3]);
361           input += inIncr;
362           }
363         }
364       else // outFormat == VTK_LUMINANCE
365         {
366         while (--i >= 0) 
367           {
368           val = VISU_ApplyLogScale(*input, range, logRange);
369           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale, bicolor); 
370           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
371                                                  cptr[2]*0.11 + 0.5);
372           input += inIncr;
373           }
374         }
375       }//log scale with blending
376
377     else //no log scale with blending
378       {
379       shift = -range[0];
380       if (range[1] <= range[0])
381         {
382         scale = VTK_LARGE_FLOAT;
383         }
384       else
385         {
386         scale = (maxIndex + 1)/(range[1] - range[0]);
387         }
388       /* correct scale
389       scale = maxIndex/(range[1] - range[0]);
390       */
391
392       if (outFormat == VTK_RGBA)
393         {
394         while (--i >= 0) 
395           {
396           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale, bicolor); 
397           *output++ = *cptr++;
398           *output++ = *cptr++;
399           *output++ = *cptr++;
400           *output++ = static_cast<unsigned char>((*cptr)*alpha); cptr++;
401           input += inIncr;
402           }
403         }
404       else if (outFormat == VTK_RGB)
405         {
406         while (--i >= 0) 
407           {
408           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale, bicolor); 
409           *output++ = *cptr++;
410           *output++ = *cptr++;
411           *output++ = *cptr++;
412           input += inIncr;
413           }
414         }
415       else if (outFormat == VTK_LUMINANCE_ALPHA)
416         {
417         while (--i >= 0) 
418           {
419           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale, bicolor); 
420           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
421                                                  cptr[2]*0.11 + 0.5);
422           *output++ = static_cast<unsigned char>(cptr[3]*alpha);
423           input += inIncr;
424           }
425         }
426       else // outFormat == VTK_LUMINANCE
427         {
428         while (--i >= 0) 
429           {
430           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale, bicolor); 
431           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
432                                                  cptr[2]*0.11 + 0.5);
433           input += inIncr;
434           }
435         }
436       }//no log scale
437     }//alpha blending
438 }
439
440 // Although this is a relatively expensive calculation,
441 // it is only done on the first render. Colors are cached
442 // for subsequent renders.
443 template<class T>
444 void VISU_LookupTableMapMag(vtkLookupTable *self, T *input, 
445                             unsigned char *output, int length, 
446                             int inIncr, int outFormat,
447                             float theMapScale, bool bicolor)
448 {
449   double tmp, sum;
450   double *mag;
451   int i, j;
452
453   mag = new double[length];
454   for (i = 0; i < length; ++i)
455     {
456     sum = 0;
457     for (j = 0; j < inIncr; ++j)
458       {
459       tmp = (double)(*input);  
460       sum += (tmp * tmp);
461       ++input;
462       }
463     mag[i] = sqrt(sum);
464     }
465
466   VISU_LookupTableMapData(self, mag, output, length, 1, outFormat, theMapScale, bicolor);
467
468   delete [] mag;
469 }
470
471
472 void VISU_LookupTable::MapScalarsThroughTable2(void *input, 
473                                                unsigned char *output,
474                                                int inputDataType, 
475                                                int numberOfValues,
476                                                int inputIncrement,
477                                                int outputFormat)
478 {
479   if (this->UseMagnitude && inputIncrement > 1)
480     {
481     switch (inputDataType)
482       {
483       case VTK_BIT:
484         vtkErrorMacro("Cannot comput magnitude of bit array.");
485         break;
486       case VTK_CHAR:
487         VISU_LookupTableMapMag(this,static_cast<char *>(input),output,
488                                numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
489         return; 
490       case VTK_UNSIGNED_CHAR:
491         VISU_LookupTableMapMag(this,static_cast<unsigned char *>(input),output,
492                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
493         return;
494       case VTK_SHORT:
495         VISU_LookupTableMapMag(this,static_cast<short *>(input),output,
496                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
497         return;
498       case VTK_UNSIGNED_SHORT:
499         VISU_LookupTableMapMag(this,static_cast<unsigned short *>(input),output,
500                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
501         return;
502       case VTK_INT:
503         VISU_LookupTableMapMag(this,static_cast<int *>(input),output,
504                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
505         return;
506       case VTK_UNSIGNED_INT:
507         VISU_LookupTableMapMag(this,static_cast<unsigned int *>(input),output,
508                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
509         return;
510       case VTK_LONG:
511         VISU_LookupTableMapMag(this,static_cast<long *>(input),output,
512                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
513         return;
514       case VTK_UNSIGNED_LONG:
515         VISU_LookupTableMapMag(this,static_cast<unsigned long *>(input),output,
516                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
517         return;
518       case VTK_FLOAT:
519         VISU_LookupTableMapMag(this,static_cast<float *>(input),output,
520                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
521         return;
522       case VTK_DOUBLE:
523         VISU_LookupTableMapMag(this,static_cast<double *>(input),output,
524                              numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
525         return;
526       default:
527         vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType");
528         return;
529       }
530     }
531
532   switch (inputDataType)
533     {
534     case VTK_BIT:
535       {
536       vtkIdType i, id;
537       vtkBitArray *bitArray = vtkBitArray::New();
538       bitArray->SetVoidArray(input,numberOfValues,1);
539       vtkUnsignedCharArray *newInput = vtkUnsignedCharArray::New();
540       newInput->SetNumberOfValues(numberOfValues);
541       for (id=i=0; i<numberOfValues; i++, id+=inputIncrement)
542         {
543         newInput->SetValue(i, bitArray->GetValue(id));
544         }
545       VISU_LookupTableMapData(this,
546                               static_cast<unsigned char*>(newInput->GetPointer(0)),
547                               output,numberOfValues,
548                               inputIncrement,outputFormat,myScale,myBicolor);
549       newInput->Delete();
550       bitArray->Delete();
551       }
552       break;
553       
554     case VTK_CHAR:
555       VISU_LookupTableMapData(this,static_cast<char *>(input),output,
556                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
557       break;
558       
559     case VTK_UNSIGNED_CHAR:
560       VISU_LookupTableMapData(this,static_cast<unsigned char *>(input),output,
561                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
562       break;
563       
564     case VTK_SHORT:
565       VISU_LookupTableMapData(this,static_cast<short *>(input),output,
566                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
567       break;
568       
569     case VTK_UNSIGNED_SHORT:
570       VISU_LookupTableMapData(this,static_cast<unsigned short *>(input),output,
571                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
572       break;
573       
574     case VTK_INT:
575       VISU_LookupTableMapData(this,static_cast<int *>(input),output,
576                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
577       break;
578       
579     case VTK_UNSIGNED_INT:
580       VISU_LookupTableMapData(this,static_cast<unsigned int *>(input),output,
581                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
582       break;
583       
584     case VTK_LONG:
585       VISU_LookupTableMapData(this,static_cast<long *>(input),output,
586                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
587       break;
588       
589     case VTK_UNSIGNED_LONG:
590       VISU_LookupTableMapData(this,static_cast<unsigned long *>(input),output,
591                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
592       break;
593       
594     case VTK_FLOAT:
595       VISU_LookupTableMapData(this,static_cast<float *>(input),output,
596                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
597       break;
598       
599     case VTK_DOUBLE:
600       VISU_LookupTableMapData(this,static_cast<double *>(input),output,
601                               numberOfValues,inputIncrement,outputFormat,myScale,myBicolor);
602       break;
603       
604     default:
605       vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType");
606       return;
607     }
608 }  
609