65042bb4eca46e48cfda928cbe6272a9c28c1526
[occt.git] / src / AIS / AIS_ColorScale.cxx
1 // Created on: 2015-02-03
2 // Copyright (c) 2015 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_ColorScale.hxx>
16 #include <AIS_InteractiveContext.hxx>
17 #include <Aspect_TypeOfColorScaleData.hxx>
18 #include <Aspect_TypeOfColorScalePosition.hxx>
19 #include <Aspect_Window.hxx>
20 #include <Geom_Line.hxx>
21 #include <GeomAdaptor_Curve.hxx>
22 #include <Graphic3d_ArrayOfPolygons.hxx>
23 #include <Graphic3d_ArrayOfPolylines.hxx>
24 #include <Graphic3d_AspectFillArea3d.hxx>
25 #include <Graphic3d_AspectText3d.hxx>
26 #include <Graphic3d_GraphicDriver.hxx>
27 #include <Graphic3d_ArrayOfTriangles.hxx>
28 #include <Prs3d_LineAspect.hxx>
29 #include <Prs3d_Root.hxx>
30 #include <Prs3d_ShadingAspect.hxx>
31 #include <Prs3d_Text.hxx>
32 #include <Prs3d_TextAspect.hxx>
33 #include <SelectMgr_EntityOwner.hxx>
34 #include <SelectMgr_Selection.hxx>
35 #include <Select3D_SensitiveBox.hxx>
36 #include <Select3D_SensitiveSegment.hxx>
37 #include <StdPrs_Curve.hxx>
38 #include <V3d_Viewer.hxx>
39 #include <V3d_View.hxx>
40
41
42 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColorScale,AIS_InteractiveObject)
43
44 //=======================================================================
45 //function : AIS_ColorScale
46 //purpose  :
47 //=======================================================================
48 AIS_ColorScale::AIS_ColorScale() :
49 myMin (0.0),
50 myMax (1.0),
51 myTitle (""),
52 myFormat ("%.4g"),
53 myInterval (10),
54 myColorType (Aspect_TOCSD_AUTO),
55 myLabelType (Aspect_TOCSD_AUTO),
56 myAtBorder (Standard_True),
57 myReversed (Standard_False),
58 myIsLogarithmic (Standard_False),
59 myLabelPos (Aspect_TOCSP_RIGHT),
60 myTitlePos (Aspect_TOCSP_CENTER),
61 myXPos (0),
62 myYPos (0),
63 myBreadth (0),
64 myHeight (0),
65 myTextHeight(20)
66 {
67 }
68
69 //=======================================================================
70 //function : GetRange
71 //purpose  :
72 //=======================================================================
73 void AIS_ColorScale::GetRange (Standard_Real& theMin, Standard_Real& theMax) const
74 {
75   theMin = myMin;
76   theMax = myMax;
77 }
78
79 //=======================================================================
80 //function : GetLabel
81 //purpose  :
82 //=======================================================================
83 TCollection_ExtendedString AIS_ColorScale::GetLabel (const Standard_Integer theIndex) const
84 {
85   if (GetLabelType() == Aspect_TOCSD_USER)
86   {
87     if (theIndex <= 0 || theIndex > myLabels.Length())
88     {
89       return "";
90     }
91     return myLabels.Value (theIndex);
92   }
93
94   // value to be shown depends on label position
95   Standard_Real aVal = IsLabelAtBorder() ? GetIntervalValue (theIndex - 1) :
96                        0.5 * (GetIntervalValue (theIndex - 1) + GetIntervalValue (theIndex));
97
98   const TCollection_AsciiString aFormat = Format();
99   Standard_Character aBuf[1024];
100   sprintf (aBuf, aFormat.ToCString(), aVal);
101   return TCollection_ExtendedString (aBuf);
102 }
103
104 //=======================================================================
105 //function : GetIntervalColor
106 //purpose  :
107 //=======================================================================
108 Quantity_Color AIS_ColorScale::GetIntervalColor (const Standard_Integer theIndex) const
109 {
110   if (GetColorType() == Aspect_TOCSD_USER)
111   {
112     if (theIndex <= 0 || theIndex > myColors.Length())
113     {
114       return Quantity_Color();
115     }
116     return myColors.Value (theIndex);
117   }
118
119   return Quantity_Color (HueFromValue (theIndex - 1, 0, GetNumberOfIntervals() - 1), 1.0, 1.0, Quantity_TOC_HLS);
120 }
121
122 //=======================================================================
123 //function : GetLabels
124 //purpose  :
125 //=======================================================================
126 void AIS_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 //=======================================================================
134 //function : GetColors
135 //purpose  :
136 //=======================================================================
137 void AIS_ColorScale::GetColors (Aspect_SequenceOfColor& theColors) const
138 {
139   theColors.Clear();
140   for (Standard_Integer i = 1; i <= myColors.Length(); i++)
141     theColors.Append (myColors.Value (i));
142 }
143
144 //=======================================================================
145 //function : SetMin
146 //purpose  :
147 //=======================================================================
148 void AIS_ColorScale::SetMin (const Standard_Real theMin)
149 {
150   SetRange (theMin, GetMax());
151 }
152
153 //=======================================================================
154 //function : SetMax
155 //purpose  :
156 //=======================================================================
157 void AIS_ColorScale::SetMax (const Standard_Real theMax)
158 {
159   SetRange (GetMin(), theMax);
160 }
161
162 //=======================================================================
163 //function : SetRange
164 //purpose  :
165 //=======================================================================
166 void AIS_ColorScale::SetRange (const Standard_Real theMin, const Standard_Real theMax)
167 {
168   if (myMin == theMin && myMax == theMax)
169     return;
170
171   myMin = Min (theMin, theMax);
172   myMax = Max (theMin, theMax);
173 }
174
175 //=======================================================================
176 //function : SetLabelType
177 //purpose  :
178 //=======================================================================
179 void AIS_ColorScale::SetLabelType (const Aspect_TypeOfColorScaleData theType)
180 {
181   if (myLabelType == theType)
182     return;
183
184   myLabelType = theType;
185 }
186
187 //=======================================================================
188 //function : SetColorType
189 //purpose  :
190 //=======================================================================
191 void AIS_ColorScale::SetColorType (const Aspect_TypeOfColorScaleData theType)
192 {
193   if (myColorType == theType)
194     return;
195
196   myColorType = theType;
197 }
198
199 //=======================================================================
200 //function : SetNumberOfIntervals
201 //purpose  :
202 //=======================================================================
203 void AIS_ColorScale::SetNumberOfIntervals (const Standard_Integer theNum)
204 {
205   if (myInterval == theNum || theNum < 1)
206     return;
207
208   myInterval = theNum;
209 }
210
211 //=======================================================================
212 //function : SetTitle
213 //purpose  :
214 //=======================================================================
215 void AIS_ColorScale::SetTitle (const TCollection_ExtendedString& theTitle)
216 {
217   if (myTitle == theTitle)
218     return;
219
220   myTitle = theTitle;
221 }
222
223 //=======================================================================
224 //function : SetFormat
225 //purpose  :
226 //=======================================================================
227 void AIS_ColorScale::SetFormat (const TCollection_AsciiString& theFormat)
228 {
229   if (myFormat == theFormat)
230     return;
231
232   myFormat = theFormat;
233 }
234
235 //=======================================================================
236 //function : SetLabel
237 //purpose  :
238 //=======================================================================
239 void AIS_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer theIndex)
240 {
241   Standard_Integer i = (theIndex <= 0 ? myLabels.Length() + 1 : theIndex);
242   while (i > myLabels.Length())
243     myLabels.Append (TCollection_ExtendedString());
244   myLabels.SetValue (i, theLabel);
245 }
246
247 //=======================================================================
248 //function : SetIntervalColor
249 //purpose  :
250 //=======================================================================
251 void AIS_ColorScale::SetIntervalColor (const Quantity_Color& theColor, const Standard_Integer theIndex)
252 {
253   Standard_Integer i = (theIndex <= 0 ? myColors.Length() + 1 : theIndex);
254   while (i > myColors.Length())
255     myColors.Append (Quantity_Color());
256   myColors.SetValue (i, theColor);
257 }
258
259 //=======================================================================
260 //function : SetLabels
261 //purpose  :
262 //=======================================================================
263 void AIS_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq)
264 {
265   myLabels.Clear();
266   for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
267     myLabels.Append (theSeq.Value (i));
268 }
269
270 //=======================================================================
271 //function : SetColors
272 //purpose  :
273 //=======================================================================
274 void AIS_ColorScale::SetColors (const Aspect_SequenceOfColor& theSeq)
275 {
276   myColors.Clear();
277   for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
278     myColors.Append (theSeq.Value (i));
279 }
280
281 //=======================================================================
282 //function : SetLabelPosition
283 //purpose  :
284 //=======================================================================
285 void AIS_ColorScale::SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos)
286 {
287   if (myLabelPos == thePos)
288     return;
289
290   myLabelPos = thePos;
291 }
292
293 //=======================================================================
294 //function : SetTitlePosition
295 //purpose  :
296 //=======================================================================
297 void AIS_ColorScale::SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos)
298 {
299   if (myTitlePos == thePos)
300     return;
301
302   myTitlePos = thePos;
303 }
304
305 //=======================================================================
306 //function : SetReversed
307 //purpose  :
308 //=======================================================================
309 void AIS_ColorScale::SetReversed (const Standard_Boolean theReverse)
310 {
311   if (myReversed == theReverse)
312     return;
313
314   myReversed = theReverse;
315 }
316
317 //=======================================================================
318 //function : SetLabelAtBorder
319 //purpose  :
320 //=======================================================================
321 void AIS_ColorScale::SetLabelAtBorder (const Standard_Boolean theOn)
322 {
323   if (myAtBorder == theOn)
324     return;
325
326   myAtBorder = theOn;
327 }
328
329 //=======================================================================
330 //function : GetPosition
331 //purpose  :
332 //=======================================================================
333 void AIS_ColorScale::GetPosition (Standard_Real& theX, Standard_Real& theY) const
334 {
335   theX = myXPos;
336   theY = myYPos;
337 }
338
339 //=======================================================================
340 //function : SetPosition
341 //purpose  :
342 //=======================================================================
343 void AIS_ColorScale::SetPosition (const Standard_Integer theX, const Standard_Integer theY)
344 {
345   if (myXPos == theX && myYPos == theY)
346     return;
347
348   myXPos = theX;
349   myYPos = theY;
350 }
351
352 //=======================================================================
353 //function : SetXPosition
354 //purpose  :
355 //=======================================================================
356 void AIS_ColorScale::SetXPosition (const Standard_Integer theX)
357 {
358   SetPosition (theX, GetYPosition());
359 }
360
361 //=======================================================================
362 //function : SetYPosition
363 //purpose  :
364 //=======================================================================
365 void AIS_ColorScale::SetYPosition (const Standard_Integer theY)
366 {
367   SetPosition (GetXPosition(), theY);
368 }
369
370 //=======================================================================
371 //function : GetSize
372 //purpose  :
373 //=======================================================================
374 void AIS_ColorScale::GetSize (Standard_Integer& theBreadth, Standard_Integer& theHeight) const
375 {
376   theBreadth = myBreadth;
377   theHeight = myHeight;
378 }
379
380 //=======================================================================
381 //function : SetSize
382 //purpose  :
383 //=======================================================================
384 void AIS_ColorScale::SetSize (const Standard_Integer theBreadth, const Standard_Integer theHeight)
385 {
386   if (myBreadth == theBreadth && myHeight == theHeight)
387     return;
388
389   myBreadth = theBreadth;
390   myHeight = theHeight;
391 }
392
393 //=======================================================================
394 //function : SetBreadth
395 //purpose  :
396 //=======================================================================
397 void AIS_ColorScale::SetBreadth (const Standard_Integer theWidth)
398 {
399   SetSize (theWidth, GetHeight());
400 }
401
402 //=======================================================================
403 //function : SetHeight
404 //purpose  :
405 //=======================================================================
406 void AIS_ColorScale::SetHeight (const Standard_Integer theHeight)
407 {
408   SetSize (GetBreadth(), theHeight);
409 }
410
411 //=======================================================================
412 //function : SizeHint
413 //purpose  :
414 //=======================================================================
415 void AIS_ColorScale::SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const
416 {
417   Standard_Integer aNum = GetNumberOfIntervals();
418
419   Standard_Integer aSpacer = 5;
420   Standard_Integer aTextWidth = 0;
421   Standard_Integer aTextHeight = TextHeight ("");
422   Standard_Integer aColorWidth = 20;
423
424   if (GetLabelPosition() != Aspect_TOCSP_NONE)
425   {
426     for (Standard_Integer idx = (IsLabelAtBorder() ? 0 : 1); idx <= aNum; idx++)
427       aTextWidth = Max (aTextWidth, TextWidth (GetLabel (idx)));
428   }
429
430   Standard_Integer aScaleWidth = 0;
431   Standard_Integer aScaleHeight = 0;
432
433   aScaleWidth = aColorWidth + aTextWidth + ( aTextWidth ? 3 : 2 ) * aSpacer;
434   aScaleHeight = (Standard_Integer)( 1.5 * ( aNum + (IsLabelAtBorder() ? 2 : 1) ) * aTextHeight );
435
436   Standard_Integer aTitleWidth = 0;
437   Standard_Integer aTitleHeight = 0;
438   if (GetTitle().Length())
439   {
440     aTitleHeight = TextHeight (GetTitle()) + aSpacer;
441     aTitleWidth =  TextWidth (GetTitle()) + 10;
442   }
443
444   theWidth = Max (aTitleWidth, aScaleWidth);
445   theHeight = aScaleHeight + aTitleHeight;
446 }
447
448 //=======================================================================
449 //function : Format
450 //purpose  :
451 //=======================================================================
452 TCollection_AsciiString AIS_ColorScale::Format() const
453 {
454   return GetFormat();
455 }
456
457 //=======================================================================
458 //function : GetIntervalValue
459 //purpose  :
460 //=======================================================================
461 Standard_Real AIS_ColorScale::GetIntervalValue (const Standard_Integer theIndex) const
462 {
463   if (GetNumberOfIntervals() <= 0)
464     return 0.;
465
466   if (IsLogarithmic())
467   {
468     Standard_Real aMin = myMin > 0 ? myMin : 1.0;
469     Standard_Real aDivisor = std::pow (myMax/aMin, 1.0/myInterval);
470     return aMin*std::pow (aDivisor,theIndex);
471   }
472
473   Standard_Real aNum = 0;
474   if (GetNumberOfIntervals() > 0)
475     aNum = GetMin() + theIndex * ( Abs (GetMax() - GetMin()) / GetNumberOfIntervals() );
476   return aNum;
477 }
478
479 //=======================================================================
480 //function : HueFromValue
481 //purpose  :
482 //=======================================================================
483 Standard_Integer AIS_ColorScale::HueFromValue (const Standard_Integer theValue,
484                                                const Standard_Integer theMin, const Standard_Integer theMax)
485 {
486   Standard_Integer aMinLimit (0), aMaxLimit (230);
487
488   Standard_Integer aHue = aMaxLimit;
489   if (theMin != theMax)
490     aHue = (Standard_Integer)( aMaxLimit - ( aMaxLimit - aMinLimit ) * ( theValue - theMin ) / ( theMax - theMin ) );
491
492   aHue = Min (Max (aMinLimit, aHue), aMaxLimit);
493
494   return aHue;
495 }
496
497 //=======================================================================
498 //function : FindColor
499 //purpose  :
500 //=======================================================================
501 Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue,
502                                             Quantity_Color& theColor) const
503 {
504   return FindColor (theValue, myMin, myMax, myInterval, theColor);
505 }
506
507 //=======================================================================
508 //function : FindColor
509 //purpose  :
510 //=======================================================================
511 Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue,
512                                             const Standard_Real theMin,
513                                             const Standard_Real theMax,
514                                             const Standard_Integer theColorsCount,
515                                             Quantity_Color& theColor)
516 {
517   if (theValue < theMin || theValue > theMax || theMax < theMin)
518     return Standard_False;
519
520   else
521   {
522     Standard_Real anIntervNumber = 0;
523     if(Abs (theMax-theMin) > Precision::Approximation())
524       anIntervNumber = Floor (Standard_Real (theColorsCount) * ( theValue - theMin ) / ( theMax - theMin ));
525
526     Standard_Integer anInterv = Standard_Integer (anIntervNumber);
527
528     theColor = Quantity_Color (HueFromValue (anInterv, 0, theColorsCount - 1), 1.0, 1.0, Quantity_TOC_HLS);
529
530     return Standard_True;
531   }
532 }
533
534 //=======================================================================
535 //function : Compute
536 //purpose  :
537 //=======================================================================
538 void AIS_ColorScale::Compute(const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
539                              const Handle(Prs3d_Presentation)& thePresentation,
540                              const Standard_Integer /*theMode*/)
541 {
542   Handle(V3d_Viewer) aViewer= GetContext()->CurrentViewer();
543   aViewer->InitActiveViews();
544   Standard_Integer aNum = GetNumberOfIntervals();
545   Aspect_TypeOfColorScalePosition aLabPos = GetLabelPosition();
546
547   Standard_Integer aSpacer = 5;
548   Standard_Integer aTextWidth = 0;
549   Standard_Integer aTextHeight = myTextHeight;
550   Standard_Boolean toDrawLabel = GetLabelPosition() != Aspect_TOCSP_NONE;
551   TCollection_ExtendedString aTitle = GetTitle();
552   Standard_Integer aTitleHeight = aSpacer;
553   Quantity_Color aFgColor (hasOwnColor ? myOwnColor : Quantity_NOC_WHITE);
554
555   // Draw title
556   if (aTitle.Length())
557   {
558     aTitleHeight += myTextHeight + aSpacer;
559     DrawText (thePresentation, aTitle, (Standard_Integer)myXPos + aSpacer, myHeight - ((Standard_Integer)myYPos - 2 * aSpacer + aTitleHeight), aFgColor);
560   }
561
562   Standard_Boolean toReverse = IsReversed();
563
564   Aspect_SequenceOfColor aColors;
565   for (Standard_Integer i = 1; i <= aNum; i++)
566   {
567     if (toReverse)
568     {
569       aColors.Prepend (GetIntervalColor (i));
570     }
571     else
572     {
573       aColors.Append (GetIntervalColor (i));
574     }
575   }
576
577   TColStd_SequenceOfExtendedString aLabels;
578   Standard_Integer aLabCount = IsLabelAtBorder() ? aNum + 1 : aNum;
579   for (Standard_Integer i = 1; i <= aLabCount; i++)
580   {
581     if (toReverse)
582     {
583       aLabels.Prepend (GetLabel (i));
584     }
585     else
586     {
587       aLabels.Append (GetLabel (i));
588     }
589   }
590
591   if (toDrawLabel)
592     for (Standard_Integer i = 1; i <= aLabels.Length(); i++)
593       aTextWidth = Max (aTextWidth, TextWidth (aLabels.Value (i)));
594
595   Standard_Integer aSpc = ( myHeight - ( ( Min (aLabCount, 2) + Abs (aLabCount - aNum - 1) ) * aTextHeight ) - aTitleHeight );
596   Standard_Real aVal = aSpc != 0 ? 1.0 * ( aLabCount - Min (aLabCount, 0) ) * aTextHeight / aSpc : 0;
597   Standard_Real anIPart;
598   Standard_Real anFPart = modf (aVal, &anIPart);
599   Standard_Integer aFilter = (Standard_Integer)anIPart + ( anFPart != 0 ? 1 : 0 );
600
601   Standard_Real aStep = 1.0 * ( myHeight - (aLabCount - aNum + Abs (aLabCount - aNum - 1)) * aTextHeight - aTitleHeight ) / aNum;
602
603   Standard_Integer anAscent = 0;
604   Standard_Integer aColorBreadth = Max (5, Min (20, myBreadth - aTextWidth - 3 * aSpacer));
605   if (aLabPos == Aspect_TOCSP_CENTER || !toDrawLabel)
606     aColorBreadth += aTextWidth;
607
608   // Draw colors
609   Standard_Integer aX = (Standard_Integer)myXPos + aSpacer;
610   if (aLabPos == Aspect_TOCSP_LEFT)
611     aX += aTextWidth + ( aTextWidth ? 1 : 0 ) * aSpacer;
612
613   Standard_Real anOffset = 1.0 * aTextHeight / 2 * ( aLabCount - aNum + Abs (aLabCount - aNum - 1) );
614   anOffset += 2*aSpacer;
615   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
616   Handle (Graphic3d_ArrayOfTriangles) aPrim;
617   Standard_Integer anEdgesPerColor = 6;
618   Standard_Integer aVerticiesPerColor = 4;
619   aPrim = new Graphic3d_ArrayOfTriangles (aColors.Length()*aVerticiesPerColor, aColors.Length()*anEdgesPerColor, 0, 1);
620   Standard_Integer aVertIndex = 1;
621   for (Standard_Integer i = 1; i <= aColors.Length() && aStep > 0; i++)
622   {
623     Standard_Integer aY = (Standard_Integer)( myYPos + ( i - 1 )* aStep + anOffset );
624     Standard_Integer aColorHeight = (Standard_Integer)( myYPos + ( i ) * aStep + anOffset ) - aY;
625     aPrim->AddVertex (gp_Pnt (aX, aY, 0.0), aColors.Value( i ));
626     aPrim->AddVertex (gp_Pnt (aX+aColorBreadth, aY, 0.0), aColors.Value( i ));
627     aPrim->AddVertex (gp_Pnt (aX, aY+aColorHeight, 0.0), aColors.Value( i ));
628     aPrim->AddVertex (gp_Pnt (aX+aColorBreadth, aY+aColorHeight, 0.0), aColors.Value( i ));
629     aPrim->AddEdge(aVertIndex);
630     aPrim->AddEdge(aVertIndex+1);
631     aPrim->AddEdge(aVertIndex+2);
632     aPrim->AddEdge(aVertIndex+1);
633     aPrim->AddEdge(aVertIndex+2);
634     aPrim->AddEdge(aVertIndex+3);
635     aVertIndex += 4;
636   }
637   aGroup->AddPrimitiveArray (aPrim);
638
639   if (aStep > 0)
640     DrawFrame (thePresentation, aX - 1, (Standard_Integer)(myYPos + anOffset - 1), aColorBreadth + 2, (Standard_Integer)(aColors.Length() * aStep + 2), aFgColor);
641
642   // Draw Labels
643   anOffset = 1.0 * Abs (aLabCount - aNum - 1) * ( aStep - aTextHeight ) / 2 + 1.0 * Abs (aLabCount - aNum - 1) * aTextHeight / 2;
644   anOffset += 2*aSpacer;
645   if (toDrawLabel && aLabels.Length() && aFilter > 0)
646   {
647     Standard_Integer i1 = 0;
648     Standard_Integer i2 = aLabCount - 1;
649     Standard_Integer aLast1( i1 ), aLast2( i2 );
650     aX = (Standard_Integer)myXPos + aSpacer;
651     switch (aLabPos)
652     {
653       case Aspect_TOCSP_NONE:
654       case Aspect_TOCSP_LEFT:
655         break;
656       case Aspect_TOCSP_CENTER:
657         aX += ( aColorBreadth - aTextWidth ) / 2;
658         break;
659       case Aspect_TOCSP_RIGHT:
660         aX += aColorBreadth + aSpacer;
661         break;
662     }
663     while (i2 - i1 >= aFilter || ( i2 == 0 && i1 == 0 ))
664     {
665       Standard_Integer aPos1 = i1;
666       Standard_Integer aPos2 = aLabCount - 1 - i2;
667       if (aFilter && !( aPos1 % aFilter ))
668       {
669         DrawText (thePresentation, aLabels.Value (i1 + 1), aX, (Standard_Integer)( myYPos + i1 * aStep + anAscent + anOffset ), aFgColor);
670         aLast1 = i1;
671       }
672       if (aFilter && !( aPos2 % aFilter ))
673       {
674         DrawText (thePresentation, aLabels.Value (i2 + 1), aX, (Standard_Integer)( myYPos + i2 * aStep + anAscent + anOffset ), aFgColor);
675         aLast2 = i2;
676       }
677       i1++;
678       i2--;
679     }
680     Standard_Integer aPos = i1;
681     Standard_Integer i0 = -1;
682     while (aPos <= i2 && i0 == -1)
683     {
684       if (aFilter && !( aPos % aFilter ) && Abs (aPos - aLast1) >= aFilter && Abs (aPos - aLast2) >= aFilter)
685         i0 = aPos;
686       aPos++;
687     }
688
689     if (i0 != -1)
690       DrawText (thePresentation, aLabels.Value (i0 + 1), aX, (Standard_Integer)( myYPos + i0 * aStep + anAscent + anOffset ), aFgColor);
691   }
692 }
693
694 //=======================================================================
695 //function : DrawFrame
696 //purpose  :
697 //=======================================================================
698 void AIS_ColorScale::DrawFrame (const Handle(Prs3d_Presentation)& thePresentation,
699                        const Standard_Integer theX, const Standard_Integer theY,
700                        const Standard_Integer theWidth, const Standard_Integer theHeight,
701                        const Quantity_Color& theColor)
702 {
703   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
704   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
705   aPrim->AddVertex (theX,theY,0.0);
706   aPrim->AddVertex (theX+theWidth,theY,0.0);
707   aPrim->AddVertex (theX+theWidth,theY+theHeight,0.0);
708   aPrim->AddVertex (theX,theY+theHeight,0.0);
709   aPrim->AddVertex (theX,theY,0.0);
710   Handle(Prs3d_LineAspect) anAspect = 
711     new Prs3d_LineAspect (theColor, Aspect_TOL_SOLID, 1.0);
712   anAspect->SetColor (theColor);
713   aGroup->SetPrimitivesAspect (anAspect->Aspect());
714   aGroup->AddPrimitiveArray (aPrim);
715 }
716
717 //=======================================================================
718 //function : DrawText
719 //purpose  :
720 //=======================================================================
721 void AIS_ColorScale::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
722                   const TCollection_ExtendedString& theText,
723                   const Standard_Integer theX, const Standard_Integer theY,
724                   const Quantity_Color& theColor)
725 {
726   if (!myDrawer->HasOwnTextAspect())
727   {
728     myDrawer->SetTextAspect (new Prs3d_TextAspect());
729     *myDrawer->TextAspect()->Aspect() = *myDrawer->Link()->TextAspect()->Aspect();
730   }
731   Handle(Prs3d_TextAspect) anAspect = myDrawer->TextAspect();
732   anAspect->SetColor (theColor);
733   anAspect->SetHeight (myTextHeight);
734   anAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT);
735   anAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
736   anAspect->Aspect()->SetTextZoomable (Standard_True);
737   anAspect->Aspect()->SetTextAngle (0.0);
738   anAspect->Aspect()->SetTextFontAspect (Font_FA_Regular);
739   Prs3d_Text::Draw (thePresentation, anAspect, theText,gp_Pnt (theX,theY,0.0));
740 }
741
742 //=======================================================================
743 //function : TextWidth
744 //purpose  :
745 //=======================================================================
746 Standard_Integer AIS_ColorScale::TextWidth (const TCollection_ExtendedString& theText) const
747 {
748   Standard_Integer aWidth, anAscent, aDescent;
749   TextSize (theText, GetTextHeight(), aWidth, anAscent, aDescent);
750   return aWidth;
751 }
752
753 //=======================================================================
754 //function : TextHeight
755 //purpose  :
756 //=======================================================================
757 Standard_Integer AIS_ColorScale::TextHeight (const TCollection_ExtendedString& theText) const
758 {
759   Standard_Integer aWidth, anAscent, aDescent;
760   TextSize (theText, GetTextHeight(), aWidth, anAscent, aDescent);
761   return anAscent+aDescent;
762 }
763
764 //=======================================================================
765 //function : TextSize
766 //purpose  :
767 //=======================================================================
768 void AIS_ColorScale::TextSize (const TCollection_ExtendedString& theText, const Standard_Integer theHeight, Standard_Integer& theWidth, Standard_Integer& theAscent, Standard_Integer& theDescent) const
769 {
770   const Handle(Graphic3d_CView)& aView = GetContext()->CurrentViewer()->ActiveView()->View();
771   Standard_ShortReal aWidth(10.0), anAscent(1.0), aDescent(1.0);
772   TCollection_AsciiString aText (theText.ToExtString(), '?');
773   GetContext()->CurrentViewer()->Driver()->TextSize (aView, aText.ToCString(), (Standard_ShortReal)theHeight, aWidth, anAscent, aDescent);
774   theWidth = (Standard_Integer)aWidth;
775   theAscent = (Standard_Integer)anAscent;
776   theDescent = (Standard_Integer)aDescent;
777 }