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