|
|
#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);
|
|
|
}
|