Skip to content

DrawViewportBorder

Description

Draw the borders of a vtkRenderer's viewports.

To use the snippet, click the Copy to clipboard at the upper right of the code blocks.

Declaration Section

#include <vtkActor2D.h>
#include <vtkCellArray.h>
#include <vtkCoordinate.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkPolyLine.h>
#include <vtkProperty2D.h>
#include <vtkRenderer.h>

#include <array>
#include <string>

namespace
{
/** Specify the rules for drawing the borders around a viewport.
 *
 * Here the borders for the viewports are defined in the order
 *  [top, left, bottom, right].
 *
 * Names for adjacent sides reflect anticlockwise ordering.
 */
static constexpr struct ViewportBorderSpecifier
{
  std::array<bool, 4> t{true, false, false, false};
  std::array<bool, 4> l{false, true, false, false};
  std::array<bool, 4> b{false, false, true, false};
  std::array<bool, 4> r{false, false, false, true};
  std::array<bool, 4> lb{false, true, true, false};
  std::array<bool, 4> lbr{false, true, true, true};
  std::array<bool, 4> tlb{true, true, true, false};
  std::array<bool, 4> tlbr{true, true, true, true};
  std::array<bool, 4> rtl{true, true, false, true};
  std::array<bool, 4> tl{true, true, false, false};
} viewportBorderSpecifier;

/** Draw a border around a viewport.
 *
 * @param renderer: The renderer corresponding to the viewport.
 * @param sides: An array of boolean corresponding to [top, left, bottom, right]
 * @param border_color: The color of the border.
 * @param border_width: The width of the border.
 * @return The border actor.
 */
vtkNew<vtkActor2D> DrawViewportBorder(std::array<bool, 4> const& sides,
                                      std::string const& border_color,
                                      unsigned int const& border_width);
}

Implementation Section

namespace
{
vtkNew<vtkActor2D> DrawViewportBorder(std::array<bool, 4> const& sides,
                                      std::string const& border_color,
                                      unsigned int const& border_width)
{
  vtkNew<vtkNamedColors> colors;

  // Points start at upper right and proceed anti-clockwise.
  vtkNew<vtkPoints> points;
  points->InsertPoint(0, 1, 1, 0);
  points->InsertPoint(1, 0, 1, 0);
  points->InsertPoint(2, 0, 0, 0);
  points->InsertPoint(3, 1, 0, 0);

  vtkNew<vtkCellArray> cells;

  if (sides[0])
  {
    // Top
    vtkNew<vtkPolyLine> top;
    top->GetPointIds()->SetNumberOfIds(2);
    top->GetPointIds()->SetId(0, 0);
    top->GetPointIds()->SetId(1, 1);
    cells->InsertNextCell(top);
  }
  if (sides[1])
  {
    // Left
    vtkNew<vtkPolyLine> left;
    left->GetPointIds()->SetNumberOfIds(2);
    left->GetPointIds()->SetId(0, 1);
    left->GetPointIds()->SetId(1, 2);
    cells->InsertNextCell(left);
  }
  if (sides[2])
  {
    // Bottom
    vtkNew<vtkPolyLine> bottom;
    bottom->GetPointIds()->SetNumberOfIds(2);
    bottom->GetPointIds()->SetId(0, 2);
    bottom->GetPointIds()->SetId(1, 3);
    cells->InsertNextCell(bottom);
  }
  if (sides[3])
  {
    // Right
    vtkNew<vtkPolyLine> right;
    right->GetPointIds()->SetNumberOfIds(2);
    right->GetPointIds()->SetId(0, 3);
    right->GetPointIds()->SetId(1, 0);
    cells->InsertNextCell(right);
  }

  // Now make the polydata and display it.
  vtkNew<vtkPolyData> poly;
  poly->SetPoints(points);
  poly->SetLines(cells);

  // Use normalized viewport coordinates since
  // they are independent of window size.
  vtkNew<vtkCoordinate> coordinate;
  coordinate->SetCoordinateSystemToNormalizedViewport();

  vtkNew<vtkPolyDataMapper2D> mapper;
  mapper->SetInputData(poly);
  mapper->SetTransformCoordinate(coordinate);

  vtkNew<vtkActor2D> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(colors->GetColor3d(border_color).GetData());
  // Line width should be at least 2 to be visible at extremes.
  actor->GetProperty()->SetLineWidth(border_width);

  return actor;
}
} // namespace

Usage

auto borderActor = DrawViewportBorder(border, "Yellow", 4);