7a324550 |
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> |
4b3d6eb1 |
16 | |
7a324550 |
17 | #include <AIS_InteractiveContext.hxx> |
18 | #include <Aspect_TypeOfColorScaleData.hxx> |
19 | #include <Aspect_TypeOfColorScalePosition.hxx> |
20 | #include <Aspect_Window.hxx> |
21 | #include <Geom_Line.hxx> |
22 | #include <GeomAdaptor_Curve.hxx> |
23 | #include <Graphic3d_ArrayOfPolygons.hxx> |
24 | #include <Graphic3d_ArrayOfPolylines.hxx> |
25 | #include <Graphic3d_AspectFillArea3d.hxx> |
26 | #include <Graphic3d_AspectText3d.hxx> |
27 | #include <Graphic3d_GraphicDriver.hxx> |
28 | #include <Graphic3d_ArrayOfTriangles.hxx> |
29 | #include <Prs3d_LineAspect.hxx> |
30 | #include <Prs3d_Root.hxx> |
31 | #include <Prs3d_ShadingAspect.hxx> |
32 | #include <Prs3d_Text.hxx> |
33 | #include <Prs3d_TextAspect.hxx> |
34 | #include <SelectMgr_EntityOwner.hxx> |
35 | #include <SelectMgr_Selection.hxx> |
36 | #include <Select3D_SensitiveBox.hxx> |
37 | #include <Select3D_SensitiveSegment.hxx> |
38 | #include <StdPrs_Curve.hxx> |
39 | #include <V3d_Viewer.hxx> |
40 | #include <V3d_View.hxx> |
41 | |
4b3d6eb1 |
42 | IMPLEMENT_STANDARD_RTTIEXT(AIS_ColorScale, AIS_InteractiveObject) |
7a324550 |
43 | |
4b3d6eb1 |
44 | namespace |
7a324550 |
45 | { |
4b3d6eb1 |
46 | //! Method to add colored quad into array of triangles. |
47 | static void addColoredQuad (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
48 | const Standard_Integer theXLeft, const Standard_Integer theYBottom, |
49 | const Standard_Integer theSizeX, const Standard_Integer theSizeY, |
50 | const Quantity_Color& theColorBottom, |
51 | const Quantity_Color& theColorTop) |
52 | { |
53 | const Standard_Integer aVertIndex = theTris->VertexNumber() + 1; |
54 | theTris->AddVertex (gp_Pnt (theXLeft, theYBottom, 0.0), theColorBottom); |
55 | theTris->AddVertex (gp_Pnt (theXLeft + theSizeX, theYBottom, 0.0), theColorBottom); |
56 | theTris->AddVertex (gp_Pnt (theXLeft, theYBottom + theSizeY, 0.0), theColorTop); |
57 | theTris->AddVertex (gp_Pnt (theXLeft + theSizeX, theYBottom + theSizeY, 0.0), theColorTop); |
58 | theTris->AddEdge (aVertIndex); |
59 | theTris->AddEdge (aVertIndex + 1); |
60 | theTris->AddEdge (aVertIndex + 2); |
61 | theTris->AddEdge (aVertIndex + 1); |
62 | theTris->AddEdge (aVertIndex + 2); |
63 | theTris->AddEdge (aVertIndex + 3); |
64 | } |
65 | |
66 | //! Compute hue angle from specified value. |
67 | static Quantity_Color colorFromValueEx (const Standard_Real theValue, |
68 | const Standard_Real theMin, |
69 | const Standard_Real theMax, |
70 | const Graphic3d_Vec3d& theHlsMin, |
71 | const Graphic3d_Vec3d& theHlsMax) |
72 | { |
73 | const Standard_Real aValueDelta = theMax - theMin; |
74 | Standard_Real aValue = 0.0; |
75 | if (aValueDelta != 0.0) |
76 | { |
77 | aValue = (theValue - theMin) / aValueDelta; |
78 | } |
79 | |
80 | Standard_Real aHue = NCollection_Lerp<Standard_Real>::Interpolate (theHlsMin[0], theHlsMax[0], aValue); |
81 | Standard_Real aLightness = NCollection_Lerp<Standard_Real>::Interpolate (theHlsMin[1], theHlsMax[1], aValue); |
82 | Standard_Real aSaturation = NCollection_Lerp<Standard_Real>::Interpolate (theHlsMin[2], theHlsMax[2], aValue); |
83 | return Quantity_Color (AIS_ColorScale::hueToValidRange (aHue), aLightness, aSaturation, Quantity_TOC_HLS); |
84 | } |
7a324550 |
85 | } |
86 | |
87 | //======================================================================= |
4b3d6eb1 |
88 | //function : AIS_ColorScale |
7a324550 |
89 | //purpose : |
90 | //======================================================================= |
4b3d6eb1 |
91 | AIS_ColorScale::AIS_ColorScale() |
92 | : myMin (0.0), |
93 | myMax (1.0), |
94 | myColorHlsMin (230.0, 1.0, 1.0), |
95 | myColorHlsMax (0.0, 1.0, 1.0), |
96 | myFormat ("%.4g"), |
97 | myNbIntervals (10), |
98 | myColorType (Aspect_TOCSD_AUTO), |
99 | myLabelType (Aspect_TOCSD_AUTO), |
100 | myIsLabelAtBorder (Standard_True), |
101 | myIsReversed (Standard_False), |
102 | myIsLogarithmic (Standard_False), |
103 | myIsSmooth (Standard_False), |
104 | myLabelPos (Aspect_TOCSP_RIGHT), |
105 | myTitlePos (Aspect_TOCSP_LEFT), |
106 | myXPos (0), |
107 | myYPos (0), |
108 | myBreadth (0), |
109 | myHeight (0), |
110 | mySpacing (5), |
111 | myTextHeight (20) |
112 | { |
113 | SetDisplayMode (0); |
7a324550 |
114 | } |
115 | |
116 | //======================================================================= |
117 | //function : GetLabel |
118 | //purpose : |
119 | //======================================================================= |
120 | TCollection_ExtendedString AIS_ColorScale::GetLabel (const Standard_Integer theIndex) const |
121 | { |
4b3d6eb1 |
122 | if (myLabelType == Aspect_TOCSD_USER) |
7a324550 |
123 | { |
4b3d6eb1 |
124 | if (theIndex >= myLabels.Lower() |
125 | || theIndex <= myLabels.Upper()) |
7a324550 |
126 | { |
4b3d6eb1 |
127 | return myLabels.Value(theIndex); |
7a324550 |
128 | } |
4b3d6eb1 |
129 | return TCollection_ExtendedString(); |
7a324550 |
130 | } |
180f89a2 |
131 | |
132 | // value to be shown depends on label position |
4b3d6eb1 |
133 | const Standard_Real aVal = myIsLabelAtBorder |
134 | ? GetIntervalValue (theIndex - 1) |
135 | : (0.5 * (GetIntervalValue (theIndex - 1) + GetIntervalValue (theIndex))); |
180f89a2 |
136 | |
4b3d6eb1 |
137 | char aBuf[1024]; |
138 | sprintf (aBuf, myFormat.ToCString(), aVal); |
7a324550 |
139 | return TCollection_ExtendedString (aBuf); |
140 | } |
141 | |
142 | //======================================================================= |
180f89a2 |
143 | //function : GetIntervalColor |
7a324550 |
144 | //purpose : |
145 | //======================================================================= |
180f89a2 |
146 | Quantity_Color AIS_ColorScale::GetIntervalColor (const Standard_Integer theIndex) const |
7a324550 |
147 | { |
4b3d6eb1 |
148 | if (myColorType== Aspect_TOCSD_USER) |
7a324550 |
149 | { |
180f89a2 |
150 | if (theIndex <= 0 || theIndex > myColors.Length()) |
7a324550 |
151 | { |
152 | return Quantity_Color(); |
153 | } |
180f89a2 |
154 | return myColors.Value (theIndex); |
7a324550 |
155 | } |
180f89a2 |
156 | |
4b3d6eb1 |
157 | return colorFromValue (theIndex - 1, 0, myNbIntervals - 1); |
7a324550 |
158 | } |
159 | |
160 | //======================================================================= |
161 | //function : GetLabels |
162 | //purpose : |
163 | //======================================================================= |
164 | void AIS_ColorScale::GetLabels (TColStd_SequenceOfExtendedString& theLabels) const |
165 | { |
166 | theLabels.Clear(); |
4b3d6eb1 |
167 | for (TColStd_SequenceOfExtendedString::Iterator aLabIter (myLabels); aLabIter.More(); aLabIter.Next()) |
168 | { |
169 | theLabels.Append (aLabIter.Value()); |
170 | } |
7a324550 |
171 | } |
172 | |
173 | //======================================================================= |
174 | //function : GetColors |
175 | //purpose : |
176 | //======================================================================= |
177 | void AIS_ColorScale::GetColors (Aspect_SequenceOfColor& theColors) const |
178 | { |
179 | theColors.Clear(); |
4b3d6eb1 |
180 | for (Aspect_SequenceOfColor::Iterator aColorIter (myColors); aColorIter.More(); aColorIter.Next()) |
181 | { |
182 | theColors.Append (aColorIter.Value()); |
183 | } |
7a324550 |
184 | } |
185 | |
186 | //======================================================================= |
187 | //function : SetRange |
188 | //purpose : |
189 | //======================================================================= |
190 | void AIS_ColorScale::SetRange (const Standard_Real theMin, const Standard_Real theMax) |
191 | { |
7a324550 |
192 | myMin = Min (theMin, theMax); |
193 | myMax = Max (theMin, theMax); |
194 | } |
195 | |
7a324550 |
196 | //======================================================================= |
197 | //function : SetNumberOfIntervals |
198 | //purpose : |
199 | //======================================================================= |
200 | void AIS_ColorScale::SetNumberOfIntervals (const Standard_Integer theNum) |
201 | { |
4b3d6eb1 |
202 | if (theNum < 1) |
203 | { |
7a324550 |
204 | return; |
4b3d6eb1 |
205 | } |
7a324550 |
206 | |
4b3d6eb1 |
207 | myNbIntervals = theNum; |
7a324550 |
208 | } |
209 | |
210 | //======================================================================= |
211 | //function : SetLabel |
212 | //purpose : |
213 | //======================================================================= |
4b3d6eb1 |
214 | void AIS_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, |
215 | const Standard_Integer theIndex) |
7a324550 |
216 | { |
4b3d6eb1 |
217 | const Standard_Integer aLabIndex = (theIndex <= 0 ? myLabels.Length() + 1 : theIndex); |
218 | while (myLabels.Length() < aLabIndex) |
219 | { |
180f89a2 |
220 | myLabels.Append (TCollection_ExtendedString()); |
4b3d6eb1 |
221 | } |
222 | myLabels.SetValue (aLabIndex, theLabel); |
7a324550 |
223 | } |
224 | |
225 | //======================================================================= |
180f89a2 |
226 | //function : SetIntervalColor |
7a324550 |
227 | //purpose : |
228 | //======================================================================= |
4b3d6eb1 |
229 | void AIS_ColorScale::SetIntervalColor (const Quantity_Color& theColor, |
230 | const Standard_Integer theIndex) |
7a324550 |
231 | { |
4b3d6eb1 |
232 | const Standard_Integer aColorIndex = (theIndex <= 0 ? myColors.Length() + 1 : theIndex); |
233 | while (myColors.Length() < aColorIndex) |
234 | { |
180f89a2 |
235 | myColors.Append (Quantity_Color()); |
4b3d6eb1 |
236 | } |
237 | myColors.SetValue (aColorIndex, theColor); |
7a324550 |
238 | } |
239 | |
240 | //======================================================================= |
241 | //function : SetLabels |
242 | //purpose : |
243 | //======================================================================= |
244 | void AIS_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq) |
245 | { |
246 | myLabels.Clear(); |
4b3d6eb1 |
247 | for (TColStd_SequenceOfExtendedString::Iterator aLabIter (theSeq); aLabIter.More(); aLabIter.Next()) |
248 | { |
249 | myLabels.Append (aLabIter.Value()); |
250 | } |
7a324550 |
251 | } |
252 | |
253 | //======================================================================= |
254 | //function : SetColors |
255 | //purpose : |
256 | //======================================================================= |
257 | void AIS_ColorScale::SetColors (const Aspect_SequenceOfColor& theSeq) |
258 | { |
259 | myColors.Clear(); |
4b3d6eb1 |
260 | for (Aspect_SequenceOfColor::Iterator aColorIter (theSeq); aColorIter.More(); aColorIter.Next()) |
261 | { |
262 | myColors.Append (aColorIter.Value()); |
263 | } |
7a324550 |
264 | } |
265 | |
266 | //======================================================================= |
267 | //function : SizeHint |
268 | //purpose : |
269 | //======================================================================= |
270 | void AIS_ColorScale::SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const |
271 | { |
4b3d6eb1 |
272 | const Standard_Integer aTextHeight = TextHeight (""); |
273 | const Standard_Integer aColorWidth = 20; |
7a324550 |
274 | Standard_Integer aTextWidth = 0; |
4b3d6eb1 |
275 | if (myLabelPos != Aspect_TOCSP_NONE) |
180f89a2 |
276 | { |
4b3d6eb1 |
277 | for (Standard_Integer aLabIter = (myIsLabelAtBorder ? 0 : 1); aLabIter <= myNbIntervals; ++aLabIter) |
278 | { |
279 | aTextWidth = Max (aTextWidth, TextWidth (GetLabel (aLabIter))); |
280 | } |
180f89a2 |
281 | } |
7a324550 |
282 | |
4b3d6eb1 |
283 | const Standard_Integer aScaleWidth = aColorWidth + aTextWidth + (aTextWidth ? 3 : 2) * mySpacing; |
284 | const Standard_Integer aScaleHeight = (Standard_Integer)(1.5 * (myNbIntervals + (myIsLabelAtBorder ? 2 : 1)) * aTextHeight); |
7a324550 |
285 | |
4b3d6eb1 |
286 | Standard_Integer aTitleWidth = 0; |
180f89a2 |
287 | Standard_Integer aTitleHeight = 0; |
4b3d6eb1 |
288 | if (!myTitle.IsEmpty()) |
7a324550 |
289 | { |
4b3d6eb1 |
290 | aTitleHeight = TextHeight (myTitle) + mySpacing; |
291 | aTitleWidth = TextWidth (myTitle) + mySpacing * 2; |
7a324550 |
292 | } |
293 | |
4b3d6eb1 |
294 | theWidth = Max (aTitleWidth, aScaleWidth); |
7a324550 |
295 | theHeight = aScaleHeight + aTitleHeight; |
296 | } |
297 | |
7a324550 |
298 | //======================================================================= |
180f89a2 |
299 | //function : GetIntervalValue |
7a324550 |
300 | //purpose : |
301 | //======================================================================= |
180f89a2 |
302 | Standard_Real AIS_ColorScale::GetIntervalValue (const Standard_Integer theIndex) const |
7a324550 |
303 | { |
4b3d6eb1 |
304 | if (myNbIntervals <= 0) |
305 | { |
306 | return 0.0; |
307 | } |
7a324550 |
308 | |
180f89a2 |
309 | if (IsLogarithmic()) |
24a88697 |
310 | { |
4b3d6eb1 |
311 | Standard_Real aMin = myMin > 0 ? myMin : 1.0; |
312 | Standard_Real aDivisor = std::pow (myMax / aMin, 1.0 / myNbIntervals); |
313 | return aMin * std::pow (aDivisor,theIndex); |
24a88697 |
314 | } |
180f89a2 |
315 | |
316 | Standard_Real aNum = 0; |
4b3d6eb1 |
317 | if (myNbIntervals > 0) |
318 | { |
319 | aNum = GetMin() + theIndex * (Abs (GetMax() - GetMin()) / myNbIntervals); |
320 | } |
180f89a2 |
321 | return aNum; |
24a88697 |
322 | } |
323 | |
324 | //======================================================================= |
4b3d6eb1 |
325 | //function : colorFromValue |
7a324550 |
326 | //purpose : |
327 | //======================================================================= |
4b3d6eb1 |
328 | Quantity_Color AIS_ColorScale::colorFromValue (const Standard_Real theValue, |
329 | const Standard_Real theMin, |
330 | const Standard_Real theMax) const |
7a324550 |
331 | { |
4b3d6eb1 |
332 | return colorFromValueEx (theValue, theMin, theMax, myColorHlsMin, myColorHlsMax); |
7a324550 |
333 | } |
334 | |
335 | //======================================================================= |
336 | //function : FindColor |
337 | //purpose : |
338 | //======================================================================= |
339 | Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue, |
340 | Quantity_Color& theColor) const |
341 | { |
d5514578 |
342 | if (theValue < myMin || theValue > myMax || myMax < myMin) |
343 | { |
344 | theColor = Quantity_Color(); |
345 | return Standard_False; |
346 | } |
347 | |
4b3d6eb1 |
348 | if (myColorType == Aspect_TOCSD_USER) |
d5514578 |
349 | { |
350 | Standard_Integer anIndex = 0; |
351 | if (Abs (myMax - myMin) > Precision::Approximation()) |
352 | { |
353 | anIndex = (theValue - myMin < Precision::Confusion()) |
354 | ? 1 |
4b3d6eb1 |
355 | : Standard_Integer (Ceiling (( theValue - myMin ) / ( (myMax - myMin) / myNbIntervals))); |
d5514578 |
356 | } |
357 | |
358 | if (anIndex <= 0 || anIndex > myColors.Length()) |
359 | { |
360 | theColor = Quantity_Color(); |
361 | return Standard_False; |
362 | } |
363 | |
364 | theColor = myColors.Value (anIndex); |
365 | return Standard_True; |
366 | } |
367 | |
4b3d6eb1 |
368 | return FindColor (theValue, myMin, myMax, myNbIntervals, theColor); |
7a324550 |
369 | } |
370 | |
371 | //======================================================================= |
372 | //function : FindColor |
373 | //purpose : |
374 | //======================================================================= |
375 | Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue, |
376 | const Standard_Real theMin, |
377 | const Standard_Real theMax, |
378 | const Standard_Integer theColorsCount, |
4b3d6eb1 |
379 | const Graphic3d_Vec3d& theColorHlsMin, |
380 | const Graphic3d_Vec3d& theColorHlsMax, |
7a324550 |
381 | Quantity_Color& theColor) |
382 | { |
383 | if (theValue < theMin || theValue > theMax || theMax < theMin) |
4b3d6eb1 |
384 | { |
7a324550 |
385 | return Standard_False; |
4b3d6eb1 |
386 | } |
7a324550 |
387 | |
4b3d6eb1 |
388 | Standard_Real anInterval = 0.0; |
389 | if (Abs (theMax - theMin) > Precision::Approximation()) |
7a324550 |
390 | { |
4b3d6eb1 |
391 | anInterval = Floor (Standard_Real (theColorsCount) * (theValue - theMin) / (theMax - theMin)); |
392 | } |
7a324550 |
393 | |
4b3d6eb1 |
394 | theColor = colorFromValueEx (anInterval, 0, theColorsCount - 1, theColorHlsMin, theColorHlsMax); |
395 | return Standard_True; |
396 | } |
7a324550 |
397 | |
4b3d6eb1 |
398 | //======================================================================= |
399 | //function : computeMaxLabelWidth |
400 | //purpose : |
401 | //======================================================================= |
402 | Standard_Integer AIS_ColorScale::computeMaxLabelWidth (const TColStd_SequenceOfExtendedString& theLabels) const |
403 | { |
404 | { |
405 | Handle(V3d_Viewer) aViewer = GetContext()->CurrentViewer(); |
406 | aViewer->InitActiveViews(); // for AIS_ColorScale::TextSize() |
407 | } |
7a324550 |
408 | |
4b3d6eb1 |
409 | Standard_Integer aWidthMax = 0; |
410 | for (TColStd_SequenceOfExtendedString::Iterator aLabIter (theLabels); aLabIter.More(); aLabIter.Next()) |
411 | { |
412 | if (!aLabIter.Value().IsEmpty()) |
413 | { |
414 | aWidthMax = Max (aWidthMax, TextWidth (aLabIter.Value())); |
415 | } |
7a324550 |
416 | } |
4b3d6eb1 |
417 | return aWidthMax; |
418 | } |
419 | |
420 | //======================================================================= |
421 | //function : updateTextAspect |
422 | //purpose : |
423 | //======================================================================= |
424 | void AIS_ColorScale::updateTextAspect() |
425 | { |
426 | // update text aspect |
427 | const Quantity_Color aFgColor (hasOwnColor ? myDrawer->Color() : Quantity_NOC_WHITE); |
428 | if (!myDrawer->HasOwnTextAspect()) |
429 | { |
430 | myDrawer->SetTextAspect (new Prs3d_TextAspect()); |
431 | *myDrawer->TextAspect()->Aspect() = *myDrawer->Link()->TextAspect()->Aspect(); |
432 | } |
433 | |
434 | const Handle(Prs3d_TextAspect)& anAspect = myDrawer->TextAspect(); |
435 | anAspect->SetColor (aFgColor); |
436 | anAspect->SetHeight (myTextHeight); |
437 | anAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT); |
438 | anAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM); |
439 | anAspect->Aspect()->SetTextZoomable (Standard_True); |
7a324550 |
440 | } |
441 | |
442 | //======================================================================= |
443 | //function : Compute |
444 | //purpose : |
445 | //======================================================================= |
4b3d6eb1 |
446 | void AIS_ColorScale::Compute (const Handle(PrsMgr_PresentationManager3d)& , |
447 | const Handle(Prs3d_Presentation)& thePrs, |
448 | const Standard_Integer theMode) |
7a324550 |
449 | { |
4b3d6eb1 |
450 | if (theMode != 0) |
451 | { |
452 | return; |
453 | } |
7a324550 |
454 | |
4b3d6eb1 |
455 | // update text aspect |
456 | updateTextAspect(); |
457 | |
458 | const Standard_Integer aTitleOffset = !myTitle.IsEmpty() ? (myTextHeight + mySpacing) : 0; |
459 | |
460 | const Standard_Integer aBarYOffset = myTextHeight / 2 + 2 * mySpacing; // a half-label offset |
461 | const Standard_Integer aBarBottom = myYPos + aBarYOffset; |
462 | const Standard_Integer aBarTop = myYPos + myHeight - aTitleOffset - aBarYOffset; |
463 | const Standard_Integer aBarHeight = aBarTop - aBarBottom; |
464 | |
465 | // draw title |
466 | if (!myTitle.IsEmpty()) |
467 | { |
468 | drawText (Prs3d_Root::CurrentGroup (thePrs), myTitle, |
469 | myXPos + mySpacing, |
470 | aBarTop + aBarYOffset, |
471 | Graphic3d_VTA_BOTTOM); |
472 | } |
473 | |
474 | TColStd_SequenceOfExtendedString aLabels; |
475 | if (myLabelType == Aspect_TOCSD_USER) |
476 | { |
477 | aLabels = myLabels; |
478 | } |
479 | else |
480 | { |
481 | const Standard_Integer aNbLabels = myIsLabelAtBorder ? myNbIntervals + 1 : myNbIntervals; |
482 | for (Standard_Integer aLabIter = 1; aLabIter <= aNbLabels; ++aLabIter) |
483 | { |
484 | if (myIsReversed) |
485 | { |
486 | aLabels.Prepend (GetLabel (aLabIter)); |
487 | } |
488 | else |
489 | { |
490 | aLabels.Append (GetLabel (aLabIter)); |
491 | } |
492 | } |
493 | } |
7a324550 |
494 | |
4b3d6eb1 |
495 | const Standard_Integer aTextWidth = myLabelPos != Aspect_TOCSP_NONE ? computeMaxLabelWidth (aLabels) : 0; |
496 | Standard_Integer aColorBreadth = Max (5, Min (20, myBreadth - aTextWidth - 3 * mySpacing)); |
497 | if (myLabelPos == Aspect_TOCSP_CENTER |
498 | || myLabelPos == Aspect_TOCSP_NONE) |
7a324550 |
499 | { |
4b3d6eb1 |
500 | aColorBreadth += aTextWidth; |
7a324550 |
501 | } |
502 | |
4b3d6eb1 |
503 | // draw colors |
504 | drawColorBar (thePrs, aBarBottom, aBarHeight, aTextWidth, aColorBreadth); |
505 | |
506 | // draw Labels |
507 | drawLabels (thePrs, aLabels, aBarBottom, aBarHeight, aTextWidth, aColorBreadth); |
508 | } |
509 | |
510 | //======================================================================= |
511 | //function : drawColorBar |
512 | //purpose : |
513 | //======================================================================= |
514 | void AIS_ColorScale::drawColorBar (const Handle(Prs3d_Presentation)& thePrs, |
515 | const Standard_Integer theBarBottom, |
516 | const Standard_Integer theBarHeight, |
517 | const Standard_Integer theMaxLabelWidth, |
518 | const Standard_Integer theColorBreadth) |
519 | { |
520 | const Standard_Real aStepY = Standard_Real(theBarHeight) / Standard_Real(myNbIntervals); |
521 | if (aStepY <= 0.0) |
522 | { |
523 | return; |
524 | } |
525 | |
526 | // Draw colors |
527 | const Standard_Integer anXLeft = myLabelPos == Aspect_TOCSP_LEFT |
528 | ? myXPos + mySpacing + theMaxLabelWidth + (theMaxLabelWidth != 0 ? 1 : 0) * mySpacing |
529 | : myXPos + mySpacing; |
7a324550 |
530 | |
531 | Aspect_SequenceOfColor aColors; |
4b3d6eb1 |
532 | for (Standard_Integer anIntervalIter = 1; anIntervalIter <= myNbIntervals; ++anIntervalIter) |
7a324550 |
533 | { |
4b3d6eb1 |
534 | if (myIsReversed) |
7a324550 |
535 | { |
4b3d6eb1 |
536 | aColors.Prepend (GetIntervalColor (anIntervalIter)); |
7a324550 |
537 | } |
538 | else |
539 | { |
4b3d6eb1 |
540 | aColors.Append (GetIntervalColor (anIntervalIter)); |
7a324550 |
541 | } |
542 | } |
543 | |
4b3d6eb1 |
544 | Handle(Graphic3d_ArrayOfTriangles) aTriangles; |
545 | if (myIsSmooth |
546 | && myColorType == Aspect_TOCSD_USER) |
7a324550 |
547 | { |
4b3d6eb1 |
548 | // Smooth custom intervals, so that the color in the center of interval is equal to specified one |
549 | // (thus the halves of first and last intervals have solid color) |
550 | aTriangles = new Graphic3d_ArrayOfTriangles ((aColors.Length() + 1) * 4, // quads |
551 | (aColors.Length() + 1) * 2 * 3, // quads as triangles |
552 | false, true); // per-vertex colors |
553 | Quantity_Color aColor1 (aColors.Value (1)), aColor2; |
554 | Standard_Integer aSizeY = Standard_Integer(aStepY / 2); |
555 | const Standard_Integer anYBottom = theBarBottom + aSizeY; |
556 | Standard_Integer anYBottomIter = anYBottom; |
557 | addColoredQuad (aTriangles, |
558 | anXLeft, theBarBottom, |
559 | theColorBreadth, aSizeY, |
560 | aColor1, aColor1); |
561 | for (Standard_Integer aColorIter = 0; aColorIter < myNbIntervals - 1; ++aColorIter) |
180f89a2 |
562 | { |
4b3d6eb1 |
563 | aColor1 = aColors.Value (aColorIter + 1); |
564 | aColor2 = aColors.Value (aColorIter + 2); |
565 | aSizeY = anYBottom + Standard_Integer((aColorIter + 1) * aStepY) - anYBottomIter; |
566 | addColoredQuad (aTriangles, |
567 | anXLeft, anYBottomIter, |
568 | theColorBreadth, aSizeY, |
569 | aColor1, aColor2); |
570 | anYBottomIter += aSizeY; |
180f89a2 |
571 | } |
4b3d6eb1 |
572 | aColor2 = aColors.Value (myNbIntervals); |
573 | aSizeY = theBarBottom + theBarHeight - anYBottomIter; |
574 | addColoredQuad (aTriangles, |
575 | anXLeft, anYBottomIter, |
576 | theColorBreadth, aSizeY, |
577 | aColor2, aColor2); |
578 | } |
579 | else if (myIsSmooth) |
580 | { |
581 | // smooth transition between standard colors - without solid color regions at the beginning and end of full color range |
582 | const Quantity_Color aColorsFixed[5] = |
583 | { |
584 | colorFromValue (0, 0, 4), |
585 | colorFromValue (1, 0, 4), |
586 | colorFromValue (2, 0, 4), |
587 | colorFromValue (3, 0, 4), |
588 | colorFromValue (4, 0, 4) |
589 | }; |
590 | aTriangles = new Graphic3d_ArrayOfTriangles (4 * 4, // quads |
591 | 4 * 2 * 3, // quads as triangles |
592 | false, true); // per-vertex colors |
593 | Standard_Integer anYBottomIter = theBarBottom; |
594 | addColoredQuad (aTriangles, |
595 | anXLeft, theBarBottom, |
596 | theColorBreadth, theBarHeight / 4, |
597 | aColorsFixed[0], aColorsFixed[1]); |
598 | anYBottomIter += theBarHeight / 4; |
599 | addColoredQuad (aTriangles, |
600 | anXLeft, anYBottomIter, |
601 | theColorBreadth, theBarHeight / 4, |
602 | aColorsFixed[1], aColorsFixed[2]); |
603 | anYBottomIter += theBarHeight / 4; |
604 | addColoredQuad (aTriangles, |
605 | anXLeft, anYBottomIter, |
606 | theColorBreadth, theBarHeight / 4, |
607 | aColorsFixed[2], aColorsFixed[3]); |
608 | anYBottomIter += theBarHeight / 4; |
609 | const Standard_Integer aLastSizeY = theBarBottom + theBarHeight - anYBottomIter; |
610 | addColoredQuad (aTriangles, |
611 | anXLeft, anYBottomIter, |
612 | theColorBreadth, aLastSizeY, |
613 | aColorsFixed[3], aColorsFixed[4]); |
614 | } |
615 | else |
616 | { |
617 | // no color smoothing |
618 | aTriangles = new Graphic3d_ArrayOfTriangles (aColors.Length() * 4, // quads |
619 | aColors.Length() * 2 * 3, // quads as triangles |
620 | false, true); // per-vertex colors |
621 | Standard_Integer anYBottomIter = theBarBottom; |
622 | for (Standard_Integer aColorIter = 0; aColorIter < myNbIntervals; ++aColorIter) |
180f89a2 |
623 | { |
4b3d6eb1 |
624 | const Quantity_Color& aColor = aColors.Value (aColorIter + 1); |
625 | const Standard_Integer aSizeY = theBarBottom + Standard_Integer((aColorIter + 1) * aStepY) - anYBottomIter; |
626 | addColoredQuad (aTriangles, |
627 | anXLeft, anYBottomIter, |
628 | theColorBreadth, aSizeY, |
629 | aColor, aColor); |
630 | anYBottomIter += aSizeY; |
180f89a2 |
631 | } |
7a324550 |
632 | } |
633 | |
4b3d6eb1 |
634 | Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs); |
635 | aGroup->AddPrimitiveArray (aTriangles); |
7a324550 |
636 | |
4b3d6eb1 |
637 | const Quantity_Color aFgColor (hasOwnColor ? myDrawer->Color() : Quantity_NOC_WHITE); |
638 | drawFrame (thePrs, |
639 | anXLeft - 1, theBarBottom - 1, |
640 | theColorBreadth + 2, |
641 | theBarHeight + 2, |
642 | aFgColor); |
643 | } |
7a324550 |
644 | |
4b3d6eb1 |
645 | //======================================================================= |
646 | //function : drawLabels |
647 | //purpose : |
648 | //======================================================================= |
649 | void AIS_ColorScale::drawLabels (const Handle(Prs3d_Presentation)& thePrs, |
650 | const TColStd_SequenceOfExtendedString& theLabels, |
651 | const Standard_Integer theBarBottom, |
652 | const Standard_Integer theBarHeight, |
653 | const Standard_Integer theMaxLabelWidth, |
654 | const Standard_Integer theColorBreadth) |
655 | { |
656 | if (myLabelPos == Aspect_TOCSP_NONE |
657 | || theLabels.IsEmpty()) |
658 | { |
659 | return; |
660 | } |
7a324550 |
661 | |
4b3d6eb1 |
662 | const Standard_Integer aNbLabels = theLabels.Size(); |
663 | const Standard_Integer aNbIntervals = myIsLabelAtBorder ? aNbLabels - 1 : aNbLabels; |
664 | const Standard_Real aStepY = Standard_Real(theBarHeight) / Standard_Real(aNbIntervals); |
665 | if (aStepY <= 0.0) |
666 | { |
667 | return; |
668 | } |
7a324550 |
669 | |
4b3d6eb1 |
670 | Standard_Integer aFilter = 0; |
671 | { |
672 | const Standard_Integer aTitleHeight = !myTitle.IsEmpty() ? (myTextHeight + 2 * mySpacing) : mySpacing; |
673 | const Standard_Integer aSpc = myHeight - aTitleHeight - ((Min (aNbLabels, 2) + Abs (aNbLabels - aNbIntervals - 1)) * myTextHeight); |
674 | if (aSpc <= 0) |
675 | { |
676 | return; |
677 | } |
678 | |
679 | const Standard_Real aVal = Standard_Real(aNbLabels) * myTextHeight / aSpc; |
680 | Standard_Real anIPart = 0.0; |
681 | Standard_Real anFPart = std::modf (aVal, &anIPart); |
682 | aFilter = (Standard_Integer )anIPart + (anFPart != 0 ? 1 : 0); |
683 | } |
684 | if (aFilter <= 0) |
685 | { |
686 | return; |
7a324550 |
687 | } |
7a324550 |
688 | |
4b3d6eb1 |
689 | Standard_Integer anXLeft = myXPos + mySpacing; |
690 | const Standard_Integer anAscent = 0; |
691 | switch (myLabelPos) |
692 | { |
693 | case Aspect_TOCSP_NONE: |
694 | case Aspect_TOCSP_LEFT: |
695 | { |
696 | break; |
697 | } |
698 | case Aspect_TOCSP_CENTER: |
699 | { |
700 | anXLeft += (theColorBreadth - theMaxLabelWidth) / 2; |
701 | break; |
702 | } |
703 | case Aspect_TOCSP_RIGHT: |
704 | { |
705 | anXLeft += theColorBreadth + mySpacing; |
706 | break; |
707 | } |
708 | } |
7a324550 |
709 | |
4b3d6eb1 |
710 | Standard_Integer i1 = 0; |
711 | Standard_Integer i2 = aNbLabels - 1; |
712 | Standard_Integer aLast1 = i1; |
713 | Standard_Integer aLast2 = i2; |
714 | const Standard_Integer anYBottom = myIsLabelAtBorder |
715 | ? theBarBottom |
716 | : theBarBottom + Standard_Integer(aStepY / 2); |
717 | while (i2 - i1 >= aFilter || ( i2 == 0 && i1 == 0 )) |
7a324550 |
718 | { |
4b3d6eb1 |
719 | Standard_Integer aPos1 = i1; |
720 | Standard_Integer aPos2 = aNbLabels - 1 - i2; |
721 | if (aFilter && !(aPos1 % aFilter)) |
7a324550 |
722 | { |
4b3d6eb1 |
723 | drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i1 + 1), |
724 | anXLeft, anYBottom + Standard_Integer(i1 * aStepY + anAscent), |
725 | Graphic3d_VTA_CENTER); |
726 | aLast1 = i1; |
7a324550 |
727 | } |
4b3d6eb1 |
728 | if (aFilter && !(aPos2 % aFilter)) |
7a324550 |
729 | { |
4b3d6eb1 |
730 | drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i2 + 1), |
731 | anXLeft, anYBottom + Standard_Integer(i2 * aStepY + anAscent), |
732 | Graphic3d_VTA_CENTER); |
733 | aLast2 = i2; |
7a324550 |
734 | } |
4b3d6eb1 |
735 | i1++; |
736 | i2--; |
737 | } |
738 | Standard_Integer aPos = i1; |
739 | Standard_Integer i0 = -1; |
740 | while (aPos <= i2 && i0 == -1) |
741 | { |
742 | if (aFilter && !(aPos % aFilter) |
743 | && Abs (aPos - aLast1) >= aFilter |
744 | && Abs (aPos - aLast2) >= aFilter) |
7a324550 |
745 | { |
4b3d6eb1 |
746 | i0 = aPos; |
7a324550 |
747 | } |
4b3d6eb1 |
748 | aPos++; |
749 | } |
7a324550 |
750 | |
4b3d6eb1 |
751 | if (i0 != -1) |
752 | { |
753 | drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i0 + 1), |
754 | anXLeft, anYBottom + Standard_Integer(i0 * aStepY + anAscent), |
755 | Graphic3d_VTA_CENTER); |
7a324550 |
756 | } |
757 | } |
758 | |
759 | //======================================================================= |
7c65581d |
760 | //function : drawFrame |
7a324550 |
761 | //purpose : |
762 | //======================================================================= |
4b3d6eb1 |
763 | void AIS_ColorScale::drawFrame (const Handle(Prs3d_Presentation)& thePrs, |
764 | const Standard_Integer theX, const Standard_Integer theY, |
765 | const Standard_Integer theWidth, const Standard_Integer theHeight, |
766 | const Quantity_Color& theColor) |
7a324550 |
767 | { |
7a324550 |
768 | Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5); |
4b3d6eb1 |
769 | aPrim->AddVertex (theX, theY, 0.0); |
770 | aPrim->AddVertex (theX + theWidth, theY, 0.0); |
771 | aPrim->AddVertex (theX + theWidth, theY + theHeight, 0.0); |
772 | aPrim->AddVertex (theX, theY + theHeight, 0.0); |
773 | aPrim->AddVertex (theX, theY, 0.0); |
774 | |
775 | Handle(Graphic3d_AspectLine3d) anAspect = new Graphic3d_AspectLine3d (theColor, Aspect_TOL_SOLID, 1.0); |
776 | Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs); |
777 | aGroup->SetPrimitivesAspect (anAspect); |
7a324550 |
778 | aGroup->AddPrimitiveArray (aPrim); |
779 | } |
780 | |
781 | //======================================================================= |
7c65581d |
782 | //function : drawText |
7a324550 |
783 | //purpose : |
784 | //======================================================================= |
4b3d6eb1 |
785 | void AIS_ColorScale::drawText (const Handle(Graphic3d_Group)& theGroup, |
786 | const TCollection_ExtendedString& theText, |
787 | const Standard_Integer theX, const Standard_Integer theY, |
788 | const Graphic3d_VerticalTextAlignment theVertAlignment) |
7a324550 |
789 | { |
4b3d6eb1 |
790 | const Handle(Prs3d_TextAspect)& anAspect = myDrawer->TextAspect(); |
791 | theGroup->SetPrimitivesAspect (anAspect->Aspect()); |
792 | theGroup->Text (theText, |
793 | gp_Ax2 (gp_Pnt (theX, theY, 0.0), gp::DZ()), |
794 | anAspect->Height(), |
795 | anAspect->Angle(), |
796 | anAspect->Orientation(), |
797 | Graphic3d_HTA_LEFT, |
798 | theVertAlignment, |
799 | Standard_True, |
800 | Standard_False); // has own anchor |
801 | |
7a324550 |
802 | } |
803 | |
804 | //======================================================================= |
805 | //function : TextWidth |
806 | //purpose : |
807 | //======================================================================= |
808 | Standard_Integer AIS_ColorScale::TextWidth (const TCollection_ExtendedString& theText) const |
809 | { |
810 | Standard_Integer aWidth, anAscent, aDescent; |
4b3d6eb1 |
811 | TextSize (theText, myTextHeight, aWidth, anAscent, aDescent); |
7a324550 |
812 | return aWidth; |
813 | } |
814 | |
815 | //======================================================================= |
816 | //function : TextHeight |
817 | //purpose : |
818 | //======================================================================= |
819 | Standard_Integer AIS_ColorScale::TextHeight (const TCollection_ExtendedString& theText) const |
820 | { |
821 | Standard_Integer aWidth, anAscent, aDescent; |
4b3d6eb1 |
822 | TextSize (theText, myTextHeight, aWidth, anAscent, aDescent); |
823 | return anAscent + aDescent; |
7a324550 |
824 | } |
825 | |
826 | //======================================================================= |
827 | //function : TextSize |
828 | //purpose : |
829 | //======================================================================= |
4b3d6eb1 |
830 | void AIS_ColorScale::TextSize (const TCollection_ExtendedString& theText, |
831 | const Standard_Integer theHeight, |
832 | Standard_Integer& theWidth, |
833 | Standard_Integer& theAscent, |
834 | Standard_Integer& theDescent) const |
7a324550 |
835 | { |
4b3d6eb1 |
836 | if (!HasInteractiveContext()) |
837 | { |
838 | return; |
839 | } |
840 | |
841 | Standard_ShortReal aWidth = 10.0f; |
842 | Standard_ShortReal anAscent = 1.0f; |
843 | Standard_ShortReal aDescent = 1.0f; |
844 | const TCollection_AsciiString aText (theText); |
845 | |
846 | const Handle(V3d_Viewer)& aViewer = GetContext()->CurrentViewer(); |
847 | const Handle(Graphic3d_CView)& aView = aViewer->ActiveViewIterator().Value()->View(); |
848 | aViewer->Driver()->TextSize (aView, aText.ToCString(), (Standard_ShortReal)theHeight, aWidth, anAscent, aDescent); |
849 | theWidth = (Standard_Integer)aWidth; |
850 | theAscent = (Standard_Integer)anAscent; |
7a324550 |
851 | theDescent = (Standard_Integer)aDescent; |
852 | } |