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