You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp

202 lines
5.6 KiB
C++

#include "nmVTKBoundsGridLayer.h"
#include <QCoreApplication>
#include <QThread>
#include <vtkCamera.h>
#include <vtkCubeAxesActor.h>
#include <vtkMath.h>
#include <vtkProperty.h>
#include <vtkTextProperty.h>
namespace {
bool isBoundsGridGuiThread()
{
QCoreApplication* pApplication = QCoreApplication::instance();
return pApplication == NULL ||
pApplication->thread() == QThread::currentThread();
}
bool isValidBounds(const double dBounds[6])
{
if(dBounds == NULL) {
return false;
}
for(int nIndex = 0; nIndex < 6; ++nIndex) {
if(!vtkMath::IsFinite(dBounds[nIndex])) {
return false;
}
}
return dBounds[0] <= dBounds[1] &&
dBounds[2] <= dBounds[3] &&
dBounds[4] <= dBounds[5];
}
}
nmVTKBoundsGridLayer::nmVTKBoundsGridLayer(const QString& sLayerId)
: nmVTKRenderLayer(sLayerId),
m_pActor(vtkSmartPointer<vtkCubeAxesActor>::New()),
m_eMode(Mode_PlanarXY),
m_bHasBounds(false)
{
Q_ASSERT(isBoundsGridGuiThread());
for(int nIndex = 0; nIndex < 6; ++nIndex) {
m_dBounds[nIndex] = 0.0;
}
// CubeAxesActor 只负责通用坐标表达,不读取 MeshLayer 或业务属性。
m_pActor->SetXTitle("X");
m_pActor->SetYTitle("Y");
m_pActor->SetZTitle("Z");
m_pActor->SetFlyModeToStaticEdges();
m_pActor->SetGridLineLocation(vtkCubeAxesActor::VTK_GRID_LINES_FURTHEST);
m_pActor->SetTickLocationToOutside();
m_pActor->XAxisMinorTickVisibilityOff();
m_pActor->YAxisMinorTickVisibilityOff();
m_pActor->ZAxisMinorTickVisibilityOff();
m_pActor->SetScreenSize(10.0);
m_pActor->PickableOff();
for(int nAxis = 0; nAxis < 3; ++nAxis) {
m_pActor->GetTitleTextProperty(nAxis)->SetColor(0.15, 0.15, 0.15);
m_pActor->GetLabelTextProperty(nAxis)->SetColor(0.15, 0.15, 0.15);
}
m_pActor->GetXAxesLinesProperty()->SetColor(0.20, 0.20, 0.20);
m_pActor->GetYAxesLinesProperty()->SetColor(0.20, 0.20, 0.20);
m_pActor->GetZAxesLinesProperty()->SetColor(0.20, 0.20, 0.20);
m_pActor->GetXAxesGridlinesProperty()->SetColor(0.55, 0.55, 0.55);
m_pActor->GetYAxesGridlinesProperty()->SetColor(0.55, 0.55, 0.55);
m_pActor->GetZAxesGridlinesProperty()->SetColor(0.55, 0.55, 0.55);
applyMode();
setRenderProp(m_pActor);
}
nmVTKBoundsGridLayer::~nmVTKBoundsGridLayer()
{
Q_ASSERT(isBoundsGridGuiThread());
// 先解除 Renderer再断开 Actor 对当前 Renderer 相机的 VTK 引用。
detach();
if(m_pActor != NULL) {
m_pActor->SetCamera(NULL);
}
}
void nmVTKBoundsGridLayer::setCamera(vtkCamera* pCamera)
{
Q_ASSERT(isBoundsGridGuiThread());
if(isBoundsGridGuiThread() && m_pActor != NULL) {
m_pActor->SetCamera(pCamera);
}
}
vtkCamera* nmVTKBoundsGridLayer::getCamera() const
{
return m_pActor != NULL ? m_pActor->GetCamera() : NULL;
}
void nmVTKBoundsGridLayer::setMode(Mode eMode)
{
Q_ASSERT(isBoundsGridGuiThread());
if(!isBoundsGridGuiThread()) {
return;
}
m_eMode = eMode == Mode_Box3D ? Mode_Box3D : Mode_PlanarXY;
applyMode();
}
nmVTKBoundsGridLayer::Mode nmVTKBoundsGridLayer::getMode() const
{
return m_eMode;
}
bool nmVTKBoundsGridLayer::setBounds(
double dXMinimum,
double dXMaximum,
double dYMinimum,
double dYMaximum,
double dZMinimum,
double dZMaximum)
{
Q_ASSERT(isBoundsGridGuiThread());
const double dIncomingBounds[6] = {
dXMinimum, dXMaximum,
dYMinimum, dYMaximum,
dZMinimum, dZMaximum
};
if(!isBoundsGridGuiThread() || !isValidBounds(dIncomingBounds) ||
m_pActor == NULL) {
return false;
}
double dDisplayBounds[6];
for(int nIndex = 0; nIndex < 6; ++nIndex) {
m_dBounds[nIndex] = dIncomingBounds[nIndex];
dDisplayBounds[nIndex] = dIncomingBounds[nIndex];
}
double dScale = dDisplayBounds[1] - dDisplayBounds[0];
const double dYScale = dDisplayBounds[3] - dDisplayBounds[2];
if(dYScale > dScale) {
dScale = dYScale;
}
if(dScale <= 0.0) {
dScale = dDisplayBounds[5] - dDisplayBounds[4];
}
if(dScale <= 0.0) {
dScale = 1.0;
}
const double dTolerance = dScale * 0.000001;
// CubeAxesActor 不接受退化包围盒;仅扩展 Actor 的局部副本。
for(int nAxis = 0; nAxis < 3; ++nAxis) {
const int nMinimumIndex = nAxis * 2;
const int nMaximumIndex = nMinimumIndex + 1;
if(dDisplayBounds[nMaximumIndex] ==
dDisplayBounds[nMinimumIndex]) {
dDisplayBounds[nMinimumIndex] -= dTolerance * 0.5;
dDisplayBounds[nMaximumIndex] += dTolerance * 0.5;
}
}
m_pActor->SetBounds(dDisplayBounds);
m_bHasBounds = true;
return true;
}
bool nmVTKBoundsGridLayer::getBounds(double dBounds[6]) const
{
if(dBounds == NULL || !m_bHasBounds) {
return false;
}
for(int nIndex = 0; nIndex < 6; ++nIndex) {
dBounds[nIndex] = m_dBounds[nIndex];
}
return true;
}
vtkCubeAxesActor* nmVTKBoundsGridLayer::getActor() const
{
return m_pActor;
}
void nmVTKBoundsGridLayer::applyMode()
{
if(m_pActor == NULL) {
return;
}
const bool bPlanar = m_eMode == Mode_PlanarXY;
m_pActor->XAxisVisibilityOn();
m_pActor->YAxisVisibilityOn();
m_pActor->SetZAxisVisibility(bPlanar ? 0 : 1);
m_pActor->DrawXGridlinesOn();
m_pActor->DrawYGridlinesOn();
m_pActor->SetDrawZGridlines(bPlanar ? 0 : 1);
m_pActor->SetZAxisLabelVisibility(bPlanar ? 0 : 1);
m_pActor->SetZAxisTickVisibility(bPlanar ? 0 : 1);
m_pActor->SetUse2DMode(bPlanar ? 1 : 0);
}