16 #include "vtkColorTransferFunction.h"
17 #include "vtkContext2D.h"
18 #include "vtkContextActor.h"
19 #include "vtkContextDevice2D.h"
20 #include "vtkContextItem.h"
21 #include "vtkContextScene.h"
22 #include "vtkDiscretizableColorTransferFunction.h"
23 #include "vtkDoubleArray.h"
24 #include "vtkFloatArray.h"
25 #include "vtkImageData.h"
26 #include "vtkLookupTable.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkOpenGLContextDevice2D.h"
31 #include "vtkOpenGLRenderWindow.h"
33 #include "vtkPointData.h"
34 #include "vtkPoints2D.h"
35 #include "vtkRenderWindow.h"
36 #include "vtkRenderer.h"
37 #include "vtkScalarsToColors.h"
38 #include "vtkTextProperty.h"
39 #include "vtkTransform2D.h"
40 #include "vtkUnsignedCharArray.h"
41 #include "vtkViewport.h"
43 #if defined(_WIN32) && !defined(__CYGWIN__)
44 #define SNPRINTF _snprintf
46 #define SNPRINTF snprintf
87 bool Paint(vtkContext2D* painter)
override {
88 bool somethingRendered =
false;
90 somethingRendered = this->
Actor->
Paint(painter);
93 return somethingRendered && this->Superclass::Paint(painter);
107 :
public std::map<double, std::string> {};
114 this->ActorDelegate = vtkContextActor::New();
116 this->TitleJustification = VTK_TEXT_LEFT;
117 this->ForceHorizontalTitle =
false;
119 this->ScalarBarThickness = 16;
120 this->ScalarBarLength = 0.33;
122 this->AutomaticLabelFormat = 1;
124 this->AddRangeLabels = 1;
125 this->AutomaticAnnotations = 0;
126 this->AddRangeAnnotations = 0;
127 this->RangeLabelFormat =
NULL;
128 this->SetRangeLabelFormat(
"%g");
130 this->OutlineScalarBar = 0;
133 this->NumberOfTicks = -1;
135 this->DrawTickMarks =
true;
137 this->UseCustomLabels =
false;
140 this->ReverseLegend =
false;
143 this->ScalarBarItem->
Actor =
this;
145 vtkContextScene* localScene = vtkContextScene::New();
146 this->ActorDelegate->SetScene(localScene);
147 localScene->AddItem(this->ScalarBarItem);
148 localScene->Delete();
150 this->CurrentViewport =
NULL;
152 this->Axis = vtkAxis::New();
153 this->Axis->SetScene(localScene);
158 this->SetLookupTable(
NULL);
159 this->ActorDelegate->Delete();
160 this->SetTitle(
NULL);
161 this->SetComponentTitle(
NULL);
162 this->ScalarBarItem->Delete();
163 this->SetTitleTextProperty(
NULL);
164 this->SetLabelTextProperty(
NULL);
165 this->Axis->Delete();
166 this->SetRangeLabelFormat(
nullptr);
171 if (useLabels != this->UseCustomLabels) {
172 this->UseCustomLabels = useLabels;
179 this->CustomLabels->SetNumberOfTuples(numLabels);
184 return this->CustomLabels->GetNumberOfTuples();
189 if (index < 0 || index >= this->CustomLabels->GetNumberOfTuples()) {
190 vtkErrorMacro(<<
"Index out of range");
194 this->CustomLabels->SetTypedTuple(index, &value);
199 this->CurrentViewport = viewport;
202 if (this->ActorDelegate) {
203 returnValue = this->ActorDelegate->RenderOverlay(viewport);
211 this->CurrentViewport = viewport;
218 if (!this->ActorDelegate || !this->ActorDelegate->GetScene() ||
219 !this->ActorDelegate->GetScene()->GetLastPainter()) {
223 vtkContextDevice2D* device =
224 this->ActorDelegate->GetScene()->GetLastPainter()->GetDevice();
228 vtkOpenGLContextDevice2D* oglDevice =
229 vtkOpenGLContextDevice2D::SafeDownCast(device);
231 oglDevice->ReleaseGraphicsResources(window);
236 void vtkContext2DScalarBarActor::UpdateScalarBarTexture(vtkImageData*
image) {
237 if (this->Orientation == VTK_ORIENT_VERTICAL) {
238 image->SetDimensions(1, 256, 1);
240 image->SetDimensions(256, 1, 1);
242 image->AllocateScalars(VTK_UNSIGNED_CHAR, 4);
244 vtkUnsignedCharArray*
colors = vtkUnsignedCharArray::SafeDownCast(
245 image->GetPointData()->GetArray(0));
247 vtkDiscretizableColorTransferFunction* ctf =
248 vtkDiscretizableColorTransferFunction::SafeDownCast(
254 double* lutRange = ctf->GetRange();
255 const int numColors = 256;
256 unsigned char color[4];
257 for (
int i = 0; i < numColors; ++i) {
260 double originalValue =
261 (((double)i / numColors) * (lutRange[1] - lutRange[0])) +
263 double value = originalValue;
264 if (this->LookupTable->UsingLogScale()) {
265 value = log10(lutRange[0]) +
266 i * (log10(lutRange[1]) - log10(lutRange[0])) / numColors;
267 value = pow(10.0, value);
270 const unsigned char* colorTmp = ctf->MapValue(value);
274 color[0] = colorTmp[0];
275 color[1] = colorTmp[1];
276 color[2] = colorTmp[2];
277 color[3] =
static_cast<unsigned char>(
278 255.0 * ctf->GetOpacity(originalValue) + 0.5);
279 if (this->ReverseLegend) {
288 void vtkContext2DScalarBarActor::GetSize(
double size[2],
289 vtkContext2D* painter) {
290 if (!this->CurrentViewport) {
295 vtkNew<vtkCoordinate> lengthCoord;
296 lengthCoord->SetCoordinateSystemToNormalizedViewport();
297 lengthCoord->SetValue(
298 this->Orientation == VTK_ORIENT_VERTICAL ? 0.0
299 : this->ScalarBarLength,
300 this->Orientation == VTK_ORIENT_VERTICAL ? this->ScalarBarLength
303 lengthCoord->GetComputedDisplayValue(this->CurrentViewport);
308 vtkNew<vtkTextProperty> textProp;
309 textProp->SetFontSize(this->ScalarBarThickness);
310 painter->ApplyTextProp(textProp.Get());
313 painter->ComputeStringBounds(
"|", bounds);
314 double thickness = bounds[3];
316 if (this->Orientation == VTK_ORIENT_VERTICAL) {
318 size[1] = lengthOffset[1];
320 size[0] = lengthOffset[0];
326 vtkRectf vtkContext2DScalarBarActor::GetColorBarRect(
double size[2]) {
327 vtkRectf rect = vtkRectf(0, 0,
size[0],
size[1]);
333 this->Orientation == VTK_ORIENT_VERTICAL ?
size[0] :
size[1];
337 double sizeReduction = 0;
338 if (this->DrawNanAnnotation) {
339 if (this->Orientation == VTK_ORIENT_VERTICAL) {
340 shift += swatchSize + this->Spacer;
342 sizeReduction += swatchSize + this->Spacer;
345 vtkDiscretizableColorTransferFunction* ctf =
346 vtkDiscretizableColorTransferFunction::SafeDownCast(
348 if (ctf && ctf->GetUseAboveRangeColor()) {
349 sizeReduction += swatchSize;
352 if (ctf && ctf->GetUseBelowRangeColor()) {
354 sizeReduction += swatchSize;
357 if (this->Orientation == VTK_ORIENT_VERTICAL) {
358 rect.SetY(rect.GetY() + shift);
359 rect.SetHeight(rect.GetHeight() - sizeReduction);
361 rect.SetX(rect.GetX() + shift);
362 rect.SetWidth(rect.GetWidth() - sizeReduction);
369 vtkRectf vtkContext2DScalarBarActor::GetFullColorBarRect(
double size[2]) {
371 vtkRectf fullRect = this->GetColorBarRect(
size);
374 vtkRectf aboveRect = this->GetAboveRangeColorRect(
size);
375 if (aboveRect.GetWidth() > 0 && aboveRect.GetHeight() > 0) {
376 fullRect.AddRect(aboveRect);
379 vtkRectf belowRect = this->GetBelowRangeColorRect(
size);
380 if (belowRect.GetWidth() > 0 && belowRect.GetHeight() > 0) {
381 fullRect.AddRect(belowRect);
388 vtkRectf vtkContext2DScalarBarActor::GetAboveRangeColorRect(
double size[2]) {
389 vtkRectf rect(0, 0, 0, 0);
391 vtkDiscretizableColorTransferFunction* ctf =
392 vtkDiscretizableColorTransferFunction::SafeDownCast(
395 if (this->LookupTable) {
396 vtkErrorMacro(<<
"Lookup table should be a "
397 "vtkDiscretizableColorTransferFunction but was a "
398 << this->LookupTable->GetClassName());
400 vtkErrorMacro(<<
"Lookup table was NULL");
405 if (ctf->GetUseAboveRangeColor()) {
406 rect = this->GetOutOfRangeColorRectInternal(
413 vtkRectf vtkContext2DScalarBarActor::GetBelowRangeColorRect(
double size[2]) {
414 vtkRectf rect(0, 0, 0, 0);
416 vtkDiscretizableColorTransferFunction* ctf =
417 vtkDiscretizableColorTransferFunction::SafeDownCast(
420 if (this->LookupTable) {
421 vtkErrorMacro(<<
"Lookup table should be a "
422 "vtkDiscretizableColorTransferFunction but was a "
423 << this->LookupTable->GetClassName());
425 vtkErrorMacro(<<
"Lookup table was NULL");
430 if (ctf->GetUseBelowRangeColor()) {
431 rect = this->GetOutOfRangeColorRectInternal(
438 vtkRectf vtkContext2DScalarBarActor::GetOutOfRangeColorRectInternal(
440 vtkRectf rect(0, 0, 0, 0);
442 !this->ReverseLegend;
443 if (graphicallyAbove) {
444 if (this->Orientation == VTK_ORIENT_VERTICAL) {
449 double nanSpace = this->GetNaNColorRect(
size).GetWidth();
451 nanSpace += this->Spacer;
459 if (this->Orientation == VTK_ORIENT_VERTICAL) {
460 double nanSpace = this->GetNaNColorRect(
size).GetHeight();
462 nanSpace += this->Spacer;
476 vtkRectf vtkContext2DScalarBarActor::GetNaNColorRect(
double size[2]) {
478 vtkRectf rect(0, 0, 0, 0);
480 if (this->DrawNanAnnotation) {
481 if (this->Orientation == VTK_ORIENT_VERTICAL) {
495 void vtkContext2DScalarBarActor::UpdateTextProperties() {
498 vtkTextProperty* axisLabelProperty = this->Axis->GetLabelProperties();
499 axisLabelProperty->SetColor(this->LabelTextProperty->GetColor());
500 axisLabelProperty->SetOpacity(this->LabelTextProperty->GetOpacity());
501 axisLabelProperty->SetBackgroundColor(
502 this->LabelTextProperty->GetBackgroundColor());
503 axisLabelProperty->SetBackgroundOpacity(
504 this->LabelTextProperty->GetBackgroundOpacity());
505 axisLabelProperty->SetFontFamilyAsString(
506 this->LabelTextProperty->GetFontFamilyAsString());
507 axisLabelProperty->SetFontFile(this->LabelTextProperty->GetFontFile());
508 axisLabelProperty->SetFontSize(this->LabelTextProperty->GetFontSize());
510 axisLabelProperty->SetBold(this->LabelTextProperty->GetBold());
511 axisLabelProperty->SetItalic(this->LabelTextProperty->GetItalic());
512 axisLabelProperty->SetShadow(this->LabelTextProperty->GetShadow());
513 axisLabelProperty->SetShadowOffset(
514 this->LabelTextProperty->GetShadowOffset());
516 vtkTextProperty* axisTitleProperty = this->Axis->GetTitleProperties();
517 axisTitleProperty->SetColor(this->TitleTextProperty->GetColor());
518 axisTitleProperty->SetOpacity(this->TitleTextProperty->GetOpacity());
519 axisTitleProperty->SetBackgroundColor(
520 this->TitleTextProperty->GetBackgroundColor());
521 axisTitleProperty->SetBackgroundOpacity(
522 this->TitleTextProperty->GetBackgroundOpacity());
523 axisTitleProperty->SetFontFamilyAsString(
524 this->TitleTextProperty->GetFontFamilyAsString());
525 axisTitleProperty->SetFontFile(this->TitleTextProperty->GetFontFile());
526 axisTitleProperty->SetFontSize(this->TitleTextProperty->GetFontSize());
528 axisTitleProperty->SetBold(this->TitleTextProperty->GetBold());
529 axisTitleProperty->SetItalic(this->TitleTextProperty->GetItalic());
530 axisTitleProperty->SetShadow(this->TitleTextProperty->GetShadow());
531 axisTitleProperty->SetShadowOffset(
532 this->TitleTextProperty->GetShadowOffset());
536 void vtkContext2DScalarBarActor::PaintColorBar(vtkContext2D* painter,
538 vtkRectf barRect = this->GetColorBarRect(
size);
540 vtkBrush* brush = painter->GetBrush();
544 vtkDiscretizableColorTransferFunction* ctf =
545 vtkDiscretizableColorTransferFunction::SafeDownCast(
552 vtkPen* pen = painter->GetPen();
553 pen->SetLineType(vtkPen::NO_PEN);
558 vtkAnnotationMap annotationAnchors;
560 if (ctf->GetIndexedLookup()) {
562 int numIndexedColors = ctf->GetNumberOfAnnotatedValues();
563 double indexedColorSwatchLength =
564 this->Orientation == VTK_ORIENT_VERTICAL ? barRect.GetHeight()
565 : barRect.GetWidth();
568 if (numIndexedColors > 0) {
569 indexedColorSwatchLength -= (numIndexedColors - 1) * this->Spacer;
570 indexedColorSwatchLength /= numIndexedColors;
575 for (
int i = 0; i < numIndexedColors; ++i) {
576 double shift = i * (indexedColorSwatchLength + this->Spacer);
577 double indexedColor[4];
578 vtkVariant annotatedValue = ctf->GetAnnotatedValue(i);
579 ctf->GetIndexedColor(i, indexedColor);
580 std::string annotation = ctf->GetAnnotation(i);
581 brush->SetColorF(indexedColor);
582 if (this->Orientation == VTK_ORIENT_VERTICAL) {
584 if (this->ReverseLegend) {
585 y = barRect.GetY() + shift;
587 y = barRect.GetY() + barRect.GetHeight() - shift -
588 indexedColorSwatchLength;
590 painter->DrawRect(
x,
y, barRect.GetWidth(),
591 indexedColorSwatchLength);
592 annotationAnchors[
y + 0.5 * indexedColorSwatchLength] =
596 if (this->ReverseLegend) {
597 x = barRect.GetX() + barRect.GetWidth() - shift -
598 indexedColorSwatchLength;
600 x = barRect.GetX() + shift;
603 painter->DrawRect(
x,
y, indexedColorSwatchLength,
604 barRect.GetHeight());
605 annotationAnchors[
x + 0.5 * indexedColorSwatchLength] =
612 vtkNew<vtkImageData>
image;
613 this->UpdateScalarBarTexture(
image.GetPointer());
615 painter->DrawImage(barRect,
image.GetPointer());
619 if (ctf->GetUseAboveRangeColor()) {
620 vtkRectf rect = this->GetAboveRangeColorRect(
size);
621 brush->SetColorF(ctf->GetAboveRangeColor());
622 pen->SetLineType(vtkPen::NO_PEN);
623 painter->DrawRect(rect.GetX(), rect.GetY(), rect.GetWidth(),
627 if (ctf->GetUseBelowRangeColor()) {
628 vtkRectf rect = this->GetBelowRangeColorRect(
size);
629 brush->SetColorF(ctf->GetBelowRangeColor());
630 pen->SetLineType(vtkPen::NO_PEN);
631 painter->DrawRect(rect.GetX(), rect.GetY(), rect.GetWidth(),
638 if (this->OutlineScalarBar) {
639 vtkRectf outlineRect = this->GetFullColorBarRect(
size);
641 brush->SetOpacity(0);
642 pen->SetLineType(vtkPen::SOLID_LINE);
643 painter->DrawRect(outlineRect.GetX(), outlineRect.GetY(),
644 outlineRect.GetWidth(), outlineRect.GetHeight());
649 lutRange[0] = this->LookupTable->GetRange()[0];
650 lutRange[1] = this->LookupTable->GetRange()[1];
651 if (this->LookupTable->UsingLogScale()) {
652 lutRange[0] = log10(lutRange[0]);
653 lutRange[1] = log10(lutRange[1]);
656 double low = barRect.GetX();
657 double high = low + barRect.GetWidth();
658 if (this->Orientation == VTK_ORIENT_VERTICAL) {
659 low = barRect.GetY();
660 high = low + barRect.GetHeight();
662 if (this->ReverseLegend) {
666 if (this->GetAutomaticAnnotations()) {
668 vtkIdType numValues = ctf->GetNumberOfAvailableColors();
669 if (ctf && ctf->GetDiscretize() && this->AutomaticAnnotations &&
671 double step = (lutRange[1] - lutRange[0]) / numValues;
672 for (vtkIdType i = 0; i <= numValues; i++) {
673 double annotatedValue = lutRange[0] + step * i;
675 double normalizedValue = (annotatedValue - lutRange[0]) /
676 (lutRange[1] - lutRange[0]);
678 double barPosition = normalizedValue * (high - low) + low;
679 if (normalizedValue >=
680 0.0 - std::numeric_limits<double>::epsilon() &&
682 1.0 + std::numeric_limits<double>::epsilon() &&
683 !vtkMath::IsNan(barPosition)) {
684 char annotation[1024];
685 if (this->LookupTable->UsingLogScale()) {
686 annotatedValue = pow(10.0, annotatedValue);
688 SNPRINTF(annotation, 1023, this->LabelFormat,
690 annotationAnchors[barPosition] = annotation;
696 int numAnnotations = ctf->GetNumberOfAnnotatedValues();
697 for (
int i = 0; i < numAnnotations; ++i) {
699 double annotatedValue = ctf->GetAnnotatedValue(i).ToDouble();
700 if (this->LookupTable->UsingLogScale()) {
702 annotatedValue = log10(annotatedValue);
705 double normalizedValue = (annotatedValue - lutRange[0]) /
706 (lutRange[1] - lutRange[0]);
708 double barPosition = normalizedValue * (high - low) + low;
709 if (normalizedValue >= 0.0 && normalizedValue <= 1.0 &&
710 !vtkMath::IsNan(barPosition)) {
711 std::string annotation = ctf->GetAnnotation(i);
712 annotationAnchors[barPosition] = annotation;
717 if (this->AddRangeAnnotations) {
718 char annotation[1024];
720 SNPRINTF(annotation, 1023, this->RangeLabelFormat, lutRange[0]);
721 annotationAnchors[low] = annotation;
723 SNPRINTF(annotation, 1023, this->RangeLabelFormat, lutRange[1]);
724 annotationAnchors[high] = annotation;
730 if (this->DrawNanAnnotation) {
732 vtkRectf rect = this->GetNaNColorRect(
size);
733 brush->SetOpacity(255);
734 brush->SetColorF(ctf->GetNanColor());
735 pen->SetLineType(vtkPen::NO_PEN);
736 painter->DrawRect(rect.GetX(), rect.GetY(), rect.GetWidth(),
740 double nanAnchor = rect.GetY() + 0.5 * rect.GetHeight();
741 if (this->Orientation == VTK_ORIENT_HORIZONTAL) {
742 nanAnchor = rect.GetX() + 0.5 * rect.GetWidth();
744 annotationAnchors[nanAnchor] = this->GetNanAnnotation();
748 if (this->GetDrawAnnotations()) {
749 this->PaintAnnotations(painter,
size, annotationAnchors);
754 void vtkContext2DScalarBarActor::PaintAxis(vtkContext2D* painter,
756 vtkRectf rect = this->GetColorBarRect(
size);
761 painter->ApplyTextProp(this->LabelTextProperty);
762 painter->ComputeStringBounds(
"|", bounds);
763 float pipeHeight = bounds[3];
769 vtkWindow* renWin = this->CurrentViewport->GetVTKWindow();
771 renWin->GetTileScale(tileScale);
772 pipeHeight /= tileScale[1];
775 float axisShift = 0.25 * pipeHeight;
778 float tickLength = 0.75 * pipeHeight;
779 if (this->Orientation == VTK_ORIENT_VERTICAL) {
780 this->Axis->SetTickLength(tickLength);
783 float labelOffset = tickLength + (0.5 * tickLength);
784 this->Axis->SetLabelOffset(labelOffset);
786 this->Axis->SetTickLength(tickLength);
788 float labelOffset = tickLength + (0.3 * tickLength);
789 this->Axis->SetLabelOffset(labelOffset);
795 if (this->Orientation == VTK_ORIENT_VERTICAL) {
796 this->Axis->SetPoint1(rect.GetX() + axisShift, rect.GetY());
797 this->Axis->SetPoint2(rect.GetX() + axisShift,
798 rect.GetY() + rect.GetHeight());
799 this->Axis->SetPosition(vtkAxis::LEFT);
802 this->Axis->SetPoint1(rect.GetX(), rect.GetY() + axisShift);
803 this->Axis->SetPoint2(rect.GetX() + rect.GetWidth(),
804 rect.GetY() + axisShift);
805 this->Axis->SetPosition(vtkAxis::BOTTOM);
809 if (this->Orientation == VTK_ORIENT_VERTICAL) {
810 this->Axis->SetPoint1(rect.GetX() + rect.GetWidth() - axisShift,
812 this->Axis->SetPoint2(rect.GetX() + rect.GetWidth() - axisShift,
813 rect.GetY() + rect.GetHeight());
814 this->Axis->SetPosition(vtkAxis::RIGHT);
817 this->Axis->SetPoint1(rect.GetX(),
818 rect.GetY() + rect.GetHeight() - axisShift);
819 this->Axis->SetPoint2(rect.GetX() + rect.GetWidth(),
820 rect.GetY() + rect.GetHeight() - axisShift);
821 this->Axis->SetPosition(vtkAxis::TOP);
827 const double* lutRange = this->LookupTable->GetRange();
829 range[0] = lutRange[0];
830 range[1] = lutRange[1];
832 if (this->ReverseLegend) {
836 vtkPen* axisPen = this->Axis->GetPen();
837 axisPen->SetColorF(this->LabelTextProperty->GetColor());
839 bool indexedMode = this->LookupTable->GetIndexedLookup() == 1;
843 this->Axis->SetTickLabelAlgorithm(vtkAxis::TICK_SIMPLE);
844 this->Axis->SetUnscaledMinimumLimit(std::numeric_limits<double>::max() *
846 this->Axis->SetUnscaledMaximumLimit(std::numeric_limits<double>::max());
847 this->Axis->SetUnscaledRange(range);
848 this->Axis->SetAxisVisible(
false);
849 this->Axis->SetLabelsVisible(!indexedMode && this->DrawTickLabels == 1);
850 this->Axis->SetTicksVisible(!indexedMode && this->DrawTickMarks);
851 this->Axis->SetGridVisible(
false);
853 if (this->AutomaticLabelFormat) {
854 this->Axis->SetNotation(vtkAxis::STANDARD_NOTATION);
856 this->Axis->SetNotation(vtkAxis::PRINTF_NOTATION);
858 this->Axis->SetLabelFormat(std::string(this->LabelFormat));
859 this->Axis->SetLogScale(this->LookupTable->UsingLogScale() == 1);
860 this->Axis->AutoScale();
861 this->Axis->SetRangeLabelsVisible(!indexedMode &&
862 this->AddRangeLabels == 1);
863 this->Axis->SetRangeLabelFormat(std::string(this->RangeLabelFormat));
864 this->Axis->SetNumberOfTicks(this->NumberOfTicks);
866 if (this->UseCustomLabels) {
867 if (this->Axis->GetLogScale()) {
869 vtkNew<vtkDoubleArray> logCustomLabels;
870 logCustomLabels->SetNumberOfTuples(
871 this->CustomLabels->GetNumberOfTuples());
872 for (vtkIdType
id = 0;
id < logCustomLabels->GetNumberOfTuples();
874 double d = this->CustomLabels->GetValue(
id);
876 logCustomLabels->SetValue(
id, d);
878 this->Axis->SetCustomTickPositions(logCustomLabels.GetPointer());
880 this->Axis->SetCustomTickPositions(this->CustomLabels);
883 this->Axis->SetCustomTickPositions(
NULL);
886 this->Axis->SetUnscaledRange(range);
887 this->Axis->RecalculateTickSpacing();
889 this->Axis->Update();
890 this->Axis->Paint(painter);
894 void vtkContext2DScalarBarActor::PaintTitle(vtkContext2D* painter,
896 std::string combinedTitle(this->Title);
897 if (this->ComponentTitle && strlen(this->ComponentTitle) > 0) {
898 combinedTitle.append(
" ");
899 combinedTitle.append(this->ComponentTitle);
902 double titleOrientation = 0.0;
903 if (this->GetOrientation() == VTK_ORIENT_VERTICAL &&
904 !this->GetForceHorizontalTitle()) {
905 titleOrientation = 90.0;
907 this->TitleTextProperty->SetOrientation(titleOrientation);
908 this->TitleTextProperty->SetJustification(this->GetTitleJustification());
909 painter->ApplyTextProp(this->TitleTextProperty);
912 float titleBounds[4];
913 painter->ComputeStringBounds(combinedTitle, titleBounds);
914 float titleWidth = titleBounds[2];
915 float titleHeight = titleBounds[3];
920 vtkNew<vtkBoundingRectContextDevice2D> boundingDevice;
921 vtkNew<vtkContextDevice2D> contextDevice;
922 boundingDevice->SetDelegateDevice(contextDevice.Get());
923 boundingDevice->Begin(this->CurrentViewport);
925 context->Begin(boundingDevice);
928 boundingDevice->End();
930 vtkRectf axisRect = boundingDevice->GetBoundingRect();
932 vtkRectf barAndAxisRect = axisRect;
933 vtkRectf colorBarRect = this->GetColorBarRect(
size);
934 barAndAxisRect.AddRect(colorBarRect);
936 float titleX = barAndAxisRect.GetX() + 0.5 * barAndAxisRect.GetWidth();
937 float titleY = colorBarRect.GetY() + 0.5 * colorBarRect.GetHeight();
938 if (this->GetOrientation() == VTK_ORIENT_HORIZONTAL ||
939 this->ForceHorizontalTitle) {
940 if (this->GetTitleJustification() == VTK_TEXT_LEFT) {
941 titleX = barAndAxisRect.GetX();
942 }
else if (this->GetTitleJustification() == VTK_TEXT_RIGHT) {
943 titleX = barAndAxisRect.GetX() + barAndAxisRect.GetWidth();
945 if (this->GetTextPosition() ==
947 titleY = axisRect.GetY() - titleHeight - 0.25 * titleHeight;
950 if (axisRect.GetHeight() < 1.0) {
951 axisRect.SetHeight(colorBarRect.GetHeight());
954 axisRect.GetY() + axisRect.GetHeight() + 0.25 * titleHeight;
958 if (this->ForceHorizontalTitle &&
959 this->GetOrientation() != VTK_ORIENT_HORIZONTAL) {
960 titleY = barAndAxisRect.GetY() + barAndAxisRect.GetHeight() +
966 if (axisRect.GetWidth() < 1.0) {
967 axisRect.SetWidth(0.25 * colorBarRect.GetWidth());
969 if (this->GetTitleJustification() == VTK_TEXT_LEFT) {
970 titleY = barAndAxisRect.GetY();
971 }
else if (this->GetTitleJustification() == VTK_TEXT_RIGHT) {
972 titleY = barAndAxisRect.GetY() + barAndAxisRect.GetHeight();
974 if (this->GetTextPosition() ==
976 titleX = colorBarRect.GetX() - axisRect.GetWidth();
978 titleX = colorBarRect.GetX() + colorBarRect.GetWidth() +
979 axisRect.GetWidth() + titleWidth;
983 painter->ApplyTextProp(this->TitleTextProperty);
984 painter->DrawString(titleX, titleY, combinedTitle);
989 if (!this->Visibility) {
993 this->UpdateTextProperties();
995 vtkPen* pen = painter->GetPen();
996 vtkBrush* brush = painter->GetBrush();
999 vtkNew<vtkPen> savePen;
1000 savePen->DeepCopy(pen);
1001 vtkNew<vtkBrush> saveBrush;
1002 saveBrush->DeepCopy(brush);
1004 pen->SetColorF(1, 1, 1);
1005 brush->SetColorF(1, 0, 0);
1007 vtkNew<vtkPoints2D> rect;
1008 rect->InsertNextPoint(0, 00);
1009 rect->InsertNextPoint(200, 40);
1011 int* displayPosition = this->PositionCoordinate->GetComputedDisplayValue(
1012 this->CurrentViewport);
1016 this->Axis->GetScene()->SetRenderer(
1017 vtkRenderer::SafeDownCast(this->CurrentViewport));
1020 this->GetSize(
size, painter);
1023 vtkNew<vtkTransform2D> tform;
1024 tform->Translate(displayPosition[0], displayPosition[1]);
1025 painter->PushMatrix();
1026 painter->AppendTransform(tform.GetPointer());
1028 this->PaintColorBar(painter,
size);
1029 this->PaintAxis(painter,
size);
1032 this->PaintTitle(painter,
size);
1035 pen->DeepCopy(savePen.GetPointer());
1036 brush->DeepCopy(saveBrush.GetPointer());
1038 painter->PopMatrix();
1046 this->ScalarBarItem, this->CurrentViewport);
1050 void vtkContext2DScalarBarActor::PaintAnnotations(
1051 vtkContext2D* painter,
1053 const vtkAnnotationMap& annotationAnchors) {
1055 painter->ApplyTextProp(this->Axis->GetLabelProperties());
1057 if (this->Orientation == VTK_ORIENT_VERTICAL) {
1058 this->PaintAnnotationsVertically(painter,
size, annotationAnchors);
1060 this->PaintAnnotationsHorizontally(painter,
size, annotationAnchors);
1075 void DistributeAnnotations(std::vector<AnnotationInfo>& annotations,
1085 bool overlapDetected =
false;
1094 std::vector<bool> overlaps(annotations.size(),
false);
1099 overlapDetected =
false;
1100 double clusterWidth = 0.0;
1101 size_t clusterCount = 0;
1102 for (
size_t j = 0; j < annotations.size(); ++j) {
1104 bool overlapsNext =
false;
1105 double lowerMax = 0.0;
1106 double upperMin = 0.0;
1108 if (j < annotations.size() - 1) {
1109 lowerMax = annotations[j].Position + 0.5 * annotations[j].Span +
1111 upperMin = annotations[j + 1].Position -
1112 0.5 * annotations[j + 1].Span - 0.5 * spacer;
1113 overlapsNext = lowerMax > upperMin;
1114 overlapDetected = overlapDetected || overlapsNext;
1117 if (overlapDetected) {
1118 clusterWidth += annotations[j].Span;
1129 if (clusterCount > 0) {
1131 double clusterCenter = 0.0;
1132 for (
size_t k = j - clusterCount + 1; k <= j; ++k) {
1133 double weight = annotations[k].Span / clusterWidth;
1134 clusterCenter += annotations[k].Anchor * weight;
1137 double accumWidth = 0.0;
1139 spacer * (clusterCount - 1);
1140 for (
size_t k = 0; k < clusterCount; ++k) {
1143 annotations[j - k].Position =
1144 clusterCenter + 0.5 * clusterWidth -
1145 accumWidth - 0.5 * annotations[j - k].Span;
1146 accumWidth += annotations[j - k].Span + spacer;
1157 }
while (overlapDetected && tries < maxTries);
1163 void vtkContext2DScalarBarActor::PaintAnnotationsVertically(
1164 vtkContext2D* painter,
1166 const vtkAnnotationMap& annotationAnchors) {
1167 vtkRectf barRect = this->GetColorBarRect(
size);
1170 std::vector<AnnotationInfo> annotations;
1171 annotations.reserve(annotationAnchors.size());
1172 vtkAnnotationMap::const_iterator annotationMapIter;
1173 for (annotationMapIter = annotationAnchors.begin();
1174 annotationMapIter != annotationAnchors.end(); ++annotationMapIter) {
1176 painter->ComputeStringBounds(annotationMapIter->second, bounds);
1179 p.Anchor = annotationMapIter->first;
1180 p.Position = annotationMapIter->first;
1181 p.Annotation = annotationMapIter->second;
1183 annotations.push_back(p);
1186 vtkWindow* renWin = this->CurrentViewport->GetVTKWindow();
1188 renWin->GetTileScale(tileScale);
1191 const float spacer =
1193 DistributeAnnotations(annotations, spacer);
1196 std::vector<AnnotationInfo>::iterator vectorIter;
1197 for (vectorIter = annotations.begin(); vectorIter != annotations.end();
1199 const int annotationLeader = 8 * tileScale[0];
1200 double anchorPt[2] = {barRect.GetX(), vectorIter->Anchor};
1201 double labelPt[2] = {anchorPt[0] - annotationLeader,
1202 vectorIter->Position};
1204 painter->GetTextProp()->SetJustification(VTK_TEXT_RIGHT);
1207 anchorPt[0] = barRect.GetX() + barRect.GetWidth();
1208 labelPt[0] = anchorPt[0] + annotationLeader;
1210 painter->GetTextProp()->SetJustification(VTK_TEXT_LEFT);
1213 vtkPen* pen = painter->GetPen();
1214 pen->SetOpacity(255);
1215 pen->SetLineType(vtkPen::SOLID_LINE);
1216 pen->SetColorF(this->Axis->GetLabelProperties()->GetColor());
1218 painter->DrawLine(anchorPt[0], anchorPt[1], labelPt[0], labelPt[1]);
1219 painter->GetTextProp()->SetVerticalJustification(VTK_TEXT_CENTERED);
1220 painter->DrawString(labelPt[0], labelPt[1], vectorIter->Annotation);
1225 void vtkContext2DScalarBarActor::PaintAnnotationsHorizontally(
1226 vtkContext2D* painter,
1228 const vtkAnnotationMap& annotationAnchors) {
1229 vtkRectf barRect = this->GetColorBarRect(
size);
1232 std::vector<AnnotationInfo> annotations;
1233 annotations.reserve(annotationAnchors.size());
1234 vtkAnnotationMap::const_iterator annotationMapIter;
1235 for (annotationMapIter = annotationAnchors.begin();
1236 annotationMapIter != annotationAnchors.end(); ++annotationMapIter) {
1238 painter->ComputeStringBounds(annotationMapIter->second, bounds);
1240 p.Anchor = annotationMapIter->first;
1241 p.Position = annotationMapIter->first;
1242 p.Annotation = annotationMapIter->second;
1244 annotations.push_back(p);
1247 vtkWindow* renWin = this->CurrentViewport->GetVTKWindow();
1249 renWin->GetTileScale(tileScale);
1254 painter->ComputeStringBounds(
"-", bounds);
1255 const float spacer = bounds[2] * tileScale[0];
1258 DistributeAnnotations(annotations, spacer);
1261 std::vector<AnnotationInfo>::iterator vectorIter;
1262 for (vectorIter = annotations.begin(); vectorIter != annotations.end();
1264 const int annotationLeader = 8 * tileScale[0];
1265 double anchorPt[2] = {vectorIter->Anchor, barRect.GetY()};
1266 double labelPt[2] = {vectorIter->Position,
1267 anchorPt[1] - annotationLeader};
1268 double labelOffset = 3;
1270 painter->GetTextProp()->SetJustification(VTK_TEXT_CENTERED);
1271 painter->GetTextProp()->SetVerticalJustification(VTK_TEXT_TOP);
1273 anchorPt[1] = barRect.GetY() + barRect.GetHeight();
1274 labelPt[1] = anchorPt[1] + annotationLeader;
1275 labelOffset *= -1.0;
1277 painter->GetTextProp()->SetVerticalJustification(VTK_TEXT_BOTTOM);
1279 painter->DrawString(labelPt[0], labelPt[1] - labelOffset,
1280 vectorIter->Annotation);
1282 vtkPen* pen = painter->GetPen();
1283 pen->SetOpacity(255);
1284 pen->SetLineType(vtkPen::SOLID_LINE);
1285 pen->SetColorF(this->Axis->GetLabelProperties()->GetColor());
1287 painter->DrawLine(anchorPt[0], anchorPt[1], labelPt[0], labelPt[1]);
1293 this->Superclass::PrintSelf(os, indent);
1298 vtkDiscretizableColorTransferFunction* ctf =
1299 vtkDiscretizableColorTransferFunction::SafeDownCast(
1304 if (this->GetAutomaticAnnotations() && !ctf->GetIndexedLookup()) {
1306 return ctf->GetNumberOfAvailableColors();
1309 return ctf->GetNumberOfAnnotatedValues();
std::shared_ptr< core::Tensor > image
vtkRectf GetBoundingRect()
vtkContext2DScalarBarActor * Actor
bool Paint(vtkContext2D *painter) override
vtkTypeMacro(vtkScalarBarItem, vtkContextItem)
static vtkScalarBarItem * New()
~vtkScalarBarItem() override
vtkRectf GetBoundingRect()
virtual bool Paint(vtkContext2D *painter)
vtkContext2DScalarBarActor()
void SetCustomLabel(vtkIdType index, double value)
void SetNumberOfCustomLabels(vtkIdType numLabels)
void ReleaseGraphicsResources(vtkWindow *window) override
void SetUseCustomLabels(bool useLabels)
~vtkContext2DScalarBarActor() override
int RenderOverlay(vtkViewport *viewport) override
int RenderOpaqueGeometry(vtkViewport *viewport) override
void PrintSelf(ostream &os, vtkIndent indent) override
vtkIdType GetNumberOfCustomLabels()
int GetEstimatedNumberOfAnnotations()
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
vtkStandardNewMacro(vtkContext2DScalarBarActor)