0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / Aspect / Aspect_ColorScale.cxx
1 // Created on: 2004-06-22
2 // Created by: STV
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Aspect_ColorScale.hxx>
18 #include <Aspect_SequenceOfColor.hxx>
19 #include <Aspect_TypeOfColorScaleData.hxx>
20 #include <Aspect_TypeOfColorScalePosition.hxx>
21 #include <Precision.hxx>
22 #include <Quantity_Color.hxx>
23 #include <Standard_Type.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <TCollection_ExtendedString.hxx>
26 #include <TColStd_SequenceOfExtendedString.hxx>
27
28 #include <stdio.h>
29 Aspect_ColorScale::Aspect_ColorScale()
30 : MMgt_TShared(),
31 myMin( 0.0 ),
32 myMax( 1.0 ),
33 myTitle( "" ),
34 myFormat( "%.4g" ),
35 myInterval( 10 ),
36 myColorType( Aspect_TOCSD_AUTO ),
37 myLabelType( Aspect_TOCSD_AUTO ),
38 myAtBorder( Standard_True ),
39 myReversed( Standard_False ),
40 myLabelPos( Aspect_TOCSP_RIGHT ),
41 myTitlePos( Aspect_TOCSP_CENTER ),
42 myXPos( 0 ),
43 myYPos( 0 ),
44 myWidth( 0.2 ),
45 myHeight( 1 ),
46 myTextHeight(20)
47 {
48 }
49
50 Standard_Real Aspect_ColorScale::GetMin() const
51 {
52   return myMin;
53 }
54
55 Standard_Real Aspect_ColorScale::GetMax() const
56 {
57   return myMax;
58 }
59
60 void Aspect_ColorScale::GetRange (Standard_Real& theMin, Standard_Real& theMax) const
61 {
62   theMin = myMin;
63   theMax = myMax;
64 }
65
66 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetLabelType() const
67 {
68   return myLabelType;
69 }
70
71 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetColorType() const
72 {
73   return myColorType;
74 }
75
76 Standard_Integer Aspect_ColorScale::GetNumberOfIntervals() const
77 {
78   return myInterval;
79 }
80
81 TCollection_ExtendedString Aspect_ColorScale::GetTitle() const
82 {
83   return myTitle;
84 }
85
86 TCollection_AsciiString Aspect_ColorScale::GetFormat() const
87 {
88   return myFormat;
89 }
90
91 TCollection_ExtendedString Aspect_ColorScale::GetLabel (const Standard_Integer theIndex) const
92 {
93   if (GetLabelType() == Aspect_TOCSD_USER)
94   {
95     if (theIndex < 0
96      || theIndex >= myLabels.Length())
97     {
98       return "";
99     }
100
101     return myLabels.Value (theIndex + 1);
102   }
103
104   const Standard_Real           aVal    = GetNumber (theIndex);
105   const TCollection_AsciiString aFormat = Format();
106   Standard_Character aBuf[1024];
107   sprintf (aBuf, aFormat.ToCString(), aVal);
108   return TCollection_ExtendedString (aBuf);
109 }
110
111 Quantity_Color Aspect_ColorScale::GetColor (const Standard_Integer theIndex) const
112 {
113   if (GetColorType() == Aspect_TOCSD_USER)
114   {
115     if (theIndex < 0
116      || theIndex >= myColors.Length())
117     {
118       return Quantity_Color();
119     }
120
121     return myColors.Value (theIndex + 1);
122   }
123   return Quantity_Color (HueFromValue (theIndex, 0, GetNumberOfIntervals() - 1), 1.0, 1.0, Quantity_TOC_HLS);
124 }
125
126 void Aspect_ColorScale::GetLabels (TColStd_SequenceOfExtendedString& theLabels) const
127 {
128   theLabels.Clear();
129   for (Standard_Integer i = 1; i <= myLabels.Length(); i++)
130     theLabels.Append (myLabels.Value (i));
131 }
132
133 void Aspect_ColorScale::GetColors (Aspect_SequenceOfColor& theColors) const
134 {
135   theColors.Clear();
136   for (Standard_Integer i = 1; i <= myColors.Length(); i++)
137     theColors.Append (myColors.Value (i));
138 }
139
140 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetLabelPosition() const
141 {
142   return myLabelPos;
143 }
144
145 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetTitlePosition() const
146 {
147   return myTitlePos;
148 }
149
150 Standard_Boolean Aspect_ColorScale::IsReversed() const
151 {
152   return myReversed;
153 }
154
155 Standard_Boolean Aspect_ColorScale::IsLabelAtBorder() const
156 {
157   return myAtBorder;
158 }
159
160 void Aspect_ColorScale::SetMin (const Standard_Real theMin)
161 {
162   SetRange (theMin, GetMax());
163 }
164
165 void Aspect_ColorScale::SetMax (const Standard_Real theMax)
166 {
167   SetRange (GetMin(), theMax);
168 }
169
170 void Aspect_ColorScale::SetRange (const Standard_Real theMin, const Standard_Real theMax)
171 {
172   if (myMin == theMin && myMax == theMax)
173     return;
174  
175   myMin = Min( theMin, theMax );
176   myMax = Max( theMin, theMax );
177
178   if (GetColorType() == Aspect_TOCSD_AUTO)
179     UpdateColorScale();
180 }
181
182 void Aspect_ColorScale::SetLabelType (const Aspect_TypeOfColorScaleData theType)
183 {
184   if (myLabelType == theType)
185     return;
186
187   myLabelType = theType;
188   UpdateColorScale();
189 }
190
191 void Aspect_ColorScale::SetColorType (const Aspect_TypeOfColorScaleData theType)
192 {
193   if (myColorType == theType)
194     return;
195
196   myColorType = theType;
197   UpdateColorScale();
198 }
199
200 void Aspect_ColorScale::SetNumberOfIntervals (const Standard_Integer theNum)
201 {
202   if (myInterval == theNum || theNum < 1)
203     return;
204
205   myInterval = theNum;
206   UpdateColorScale();
207 }
208
209 void Aspect_ColorScale::SetTitle (const TCollection_ExtendedString& theTitle)
210 {
211   if (myTitle == theTitle)
212     return;
213
214   myTitle = theTitle;
215   UpdateColorScale();
216 }
217
218 void Aspect_ColorScale::SetFormat (const TCollection_AsciiString& theFormat)
219 {
220   if (myFormat == theFormat)
221     return;
222
223   myFormat = theFormat;
224   if (GetLabelType() == Aspect_TOCSD_AUTO)
225     UpdateColorScale();
226 }
227
228 void Aspect_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer theIndex)
229 {
230   Standard_Boolean changed = Standard_False;
231   Standard_Integer i = theIndex < 0 ? myLabels.Length() + 1 : theIndex + 1;
232   if (i <= myLabels.Length()) {
233     changed = myLabels.Value (i) != theLabel;
234     myLabels.SetValue (i, theLabel);
235   }
236   else {
237     changed = Standard_True;
238     while (i > myLabels.Length())
239       myLabels.Append (TCollection_ExtendedString());
240     myLabels.SetValue (i, theLabel);
241   }
242   if (changed)
243     UpdateColorScale();
244 }
245
246 void Aspect_ColorScale::SetColor (const Quantity_Color& theColor, const Standard_Integer theIndex)
247 {
248   Standard_Boolean changed = Standard_False;
249   Standard_Integer i = theIndex < 0 ? myColors.Length() + 1 : theIndex + 1;
250   if (i <= myColors.Length()) {
251     changed = myColors.Value (i) != theColor;
252     myColors.SetValue (i, theColor);
253   }
254   else {
255     changed = Standard_True;
256     while ( i > myColors.Length() )
257       myColors.Append (Quantity_Color());
258     myColors.SetValue (i, theColor);
259   }
260   if (changed)
261     UpdateColorScale();
262 }
263
264 void Aspect_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq)
265 {
266   myLabels.Clear();
267   for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
268     myLabels.Append (theSeq.Value (i));
269 }
270
271 void Aspect_ColorScale::SetColors (const Aspect_SequenceOfColor& theSeq)
272 {
273   myColors.Clear();
274   for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
275     myColors.Append (theSeq.Value (i));
276 }
277
278 void Aspect_ColorScale::SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos)
279 {
280   if (myLabelPos == thePos)
281     return;
282
283   myLabelPos = thePos;
284   UpdateColorScale();
285 }
286
287 void Aspect_ColorScale::SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos)
288 {
289   if (myTitlePos == thePos)
290     return;
291
292   myTitlePos = thePos;
293   UpdateColorScale();
294 }
295
296 void Aspect_ColorScale::SetReversed (const Standard_Boolean theReverse)
297 {
298   if (myReversed == theReverse)
299     return;
300
301   myReversed = theReverse;
302   UpdateColorScale();
303 }
304
305 void Aspect_ColorScale::SetLabelAtBorder (const Standard_Boolean theOn)
306 {
307   if (myAtBorder == theOn)
308     return;
309
310   myAtBorder = theOn;
311   UpdateColorScale();
312 }
313
314 void Aspect_ColorScale::GetPosition (Standard_Real& theX, Standard_Real& theY) const
315 {
316   theX = myXPos;
317   theY = myYPos;
318 }
319
320 Standard_Real Aspect_ColorScale::GetXPosition() const
321 {
322   return myXPos;
323 }
324
325 Standard_Real Aspect_ColorScale::GetYPosition() const
326 {
327   return myYPos;
328 }
329
330 void Aspect_ColorScale::SetPosition (const Standard_Real theX, const Standard_Real theY)
331 {
332   if (myXPos == theX && myYPos == theY)
333     return;
334
335   myXPos = theX;
336   myYPos = theY;
337
338   UpdateColorScale();
339 }
340
341 void Aspect_ColorScale::SetXPosition (const Standard_Real theX)
342 {
343   SetPosition (theX, GetYPosition());
344 }
345
346 void Aspect_ColorScale::SetYPosition (const Standard_Real theY)
347 {
348   SetPosition (GetXPosition(), theY);
349 }
350
351 void Aspect_ColorScale::GetSize (Standard_Real& theWidth, Standard_Real& theHeight) const
352 {
353   theWidth = myWidth;
354   theHeight = myHeight;
355 }
356
357 Standard_Real Aspect_ColorScale::GetWidth() const
358 {
359   return myWidth;
360 }
361
362 Standard_Real Aspect_ColorScale::GetHeight() const
363 {
364   return myHeight;
365 }
366
367 void Aspect_ColorScale::SetSize (const Standard_Real theWidth, const Standard_Real theHeight)
368 {
369   if (myWidth == theWidth && myHeight == theHeight)
370     return;
371
372   myWidth = theWidth;
373   myHeight = theHeight;
374
375   UpdateColorScale();
376 }
377
378 void Aspect_ColorScale::SetWidth (const Standard_Real theWidth)
379 {
380   SetSize (theWidth, GetHeight());
381 }
382
383 void Aspect_ColorScale::SetHeight (const Standard_Real theHeight)
384 {
385   SetSize (GetWidth(), theHeight);
386 }
387
388 void Aspect_ColorScale::SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const
389 {
390   Standard_Integer num = GetNumberOfIntervals();
391
392   Standard_Integer spacer = 5;
393   Standard_Integer textWidth = 0;
394   Standard_Integer textHeight = TextHeight ("");
395   Standard_Integer colorWidth = 20;
396
397   if (GetLabelPosition() != Aspect_TOCSP_NONE)
398     for (Standard_Integer idx = 0; idx < num; idx++)
399       textWidth = Max (textWidth, TextWidth (GetLabel (idx + 1)));
400
401   Standard_Integer scaleWidth = 0;
402   Standard_Integer scaleHeight = 0;
403
404   Standard_Integer titleWidth = 0;
405   Standard_Integer titleHeight = 0;
406
407   if (IsLabelAtBorder()) {
408     num++;
409     if (GetTitle().Length())
410       titleHeight += 10;
411   }
412
413   scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
414   scaleHeight = (Standard_Integer)( 1.5 * ( num + 1 ) * textHeight );
415   
416   if (GetTitle().Length()) {
417     titleHeight = TextHeight (GetTitle()) + spacer;
418     titleWidth =  TextWidth (GetTitle()) + 10;
419   }
420
421   theWidth = Max (titleWidth, scaleWidth);
422   theHeight = scaleHeight + titleHeight;
423 }
424
425 void Aspect_ColorScale::DrawScale ( const Quantity_Color& theBgColor,
426                                       const Standard_Integer theX, const Standard_Integer theY,
427                                       const Standard_Integer theWidth, const Standard_Integer theHeight)
428 {
429   if (!BeginPaint())
430     return;
431
432   Standard_Integer num = GetNumberOfIntervals();
433   Aspect_TypeOfColorScalePosition labPos = GetLabelPosition();
434
435   Standard_Integer spacer = 5;
436   Standard_Integer textWidth = 0;
437   Standard_Integer textHeight = TextHeight ("");
438
439   Standard_Boolean drawLabel = GetLabelPosition() != Aspect_TOCSP_NONE;
440
441   TCollection_ExtendedString aTitle = GetTitle();
442
443   Standard_Integer titleHeight = 0;
444
445   Standard_Integer aGray = (Standard_Integer)(255 * ( theBgColor.Red() * 11 + theBgColor.Green() * 16 + theBgColor.Blue() * 5 ) / 32);
446   Quantity_Color aFgColor (aGray < 128 ? Quantity_NOC_WHITE : Quantity_NOC_BLACK);
447
448   // Draw title
449   if (aTitle.Length()) {
450     titleHeight = TextHeight (aTitle) + 2 * spacer;
451     PaintText (aTitle, theX + spacer, theY + spacer, aFgColor);
452   }
453
454   Standard_Boolean reverse = IsReversed();
455
456   Aspect_SequenceOfColor colors;
457   TColStd_SequenceOfExtendedString labels;
458   for (int idx = 0; idx < num; idx++) {
459     if (reverse) {
460       colors.Append (GetColor (idx));
461       labels.Append (GetLabel (idx));
462     }
463     else {
464       colors.Prepend (GetColor (idx));
465       labels.Prepend (GetLabel (idx));
466     }
467   }
468
469   if (IsLabelAtBorder()) {
470     if (reverse)
471       labels.Append (GetLabel (num));
472     else
473       labels.Prepend (GetLabel (num));
474   }
475
476   if (drawLabel)
477     for (Standard_Integer i = 1; i <= labels.Length(); i++)
478       textWidth = Max (textWidth, TextWidth (labels.Value (i)));
479
480   Standard_Integer lab = labels.Length();
481
482   Standard_Real spc = ( theHeight - ( ( Min (lab, 2) + Abs (lab - num - 1) ) * textHeight ) - titleHeight );
483   Standard_Real val = spc != 0 ? 1.0 * ( lab - Min (lab, 1) ) * textHeight / spc : 0;
484   Standard_Real iPart;
485   Standard_Real fPart = modf (val, &iPart);
486   Standard_Integer filter = (Standard_Integer)iPart + ( fPart != 0 ? 1 : 0 );
487
488   Standard_Real step = 1.0 * ( theHeight - ( lab - num + Abs (lab - num - 1) ) * textHeight - titleHeight ) / num;
489
490   Standard_Integer ascent = 0;
491   Standard_Integer colorWidth = Max (5, Min (20, theWidth - textWidth - 3 * spacer));
492   if (labPos == Aspect_TOCSP_CENTER || !drawLabel)
493     colorWidth = theWidth - 2 * spacer;
494
495   // Draw colors
496   Standard_Integer x = theX + spacer;
497   if (labPos == Aspect_TOCSP_LEFT)
498     x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
499
500   Standard_Real offset = 1.0 * textHeight / 2 * ( lab - num + Abs (lab - num - 1) ) + titleHeight;
501   for (Standard_Integer ci = 1; ci <= colors.Length() && step > 0; ci++ ) {
502     Standard_Integer y = (Standard_Integer)( theY + ( ci - 1 )* step + offset);
503     Standard_Integer h = (Standard_Integer)( theY + ( ci ) * step + offset ) - y;
504     PaintRect (x, y, colorWidth, h, colors.Value (ci), Standard_True);
505   }
506
507   if (step > 0)
508     PaintRect (x - 1, (Standard_Integer)(theY + offset - 1), colorWidth + 2, (Standard_Integer)(colors.Length() * step + 2), aFgColor);
509
510   // Draw labels
511   offset = 1.0 * Abs (lab - num - 1) * ( step - textHeight ) / 2 + 1.0 * Abs (lab - num - 1) * textHeight / 2;
512   offset += titleHeight;
513   if (drawLabel && labels.Length() && filter > 0) {
514     Standard_Integer i1 = 0;
515     Standard_Integer i2 = lab - 1;
516     Standard_Integer last1 (i1), last2 (i2);
517     x = theX + spacer;
518     switch ( labPos ) {
519     case Aspect_TOCSP_NONE:
520     case Aspect_TOCSP_LEFT:
521       break;
522     case Aspect_TOCSP_CENTER:
523       x += ( colorWidth - textWidth ) / 2;
524       break;
525     case Aspect_TOCSP_RIGHT:
526       x += colorWidth + spacer;
527       break;
528     }
529     while (i2 - i1 >= filter || ( i2 == 0 && i1 == 0 )) {
530       Standard_Integer pos1 = i1;
531       Standard_Integer pos2 = lab - 1 - i2;
532       if (filter && !( pos1 % filter )) {
533         PaintText (labels.Value (i1 + 1), x, (Standard_Integer)( theY + i1 * step + ascent + offset ), aFgColor);
534         last1 = i1;
535       }
536       if (filter && !( pos2 % filter )) {
537         PaintText (labels.Value (i2 + 1), x, (Standard_Integer)( theY + i2 * step + ascent + offset ), aFgColor);
538         last2 = i2;
539       }
540       i1++;
541       i2--;
542     }
543     Standard_Integer pos = i1;
544     Standard_Integer i0 = -1;
545     while (pos <= i2 && i0 == -1) {
546       if (filter && !( pos % filter ) && Abs (pos - last1) >= filter && Abs (pos - last2) >= filter)
547         i0 = pos;
548       pos++;
549     }
550
551     if (i0 != -1)
552       PaintText (labels.Value (i0 + 1), x, (Standard_Integer)( theY + i0 * step + ascent + offset ), aFgColor);
553   }
554
555   EndPaint();
556 }
557
558 Standard_Boolean Aspect_ColorScale::BeginPaint()
559 {
560   return Standard_True;
561 }
562
563 Standard_Boolean Aspect_ColorScale::EndPaint()
564 {
565   return Standard_True;
566 }
567
568 void Aspect_ColorScale::UpdateColorScale()
569 {
570 }
571
572 TCollection_AsciiString Aspect_ColorScale::Format() const
573 {
574   return GetFormat();
575 }
576
577 Standard_Real Aspect_ColorScale::GetNumber (const Standard_Integer theIndex) const
578 {
579   Standard_Real aNum = 0;
580   if (GetNumberOfIntervals() > 0)
581     aNum = GetMin() + theIndex * ( Abs (GetMax() - GetMin()) / GetNumberOfIntervals() );
582   return aNum;
583 }
584
585 Standard_Integer Aspect_ColorScale::HueFromValue (const Standard_Integer theValue,
586                                                   const Standard_Integer theMin, const Standard_Integer theMax)
587 {
588   Standard_Integer minLimit (0), maxLimit (230);
589
590   Standard_Integer aHue = maxLimit;
591   if (theMin != theMax)
592     aHue = (Standard_Integer)( maxLimit - ( maxLimit - minLimit ) * ( theValue - theMin ) / ( theMax - theMin ) );
593
594   aHue = Min (Max (minLimit, aHue), maxLimit);
595
596   return aHue;
597 }
598
599 Standard_Integer  Aspect_ColorScale::GetTextHeight() const {
600   return myTextHeight;
601 }
602
603 void Aspect_ColorScale::SetTextHeight (const Standard_Integer theHeight) {
604   myTextHeight = theHeight;
605   UpdateColorScale ();
606 }
607
608
609 Standard_Boolean Aspect_ColorScale::FindColor (const Standard_Real theValue,
610                                                Quantity_Color& theColor) const
611 {
612   return FindColor (theValue, myMin, myMax, myInterval, theColor);
613 }
614
615
616 Standard_Boolean Aspect_ColorScale::FindColor (const Standard_Real theValue,
617                                                const Standard_Real theMin,
618                                                const Standard_Real theMax,
619                                                const Standard_Integer theColorsCount,
620                                                Quantity_Color& theColor)
621 {
622   if(theValue<theMin || theValue>theMax || theMax<theMin)
623     return Standard_False;
624
625   else
626   {
627     Standard_Real IntervNumber = 0;
628     if(Abs (theMax-theMin) > Precision::Approximation())
629       IntervNumber = Floor (Standard_Real( theColorsCount ) * ( theValue - theMin ) / ( theMax - theMin ));
630
631     Standard_Integer Interv = Standard_Integer (IntervNumber);
632
633     theColor = Quantity_Color (HueFromValue (Interv, 0, theColorsCount - 1), 1.0, 1.0, Quantity_TOC_HLS);
634
635     return Standard_True;
636   } 
637 }