CameraOrientationWidget
Description¶
Use multiple camera orientation widgets in a window with the provision to relabel the axes labels and change axis colors.
To use the snippet, click the Copy to clipboard at the upper right of the code blocks.
Declaration Section¶
#include <vtkCameraOrientationRepresentation.h>
#include <vtkCameraOrientationWidget.h>
#include <vtkNew.h>
#include <vtk_fmt.h>
// clang-format off
#include VTK_FMT(fmt/format.h)
// clang-format on
// #include <iostream>
// #include <map>
// #include <set>
// #include <string>
// #include <vector>
namespace {
typedef std::map<std::string, std::string> TAxisParams;
typedef std::map<std::string, TAxisParams> TAxesParams;
/**
* @brief Define the axes labels.
*
* @return The axes labels.
*/
TAxesParams DefineAxesLabels();
/**
* @brief Define the axes colors.
*
* @return The axes colors.
*/
TAxesParams DefineAxesColors();
/**
* @brief Gather the defined axes labels and colors into a map.
*
* @return The map of axes labels and colors.
*/
std::map<std::string, std::pair<TAxisParams, TAxisParams>> GetAxesParams();
/**
* @brief Make a camera orientation widget for a given renderer.
*
* position has these values 0: LowerLeft, 1: UpperLeft, 2: LowerRight, 3:
* UpperRight
*
* @param ren The renderer.
* @param alc The key specifying the desired labels and colors for the axes.
* @param colors A reference to the vtkNamedColors object.
* @param position Position the camera orientation widget, default is upper right.
*
* @return The camera orientation widget.
*/
vtkNew<vtkCameraOrientationWidget>
MakeCameraOrientationWidget(vtkRenderer* ren, std::string alcKey = "xyz",
int const& position = 3);
} // namespace
Implementation Section¶
namespace {
TAxesParams DefineAxesLabels()
{
// clang-format off
return {
// Labels are: Anterior, Posterior, Dorsal, Ventral, Left, Right
{"apdvlr", {{"+X", "A"},{"-X", "P"},{"+Y", "D"},{"-Y", "V"},{"+Z", "L"},{"-Z", "R"}}},
{"apdvrl", {{"+X", "A"},{"-X", "P"},{"+Y", "D"},{"-Y", "V"},{"+Z", "R"},{"-Z", "L"}}},
{"aprlvd", {{"+X", "A"},{"-X", "P"},{"+Y", "R"},{"-Y", "L"},{"+Z", "V"},{"-Z", "D"}}},
{"padvlr", {{"+X", "P"},{"-X", "A"},{"+Y", "D"},{"-Y", "V"},{"+Z", "L"},{"-Z", "R"}}},
// Labels are: Left, Right, Superior, Inferior, Anterior, Posterior
{"lrsiap", {{"+X", "L"},{"-X", "R"},{"+Y", "S"},{"-Y", "I"},{"+Z", "A"},{"-Z", "P"}}},
{"lrpasi", {{"+X", "L"},{"-X", "R"},{"+Y", "P"},{"-Y", "A"},{"+Z", "S"},{"-Z", "I"}}},
{"rlpais", {{"+X", "R"},{"-X", "L"},{"+Y", "P"},{"-Y", "A"},{"+Z", "I"},{"-Z", "S"}}},
// Default labels.
{"xyz", {}},
};
// clang-format on
}
TAxesParams DefineAxesColors()
{
// clang-format off
TAxisParams color1{{"+X", "IndianRed"},{"-X", "FireBrick"},
{"+Y", "LimeGreen"},{"-Y", "DarkGreen"},
{"+Z", "Blue"}, {"-Z", "SteelBlue"}};
return {
{"apdvlr",color1},
{"apdvrl",color1},
{"aprlvd",color1},
{"padvlr",color1},
{"lrsiap",color1},
// Default colors.
{"lrpasi", {}},
{"rlpais", {}},
{"xyz", {}},
};
// clang-format on
}
std::map<std::string, std::pair<TAxisParams, TAxisParams>> GetAxesParams()
{
vtkNew<vtkNamedColors> colors;
// The keys must be the same.
auto axesLabels = DefineAxesLabels();
auto axesColors = DefineAxesColors();
// Get the keys.
std::set<std::string> labelKeys;
for (auto&& label : axesLabels)
{
labelKeys.insert(label.first);
}
std::set<std::string> colorKeys;
for (auto&& label : axesLabels)
{
colorKeys.insert(label.first);
}
std::vector<std::string> commonKeys;
std::set_intersection(labelKeys.begin(), labelKeys.end(), colorKeys.begin(),
colorKeys.end(), std::back_inserter(commonKeys));
std::map<std::string, std::pair<TAxisParams, TAxisParams>> alc;
for (auto&& k : commonKeys)
{
alc[k] = std::pair<TAxisParams, TAxisParams>{axesLabels[k], axesColors[k]};
}
return alc;
};
vtkNew<vtkCameraOrientationWidget>
MakeCameraOrientationWidget(vtkRenderer* ren, std::string alcKey,
int const& position)
{
vtkNew<vtkCameraOrientationWidget> cow;
cow->SetParentRenderer(ren);
cow->EnabledOn();
auto axesParameters = GetAxesParams();
std::set<std::string> keys;
for (auto&& label : axesParameters)
{
keys.insert(label.first);
}
auto it = keys.find(alcKey);
if (it == keys.end())
{
std::string res =
"Invalid key for axes labels and colors.\nValid keys are: ";
for (const auto& [key, value] : axesParameters)
{
res += fmt::format("{:s}, ", key);
}
if (res.length() >= 2)
{
auto pos = res.length() - 2;
res.replace(pos, 2, "");
}
res += "\nUsing the key: xyz";
std::cout << res << std::endl;
alcKey = "xyz";
}
auto alc = axesParameters[alcKey];
vtkNew<vtkCameraOrientationRepresentation> rep;
switch (position)
{
case 0:
rep->AnchorToLowerLeft();
break;
case 1:
rep->AnchorToUpperLeft();
break;
case 2:
rep->AnchorToLowerRight();
break;
default:
rep->AnchorToUpperRight();
}
if (!alc.first.empty())
{
rep->SetXPlusLabelText(alc.first["+X"]);
rep->SetXMinusLabelText(alc.first["-X"]);
rep->SetYPlusLabelText(alc.first["+Y"]);
rep->SetYMinusLabelText(alc.first["-Y"]);
rep->SetZPlusLabelText(alc.first["+Z"]);
rep->SetZMinusLabelText(alc.first["-Z"]);
}
if (!alc.second.empty())
{
vtkNew<vtkNamedColors> colors;
rep->SetXAxisColor(colors->GetColor3d(alc.second["+X"]).GetData());
rep->SetYAxisColor(colors->GetColor3d(alc.second["+Y"]).GetData());
rep->SetZAxisColor(colors->GetColor3d(alc.second["+Z"]).GetData());
}
cow->SetRepresentation(rep);
cow->Off();
return cow;
}
} // namespace
Usage¶
Here we have a custom widget positioned upper left and the default widget positioned upper right.
// Important: The interactor must be set prior to enabling the widget.
auto category = "lrpasi";
auto cow = MakeCameraOrientationWidget(ren, category, 1);
cow->On();
auto cow1 = MakeCameraOrientationWidget(ren);
cow1->On();