From 4b3d6eb1d2b6832a31ff1bb3f65c052838c15710 Mon Sep 17 00:00:00 2001 From: kgv Date: Thu, 22 Dec 2016 12:39:13 +0300 Subject: [PATCH] 0028004: Visualization, AIS_ColorScale - allow defining labels list not equal to intervals list Cosmetics, code clean up. AIS_ColorScale now draw labels using Graphic3d_VTA_CENTER vertical alignment flag, instead of incorrect own alignment logic. The color bar now adds margin on the top simmetrical to the bottom. AIS_ColorScale::SetSmoothTransition() - added new property for displaying colorscale with smooth transition between color intervals. AIS_ColorScale::SetHueRange() - added new property defining the hue angles corresponding to minimal and maximum values on the color scale. AIS_ColorScale::SetLabels() now allows setting the sequence of free labels, which number does not match the number of intervals. In this case the labels will be displayed at positions of virtual intervals corresponding to the number of labels. --- src/AIS/AIS_ColorScale.cxx | 1027 +++++++++--------- src/AIS/AIS_ColorScale.hxx | 493 ++++++--- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 514 ++++----- tests/bugs/vis/bug25136 | 30 +- tests/bugs/vis/bug28004 | 31 + 5 files changed, 1175 insertions(+), 920 deletions(-) create mode 100644 tests/bugs/vis/bug28004 diff --git a/src/AIS/AIS_ColorScale.cxx b/src/AIS/AIS_ColorScale.cxx index 9db164a9a0..ebcad40889 100644 --- a/src/AIS/AIS_ColorScale.cxx +++ b/src/AIS/AIS_ColorScale.cxx @@ -13,6 +13,7 @@ // commercial license or contractual agreement. #include + #include #include #include @@ -38,42 +39,78 @@ #include #include +IMPLEMENT_STANDARD_RTTIEXT(AIS_ColorScale, AIS_InteractiveObject) -IMPLEMENT_STANDARD_RTTIEXT(AIS_ColorScale,AIS_InteractiveObject) +namespace +{ + //! Method to add colored quad into array of triangles. + static void addColoredQuad (const Handle(Graphic3d_ArrayOfTriangles)& theTris, + const Standard_Integer theXLeft, const Standard_Integer theYBottom, + const Standard_Integer theSizeX, const Standard_Integer theSizeY, + const Quantity_Color& theColorBottom, + const Quantity_Color& theColorTop) + { + const Standard_Integer aVertIndex = theTris->VertexNumber() + 1; + theTris->AddVertex (gp_Pnt (theXLeft, theYBottom, 0.0), theColorBottom); + theTris->AddVertex (gp_Pnt (theXLeft + theSizeX, theYBottom, 0.0), theColorBottom); + theTris->AddVertex (gp_Pnt (theXLeft, theYBottom + theSizeY, 0.0), theColorTop); + theTris->AddVertex (gp_Pnt (theXLeft + theSizeX, theYBottom + theSizeY, 0.0), theColorTop); + theTris->AddEdge (aVertIndex); + theTris->AddEdge (aVertIndex + 1); + theTris->AddEdge (aVertIndex + 2); + theTris->AddEdge (aVertIndex + 1); + theTris->AddEdge (aVertIndex + 2); + theTris->AddEdge (aVertIndex + 3); + } + + //! Compute hue angle from specified value. + static Quantity_Color colorFromValueEx (const Standard_Real theValue, + const Standard_Real theMin, + const Standard_Real theMax, + const Graphic3d_Vec3d& theHlsMin, + const Graphic3d_Vec3d& theHlsMax) + { + const Standard_Real aValueDelta = theMax - theMin; + Standard_Real aValue = 0.0; + if (aValueDelta != 0.0) + { + aValue = (theValue - theMin) / aValueDelta; + } + + Standard_Real aHue = NCollection_Lerp::Interpolate (theHlsMin[0], theHlsMax[0], aValue); + Standard_Real aLightness = NCollection_Lerp::Interpolate (theHlsMin[1], theHlsMax[1], aValue); + Standard_Real aSaturation = NCollection_Lerp::Interpolate (theHlsMin[2], theHlsMax[2], aValue); + return Quantity_Color (AIS_ColorScale::hueToValidRange (aHue), aLightness, aSaturation, Quantity_TOC_HLS); + } +} //======================================================================= //function : AIS_ColorScale //purpose : //======================================================================= -AIS_ColorScale::AIS_ColorScale() : -myMin (0.0), -myMax (1.0), -myTitle (""), -myFormat ("%.4g"), -myInterval (10), -myColorType (Aspect_TOCSD_AUTO), -myLabelType (Aspect_TOCSD_AUTO), -myAtBorder (Standard_True), -myReversed (Standard_False), -myIsLogarithmic (Standard_False), -myLabelPos (Aspect_TOCSP_RIGHT), -myTitlePos (Aspect_TOCSP_CENTER), -myXPos (0), -myYPos (0), -myBreadth (0), -myHeight (0), -myTextHeight(20) +AIS_ColorScale::AIS_ColorScale() +: myMin (0.0), + myMax (1.0), + myColorHlsMin (230.0, 1.0, 1.0), + myColorHlsMax (0.0, 1.0, 1.0), + myFormat ("%.4g"), + myNbIntervals (10), + myColorType (Aspect_TOCSD_AUTO), + myLabelType (Aspect_TOCSD_AUTO), + myIsLabelAtBorder (Standard_True), + myIsReversed (Standard_False), + myIsLogarithmic (Standard_False), + myIsSmooth (Standard_False), + myLabelPos (Aspect_TOCSP_RIGHT), + myTitlePos (Aspect_TOCSP_LEFT), + myXPos (0), + myYPos (0), + myBreadth (0), + myHeight (0), + mySpacing (5), + myTextHeight (20) { -} - -//======================================================================= -//function : GetRange -//purpose : -//======================================================================= -void AIS_ColorScale::GetRange (Standard_Real& theMin, Standard_Real& theMax) const -{ - theMin = myMin; - theMax = myMax; + SetDisplayMode (0); } //======================================================================= @@ -82,22 +119,23 @@ void AIS_ColorScale::GetRange (Standard_Real& theMin, Standard_Real& theMax) con //======================================================================= TCollection_ExtendedString AIS_ColorScale::GetLabel (const Standard_Integer theIndex) const { - if (GetLabelType() == Aspect_TOCSD_USER) + if (myLabelType == Aspect_TOCSD_USER) { - if (theIndex <= 0 || theIndex > myLabels.Length()) + if (theIndex >= myLabels.Lower() + || theIndex <= myLabels.Upper()) { - return ""; + return myLabels.Value(theIndex); } - return myLabels.Value (theIndex); + return TCollection_ExtendedString(); } // value to be shown depends on label position - Standard_Real aVal = IsLabelAtBorder() ? GetIntervalValue (theIndex - 1) : - 0.5 * (GetIntervalValue (theIndex - 1) + GetIntervalValue (theIndex)); + const Standard_Real aVal = myIsLabelAtBorder + ? GetIntervalValue (theIndex - 1) + : (0.5 * (GetIntervalValue (theIndex - 1) + GetIntervalValue (theIndex))); - const TCollection_AsciiString aFormat = Format(); - Standard_Character aBuf[1024]; - sprintf (aBuf, aFormat.ToCString(), aVal); + char aBuf[1024]; + sprintf (aBuf, myFormat.ToCString(), aVal); return TCollection_ExtendedString (aBuf); } @@ -107,7 +145,7 @@ TCollection_ExtendedString AIS_ColorScale::GetLabel (const Standard_Integer theI //======================================================================= Quantity_Color AIS_ColorScale::GetIntervalColor (const Standard_Integer theIndex) const { - if (GetColorType() == Aspect_TOCSD_USER) + if (myColorType== Aspect_TOCSD_USER) { if (theIndex <= 0 || theIndex > myColors.Length()) { @@ -116,7 +154,7 @@ Quantity_Color AIS_ColorScale::GetIntervalColor (const Standard_Integer theIndex return myColors.Value (theIndex); } - return Quantity_Color (HueFromValue (theIndex - 1, 0, GetNumberOfIntervals() - 1), 1.0, 1.0, Quantity_TOC_HLS); + return colorFromValue (theIndex - 1, 0, myNbIntervals - 1); } //======================================================================= @@ -126,8 +164,10 @@ Quantity_Color AIS_ColorScale::GetIntervalColor (const Standard_Integer theIndex void AIS_ColorScale::GetLabels (TColStd_SequenceOfExtendedString& theLabels) const { theLabels.Clear(); - for (Standard_Integer i = 1; i <= myLabels.Length(); i++) - theLabels.Append (myLabels.Value (i)); + for (TColStd_SequenceOfExtendedString::Iterator aLabIter (myLabels); aLabIter.More(); aLabIter.Next()) + { + theLabels.Append (aLabIter.Value()); + } } //======================================================================= @@ -137,26 +177,10 @@ void AIS_ColorScale::GetLabels (TColStd_SequenceOfExtendedString& theLabels) con void AIS_ColorScale::GetColors (Aspect_SequenceOfColor& theColors) const { theColors.Clear(); - for (Standard_Integer i = 1; i <= myColors.Length(); i++) - theColors.Append (myColors.Value (i)); -} - -//======================================================================= -//function : SetMin -//purpose : -//======================================================================= -void AIS_ColorScale::SetMin (const Standard_Real theMin) -{ - SetRange (theMin, GetMax()); -} - -//======================================================================= -//function : SetMax -//purpose : -//======================================================================= -void AIS_ColorScale::SetMax (const Standard_Real theMax) -{ - SetRange (GetMin(), theMax); + for (Aspect_SequenceOfColor::Iterator aColorIter (myColors); aColorIter.More(); aColorIter.Next()) + { + theColors.Append (aColorIter.Value()); + } } //======================================================================= @@ -165,95 +189,52 @@ void AIS_ColorScale::SetMax (const Standard_Real theMax) //======================================================================= void AIS_ColorScale::SetRange (const Standard_Real theMin, const Standard_Real theMax) { - if (myMin == theMin && myMax == theMax) - return; - myMin = Min (theMin, theMax); myMax = Max (theMin, theMax); } -//======================================================================= -//function : SetLabelType -//purpose : -//======================================================================= -void AIS_ColorScale::SetLabelType (const Aspect_TypeOfColorScaleData theType) -{ - if (myLabelType == theType) - return; - - myLabelType = theType; -} - -//======================================================================= -//function : SetColorType -//purpose : -//======================================================================= -void AIS_ColorScale::SetColorType (const Aspect_TypeOfColorScaleData theType) -{ - if (myColorType == theType) - return; - - myColorType = theType; -} - //======================================================================= //function : SetNumberOfIntervals //purpose : //======================================================================= void AIS_ColorScale::SetNumberOfIntervals (const Standard_Integer theNum) { - if (myInterval == theNum || theNum < 1) + if (theNum < 1) + { return; + } - myInterval = theNum; -} - -//======================================================================= -//function : SetTitle -//purpose : -//======================================================================= -void AIS_ColorScale::SetTitle (const TCollection_ExtendedString& theTitle) -{ - if (myTitle == theTitle) - return; - - myTitle = theTitle; -} - -//======================================================================= -//function : SetFormat -//purpose : -//======================================================================= -void AIS_ColorScale::SetFormat (const TCollection_AsciiString& theFormat) -{ - if (myFormat == theFormat) - return; - - myFormat = theFormat; + myNbIntervals = theNum; } //======================================================================= //function : SetLabel //purpose : //======================================================================= -void AIS_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer theIndex) +void AIS_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, + const Standard_Integer theIndex) { - Standard_Integer i = (theIndex <= 0 ? myLabels.Length() + 1 : theIndex); - while (i > myLabels.Length()) + const Standard_Integer aLabIndex = (theIndex <= 0 ? myLabels.Length() + 1 : theIndex); + while (myLabels.Length() < aLabIndex) + { myLabels.Append (TCollection_ExtendedString()); - myLabels.SetValue (i, theLabel); + } + myLabels.SetValue (aLabIndex, theLabel); } //======================================================================= //function : SetIntervalColor //purpose : //======================================================================= -void AIS_ColorScale::SetIntervalColor (const Quantity_Color& theColor, const Standard_Integer theIndex) +void AIS_ColorScale::SetIntervalColor (const Quantity_Color& theColor, + const Standard_Integer theIndex) { - Standard_Integer i = (theIndex <= 0 ? myColors.Length() + 1 : theIndex); - while (i > myColors.Length()) + const Standard_Integer aColorIndex = (theIndex <= 0 ? myColors.Length() + 1 : theIndex); + while (myColors.Length() < aColorIndex) + { myColors.Append (Quantity_Color()); - myColors.SetValue (i, theColor); + } + myColors.SetValue (aColorIndex, theColor); } //======================================================================= @@ -263,8 +244,10 @@ void AIS_ColorScale::SetIntervalColor (const Quantity_Color& theColor, const Sta void AIS_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq) { myLabels.Clear(); - for (Standard_Integer i = 1; i <= theSeq.Length(); i++) - myLabels.Append (theSeq.Value (i)); + for (TColStd_SequenceOfExtendedString::Iterator aLabIter (theSeq); aLabIter.More(); aLabIter.Next()) + { + myLabels.Append (aLabIter.Value()); + } } //======================================================================= @@ -274,138 +257,10 @@ void AIS_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq) void AIS_ColorScale::SetColors (const Aspect_SequenceOfColor& theSeq) { myColors.Clear(); - for (Standard_Integer i = 1; i <= theSeq.Length(); i++) - myColors.Append (theSeq.Value (i)); -} - -//======================================================================= -//function : SetLabelPosition -//purpose : -//======================================================================= -void AIS_ColorScale::SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos) -{ - if (myLabelPos == thePos) - return; - - myLabelPos = thePos; -} - -//======================================================================= -//function : SetTitlePosition -//purpose : -//======================================================================= -void AIS_ColorScale::SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos) -{ - if (myTitlePos == thePos) - return; - - myTitlePos = thePos; -} - -//======================================================================= -//function : SetReversed -//purpose : -//======================================================================= -void AIS_ColorScale::SetReversed (const Standard_Boolean theReverse) -{ - if (myReversed == theReverse) - return; - - myReversed = theReverse; -} - -//======================================================================= -//function : SetLabelAtBorder -//purpose : -//======================================================================= -void AIS_ColorScale::SetLabelAtBorder (const Standard_Boolean theOn) -{ - if (myAtBorder == theOn) - return; - - myAtBorder = theOn; -} - -//======================================================================= -//function : GetPosition -//purpose : -//======================================================================= -void AIS_ColorScale::GetPosition (Standard_Real& theX, Standard_Real& theY) const -{ - theX = myXPos; - theY = myYPos; -} - -//======================================================================= -//function : SetPosition -//purpose : -//======================================================================= -void AIS_ColorScale::SetPosition (const Standard_Integer theX, const Standard_Integer theY) -{ - if (myXPos == theX && myYPos == theY) - return; - - myXPos = theX; - myYPos = theY; -} - -//======================================================================= -//function : SetXPosition -//purpose : -//======================================================================= -void AIS_ColorScale::SetXPosition (const Standard_Integer theX) -{ - SetPosition (theX, GetYPosition()); -} - -//======================================================================= -//function : SetYPosition -//purpose : -//======================================================================= -void AIS_ColorScale::SetYPosition (const Standard_Integer theY) -{ - SetPosition (GetXPosition(), theY); -} - -//======================================================================= -//function : GetSize -//purpose : -//======================================================================= -void AIS_ColorScale::GetSize (Standard_Integer& theBreadth, Standard_Integer& theHeight) const -{ - theBreadth = myBreadth; - theHeight = myHeight; -} - -//======================================================================= -//function : SetSize -//purpose : -//======================================================================= -void AIS_ColorScale::SetSize (const Standard_Integer theBreadth, const Standard_Integer theHeight) -{ - if (myBreadth == theBreadth && myHeight == theHeight) - return; - - myBreadth = theBreadth; - myHeight = theHeight; -} - -//======================================================================= -//function : SetBreadth -//purpose : -//======================================================================= -void AIS_ColorScale::SetBreadth (const Standard_Integer theWidth) -{ - SetSize (theWidth, GetHeight()); -} - -//======================================================================= -//function : SetHeight -//purpose : -//======================================================================= -void AIS_ColorScale::SetHeight (const Standard_Integer theHeight) -{ - SetSize (GetBreadth(), theHeight); + for (Aspect_SequenceOfColor::Iterator aColorIter (theSeq); aColorIter.More(); aColorIter.Next()) + { + myColors.Append (aColorIter.Value()); + } } //======================================================================= @@ -414,84 +269,67 @@ void AIS_ColorScale::SetHeight (const Standard_Integer theHeight) //======================================================================= void AIS_ColorScale::SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const { - Standard_Integer aNum = GetNumberOfIntervals(); - - Standard_Integer aSpacer = 5; + const Standard_Integer aTextHeight = TextHeight (""); + const Standard_Integer aColorWidth = 20; Standard_Integer aTextWidth = 0; - Standard_Integer aTextHeight = TextHeight (""); - Standard_Integer aColorWidth = 20; - - if (GetLabelPosition() != Aspect_TOCSP_NONE) + if (myLabelPos != Aspect_TOCSP_NONE) { - for (Standard_Integer idx = (IsLabelAtBorder() ? 0 : 1); idx <= aNum; idx++) - aTextWidth = Max (aTextWidth, TextWidth (GetLabel (idx))); + for (Standard_Integer aLabIter = (myIsLabelAtBorder ? 0 : 1); aLabIter <= myNbIntervals; ++aLabIter) + { + aTextWidth = Max (aTextWidth, TextWidth (GetLabel (aLabIter))); + } } - Standard_Integer aScaleWidth = 0; - Standard_Integer aScaleHeight = 0; + const Standard_Integer aScaleWidth = aColorWidth + aTextWidth + (aTextWidth ? 3 : 2) * mySpacing; + const Standard_Integer aScaleHeight = (Standard_Integer)(1.5 * (myNbIntervals + (myIsLabelAtBorder ? 2 : 1)) * aTextHeight); - aScaleWidth = aColorWidth + aTextWidth + ( aTextWidth ? 3 : 2 ) * aSpacer; - aScaleHeight = (Standard_Integer)( 1.5 * ( aNum + (IsLabelAtBorder() ? 2 : 1) ) * aTextHeight ); - - Standard_Integer aTitleWidth = 0; + Standard_Integer aTitleWidth = 0; Standard_Integer aTitleHeight = 0; - if (GetTitle().Length()) + if (!myTitle.IsEmpty()) { - aTitleHeight = TextHeight (GetTitle()) + aSpacer; - aTitleWidth = TextWidth (GetTitle()) + 10; + aTitleHeight = TextHeight (myTitle) + mySpacing; + aTitleWidth = TextWidth (myTitle) + mySpacing * 2; } - theWidth = Max (aTitleWidth, aScaleWidth); + theWidth = Max (aTitleWidth, aScaleWidth); theHeight = aScaleHeight + aTitleHeight; } -//======================================================================= -//function : Format -//purpose : -//======================================================================= -TCollection_AsciiString AIS_ColorScale::Format() const -{ - return GetFormat(); -} - //======================================================================= //function : GetIntervalValue //purpose : //======================================================================= Standard_Real AIS_ColorScale::GetIntervalValue (const Standard_Integer theIndex) const { - if (GetNumberOfIntervals() <= 0) - return 0.; + if (myNbIntervals <= 0) + { + return 0.0; + } if (IsLogarithmic()) { - Standard_Real aMin = myMin > 0 ? myMin : 1.0; - Standard_Real aDivisor = std::pow (myMax/aMin, 1.0/myInterval); - return aMin*std::pow (aDivisor,theIndex); + Standard_Real aMin = myMin > 0 ? myMin : 1.0; + Standard_Real aDivisor = std::pow (myMax / aMin, 1.0 / myNbIntervals); + return aMin * std::pow (aDivisor,theIndex); } Standard_Real aNum = 0; - if (GetNumberOfIntervals() > 0) - aNum = GetMin() + theIndex * ( Abs (GetMax() - GetMin()) / GetNumberOfIntervals() ); + if (myNbIntervals > 0) + { + aNum = GetMin() + theIndex * (Abs (GetMax() - GetMin()) / myNbIntervals); + } return aNum; } //======================================================================= -//function : HueFromValue +//function : colorFromValue //purpose : //======================================================================= -Standard_Integer AIS_ColorScale::HueFromValue (const Standard_Integer theValue, - const Standard_Integer theMin, const Standard_Integer theMax) +Quantity_Color AIS_ColorScale::colorFromValue (const Standard_Real theValue, + const Standard_Real theMin, + const Standard_Real theMax) const { - Standard_Integer aMinLimit (0), aMaxLimit (230); - - Standard_Integer aHue = aMaxLimit; - if (theMin != theMax) - aHue = (Standard_Integer)( aMaxLimit - ( aMaxLimit - aMinLimit ) * ( theValue - theMin ) / ( theMax - theMin ) ); - - aHue = Min (Max (aMinLimit, aHue), aMaxLimit); - - return aHue; + return colorFromValueEx (theValue, theMin, theMax, myColorHlsMin, myColorHlsMax); } //======================================================================= @@ -507,14 +345,14 @@ Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue, return Standard_False; } - if (GetColorType() == Aspect_TOCSD_USER) + if (myColorType == Aspect_TOCSD_USER) { Standard_Integer anIndex = 0; if (Abs (myMax - myMin) > Precision::Approximation()) { anIndex = (theValue - myMin < Precision::Confusion()) ? 1 - : Standard_Integer (Ceiling (( theValue - myMin ) / ( (myMax - myMin) / myInterval))); + : Standard_Integer (Ceiling (( theValue - myMin ) / ( (myMax - myMin) / myNbIntervals))); } if (anIndex <= 0 || anIndex > myColors.Length()) @@ -527,7 +365,7 @@ Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue, return Standard_True; } - return FindColor (theValue, myMin, myMax, myInterval, theColor); + return FindColor (theValue, myMin, myMax, myNbIntervals, theColor); } //======================================================================= @@ -538,182 +376,383 @@ Standard_Boolean AIS_ColorScale::FindColor (const Standard_Real theValue, const Standard_Real theMin, const Standard_Real theMax, const Standard_Integer theColorsCount, + const Graphic3d_Vec3d& theColorHlsMin, + const Graphic3d_Vec3d& theColorHlsMax, Quantity_Color& theColor) { if (theValue < theMin || theValue > theMax || theMax < theMin) - return Standard_False; - - else { - Standard_Real anIntervNumber = 0; - if(Abs (theMax-theMin) > Precision::Approximation()) - anIntervNumber = Floor (Standard_Real (theColorsCount) * ( theValue - theMin ) / ( theMax - theMin )); - - Standard_Integer anInterv = Standard_Integer (anIntervNumber); - - theColor = Quantity_Color (HueFromValue (anInterv, 0, theColorsCount - 1), 1.0, 1.0, Quantity_TOC_HLS); - - return Standard_True; + return Standard_False; } + + Standard_Real anInterval = 0.0; + if (Abs (theMax - theMin) > Precision::Approximation()) + { + anInterval = Floor (Standard_Real (theColorsCount) * (theValue - theMin) / (theMax - theMin)); + } + + theColor = colorFromValueEx (anInterval, 0, theColorsCount - 1, theColorHlsMin, theColorHlsMax); + return Standard_True; +} + +//======================================================================= +//function : computeMaxLabelWidth +//purpose : +//======================================================================= +Standard_Integer AIS_ColorScale::computeMaxLabelWidth (const TColStd_SequenceOfExtendedString& theLabels) const +{ + { + Handle(V3d_Viewer) aViewer = GetContext()->CurrentViewer(); + aViewer->InitActiveViews(); // for AIS_ColorScale::TextSize() + } + + Standard_Integer aWidthMax = 0; + for (TColStd_SequenceOfExtendedString::Iterator aLabIter (theLabels); aLabIter.More(); aLabIter.Next()) + { + if (!aLabIter.Value().IsEmpty()) + { + aWidthMax = Max (aWidthMax, TextWidth (aLabIter.Value())); + } + } + return aWidthMax; +} + +//======================================================================= +//function : updateTextAspect +//purpose : +//======================================================================= +void AIS_ColorScale::updateTextAspect() +{ + // update text aspect + const Quantity_Color aFgColor (hasOwnColor ? myDrawer->Color() : Quantity_NOC_WHITE); + if (!myDrawer->HasOwnTextAspect()) + { + myDrawer->SetTextAspect (new Prs3d_TextAspect()); + *myDrawer->TextAspect()->Aspect() = *myDrawer->Link()->TextAspect()->Aspect(); + } + + const Handle(Prs3d_TextAspect)& anAspect = myDrawer->TextAspect(); + anAspect->SetColor (aFgColor); + anAspect->SetHeight (myTextHeight); + anAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT); + anAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM); + anAspect->Aspect()->SetTextZoomable (Standard_True); } //======================================================================= //function : Compute //purpose : //======================================================================= -void AIS_ColorScale::Compute(const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/, - const Handle(Prs3d_Presentation)& thePresentation, - const Standard_Integer /*theMode*/) +void AIS_ColorScale::Compute (const Handle(PrsMgr_PresentationManager3d)& , + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) { - Handle(V3d_Viewer) aViewer= GetContext()->CurrentViewer(); - aViewer->InitActiveViews(); - Standard_Integer aNum = GetNumberOfIntervals(); - Aspect_TypeOfColorScalePosition aLabPos = GetLabelPosition(); - - Standard_Integer aSpacer = 5; - Standard_Integer aTextWidth = 0; - Standard_Integer aTextHeight = myTextHeight; - Standard_Boolean toDrawLabel = GetLabelPosition() != Aspect_TOCSP_NONE; - TCollection_ExtendedString aTitle = GetTitle(); - Standard_Integer aTitleHeight = aSpacer; - Quantity_Color aFgColor (hasOwnColor ? myDrawer->Color() : Quantity_NOC_WHITE); - - // Draw title - if (aTitle.Length()) + if (theMode != 0) { - aTitleHeight += myTextHeight + aSpacer; - drawText (thePresentation, aTitle, (Standard_Integer)myXPos + aSpacer, myHeight - ((Standard_Integer)myYPos - 2 * aSpacer + aTitleHeight), aFgColor); + return; } - Standard_Boolean toReverse = IsReversed(); + // update text aspect + updateTextAspect(); - Aspect_SequenceOfColor aColors; - for (Standard_Integer i = 1; i <= aNum; i++) + const Standard_Integer aTitleOffset = !myTitle.IsEmpty() ? (myTextHeight + mySpacing) : 0; + + const Standard_Integer aBarYOffset = myTextHeight / 2 + 2 * mySpacing; // a half-label offset + const Standard_Integer aBarBottom = myYPos + aBarYOffset; + const Standard_Integer aBarTop = myYPos + myHeight - aTitleOffset - aBarYOffset; + const Standard_Integer aBarHeight = aBarTop - aBarBottom; + + // draw title + if (!myTitle.IsEmpty()) { - if (toReverse) - { - aColors.Prepend (GetIntervalColor (i)); - } - else - { - aColors.Append (GetIntervalColor (i)); - } + drawText (Prs3d_Root::CurrentGroup (thePrs), myTitle, + myXPos + mySpacing, + aBarTop + aBarYOffset, + Graphic3d_VTA_BOTTOM); } TColStd_SequenceOfExtendedString aLabels; - Standard_Integer aLabCount = IsLabelAtBorder() ? aNum + 1 : aNum; - for (Standard_Integer i = 1; i <= aLabCount; i++) + if (myLabelType == Aspect_TOCSD_USER) { - if (toReverse) + aLabels = myLabels; + } + else + { + const Standard_Integer aNbLabels = myIsLabelAtBorder ? myNbIntervals + 1 : myNbIntervals; + for (Standard_Integer aLabIter = 1; aLabIter <= aNbLabels; ++aLabIter) { - aLabels.Prepend (GetLabel (i)); + if (myIsReversed) + { + aLabels.Prepend (GetLabel (aLabIter)); + } + else + { + aLabels.Append (GetLabel (aLabIter)); + } + } + } + + const Standard_Integer aTextWidth = myLabelPos != Aspect_TOCSP_NONE ? computeMaxLabelWidth (aLabels) : 0; + Standard_Integer aColorBreadth = Max (5, Min (20, myBreadth - aTextWidth - 3 * mySpacing)); + if (myLabelPos == Aspect_TOCSP_CENTER + || myLabelPos == Aspect_TOCSP_NONE) + { + aColorBreadth += aTextWidth; + } + + // draw colors + drawColorBar (thePrs, aBarBottom, aBarHeight, aTextWidth, aColorBreadth); + + // draw Labels + drawLabels (thePrs, aLabels, aBarBottom, aBarHeight, aTextWidth, aColorBreadth); +} + +//======================================================================= +//function : drawColorBar +//purpose : +//======================================================================= +void AIS_ColorScale::drawColorBar (const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theBarBottom, + const Standard_Integer theBarHeight, + const Standard_Integer theMaxLabelWidth, + const Standard_Integer theColorBreadth) +{ + const Standard_Real aStepY = Standard_Real(theBarHeight) / Standard_Real(myNbIntervals); + if (aStepY <= 0.0) + { + return; + } + + // Draw colors + const Standard_Integer anXLeft = myLabelPos == Aspect_TOCSP_LEFT + ? myXPos + mySpacing + theMaxLabelWidth + (theMaxLabelWidth != 0 ? 1 : 0) * mySpacing + : myXPos + mySpacing; + + Aspect_SequenceOfColor aColors; + for (Standard_Integer anIntervalIter = 1; anIntervalIter <= myNbIntervals; ++anIntervalIter) + { + if (myIsReversed) + { + aColors.Prepend (GetIntervalColor (anIntervalIter)); } else { - aLabels.Append (GetLabel (i)); + aColors.Append (GetIntervalColor (anIntervalIter)); } } - if (toDrawLabel) - for (Standard_Integer i = 1; i <= aLabels.Length(); i++) - aTextWidth = Max (aTextWidth, TextWidth (aLabels.Value (i))); - - Standard_Integer aSpc = ( myHeight - ( ( Min (aLabCount, 2) + Abs (aLabCount - aNum - 1) ) * aTextHeight ) - aTitleHeight ); - Standard_Real aVal = aSpc != 0 ? 1.0 * ( aLabCount - Min (aLabCount, 0) ) * aTextHeight / aSpc : 0; - Standard_Real anIPart; - Standard_Real anFPart = modf (aVal, &anIPart); - Standard_Integer aFilter = (Standard_Integer)anIPart + ( anFPart != 0 ? 1 : 0 ); - - Standard_Real aStep = 1.0 * ( myHeight - (aLabCount - aNum + Abs (aLabCount - aNum - 1)) * aTextHeight - aTitleHeight ) / aNum; - - Standard_Integer anAscent = 0; - Standard_Integer aColorBreadth = Max (5, Min (20, myBreadth - aTextWidth - 3 * aSpacer)); - if (aLabPos == Aspect_TOCSP_CENTER || !toDrawLabel) - aColorBreadth += aTextWidth; - - // Draw colors - Standard_Integer aX = (Standard_Integer)myXPos + aSpacer; - if (aLabPos == Aspect_TOCSP_LEFT) - aX += aTextWidth + ( aTextWidth ? 1 : 0 ) * aSpacer; - - Standard_Real anOffset = 1.0 * aTextHeight / 2 * ( aLabCount - aNum + Abs (aLabCount - aNum - 1) ); - anOffset += 2*aSpacer; - Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation); - Handle (Graphic3d_ArrayOfTriangles) aPrim; - Standard_Integer anEdgesPerColor = 6; - Standard_Integer aVerticiesPerColor = 4; - aPrim = new Graphic3d_ArrayOfTriangles (aColors.Length()*aVerticiesPerColor, aColors.Length()*anEdgesPerColor, 0, 1); - Standard_Integer aVertIndex = 1; - for (Standard_Integer i = 1; i <= aColors.Length() && aStep > 0; i++) + Handle(Graphic3d_ArrayOfTriangles) aTriangles; + if (myIsSmooth + && myColorType == Aspect_TOCSD_USER) { - Standard_Integer aY = (Standard_Integer)( myYPos + ( i - 1 )* aStep + anOffset ); - Standard_Integer aColorHeight = (Standard_Integer)( myYPos + ( i ) * aStep + anOffset ) - aY; - aPrim->AddVertex (gp_Pnt (aX, aY, 0.0), aColors.Value( i )); - aPrim->AddVertex (gp_Pnt (aX+aColorBreadth, aY, 0.0), aColors.Value( i )); - aPrim->AddVertex (gp_Pnt (aX, aY+aColorHeight, 0.0), aColors.Value( i )); - aPrim->AddVertex (gp_Pnt (aX+aColorBreadth, aY+aColorHeight, 0.0), aColors.Value( i )); - aPrim->AddEdge(aVertIndex); - aPrim->AddEdge(aVertIndex+1); - aPrim->AddEdge(aVertIndex+2); - aPrim->AddEdge(aVertIndex+1); - aPrim->AddEdge(aVertIndex+2); - aPrim->AddEdge(aVertIndex+3); - aVertIndex += 4; + // Smooth custom intervals, so that the color in the center of interval is equal to specified one + // (thus the halves of first and last intervals have solid color) + aTriangles = new Graphic3d_ArrayOfTriangles ((aColors.Length() + 1) * 4, // quads + (aColors.Length() + 1) * 2 * 3, // quads as triangles + false, true); // per-vertex colors + Quantity_Color aColor1 (aColors.Value (1)), aColor2; + Standard_Integer aSizeY = Standard_Integer(aStepY / 2); + const Standard_Integer anYBottom = theBarBottom + aSizeY; + Standard_Integer anYBottomIter = anYBottom; + addColoredQuad (aTriangles, + anXLeft, theBarBottom, + theColorBreadth, aSizeY, + aColor1, aColor1); + for (Standard_Integer aColorIter = 0; aColorIter < myNbIntervals - 1; ++aColorIter) + { + aColor1 = aColors.Value (aColorIter + 1); + aColor2 = aColors.Value (aColorIter + 2); + aSizeY = anYBottom + Standard_Integer((aColorIter + 1) * aStepY) - anYBottomIter; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, aSizeY, + aColor1, aColor2); + anYBottomIter += aSizeY; + } + aColor2 = aColors.Value (myNbIntervals); + aSizeY = theBarBottom + theBarHeight - anYBottomIter; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, aSizeY, + aColor2, aColor2); } - aGroup->AddPrimitiveArray (aPrim); - - if (aStep > 0) - drawFrame (thePresentation, aX - 1, (Standard_Integer)(myYPos + anOffset - 1), aColorBreadth + 2, (Standard_Integer)(aColors.Length() * aStep + 2), aFgColor); - - // Draw Labels - anOffset = 1.0 * Abs (aLabCount - aNum - 1) * ( aStep - aTextHeight ) / 2 + 1.0 * Abs (aLabCount - aNum - 1) * aTextHeight / 2; - anOffset += 2*aSpacer; - if (toDrawLabel && aLabels.Length() && aFilter > 0) + else if (myIsSmooth) { - Standard_Integer i1 = 0; - Standard_Integer i2 = aLabCount - 1; - Standard_Integer aLast1( i1 ), aLast2( i2 ); - aX = (Standard_Integer)myXPos + aSpacer; - switch (aLabPos) + // smooth transition between standard colors - without solid color regions at the beginning and end of full color range + const Quantity_Color aColorsFixed[5] = { - case Aspect_TOCSP_NONE: - case Aspect_TOCSP_LEFT: - break; - case Aspect_TOCSP_CENTER: - aX += ( aColorBreadth - aTextWidth ) / 2; - break; - case Aspect_TOCSP_RIGHT: - aX += aColorBreadth + aSpacer; - break; + colorFromValue (0, 0, 4), + colorFromValue (1, 0, 4), + colorFromValue (2, 0, 4), + colorFromValue (3, 0, 4), + colorFromValue (4, 0, 4) + }; + aTriangles = new Graphic3d_ArrayOfTriangles (4 * 4, // quads + 4 * 2 * 3, // quads as triangles + false, true); // per-vertex colors + Standard_Integer anYBottomIter = theBarBottom; + addColoredQuad (aTriangles, + anXLeft, theBarBottom, + theColorBreadth, theBarHeight / 4, + aColorsFixed[0], aColorsFixed[1]); + anYBottomIter += theBarHeight / 4; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, theBarHeight / 4, + aColorsFixed[1], aColorsFixed[2]); + anYBottomIter += theBarHeight / 4; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, theBarHeight / 4, + aColorsFixed[2], aColorsFixed[3]); + anYBottomIter += theBarHeight / 4; + const Standard_Integer aLastSizeY = theBarBottom + theBarHeight - anYBottomIter; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, aLastSizeY, + aColorsFixed[3], aColorsFixed[4]); + } + else + { + // no color smoothing + aTriangles = new Graphic3d_ArrayOfTriangles (aColors.Length() * 4, // quads + aColors.Length() * 2 * 3, // quads as triangles + false, true); // per-vertex colors + Standard_Integer anYBottomIter = theBarBottom; + for (Standard_Integer aColorIter = 0; aColorIter < myNbIntervals; ++aColorIter) + { + const Quantity_Color& aColor = aColors.Value (aColorIter + 1); + const Standard_Integer aSizeY = theBarBottom + Standard_Integer((aColorIter + 1) * aStepY) - anYBottomIter; + addColoredQuad (aTriangles, + anXLeft, anYBottomIter, + theColorBreadth, aSizeY, + aColor, aColor); + anYBottomIter += aSizeY; } - while (i2 - i1 >= aFilter || ( i2 == 0 && i1 == 0 )) + } + + Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs); + aGroup->AddPrimitiveArray (aTriangles); + + const Quantity_Color aFgColor (hasOwnColor ? myDrawer->Color() : Quantity_NOC_WHITE); + drawFrame (thePrs, + anXLeft - 1, theBarBottom - 1, + theColorBreadth + 2, + theBarHeight + 2, + aFgColor); +} + +//======================================================================= +//function : drawLabels +//purpose : +//======================================================================= +void AIS_ColorScale::drawLabels (const Handle(Prs3d_Presentation)& thePrs, + const TColStd_SequenceOfExtendedString& theLabels, + const Standard_Integer theBarBottom, + const Standard_Integer theBarHeight, + const Standard_Integer theMaxLabelWidth, + const Standard_Integer theColorBreadth) +{ + if (myLabelPos == Aspect_TOCSP_NONE + || theLabels.IsEmpty()) + { + return; + } + + const Standard_Integer aNbLabels = theLabels.Size(); + const Standard_Integer aNbIntervals = myIsLabelAtBorder ? aNbLabels - 1 : aNbLabels; + const Standard_Real aStepY = Standard_Real(theBarHeight) / Standard_Real(aNbIntervals); + if (aStepY <= 0.0) + { + return; + } + + Standard_Integer aFilter = 0; + { + const Standard_Integer aTitleHeight = !myTitle.IsEmpty() ? (myTextHeight + 2 * mySpacing) : mySpacing; + const Standard_Integer aSpc = myHeight - aTitleHeight - ((Min (aNbLabels, 2) + Abs (aNbLabels - aNbIntervals - 1)) * myTextHeight); + if (aSpc <= 0) { - Standard_Integer aPos1 = i1; - Standard_Integer aPos2 = aLabCount - 1 - i2; - if (aFilter && !( aPos1 % aFilter )) - { - drawText (thePresentation, aLabels.Value (i1 + 1), aX, (Standard_Integer)( myYPos + i1 * aStep + anAscent + anOffset ), aFgColor); - aLast1 = i1; - } - if (aFilter && !( aPos2 % aFilter )) - { - drawText (thePresentation, aLabels.Value (i2 + 1), aX, (Standard_Integer)( myYPos + i2 * aStep + anAscent + anOffset ), aFgColor); - aLast2 = i2; - } - i1++; - i2--; - } - Standard_Integer aPos = i1; - Standard_Integer i0 = -1; - while (aPos <= i2 && i0 == -1) - { - if (aFilter && !( aPos % aFilter ) && Abs (aPos - aLast1) >= aFilter && Abs (aPos - aLast2) >= aFilter) - i0 = aPos; - aPos++; + return; } - if (i0 != -1) - drawText (thePresentation, aLabels.Value (i0 + 1), aX, (Standard_Integer)( myYPos + i0 * aStep + anAscent + anOffset ), aFgColor); + const Standard_Real aVal = Standard_Real(aNbLabels) * myTextHeight / aSpc; + Standard_Real anIPart = 0.0; + Standard_Real anFPart = std::modf (aVal, &anIPart); + aFilter = (Standard_Integer )anIPart + (anFPart != 0 ? 1 : 0); + } + if (aFilter <= 0) + { + return; + } + + Standard_Integer anXLeft = myXPos + mySpacing; + const Standard_Integer anAscent = 0; + switch (myLabelPos) + { + case Aspect_TOCSP_NONE: + case Aspect_TOCSP_LEFT: + { + break; + } + case Aspect_TOCSP_CENTER: + { + anXLeft += (theColorBreadth - theMaxLabelWidth) / 2; + break; + } + case Aspect_TOCSP_RIGHT: + { + anXLeft += theColorBreadth + mySpacing; + break; + } + } + + Standard_Integer i1 = 0; + Standard_Integer i2 = aNbLabels - 1; + Standard_Integer aLast1 = i1; + Standard_Integer aLast2 = i2; + const Standard_Integer anYBottom = myIsLabelAtBorder + ? theBarBottom + : theBarBottom + Standard_Integer(aStepY / 2); + while (i2 - i1 >= aFilter || ( i2 == 0 && i1 == 0 )) + { + Standard_Integer aPos1 = i1; + Standard_Integer aPos2 = aNbLabels - 1 - i2; + if (aFilter && !(aPos1 % aFilter)) + { + drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i1 + 1), + anXLeft, anYBottom + Standard_Integer(i1 * aStepY + anAscent), + Graphic3d_VTA_CENTER); + aLast1 = i1; + } + if (aFilter && !(aPos2 % aFilter)) + { + drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i2 + 1), + anXLeft, anYBottom + Standard_Integer(i2 * aStepY + anAscent), + Graphic3d_VTA_CENTER); + aLast2 = i2; + } + i1++; + i2--; + } + Standard_Integer aPos = i1; + Standard_Integer i0 = -1; + while (aPos <= i2 && i0 == -1) + { + if (aFilter && !(aPos % aFilter) + && Abs (aPos - aLast1) >= aFilter + && Abs (aPos - aLast2) >= aFilter) + { + i0 = aPos; + } + aPos++; + } + + if (i0 != -1) + { + drawText (Prs3d_Root::CurrentGroup (thePrs), theLabels.Value (i0 + 1), + anXLeft, anYBottom + Standard_Integer(i0 * aStepY + anAscent), + Graphic3d_VTA_CENTER); } } @@ -721,22 +760,21 @@ void AIS_ColorScale::Compute(const Handle(PrsMgr_PresentationManager3d)& /*thePr //function : drawFrame //purpose : //======================================================================= -void AIS_ColorScale::drawFrame (const Handle(Prs3d_Presentation)& thePresentation, - const Standard_Integer theX, const Standard_Integer theY, - const Standard_Integer theWidth, const Standard_Integer theHeight, - const Quantity_Color& theColor) +void AIS_ColorScale::drawFrame (const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theX, const Standard_Integer theY, + const Standard_Integer theWidth, const Standard_Integer theHeight, + const Quantity_Color& theColor) { - Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation); Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5); - aPrim->AddVertex (theX,theY,0.0); - aPrim->AddVertex (theX+theWidth,theY,0.0); - aPrim->AddVertex (theX+theWidth,theY+theHeight,0.0); - aPrim->AddVertex (theX,theY+theHeight,0.0); - aPrim->AddVertex (theX,theY,0.0); - Handle(Prs3d_LineAspect) anAspect = - new Prs3d_LineAspect (theColor, Aspect_TOL_SOLID, 1.0); - anAspect->SetColor (theColor); - aGroup->SetPrimitivesAspect (anAspect->Aspect()); + aPrim->AddVertex (theX, theY, 0.0); + aPrim->AddVertex (theX + theWidth, theY, 0.0); + aPrim->AddVertex (theX + theWidth, theY + theHeight, 0.0); + aPrim->AddVertex (theX, theY + theHeight, 0.0); + aPrim->AddVertex (theX, theY, 0.0); + + Handle(Graphic3d_AspectLine3d) anAspect = new Graphic3d_AspectLine3d (theColor, Aspect_TOL_SOLID, 1.0); + Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs); + aGroup->SetPrimitivesAspect (anAspect); aGroup->AddPrimitiveArray (aPrim); } @@ -744,25 +782,23 @@ void AIS_ColorScale::drawFrame (const Handle(Prs3d_Presentation)& thePresentatio //function : drawText //purpose : //======================================================================= -void AIS_ColorScale::drawText (const Handle(Prs3d_Presentation)& thePresentation, - const TCollection_ExtendedString& theText, - const Standard_Integer theX, const Standard_Integer theY, - const Quantity_Color& theColor) +void AIS_ColorScale::drawText (const Handle(Graphic3d_Group)& theGroup, + const TCollection_ExtendedString& theText, + const Standard_Integer theX, const Standard_Integer theY, + const Graphic3d_VerticalTextAlignment theVertAlignment) { - if (!myDrawer->HasOwnTextAspect()) - { - myDrawer->SetTextAspect (new Prs3d_TextAspect()); - *myDrawer->TextAspect()->Aspect() = *myDrawer->Link()->TextAspect()->Aspect(); - } - Handle(Prs3d_TextAspect) anAspect = myDrawer->TextAspect(); - anAspect->SetColor (theColor); - anAspect->SetHeight (myTextHeight); - anAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT); - anAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM); - anAspect->Aspect()->SetTextZoomable (Standard_True); - anAspect->Aspect()->SetTextAngle (0.0); - anAspect->Aspect()->SetTextFontAspect (Font_FA_Regular); - Prs3d_Text::Draw (Prs3d_Root::CurrentGroup (thePresentation), anAspect, theText, gp_Ax2 (gp_Pnt (theX, theY, 0.0), gp::DZ()), Standard_False); + const Handle(Prs3d_TextAspect)& anAspect = myDrawer->TextAspect(); + theGroup->SetPrimitivesAspect (anAspect->Aspect()); + theGroup->Text (theText, + gp_Ax2 (gp_Pnt (theX, theY, 0.0), gp::DZ()), + anAspect->Height(), + anAspect->Angle(), + anAspect->Orientation(), + Graphic3d_HTA_LEFT, + theVertAlignment, + Standard_True, + Standard_False); // has own anchor + } //======================================================================= @@ -772,7 +808,7 @@ void AIS_ColorScale::drawText (const Handle(Prs3d_Presentation)& thePresentation Standard_Integer AIS_ColorScale::TextWidth (const TCollection_ExtendedString& theText) const { Standard_Integer aWidth, anAscent, aDescent; - TextSize (theText, GetTextHeight(), aWidth, anAscent, aDescent); + TextSize (theText, myTextHeight, aWidth, anAscent, aDescent); return aWidth; } @@ -783,21 +819,34 @@ Standard_Integer AIS_ColorScale::TextWidth (const TCollection_ExtendedString& th Standard_Integer AIS_ColorScale::TextHeight (const TCollection_ExtendedString& theText) const { Standard_Integer aWidth, anAscent, aDescent; - TextSize (theText, GetTextHeight(), aWidth, anAscent, aDescent); - return anAscent+aDescent; + TextSize (theText, myTextHeight, aWidth, anAscent, aDescent); + return anAscent + aDescent; } //======================================================================= //function : TextSize //purpose : //======================================================================= -void AIS_ColorScale::TextSize (const TCollection_ExtendedString& theText, const Standard_Integer theHeight, Standard_Integer& theWidth, Standard_Integer& theAscent, Standard_Integer& theDescent) const +void AIS_ColorScale::TextSize (const TCollection_ExtendedString& theText, + const Standard_Integer theHeight, + Standard_Integer& theWidth, + Standard_Integer& theAscent, + Standard_Integer& theDescent) const { - const Handle(Graphic3d_CView)& aView = GetContext()->CurrentViewer()->ActiveViewIterator().Value()->View(); - Standard_ShortReal aWidth(10.0), anAscent(1.0), aDescent(1.0); - TCollection_AsciiString aText (theText.ToExtString(), '?'); - GetContext()->CurrentViewer()->Driver()->TextSize (aView, aText.ToCString(), (Standard_ShortReal)theHeight, aWidth, anAscent, aDescent); - theWidth = (Standard_Integer)aWidth; - theAscent = (Standard_Integer)anAscent; + if (!HasInteractiveContext()) + { + return; + } + + Standard_ShortReal aWidth = 10.0f; + Standard_ShortReal anAscent = 1.0f; + Standard_ShortReal aDescent = 1.0f; + const TCollection_AsciiString aText (theText); + + const Handle(V3d_Viewer)& aViewer = GetContext()->CurrentViewer(); + const Handle(Graphic3d_CView)& aView = aViewer->ActiveViewIterator().Value()->View(); + aViewer->Driver()->TextSize (aView, aText.ToCString(), (Standard_ShortReal)theHeight, aWidth, anAscent, aDescent); + theWidth = (Standard_Integer)aWidth; + theAscent = (Standard_Integer)anAscent; theDescent = (Standard_Integer)aDescent; } diff --git a/src/AIS/AIS_ColorScale.hxx b/src/AIS/AIS_ColorScale.hxx index ea2a146159..3dc3e4041b 100644 --- a/src/AIS/AIS_ColorScale.hxx +++ b/src/AIS/AIS_ColorScale.hxx @@ -33,8 +33,43 @@ //! Colors and labels can be either defined automatically or set by the user. //! Automatic labels are calculated from numerical limits of the scale, //! its type (logarithmic or plain), and formatted by specified format string. +class AIS_ColorScale : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTIEXT(AIS_ColorScale, AIS_InteractiveObject) +public: -class AIS_ColorScale : public AIS_InteractiveObject { + //! Calculate color according passed value; returns true if value is in range or false, if isn't + Standard_EXPORT static Standard_Boolean FindColor (const Standard_Real theValue, + const Standard_Real theMin, + const Standard_Real theMax, + const Standard_Integer theColorsCount, + const Graphic3d_Vec3d& theColorHlsMin, + const Graphic3d_Vec3d& theColorHlsMax, + Quantity_Color& theColor); + + //! Calculate color according passed value; returns true if value is in range or false, if isn't + static Standard_Boolean FindColor (const Standard_Real theValue, + const Standard_Real theMin, + const Standard_Real theMax, + const Standard_Integer theColorsCount, + Quantity_Color& theColor) + { + return FindColor (theValue, theMin, theMax, theColorsCount, + Graphic3d_Vec3d (230.0, 1.0, 1.0), + Graphic3d_Vec3d (0.0, 1.0, 1.0), + theColor); + } + + //! Shift hue into valid range. + //! Lightness and Saturation should be specified in valid range [0.0, 1.0], + //! however Hue might be given out of Quantity_Color range to specify desired range for interpolation. + static Standard_Real hueToValidRange (const Standard_Real theHue) + { + Standard_Real aHue = theHue; + while (aHue < 0.0) { aHue += 360.0; } + while (aHue > 360.0) { aHue -= 360.0; } + return aHue; + } public: @@ -44,38 +79,111 @@ public: //! Calculate color according passed value; returns true if value is in range or false, if isn't Standard_EXPORT Standard_Boolean FindColor (const Standard_Real theValue, Quantity_Color& theColor) const; - //! Calculate color according passed value; returns true if value is in range or false, if isn't - Standard_EXPORT static Standard_Boolean FindColor (const Standard_Real theValue, const Standard_Real theMin, const Standard_Real theMax, const Standard_Integer theColorsCount, Quantity_Color& theColor); + //! Returns minimal value of color scale, 0.0 by default. + Standard_Real GetMin() const { return myMin; } - //! Returns minimal value of color scale; - Standard_EXPORT Standard_Real GetMin() const { return myMin; } + //! Sets the minimal value of color scale. + void SetMin (const Standard_Real theMin) { SetRange (theMin, GetMax()); } - //! Returns maximal value of color scale; - Standard_EXPORT Standard_Real GetMax() const { return myMax; } + //! Returns maximal value of color scale, 1.0 by default. + Standard_Real GetMax() const { return myMax; } - //! Returns minimal and maximal values of color scale; - Standard_EXPORT void GetRange (Standard_Real& theMin, Standard_Real& theMax) const; + //! Sets the maximal value of color scale. + void SetMax (const Standard_Real theMax) { SetRange (GetMin(), theMax); } - //! Returns the type of labels; + //! Returns minimal and maximal values of color scale, 0.0 to 1.0 by default. + void GetRange (Standard_Real& theMin, Standard_Real& theMax) const + { + theMin = myMin; + theMax = myMax; + } + + //! Sets the minimal and maximal value of color scale. + //! Note that values order will be ignored - the minimum and maximum values will be swapped if needed. + //! ::SetReversed() should be called to swap displaying order. + Standard_EXPORT void SetRange (const Standard_Real theMin, const Standard_Real theMax); + + //! Returns the hue angle corresponding to minimum value, 230 by default (blue). + Standard_Real HueMin() const { return myColorHlsMin[0]; } + + //! Returns the hue angle corresponding to maximum value, 0 by default (red). + Standard_Real HueMax() const { return myColorHlsMax[0]; } + + //! Returns the hue angle range corresponding to minimum and maximum values, 230 to 0 by default (blue to red). + void HueRange (Standard_Real& theMinAngle, + Standard_Real& theMaxAngle) const + { + theMinAngle = myColorHlsMin[0]; + theMaxAngle = myColorHlsMax[0]; + } + + //! Sets hue angle range corresponding to minimum and maximum values. + //! The valid angle range is [0, 360], see Quantity_Color and Quantity_TOC_HLS for more details. + void SetHueRange (const Standard_Real theMinAngle, + const Standard_Real theMaxAngle) + { + myColorHlsMin[0] = theMinAngle; + myColorHlsMax[0] = theMaxAngle; + } + + //! Returns color range corresponding to minimum and maximum values, blue to red by default. + void ColorRange (Quantity_Color& theMinColor, + Quantity_Color& theMaxColor) const + { + theMinColor.SetValues (hueToValidRange (myColorHlsMin[0]), myColorHlsMin[1], myColorHlsMin[2], Quantity_TOC_HLS); + theMaxColor.SetValues (hueToValidRange (myColorHlsMin[0]), myColorHlsMin[1], myColorHlsMin[2], Quantity_TOC_HLS); + } + + //! Sets color range corresponding to minimum and maximum values. + void SetColorRange (const Quantity_Color& theMinColor, + const Quantity_Color& theMaxColor) + { + theMinColor.Values (myColorHlsMin[0], myColorHlsMin[1], myColorHlsMin[2], Quantity_TOC_HLS); + theMaxColor.Values (myColorHlsMax[0], myColorHlsMax[1], myColorHlsMax[2], Quantity_TOC_HLS); + } + + //! Returns the type of labels, Aspect_TOCSD_AUTO by default. //! Aspect_TOCSD_AUTO - labels as boundary values for intervals //! Aspect_TOCSD_USER - user specified label is used - Standard_EXPORT Aspect_TypeOfColorScaleData GetLabelType() const { return myLabelType; } + Aspect_TypeOfColorScaleData GetLabelType() const { return myLabelType; } - //! Returns the type of colors; + //! Sets the type of labels. + //! Aspect_TOCSD_AUTO - labels as boundary values for intervals + //! Aspect_TOCSD_USER - user specified label is used + void SetLabelType (const Aspect_TypeOfColorScaleData theType) { myLabelType = theType; } + + //! Returns the type of colors, Aspect_TOCSD_AUTO by default. //! Aspect_TOCSD_AUTO - value between Red and Blue //! Aspect_TOCSD_USER - user specified color from color map - Standard_EXPORT Aspect_TypeOfColorScaleData GetColorType() const { return myColorType; } + Aspect_TypeOfColorScaleData GetColorType() const { return myColorType; } - //! Returns the number of color scale intervals; - Standard_EXPORT Standard_Integer GetNumberOfIntervals() const { return myInterval; } + //! Sets the type of colors. + //! Aspect_TOCSD_AUTO - value between Red and Blue + //! Aspect_TOCSD_USER - user specified color from color map + void SetColorType (const Aspect_TypeOfColorScaleData theType) { myColorType = theType; } - //! Returns the color scale title string; - Standard_EXPORT TCollection_ExtendedString GetTitle() const { return myTitle; } + //! Returns the number of color scale intervals, 10 by default. + Standard_Integer GetNumberOfIntervals() const { return myNbIntervals; } - //! Returns the format for numbers. + //! Sets the number of color scale intervals. + Standard_EXPORT void SetNumberOfIntervals (const Standard_Integer theNum); + + //! Returns the color scale title string, empty string by default. + const TCollection_ExtendedString& GetTitle() const { return myTitle; } + + //! Sets the color scale title string. + void SetTitle (const TCollection_ExtendedString& theTitle) { myTitle = theTitle; } + + //! Returns the format for numbers, "%.4g" by default. //! The same like format for function printf(). //! Used if GetLabelType() is TOCSD_AUTO; - Standard_EXPORT TCollection_AsciiString GetFormat() const { return myFormat; } + const TCollection_AsciiString& GetFormat() const { return myFormat; } + + //! Returns the format of text. + const TCollection_AsciiString& Format() const { return myFormat; } + + //! Sets the color scale auto label format specification. + void SetFormat (const TCollection_AsciiString& theFormat) { myFormat = theFormat; } //! Returns the user specified label with index theIndex. //! Index is in range from 1 to GetNumberOfIntervals() or to @@ -83,134 +191,154 @@ public: //! Returns empty string if label not defined. Standard_EXPORT TCollection_ExtendedString GetLabel (const Standard_Integer theIndex) const; - //! Returns the user specified color from color map with index (starts at 1). + //! Returns the user specified color from color map with index (starts at 1). //! Returns default color if index is out of range in color map. Standard_EXPORT Quantity_Color GetIntervalColor (const Standard_Integer theIndex) const; + //! Sets the color of the specified interval. + //! Note that list is automatically resized to include specified index. + //! @param theColor color value to set + //! @param theIndex index in range [1, GetNumberOfIntervals()]; + //! appended to the end of list if -1 is specified + Standard_EXPORT void SetIntervalColor (const Quantity_Color& theColor, const Standard_Integer theIndex); + //! Returns the user specified labels. Standard_EXPORT void GetLabels (TColStd_SequenceOfExtendedString& theLabels) const; + //! Returns the user specified labels. + const TColStd_SequenceOfExtendedString& Labels() const { return myLabels; } + + //! Sets the color scale labels. + //! The length of the sequence should be equal to GetNumberOfIntervals() or to GetNumberOfIntervals() + 1 if IsLabelAtBorder() is true. + //! If length of the sequence does not much the number of intervals, + //! then these labels will be considered as "free" and will be located + //! at the virtual intervals corresponding to the number of labels + //! (with flag IsLabelAtBorder() having the same effect as in normal case). + Standard_EXPORT void SetLabels (const TColStd_SequenceOfExtendedString& theSeq); + //! Returns the user specified colors. Standard_EXPORT void GetColors (Aspect_SequenceOfColor& theColors) const; - //! Returns the position of labels concerning color filled rectangles. - Standard_EXPORT Aspect_TypeOfColorScalePosition GetLabelPosition() const { return myLabelPos; } - - //! Returns the position of color scale title. - Standard_EXPORT Aspect_TypeOfColorScalePosition GetTitlePosition() const { return myTitlePos; } - - //! Returns true if the labels and colors used in reversed order. - Standard_EXPORT Standard_Boolean IsReversed() const { return myReversed; } - - //! Returns true if the labels are placed at border of color intervals. - Standard_EXPORT Standard_Boolean IsLabelAtBorder() const { return myAtBorder; } - - //! Returns true if the color scale has logarithmic intervals - Standard_Boolean IsLogarithmic() const { return myIsLogarithmic; } - - //! Sets the minimal value of color scale. - Standard_EXPORT void SetMin (const Standard_Real theMin); - - //! Sets the maximal value of color scale. - Standard_EXPORT void SetMax (const Standard_Real theMax); - - //! Sets the minimal and maximal value of color scale. - Standard_EXPORT void SetRange (const Standard_Real theMin, const Standard_Real theMax); - - //! Sets the type of labels. - //! Aspect_TOCSD_AUTO - labels as boundary values for intervals - //! Aspect_TOCSD_USER - user specified label is used - Standard_EXPORT void SetLabelType (const Aspect_TypeOfColorScaleData theType); - - //! Sets the type of colors. - //! Aspect_TOCSD_AUTO - value between Red and Blue - //! Aspect_TOCSD_USER - user specified color from color map - Standard_EXPORT void SetColorType (const Aspect_TypeOfColorScaleData theType); - - //! Sets the number of color scale intervals. - Standard_EXPORT void SetNumberOfIntervals (const Standard_Integer theNum); - - //! Sets the color scale title string. - Standard_EXPORT void SetTitle (const TCollection_ExtendedString& theTitle); - - //! Sets the color scale auto label format specification. - Standard_EXPORT void SetFormat (const TCollection_AsciiString& theFormat); - - //! Sets the color scale label at index. - //! Index is in range from 1 to GetNumberOfIntervals() or to - //! GetNumberOfIntervals() + 1 if IsLabelAtBorder() is true. - Standard_EXPORT void SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer anIndex); - - //! Sets the color of the specified interval. - //! Index is in range from 1 to GetNumberOfIntervals(). - Standard_EXPORT void SetIntervalColor (const Quantity_Color& theColor, const Standard_Integer theIndex); - - //! Sets the color scale labels. - //! The length of the sequence should be equal to GetNumberOfIntervals() or to - //! GetNumberOfIntervals() + 1 if IsLabelAtBorder() is true. - Standard_EXPORT void SetLabels (const TColStd_SequenceOfExtendedString& theSeq); + //! Returns the user specified colors. + const Aspect_SequenceOfColor& GetColors() const { return myColors; } //! Sets the color scale colors. //! The length of the sequence should be equal to GetNumberOfIntervals(). Standard_EXPORT void SetColors (const Aspect_SequenceOfColor& theSeq); + //! Returns the position of labels concerning color filled rectangles, Aspect_TOCSP_RIGHT by default. + Aspect_TypeOfColorScalePosition GetLabelPosition() const { return myLabelPos; } + //! Sets the color scale labels position relative to color bar. - Standard_EXPORT void SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos); + void SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos) { myLabelPos = thePos; } + + //! Returns the position of color scale title, Aspect_TOCSP_LEFT by default. + Aspect_TypeOfColorScalePosition GetTitlePosition() const { return myTitlePos; } //! Sets the color scale title position. - Standard_EXPORT void SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos); + Standard_DEPRECATED("AIS_ColorScale::SetTitlePosition() has no effect!") + void SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos) { myTitlePos = thePos; } + + //! Returns TRUE if the labels and colors used in reversed order, FALSE by default. + //! - Normal, bottom-up order with Minimal value on the Bottom and Maximum value on Top. + //! - Reversed, top-down order with Maximum value on the Bottom and Minimum value on Top. + Standard_Boolean IsReversed() const { return myIsReversed; } //! Sets true if the labels and colors used in reversed order. - Standard_EXPORT void SetReversed (const Standard_Boolean theReverse); + void SetReversed (const Standard_Boolean theReverse) { myIsReversed = theReverse; } - //! Sets true if the labels are placed at border of color intervals (true by default). + //! Return TRUE if color transition between neighbor intervals + //! should be linearly interpolated, FALSE by default. + Standard_Boolean IsSmoothTransition() const { return myIsSmooth; } + + //! Setup smooth color transition. + void SetSmoothTransition (const Standard_Boolean theIsSmooth) { myIsSmooth = theIsSmooth; } + + //! Returns TRUE if the labels are placed at border of color intervals, TRUE by default. + //! The automatically generated label will show value exactly on the current position: + //! - value connecting two neighbor intervals (TRUE) + //! - value in the middle of interval (FALSE) + Standard_Boolean IsLabelAtBorder() const { return myIsLabelAtBorder; } + + //! Sets true if the labels are placed at border of color intervals (TRUE by default). //! If set to False, labels will be drawn at color intervals rather than at borders. - Standard_EXPORT void SetLabelAtBorder (const Standard_Boolean theOn); + void SetLabelAtBorder (const Standard_Boolean theOn) { myIsLabelAtBorder = theOn; } + + //! Returns TRUE if the color scale has logarithmic intervals, FALSE by default. + Standard_Boolean IsLogarithmic() const { return myIsLogarithmic; } //! Sets true if the color scale has logarithmic intervals. - void SetLogarithmic (const Standard_Boolean isLogarithmic) { myIsLogarithmic = isLogarithmic; }; + void SetLogarithmic (const Standard_Boolean isLogarithmic) { myIsLogarithmic = isLogarithmic; } - //! Returns the size of color bar. - Standard_EXPORT void GetSize (Standard_Integer& theBreadth, Standard_Integer& theHeight) const; + //! Sets the color scale label at index. + //! Note that list is automatically resized to include specified index. + //! @param theLabel new label text + //! @param theIndex index in range [1, GetNumberOfIntervals()] or [1, GetNumberOfIntervals() + 1] if IsLabelAtBorder() is true; + //! label is appended to the end of list if negative index is specified + Standard_EXPORT void SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer theIndex); - //! Returns the breadth of color bar. - Standard_EXPORT Standard_Integer GetBreadth() const { return myBreadth; } - - //! Returns the height of color bar. - Standard_EXPORT Standard_Integer GetHeight() const { return myHeight; } + //! Returns the size of color bar, 0 and 0 by default + //! (e.g. should be set by user explicitly before displaying). + void GetSize (Standard_Integer& theBreadth, Standard_Integer& theHeight) const + { + theBreadth = myBreadth; + theHeight = myHeight; + } //! Sets the size of color bar. - Standard_EXPORT void SetSize (const Standard_Integer theWidth, const Standard_Integer theHeight); + void SetSize (const Standard_Integer theBreadth, const Standard_Integer theHeight) + { + myBreadth = theBreadth; + myHeight = theHeight; + } + + //! Returns the breadth of color bar, 0 by default + //! (e.g. should be set by user explicitly before displaying). + Standard_Integer GetBreadth() const { return myBreadth; } //! Sets the width of color bar. - Standard_EXPORT void SetBreadth (const Standard_Integer theBreadth); + void SetBreadth (const Standard_Integer theBreadth) { myBreadth = theBreadth; } + + //! Returns the height of color bar, 0 by default + //! (e.g. should be set by user explicitly before displaying). + Standard_Integer GetHeight() const { return myHeight; } //! Sets the height of color bar. - Standard_EXPORT void SetHeight (const Standard_Integer theHeight); + void SetHeight (const Standard_Integer theHeight) { myHeight = theHeight; } - //! Returns the position of color scale. - Standard_EXPORT void GetPosition (Standard_Real& theX, Standard_Real& theY) const; - - //! Returns the X position of color scale. - Standard_EXPORT Standard_Integer GetXPosition() const { return myXPos; } - - //! Returns the height of color scale. - Standard_EXPORT Standard_Integer GetYPosition() const { return myYPos; } + //! Returns the bottom-left position of color scale, 0x0 by default. + void GetPosition (Standard_Real& theX, Standard_Real& theY) const + { + theX = myXPos; + theY = myYPos; + } //! Sets the position of color scale. - Standard_EXPORT void SetPosition (const Standard_Integer theX, const Standard_Integer theY); + void SetPosition (const Standard_Integer theX, const Standard_Integer theY) + { + myXPos = theX; + myYPos = theY; + } - //! Sets the X position of color scale. - Standard_EXPORT void SetXPosition (const Standard_Integer theX); + //! Returns the left position of color scale, 0 by default. + Standard_Integer GetXPosition() const { return myXPos; } - //! Sets the Y position of color scale. - Standard_EXPORT void SetYPosition (const Standard_Integer theY); + //! Sets the left position of color scale. + void SetXPosition (const Standard_Integer theX) { myXPos = theX; } - //! Returns the height of text of color scale. - Standard_EXPORT Standard_Integer GetTextHeight() const { return myTextHeight; } + //! Returns the bottom position of color scale, 0 by default. + Standard_Integer GetYPosition() const { return myYPos; } + + //! Sets the bottom position of color scale. + void SetYPosition (const Standard_Integer theY) { myYPos = theY; } + + //! Returns the font height of text labels, 20 by default. + Standard_Integer GetTextHeight() const { return myTextHeight; } //! Sets the height of text of color scale. - Standard_EXPORT void SetTextHeight (const Standard_Integer theHeight) { myTextHeight = theHeight; } + void SetTextHeight (const Standard_Integer theHeight) { myTextHeight = theHeight; } + +public: //! Returns the width of text. //! @param theText [in] the text of which to calculate width. @@ -220,33 +348,25 @@ public: //! @param theText [in] the text of which to calculate height. Standard_EXPORT Standard_Integer TextHeight (const TCollection_ExtendedString& theText) const; - Standard_EXPORT void TextSize (const TCollection_ExtendedString& theText, const Standard_Integer theHeight, Standard_Integer& theWidth, Standard_Integer& theAscent, Standard_Integer& theDescent) const; + Standard_EXPORT void TextSize (const TCollection_ExtendedString& theText, + const Standard_Integer theHeight, + Standard_Integer& theWidth, + Standard_Integer& theAscent, + Standard_Integer& theDescent) const; +public: - DEFINE_STANDARD_RTTIEXT(AIS_ColorScale,AIS_InteractiveObject) + //! Return true if specified display mode is supported. + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } -protected: + //! Compute presentation. + Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode) Standard_OVERRIDE; - //! Draws a frame. - //! @param theX [in] the X coordinate of frame position. - //! @param theY [in] the Y coordinate of frame position. - //! @param theWidth [in] the width of frame. - //! @param theHeight [in] the height of frame. - //! @param theColor [in] the color of frame. - Standard_EXPORT void drawFrame (const Handle(Prs3d_Presentation)& thePresentation, - const Standard_Integer theX, const Standard_Integer theY, - const Standard_Integer theWidth, const Standard_Integer theHeight, - const Quantity_Color& theColor); - - //! Draws a text. - //! @param theText [in] the text to draw. - //! @param theX [in] the X coordinate of text position. - //! @param theY [in] the Y coordinate of text position. - //! @param theColor [in] the color of text. - Standard_EXPORT void drawText (const Handle(Prs3d_Presentation)& thePresentation, - const TCollection_ExtendedString& theText, - const Standard_Integer theX, const Standard_Integer theY, - const Quantity_Color& theColor); + //! Compute selection - not implemented for color scale. + virtual void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/, + const Standard_Integer /*aMode*/) Standard_OVERRIDE {} private: @@ -255,47 +375,86 @@ private: //! @param theHeight [out] the height of color scale. void SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const; - void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, - const Handle(Prs3d_Presentation)& thePresentation, - const Standard_Integer theMode) Standard_OVERRIDE; - - void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/, - const Standard_Integer /*aMode*/) Standard_OVERRIDE - {} - - //! Returns the format of text. - TCollection_AsciiString Format() const; - //! Returns the upper value of given interval, or minimum for theIndex = 0. Standard_Real GetIntervalValue (const Standard_Integer theIndex) const; - //! Returns the color's hue for the given value in the given interval. - //! @param theValue [in] the current value of interval. - //! @param theMin [in] the min value of interval. - //! @param theMax [in] the max value of interval. - static Standard_Integer HueFromValue (const Standard_Integer theValue, const Standard_Integer theMin, const Standard_Integer theMax); + //! Returns the color for the given value in the given interval. + //! @param theValue [in] the current value of interval + //! @param theMin [in] the min value of interval + //! @param theMax [in] the max value of interval + Quantity_Color colorFromValue (const Standard_Real theValue, + const Standard_Real theMin, + const Standard_Real theMax) const; + + //! Initialize text aspect for drawing the labels. + void updateTextAspect(); + + //! Simple alias for Prs3d_Text::Draw(). + //! @param theGroup [in] presentation group + //! @param theText [in] text to draw + //! @param theX [in] X coordinate of text position + //! @param theY [in] Y coordinate of text position + //! @param theVertAlignment [in] text vertical alignment + void drawText (const Handle(Graphic3d_Group)& theGroup, + const TCollection_ExtendedString& theText, + const Standard_Integer theX, const Standard_Integer theY, + const Graphic3d_VerticalTextAlignment theVertAlignment); + + //! Determine the maximum text label width in pixels. + Standard_Integer computeMaxLabelWidth (const TColStd_SequenceOfExtendedString& theLabels) const; + + //! Draw labels. + void drawLabels (const Handle(Prs3d_Presentation)& thePrs, + const TColStd_SequenceOfExtendedString& theLabels, + const Standard_Integer theBarBottom, + const Standard_Integer theBarHeight, + const Standard_Integer theMaxLabelWidth, + const Standard_Integer theColorBreadth); + + //! Draw a color bar. + void drawColorBar (const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theBarBottom, + const Standard_Integer theBarHeight, + const Standard_Integer theMaxLabelWidth, + const Standard_Integer theColorBreadth); + + //! Draw a frame. + //! @param theX [in] the X coordinate of frame position. + //! @param theY [in] the Y coordinate of frame position. + //! @param theWidth [in] the width of frame. + //! @param theHeight [in] the height of frame. + //! @param theColor [in] the color of frame. + void drawFrame (const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theX, const Standard_Integer theY, + const Standard_Integer theWidth, const Standard_Integer theHeight, + const Quantity_Color& theColor); private: - Standard_Real myMin; - Standard_Real myMax; - TCollection_ExtendedString myTitle; - TCollection_AsciiString myFormat; - Standard_Integer myInterval; //! Number of intervals - Aspect_TypeOfColorScaleData myColorType; - Aspect_TypeOfColorScaleData myLabelType; - Standard_Boolean myAtBorder; - Standard_Boolean myReversed; - Standard_Boolean myIsLogarithmic; - Aspect_SequenceOfColor myColors; //! Sequence of custom colors - TColStd_SequenceOfExtendedString myLabels; - Aspect_TypeOfColorScalePosition myLabelPos; - Aspect_TypeOfColorScalePosition myTitlePos; - Standard_Integer myXPos; - Standard_Integer myYPos; - Standard_Integer myBreadth; - Standard_Integer myHeight; - Standard_Integer myTextHeight; - Quantity_Color myBgColor; + Standard_Real myMin; //!< values range - minimal value + Standard_Real myMax; //!< values range - maximal value + Graphic3d_Vec3d myColorHlsMin; //!< HLS color corresponding to minimum value + Graphic3d_Vec3d myColorHlsMax; //!< HLS color corresponding to maximum value + TCollection_ExtendedString myTitle; //!< optional title string + TCollection_AsciiString myFormat; //!< sprintf() format for generating label from value + Standard_Integer myNbIntervals; //!< number of intervals + Aspect_TypeOfColorScaleData myColorType; //!< color type + Aspect_TypeOfColorScaleData myLabelType; //!< label type + Standard_Boolean myIsLabelAtBorder; //!< at border + Standard_Boolean myIsReversed; //!< flag indicating reversed order + Standard_Boolean myIsLogarithmic; //!< flag indicating logarithmic scale + Standard_Boolean myIsSmooth; //!< flag indicating smooth transition between the colors + Aspect_SequenceOfColor myColors; //!< sequence of custom colors + TColStd_SequenceOfExtendedString myLabels; //!< sequence of custom text labels + Aspect_TypeOfColorScalePosition myLabelPos; //!< label position relative to the color scale + Aspect_TypeOfColorScalePosition myTitlePos; //!< title position + Standard_Integer myXPos; //!< left position + Standard_Integer myYPos; //!< bottom position + Standard_Integer myBreadth; //!< color scale breadth + Standard_Integer myHeight; //!< height of the color scale + Standard_Integer mySpacing; //!< extra spacing between element + Standard_Integer myTextHeight; //!< label font height + }; + #endif diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 4f2bd01db8..d4a1ec3f4a 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -3428,38 +3428,6 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg return 0; } -//============================================================================== -//function : VColorScale -//purpose : representation color scale -//============================================================================== - -static Standard_Boolean checkColor (const TCollection_AsciiString& theRed, - const TCollection_AsciiString& theGreen, - const TCollection_AsciiString& theBlue, - Standard_Real& theRedValue, - Standard_Real& theGreenValue, - Standard_Real& theBlueValue) -{ - if (!theRed.IsRealValue() - || !theGreen.IsRealValue() - || !theBlue.IsRealValue()) - { - std::cout << "Error: RGB color values should be real!\n"; - return Standard_True; - } - theRedValue = theRed .RealValue(); - theGreenValue = theGreen.RealValue(); - theBlueValue = theBlue .RealValue(); - if (theRedValue < 0.0 || theRedValue > 1.0 - || theGreenValue < 0.0 || theGreenValue > 1.0 - || theBlueValue < 0.0 || theBlueValue > 1.0) - { - std::cout << "Error: RGB color values should be within range 0..1!\n"; - return Standard_True; - } - return Standard_False; -} - static int VColorScale (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) @@ -3477,57 +3445,35 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - Handle(AIS_ColorScale) aCS; - // find object - Handle(AIS_InteractiveObject) anIObj; + Handle(AIS_ColorScale) aColorScale; if (GetMapOfAIS().IsBound2 (theArgVec[1])) { - aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1])); - if (aCS.IsNull()) + // find existing object + aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1])); + if (aColorScale.IsNull()) { std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n"; return 1; } } - else - { - aCS = new AIS_ColorScale(); - GetMapOfAIS().Bind (aCS,theArgVec[1]); - } - - if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD) - { - aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD); - } - if (aCS->TransformPersistence().IsNull() - || aCS->TransformPersistence()->Mode() != Graphic3d_TMF_2d) - { - aContext->SetTransformPersistence (aCS, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER)); - } - - Standard_Real aMinRange = aCS->GetMin(); - Standard_Real aMaxRange = aCS->GetMax(); - Standard_Integer aBreadth = aCS->GetBreadth(); - Standard_Integer aHeight = aCS->GetHeight(); - Standard_Integer aNbIntervals = aCS->GetNumberOfIntervals(); - Standard_Integer aTextHeight = aCS->GetTextHeight(); - Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition(); - Standard_Integer aPosX = aCS->GetXPosition(); - Standard_Integer aPosY = aCS->GetYPosition(); - - ViewerTest_AutoUpdater anUpdateTool (aContext, aView); if (theArgNb <= 2) { + if (aColorScale.IsNull()) + { + std::cout << "Syntax error: colorscale with a given name does not exist.\n"; + return 1; + } + theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n" - << "Min range: " << aMinRange << "\n" - << "Max range: " << aMaxRange << "\n" - << "Number of intervals: " << aNbIntervals << "\n" - << "Text height: " << aTextHeight << "\n" - << "Color scale position: " << aPosX <<" "<< aPosY<< "\n" - << "Color scale title: " << aCS->GetTitle() << "\n" + << "Min range: " << aColorScale->GetMin() << "\n" + << "Max range: " << aColorScale->GetMax() << "\n" + << "Number of intervals: " << aColorScale->GetNumberOfIntervals() << "\n" + << "Text height: " << aColorScale->GetTextHeight() << "\n" + << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n" + << "Color scale title: " << aColorScale->GetTitle() << "\n" << "Label position: "; - switch (aLabPosition) + switch (aColorScale->GetLabelPosition()) { case Aspect_TOCSP_NONE: theDI << "None\n"; @@ -3545,6 +3491,14 @@ static int VColorScale (Draw_Interpretor& theDI, return 0; } + if (aColorScale.IsNull()) + { + aColorScale = new AIS_ColorScale(); + aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD); + aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER)); + } + + ViewerTest_AutoUpdater anUpdateTool (aContext, aView); for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter) { Standard_CString anArg = theArgVec[anArgIter]; @@ -3562,28 +3516,23 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - TCollection_AsciiString anArg1 (theArgVec[++anArgIter]); - TCollection_AsciiString anArg2 (theArgVec[++anArgIter]); - TCollection_AsciiString anArg3 (theArgVec[++anArgIter]); - if (!anArg1.IsRealValue()) + const TCollection_AsciiString aRangeMin (theArgVec[++anArgIter]); + const TCollection_AsciiString aRangeMax (theArgVec[++anArgIter]); + const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]); + if (!aRangeMin.IsRealValue() + || !aRangeMax.IsRealValue()) { - std::cout << "Error: the minRange value should be real!\n"; + std::cout << "Error: the range values should be real!\n"; return 1; } - else if (!anArg2.IsRealValue()) - { - std::cout << "Error: the maxRange value should be real!\n"; - return 1; - } - else if (!anArg3.IsIntegerValue()) + else if (!aNbIntervals.IsIntegerValue()) { std::cout << "Error: the number of intervals should be integer!\n"; return 1; } - aMinRange = anArg1.RealValue(); - aMaxRange = anArg2.RealValue(); - aNbIntervals = anArg3.IntegerValue(); + aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue()); + aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue()); } else if (aFlag == "-font") { @@ -3599,7 +3548,7 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - aTextHeight = aFontArg.IntegerValue(); + aColorScale->SetTextHeight (aFontArg.IntegerValue()); anArgIter += 1; } else if (aFlag == "-textpos") @@ -3609,8 +3558,10 @@ static int VColorScale (Draw_Interpretor& theDI, std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; return 1; } + TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]); aTextPosArg.LowerCase(); + Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE; if (aTextPosArg == "none") { aLabPosition = Aspect_TOCSP_NONE; @@ -3632,6 +3583,7 @@ static int VColorScale (Draw_Interpretor& theDI, std::cout << "Error: unknown position '" << aTextPosArg << "'!\n"; return 1; } + aColorScale->SetLabelPosition (aLabPosition); } else if (aFlag == "-logarithmic" || aFlag == "-log") @@ -3641,13 +3593,71 @@ static int VColorScale (Draw_Interpretor& theDI, std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; return 1; } + Standard_Boolean IsLog; if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog)) { std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; return 1; } - aCS->SetLogarithmic (IsLog); + aColorScale->SetLogarithmic (IsLog); + } + else if (aFlag == "-huerange" + || aFlag == "-hue") + { + if (anArgIter + 2 >= theArgNb) + { + std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; + return 1; + } + + const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]); + const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]); + aColorScale->SetHueRange (aHueMin, aHueMax); + } + else if (aFlag == "-colorrange") + { + Quantity_Color aColorMin, aColorMax; + Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb - (anArgIter + 1), + theArgVec + (anArgIter + 1), + aColorMin); + anArgIter += aNbParsed1; + Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb - (anArgIter + 1), + theArgVec + (anArgIter + 1), + aColorMax); + anArgIter += aNbParsed2; + if (aNbParsed1 == 0 + || aNbParsed2 == 0) + { + std::cerr << "Error: wrong syntax at '" << anArg << "'\n"; + return 1; + } + + aColorScale->SetColorRange (aColorMin, aColorMax); + } + else if (aFlag == "-reversed" + || aFlag == "-inverted" + || aFlag == "-topdown" + || aFlag == "-bottomup") + { + Standard_Boolean toEnable = Standard_True; + if (anArgIter + 1 < theArgNb + && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable)) + { + ++anArgIter; + } + aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable); + } + else if (aFlag == "-smooth" + || aFlag == "-smoothtransition") + { + Standard_Boolean toEnable = Standard_True; + if (anArgIter + 1 < theArgNb + && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable)) + { + ++anArgIter; + } + aColorScale->SetSmoothTransition (toEnable); } else if (aFlag == "-xy") { @@ -3657,20 +3667,20 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - TCollection_AsciiString aX (theArgVec[++anArgIter]); - TCollection_AsciiString aY (theArgVec[++anArgIter]); - if (!aX.IsIntegerValue() - || !aY.IsIntegerValue()) + const TCollection_AsciiString anX (theArgVec[++anArgIter]); + const TCollection_AsciiString anY (theArgVec[++anArgIter]); + if (!anX.IsIntegerValue() + || !anY.IsIntegerValue()) { std::cout << "Error: coordinates should be integer values!\n"; return 1; } - aPosX = aX.IntegerValue(); - aPosY = aY.IntegerValue(); + aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue()); } else if (aFlag == "-width" - || aFlag == "-w") + || aFlag == "-w" + || aFlag == "-breadth") { if (anArgIter + 1 >= theArgNb) { @@ -3678,14 +3688,13 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - TCollection_AsciiString aW (theArgVec[++anArgIter]); - if (!aW.IsIntegerValue()) + const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]); + if (!aBreadth.IsIntegerValue()) { std::cout << "Error: a width should be an integer value!\n"; return 1; } - - aBreadth = aW.IntegerValue(); + aColorScale->SetBreadth (aBreadth.IntegerValue()); } else if (aFlag == "-height" || aFlag == "-h") @@ -3696,75 +3705,56 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } - TCollection_AsciiString aH (theArgVec[++anArgIter]); - if (!aH.IsIntegerValue()) + const TCollection_AsciiString aHeight (theArgVec[++anArgIter]); + if (!aHeight.IsIntegerValue()) { std::cout << "Error: a width should be an integer value!\n"; return 1; } - - aHeight = aH.IntegerValue(); + aColorScale->SetHeight (aHeight.IntegerValue()); } else if (aFlag == "-color") { - if (aCS->GetColorType() != Aspect_TOCSD_USER) + if (aColorScale->GetColorType() != Aspect_TOCSD_USER) { std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n"; return 1; } - - Quantity_NameOfColor aColorName; - if (anArgIter + 4 >= theArgNb) + else if (anArgIter + 2 >= theArgNb) { - if (anArgIter + 2 >= theArgNb) - { - std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; - return 1; - } - else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName)) - { - std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n"; - return 1; - } + std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n"; + return 1; } - TCollection_AsciiString anInd (theArgVec[anArgIter + 1]); + const TCollection_AsciiString anInd (theArgVec[++anArgIter]); if (!anInd.IsIntegerValue()) { std::cout << "Error: Index value should be integer!\n"; return 1; } - - Standard_Integer anIndex = anInd.IntegerValue(); - if (anIndex <= 0 || anIndex > aNbIntervals) + const Standard_Integer anIndex = anInd.IntegerValue(); + if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals()) { - std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n"; + std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n"; return 1; } - if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName)) - { - aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex); - aCS->SetColorType (Aspect_TOCSD_USER); - anArgIter += 2; - continue; - } - - TCollection_AsciiString aRed (theArgVec[anArgIter + 2]); - TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]); - TCollection_AsciiString aBlue (theArgVec[anArgIter + 4]); - Standard_Real aRedValue,aGreenValue, aBlueValue; - if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue)) + Quantity_Color aColor; + Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb - (anArgIter + 1), + theArgVec + (anArgIter + 1), + aColor); + if (aNbParsed == 0) { + std::cerr << "Error: wrong syntax at '" << anArg << "'\n"; return 1; } - aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex); - aCS->SetColorType (Aspect_TOCSD_USER); - anArgIter += 4; + aColorScale->SetIntervalColor (aColor, anIndex); + aColorScale->SetColorType (Aspect_TOCSD_USER); + anArgIter += aNbParsed; } else if (aFlag == "-label") { - if (aCS->GetColorType() != Aspect_TOCSD_USER) + if (aColorScale->GetColorType() != Aspect_TOCSD_USER) { std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n"; return 1; @@ -3776,90 +3766,115 @@ static int VColorScale (Draw_Interpretor& theDI, } Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]); - if (anIndex <= 0 || anIndex > aNbIntervals+1) + if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1) { - std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n"; + std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n"; return 1; } TCollection_ExtendedString aText (theArgVec[anArgIter + 2]); - aCS->SetLabel (aText, anIndex); - aCS->SetLabelType (Aspect_TOCSD_USER); + aColorScale->SetLabel (aText, anIndex); + aColorScale->SetLabelType (Aspect_TOCSD_USER); anArgIter += 2; } + else if (aFlag == "-labelat" + || aFlag == "-labat" + || aFlag == "-labelatborder" + || aFlag == "-labatborder" + || aFlag == "-labelatcenter" + || aFlag == "-labatcenter") + { + Standard_Boolean toEnable = Standard_True; + if (aFlag == "-labelat" + || aFlag == "-labat") + { + Standard_Integer aLabAtBorder = -1; + if (++anArgIter >= theArgNb) + { + TCollection_AsciiString anAtBorder (theArgVec[anArgIter]); + anAtBorder.LowerCase(); + if (anAtBorder == "border") + { + aLabAtBorder = 1; + } + else if (anAtBorder == "center") + { + aLabAtBorder = 0; + } + } + if (aLabAtBorder == -1) + { + std::cout << "Syntax error at argument '" << anArg << "'!\n"; + return 1; + } + toEnable = (aLabAtBorder == 1); + } + else if (anArgIter + 1 < theArgNb + && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable)) + { + ++anArgIter; + } + aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter" + || aFlag == "-labatcenter" + ? !toEnable + : toEnable); + } else if (aFlag == "-colors") { Aspect_SequenceOfColor aSeq; - if (anArgIter + aNbIntervals + 1 > theArgNb) + for (;;) { - std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the " - << aNbIntervals << " intervals\n"; - return 1; - } - - Standard_Integer aColorIter = anArgIter + 1; - while (aColorIter < theArgNb) - { - if (theArgVec[aColorIter][0] == '-') + Quantity_Color aColor; + Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb - (anArgIter + 1), + theArgVec + (anArgIter + 1), + aColor); + if (aNbParsed == 0) { break; } - - else if (theArgVec[aColorIter][0] >= 97 - && theArgVec[aColorIter][0] <= 122) - { - Quantity_NameOfColor aColorName; - if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName)) - { - std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n"; - return 1; - } - aSeq.Append (Quantity_Color (aColorName)); - aColorIter++; - anArgIter++; - } - else - { - TCollection_AsciiString aRed (theArgVec[aColorIter]); - TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]); - TCollection_AsciiString aBlue (theArgVec[aColorIter + 2]); - Standard_Real aRedValue,aGreenValue, aBlueValue; - if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue)) - { - return 1; - } - aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB)); - aColorIter += 3; - anArgIter += 3; - } + anArgIter += aNbParsed; + aSeq.Append (aColor); } - if (aSeq.Length() < aNbIntervals) + if (aSeq.Length() != aColorScale->GetNumberOfIntervals()) { std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the " - << aNbIntervals << " intervals\n"; + << aColorScale->GetNumberOfIntervals() << " intervals\n"; return 1; } - aCS->SetColors (aSeq); - aCS->SetColorType (Aspect_TOCSD_USER); + aColorScale->SetColors (aSeq); + aColorScale->SetColorType (Aspect_TOCSD_USER); } - else if (aFlag == "-labels") + else if (aFlag == "-labels" + || aFlag == "-freelabels") { - if (anArgIter + aNbIntervals + 1 >= theArgNb) + if (anArgIter + 1 >= theArgNb) { - std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1) - << " text labels for " << aNbIntervals << " intervals.\n"; + std::cout << "Syntax error at argument '" << anArg << "'!\n"; + return 1; + } + + Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder() + ? aColorScale->GetNumberOfIntervals() + 1 + : aColorScale->GetNumberOfIntervals(); + if (aFlag == "-freelabels") + { + ++anArgIter; + aNbLabels = Draw::Atoi (theArgVec[anArgIter]); + } + if (anArgIter + aNbLabels >= theArgNb) + { + std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n"; return 1; } TColStd_SequenceOfExtendedString aSeq; - for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1) + for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter) { - aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter])); + aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter])); } - aCS->SetLabels (aSeq); - aCS->SetLabelType (Aspect_TOCSD_USER); - anArgIter += aSeq.Length(); + aColorScale->SetLabels (aSeq); + aColorScale->SetLabelType (Aspect_TOCSD_USER); } else if (aFlag == "-title") { @@ -3874,29 +3889,31 @@ static int VColorScale (Draw_Interpretor& theDI, { TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]); aSecondArg.LowerCase(); + Standard_DISABLE_DEPRECATION_WARNINGS if (aSecondArg == "none") { - aCS->SetTitlePosition (Aspect_TOCSP_NONE); + aColorScale->SetTitlePosition (Aspect_TOCSP_NONE); isTwoArgs = Standard_True; } else if (aSecondArg == "left") { - aCS->SetTitlePosition (Aspect_TOCSP_LEFT); + aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT); isTwoArgs = Standard_True; } else if (aSecondArg == "right") { - aCS->SetTitlePosition (Aspect_TOCSP_RIGHT); + aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT); isTwoArgs = Standard_True; } else if (aSecondArg == "center") { - aCS->SetTitlePosition (Aspect_TOCSP_CENTER); + aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER); isTwoArgs = Standard_True; } + Standard_ENABLE_DEPRECATION_WARNINGS } - aCS->SetTitle (theArgVec[anArgIter + 1]); + aColorScale->SetTitle (theArgVec[anArgIter + 1]); if (isTwoArgs) { anArgIter += 1; @@ -3906,17 +3923,15 @@ static int VColorScale (Draw_Interpretor& theDI, else if (aFlag == "-demoversion" || aFlag == "-demo") { - aPosX = 0; - aPosY = 0; - aTextHeight = 16; - aMinRange = 0.0; - aMaxRange = 100; - aNbIntervals = 10; - aBreadth = 0; - aHeight = 0; - aLabPosition = Aspect_TOCSP_RIGHT; - aCS->SetColorType (Aspect_TOCSD_AUTO); - aCS->SetLabelType (Aspect_TOCSD_AUTO); + aColorScale->SetPosition (0, 0); + aColorScale->SetTextHeight (16); + aColorScale->SetRange (0.0, 100.0); + aColorScale->SetNumberOfIntervals (10); + aColorScale->SetBreadth (0); + aColorScale->SetHeight (0); + aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT); + aColorScale->SetColorType (Aspect_TOCSD_AUTO); + aColorScale->SetLabelType (Aspect_TOCSD_AUTO); } else if (aFlag == "-findcolor") { @@ -3935,7 +3950,7 @@ static int VColorScale (Draw_Interpretor& theDI, } Quantity_Color aColor; - aCS->FindColor (anArg1.RealValue(), aColor); + aColorScale->FindColor (anArg1.RealValue(), aColor); theDI << Quantity_Color::StringName (aColor.Name()); return 0; } @@ -3945,29 +3960,19 @@ static int VColorScale (Draw_Interpretor& theDI, return 1; } } - if (!aBreadth || !aHeight) - { - Standard_Integer aWinWidth, aWinHeight; - aView->Window()->Size (aWinWidth, aWinHeight); - if (!aBreadth) - { - aBreadth = aWinWidth; - } - if (!aHeight) - { - aHeight = aWinHeight; - } - } - aCS->SetSize (aBreadth, aHeight); - aCS->SetPosition (aPosX, aPosY); - aCS->SetTextHeight (aTextHeight); - aCS->SetRange (aMinRange, aMaxRange); - aCS->SetNumberOfIntervals (aNbIntervals); - aCS->SetLabelPosition (aLabPosition); -// aCS->SetColor (aView->BackgroundColor().Invert()); - aCS->SetToUpdate(); - aContext->Display (aCS); + Standard_Integer aWinWidth = 0, aWinHeight = 0; + aView->Window()->Size (aWinWidth, aWinHeight); + if (aColorScale->GetBreadth() == 0) + { + aColorScale->SetBreadth (aWinWidth); + } + if (aColorScale->GetHeight() == 0) + { + aColorScale->SetHeight (aWinHeight); + } + aColorScale->SetToUpdate(); + ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True); return 0; } @@ -10341,22 +10346,35 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) " : notice that EMF format requires patched gl2ps", __FILE__,VExport,group); theCommands.Add("vcolorscale", - "vcolorscale : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16 -textpos " - "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n" - "-demo/-demoversion draw a demoversion of color scale.\n" - "-show/display display color scale.\n" - "-hide/erase erase color scale.\n" - "Please note that -show/-hide option must be the first argument!\n" - "-color Index R G B: set color for indexed interval\n" - "-color Index ColorName: set color for indexed interval\n" - "-colors R G B R G B ...: set colors for all intervals\n" - "-colors ColorName1 ColorName2 ...: set colors for all intervals\n" - "-colors supports both color names and rgb values in one call\n" - "-label Index Text: set label for indexed interval\n" - "-labels Text Text Text ...: set labels for all intervals\n" - "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n" - "Available text positions: left, right, center, none;\n", - __FILE__,VColorScale,group); + "vcolorscale name [-noupdate|-update] [-demo]" + "\n\t\t: [-range RangeMin=0 RangeMax=1 NbIntervals=10]" + "\n\t\t: [-font HeightFont=20]" + "\n\t\t: [-logarithmic {on|off}=off] [-reversed {on|off}=off]" + "\n\t\t: [-smoothTransition {on|off}=off]" + "\n\t\t: [-hueRange MinAngle=230 MaxAngle=0]" + "\n\t\t: [-colorRange MinColor=BLUE1 MaxColor=RED]" + "\n\t\t: [-textpos {left|right|center|none}=right]" + "\n\t\t: [-labelAtBorder {on|off}=on]" + "\n\t\t: [-colors Color1 Color2 ...] [-color Index Color]" + "\n\t\t: [-labels Label1 Label2 ...] [-label Index Label]" + "\n\t\t: [-freeLabels NbOfLabels Label1 Label2 ...]" + "\n\t\t: [-xy Left=0 Bottom=0]" + "\n\t\t: -demo - displays a color scale with demonstratio values" + "\n\t\t: -colors - set colors for all intervals" + "\n\t\t: -color - set color for specific interval" + "\n\t\t: -textpos - horizontal label position relative to color scale bar" + "\n\t\t: -labelAtBorder - vertical label position relative to color interval;" + "\n\t\t: at border means the value inbetween neighbor intervals," + "\n\t\t: at center means the center value within current interval" + "\n\t\t: -labels - set labels for all intervals" + "\n\t\t: -freeLabels - same as -labels but does not require" + "\n\t\t: matching the number of intervals" + "\n\t\t: -label - set label for specific interval" + "\n\t\t: -title - set title" + "\n\t\t: -reversed - setup smooth color transition between intervals" + "\n\t\t: -smoothTransition - swap colorscale direction" + "\n\t\t: -hueRange - set hue angles corresponding to minimum and maximum values" + __FILE__, VColorScale, group); theCommands.Add("vgraduatedtrihedron", "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n" "\t[-namefont Name] [-valuesfont Name]\n" diff --git a/tests/bugs/vis/bug25136 b/tests/bugs/vis/bug25136 index c9a0930239..f63a497a13 100644 --- a/tests/bugs/vis/bug25136 +++ b/tests/bugs/vis/bug25136 @@ -4,29 +4,27 @@ puts "Display customized colorscale." puts "============" puts "" -vinit View1 vclear +vinit View1 vaxo # create default color scale -vcolorscale cs -demo -vdump ${imagedir}/${casename}_1.png +vcolorscale cs1 -demo -xy 0 0 +foreach {y aColor} {20 RED 60 DARKORANGE1 100 GOLD 140 GREENYELLOW 180 CHARTREUSE2 220 GREEN 250 MEDIUMSPRINGGREEN 290 CYAN1 330 DODGERBLUE1 370 BLUE1} { if { [vreadpixel 15 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } # reduce color scale range and number of intervals -vcolorscale cs -range 0 20 5 -vdump ${imagedir}/${casename}_2.png +vcolorscale cs2 -range 0 20 5 -xy 60 0 +foreach {y aColor} {40 RED 120 YELLOW 200 GREEN 280 CYAN2 350 BLUE1} { if { [vreadpixel 75 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } # set user-defined colors and labels for color scale -vcolorscale cs -colors white 0 0 1 green 1 0 0 1 1 1 -labels start 1 2 3 4 end -vdump ${imagedir}/${casename}_3.png +vcolorscale cs3 -range 0 20 5 -colors white 0 0 1 green 1 0 0 1 1 1 -labels start 1 2 3 4 end -xy 120 0 +foreach {y aColor} {40 WHITE 120 RED 200 GREEN 280 BLUE1 350 WHITE} { if { [vreadpixel 135 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } # change colors of first and last intervals -vcolorscale cs -color 1 0.42 0.35 0.8 -vcolorscale cs -color 5 pink - -# change last label -vcolorscale cs -label 6 "last" - -# set a title for color scale -vcolorscale cs -title "My color scale" -vdump ${imagedir}/${casename}_4.png +vcolorscale cs4 -range 0 20 5 -colors white 0 0 1 green 1 0 0 1 1 1 -labels start 1 2 3 4 end -xy 200 0 +vcolorscale cs4 -color 1 0.42 0.35 0.8 +vcolorscale cs4 -color 5 pink +vcolorscale cs4 -label 6 "last" +vcolorscale cs4 -title "My color scale" +foreach {y aColor} {60 PINK 120 RED 200 GREEN 280 BLUE1 350 SLATEBLUE} { if { [vreadpixel 215 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } +vdump ${imagedir}/${casename}.png diff --git a/tests/bugs/vis/bug28004 b/tests/bugs/vis/bug28004 new file mode 100644 index 0000000000..7ab866dd12 --- /dev/null +++ b/tests/bugs/vis/bug28004 @@ -0,0 +1,31 @@ +puts "============" +puts "OCC28004" +puts "Visualization, AIS_ColorScale - allow defining labels list not equal to intervals list" +puts "============" +puts "" + +vclear +vinit View1 +vaxo + +# create default color scale +vcolorscale cs1 -demo -smooth 0 -xy 0 0 +vcolorscale cs2 -demo -smooth 1 -xy 60 0 +foreach {y aColor} {20 RED 60 DARKORANGE1 100 GOLD 140 GREENYELLOW 180 CHARTREUSE2 220 GREEN 250 MEDIUMSPRINGGREEN 290 CYAN1 330 DODGERBLUE1 370 BLUE1} { if { [vreadpixel 15 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } +foreach {y aColor} {20 RED 60 DARKORANGE1 100 GOLD 140 GREENYELLOW 180 CHARTREUSE2 220 GREEN 250 MEDIUMSPRINGGREEN 290 CYAN1 330 DODGERBLUE1 370 BLUE1} { if { [vreadpixel 15 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } + +# reduce color scale range and number of intervals +vcolorscale cs3 -range 0 20 5 -font 16 -colors white 0 0 1 green 1 0 0 1 1 1 -labels start 1 2 3 4 end -smooth 0 -xy 120 0 +vcolorscale cs4 -range 0 20 5 -font 16 -colors white 0 0 1 green 1 0 0 1 1 1 -labels start 1 2 3 4 end -smooth 1 -xy 180 0 +foreach {y aColor} {40 WHITE 120 RED 200 GREEN 280 BLUE1 350 WHITE} { if { [vreadpixel 135 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } + +# color scale with overridden hue range +vcolorscale cs5 -demo -smooth 0 -hueRange 300 130 -xy 240 0 +vcolorscale cs6 -demo -smooth 1 -hueRange 300 130 -xy 300 0 +foreach {y aColor} {20 GREEN 60 SPRINGGREEN 100 CYAN2 140 TURQUOISE2 180 DODGERBLUE1 220 BLUE1 250 BLUE1 290 BLUEVIOLET 330 PURPLE 370 MAGENTA1} { if { [vreadpixel 245 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } +foreach {y aColor} {20 GREEN 60 SPRINGGREEN 100 CYAN2 140 TURQUOISE2 180 DODGERBLUE1 220 DODGERBLUE2 250 BLUE1 290 BLUE1 330 PURPLE 370 MAGENTA2} { if { [vreadpixel 315 $y rgb name] != "$aColor" } { puts "Error: wrong color at $y" } } + +# free labels +vcolorscale cs7 -demo -smooth 0 -colorRange BLACK WHITE -xy 360 0 -freeLabels 3 l1 l2 l3 + +vdump ${imagedir}/${casename}.png