阅片器机制分析

VolumeReader::read

void VolumeReader::read(Volume *volume)
{
    this->executePixelDataReader(volume);
    this->showMessageBoxWithLastError();
}

m_lastError = m_volumePixelDataReader->read(fileList);
            if (m_lastError == VolumePixelDataReader::NoError)
            {
                // Tot ha anat ok, assignem les dades al volum
                volume->setPixelData(m_volumePixelDataReader->getVolumePixelData());
                runPostprocessors(volume);
                fixSpacingIssues(volume);
            }
            else
            {
                volume->convertToNeutralVolume();
                this->logWarningLastError(fileList);
            }
void Volume::setPixelData(VolumePixelData *pixelData)
{
    Q_ASSERT(pixelData != 0);
    m_volumePixelData = pixelData;
    // Set the number of phases to the new pixel data
    m_volumePixelData->setNumberOfPhases(m_numberOfPhases);
}


更新slice分析
void Q2DViewer::updateSliceToDisplay(int value, SliceDimension dimension)
{
    if (hasInput())
    {
        int oldSlice = getCurrentSlice();
        int oldPhase = getCurrentPhase();

        // First update the index of the corresponding dimension
        switch (dimension)
        {
            case SpatialDimension:
                getMainDisplayUnit()->setSlice(value);
                updateSecondaryVolumesSlices();
                break;

            case TemporalDimension:
                getMainDisplayUnit()->setPhase(value);
                break;
        }

        // Then update display (image and associated annotations)
        updateImageSlices();

void Q2DViewer::updateImageSlices()
{
    // Ens assegurem que tenim dades vàlides
    if (!getMainInput()->isPixelDataLoaded())
    {
        return;
    }

    // We only need to update the main vdu, since it will modify the camera and thus the others will also be updated
    getMainDisplayUnit()->updateImageSlice(m_renderer->GetActiveCamera());

    // TODO Si separem els renderers potser caldria aplicar-ho a cada renderer?
    getRenderer()->ResetCameraClippingRange();
}
//此处更新相机焦点
void VolumeDisplayUnit::updateImageSlice(vtkCamera *camera)
{
    if (!m_volume || !m_volume->isPixelDataLoaded())
    {
        return;
    }

    int imageIndex = getSlice();
    int zIndex = this->getViewPlane().getZIndex();
    double origin[3];
    m_volume->getOrigin(origin);
    double spacing[3];
    m_volume->getSpacing(spacing);
    double focalPoint[3];
    camera->GetFocalPoint(focalPoint);
    focalPoint[zIndex] = origin[zIndex] + imageIndex * spacing[zIndex];
    camera->SetFocalPoint(focalPoint);
}

//最适合的填充窗口
void QViewer::fitRenderingIntoViewport()
{
    // First we get the bounds of the current rendered item in world coordinates
    double bounds[6];
    getCurrentRenderedItemBounds(bounds);
    
    double topCorner[3];
    double bottomCorner[3];
    for (int i = 0; i < 3; ++i)
    {
        topCorner[i] = bounds[i * 2];
        bottomCorner[i] = bounds[i * 2 + 1];
    }

    // Scaling the viewport to fit the current item bounds
    if (scaleToFit3D(topCorner, bottomCorner, m_defaultFitIntoViewportMarginRate))
    {
        render();
    }
}
bool QViewer::scaleToFit3D(double topCorner[3], double bottomCorner[3], double marginRate)
{
    if (!hasInput())
    {
        return false;
    }

    // Calcular la width i height en coordenades de display
    double displayTopLeft[3], displayBottomRight[3];
    this->computeWorldToDisplay(topCorner[0], topCorner[1], topCorner[2], displayTopLeft);
    this->computeWorldToDisplay(bottomCorner[0], bottomCorner[1], bottomCorner[2], displayBottomRight);

    // Recalculem tenint en compte el display
    double width, height;
    width = fabs(displayTopLeft[0] - displayBottomRight[0]);
    height = fabs(displayTopLeft[1] - displayBottomRight[1]);


    QSize size = this->getRenderWindowSize();
    double ratio = qMin(size.width() / width, size.height() / height);
    double factor = ratio * (1.0 - marginRate);
    
    return adjustCameraScaleFactor(factor);
}
bool QViewer::adjustCameraScaleFactor(double factor)
{
    if (MathTools::isNaN(factor))
    {
        DEBUG_LOG("Scale factor is NaN. No scale factor will be applied.");
        return false;
    }

    vtkRenderer *renderer = getRenderer();
    if (!renderer)
    {
        DEBUG_LOG("Renderer is NULL. No scale factor will be applied.");
        return false;
    }
    
    getActiveCamera()->Zoom(factor);
    
    if (this->getInteractor()->GetLightFollowCamera())
    {
        renderer->UpdateLightsGeometryToFollowCamera();
    }

    return true;
}

//工具链
注册事件
void Q2DViewerExtension::initializeTools()
{
    // Creem el tool manager
    m_toolManager = new ToolManager(this);
    // Obtenim les accions de cada tool que volem
    m_zoomToolButton->setDefaultAction(m_toolManager->registerTool("ZoomTool"));
    m_slicingToolButton->setDefaultAction(m_toolManager->registerTool("SlicingMouseTool"));
    m_translateLeftToolButton->setDefaultAction(m_toolManager->registerTool("TranslateLeftTool"));
    m_windowLevelLeftToolButton->setDefaultAction(m_toolManager->registerTool("WindowLevelLeftTool"));
    m_toolManager->registerTool("TranslateTool");
    m_toolManager->registerTool("WindowLevelTool");
    m_referenceLinesToolButton->setDefaultAction(m_toolManager->registerTool("ReferenceLinesTool"));

void QViewer::setupInteraction()
{
    Q_ASSERT(m_renderer);

    // TODO Fer això aquí? o fer-ho en el tool manager?
    this->getInteractor()->RemoveObservers(vtkCommand::LeftButtonPressEvent);
    this->getInteractor()->RemoveObservers(vtkCommand::RightButtonPressEvent);
    this->getInteractor()->RemoveObservers(vtkCommand::MouseWheelForwardEvent);
    this->getInteractor()->RemoveObservers(vtkCommand::MouseWheelBackwardEvent);
    this->getInteractor()->RemoveObservers(vtkCommand::MiddleButtonPressEvent);
    this->getInteractor()->RemoveObservers(vtkCommand::CharEvent);

    m_vtkQtConnections = vtkEventQtSlotConnect::New();
    // Despatxa qualsevol event-> tools
    m_vtkQtConnections->Connect(this->getInteractor(), vtkCommand::AnyEvent, this, SLOT(eventHandler(vtkObject*, unsigned long, void*, void*,

vtkCommand*)));

void QViewer::eventHandler(vtkObject *object, unsigned long vtkEvent, void *clientData, void *callData, vtkCommand *command)
{
    .........
    switch (vtkEvent)
    {
        case QVTKWidget::ContextMenuEvent:
        case vtkCommand::LeftButtonPressEvent:
        case vtkCommand::RightButtonPressEvent:
        case vtkCommand::MiddleButtonPressEvent:
        case vtkCommand::MouseWheelForwardEvent:
        case vtkCommand::MouseWheelBackwardEvent:
            m_mouseHasMoved = false;
            setActive(true);
            if (vtkEvent == vtkCommand::LeftButtonPressEvent && getInteractor()->GetRepeatCount() == 1)
            {
                emit doubleClicked();
            }
            break;

        case vtkCommand::MouseMoveEvent:
            m_mouseHasMoved = true;
            break;

        case vtkCommand::RightButtonReleaseEvent:
            if (!m_mouseHasMoved)
            {
                contextMenuRelease();
            }
            break;
    }
    emit eventReceived(vtkEvent);
}
}

QViewer::QViewer(QWidget *parent)
 : QWidget(parent), m_mainVolume(0), m_contextMenuActive(true), m_mouseHasMoved(false), m_voiLutData(0),
   m_isRenderingEnabled(true), m_isActive(false)
{
    m_lastAngleDelta = QPoint();
    m_defaultFitIntoViewportMarginRate = 0.0;
    m_vtkWidget = new QVTKWidget(this);
    m_vtkWidget->setFocusPolicy(Qt::WheelFocus);
    m_renderer = vtkRenderer::New();

    m_windowToImageFilter = vtkWindowToImageFilter::New();

    setupRenderWindow();

    this->setCurrentViewPlane(OrthogonalPlane::XYPlane);

    // Connectem els events
    setupInteraction();

    m_toolProxy = new ToolProxy(this);
    connect(this, SIGNAL(eventReceived(unsigned long)), m_toolProxy, SLOT(forwardEvent(unsigned long)));

void ToolProxy::forwardEvent(unsigned long eventID)
{
    // No es pot fer un foreach sobre un map perquè retorna parella d'elements, per això passem tots els elements del map a una QList.
    QList<Tool*> toolsList = m_toolsMap.values();

    foreach (Tool *tool, toolsList)
    {
        tool->handleEvent(eventID);
    }
}

工具在下面代码中激活
void ToolManager::triggeredToolAction(const QString &toolName)
{
    // TODO Cal repassar tot això. Hauria d'anar amb llistes internes de tools activades/desactivades
    // obtenim l'acció que l'ha provocat
    QAction *toolAction = getRegisteredToolAction(toolName);
    if (toolAction)
    {
        // Si està checked és que s'ha d'activar, altrament desactivar
        if (toolAction->isChecked())
        {
            activateTool(toolName);
        }
        else
        {
            deactivateTool(toolName);
        }
    }
    else
    {
        DEBUG_LOG(QString("No hi ha cap tool Action per la tool anomenada: ") + toolName);
    }
}


void ToolManager::activateTool(const QString &toolName)
{
    // TODO Caldria comprovar si la tool es troba en un grup exclusiu per "fer fora" les altres tools
    // en el cas que prescindíssim del mecanisme que fem servir amb QActionToolGroup
    QList<ViewerToolConfigurationPairType> viewerConfigList = m_toolViewerMap.values(toolName);

    ToolData *data = m_sharedToolDataRepository.value(toolName);
    // Declarem aquestes variables per fer-ho més llegible
    QViewer *viewer;
    ToolConfiguration *configuration;
    foreach (const ViewerToolConfigurationPairType &pair, viewerConfigList)
    {
        viewer = pair.first;
        configuration = pair.second;
        Tool *tool = 0;

        // Hem de comprovar si el proxy ja té o no la tool
        if (!viewer->getToolProxy()->isToolActive(toolName))
        {
            // Com que el proxy no té aquesta tool
            // la produim i la posem a punt amb les dades i la configuració
            tool = m_toolRegistry->getTool(toolName, viewer);
            // Si no tenim cap configuració guardada, no cal fer res, es queda amb la que té per defecte
            if (configuration)
            {
                tool->setConfiguration(configuration);
            }
            // Afegim la tool al proxy
            viewer->getToolProxy()->addTool(tool);
            // Comprovem les dades per si cal donar-n'hi
            if (tool->hasSharedData())
            {
                // No hi són al repositori, les obtindrem de la pròpia tool i les registrarem al repositori
                if (!data)
                {
                    data = tool->getToolData();
                    m_sharedToolDataRepository[toolName] = data;
                }
                else
                {
                    // Si ja les hem creat abans, li assignem les de la primera tool creada
                    tool->setToolData(data);
                }
            }
        }
    }
}

//单个按钮触发机制
 m_slicingToolButton->setDefaultAction(m_toolManager->registerTool("SlicingMouseTool"));

connect(toolAction, SIGNAL(triggered()), m_toolsActionSignalMapper, SLOT(map()));

connect(m_toolsActionSignalMapper, SIGNAL(mapped(const QString&)), SLOT(triggeredToolAction(const QString&)));

void ToolManager::triggeredToolAction(const QString &toolName)
{
    // TODO Cal repassar tot això. Hauria d'anar amb llistes internes de tools activades/desactivades
    // obtenim l'acció que l'ha provocat
    QAction *toolAction = getRegisteredToolAction(toolName);
    if (toolAction)
    {
        // Si està checked és que s'ha d'activar, altrament desactivar
        if (toolAction->isChecked())
        {
            activateTool(toolName);
        }
        else
        {
            deactivateTool(toolName);
        }
    }
    else
    {
        DEBUG_LOG(QString("No hi ha cap tool Action per la tool anomenada: ") + toolName);
    }
}

activateTool中激活相应的事件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值