#include "nmVTKBoundsGridLayer.h" #include #include #include #include #include #include #include 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::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); }