/*========================================================================= medInria Copyright (c) INRIA 2013 - 2020. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * @fn QPointF medAbstractImageView::mapWorldToDisplayCoordinates( const QVector3D & worldVec ) * @brief Convert from world coordinates to scene coordinates. */ /** * @fn QVector3D medAbstractImageView::mapDisplayToWorldCoordinates( const QPointF & scenePoint ) * @brief Convert from scene coordinates to world coordinates. */ /** * @fn QVector3D medAbstractImageView::viewCenter() * @brief Get the view center vector in world space, the center of the slice for 2d views. */ /** * @fn QVector3D medAbstractImageView::viewPlaneNormal() * @brief Get the view plane normal vector in world space. */ /** * @fn QVector3D medAbstractImageView::viewUp() * @brief Get the view plane up vector in world space. */ /** * @fn bool medAbstractImageView::is2D() * @brief Is the scene 2D (true) or 3D (false) */ /** * @fn qreal medAbstractImageView::sliceThickness() * @brief What is the thickness of the current slice (2D) */ /** * @fn qreal medAbstractImageView::scale() * @brief The scale (number of pixels on screen per mm) */ class medAbstractImageViewPrivate { public: QHash primaryInteractorsHash; QHash > extraInteractorsHash; medAbstractImageViewNavigator* primaryNavigator; QList extraNavigators; }; medAbstractImageView::medAbstractImageView(QObject *parent) : medAbstractLayeredView(parent), d(new medAbstractImageViewPrivate) { d->primaryNavigator = nullptr; } medAbstractImageView::~medAbstractImageView() { disconnect(this,SIGNAL(layerRemoved(unsigned int)),this,SLOT(updateDataListParameter(unsigned int))); int c = layersCount()-1; for(int i=c; i>=0; i--) removeLayer(i); delete d; } medAbstractImageViewInteractor* medAbstractImageView::primaryInteractor(medAbstractData* data) { if(d->primaryInteractorsHash.isEmpty()) return nullptr; return d->primaryInteractorsHash.value(data); } QList medAbstractImageView::extraInteractors(medAbstractData* data) { return d->extraInteractorsHash.value(data); } medAbstractImageViewInteractor* medAbstractImageView::primaryInteractor(unsigned int layer) { return d->primaryInteractorsHash.value(this->layerData(layer)); } QList medAbstractImageView::extraInteractors(unsigned int layer) { return d->extraInteractorsHash.value(this->layerData(layer)); } medAbstractImageViewNavigator* medAbstractImageView::primaryNavigator() { return d->primaryNavigator; } QList medAbstractImageView::extraNavigators() { return d->extraNavigators; } void medAbstractImageView::removeInteractors(medAbstractData *data) { medAbstractLayeredViewInteractor* pInteractor = d->primaryInteractorsHash.take(data); pInteractor->removeData(); delete pInteractor; QList extraInt = d->extraInteractorsHash.take(data); for(medAbstractInteractor* extra : extraInt) { delete extra; } extraInt.clear(); } bool medAbstractImageView::initialiseInteractors(medAbstractData *data) { // primary medViewFactory* factory = medViewFactory::instance(); QStringList primaryInt = factory->interactorsAbleToHandle(this->identifier(), data->identifier()); if(primaryInt.isEmpty()) { qWarning() << "Unable to find any primary interactor for: " << this->identifier() << "and" << data->identifier(); return false; } else { medAbstractImageViewInteractor* interactor = factory->createInteractor(primaryInt.first(), this); connect(this, SIGNAL(orientationChanged()), interactor, SLOT(updateWidgets())); connect(this, SIGNAL(currentLayerChanged()), interactor, SLOT(updateWidgets())); interactor->setInputData(data); d->primaryInteractorsHash.insert(data, interactor); } // extra QStringList extraInt = factory->additionalInteractorsAbleToHandle(this->identifier(), data->identifier()); if(!extraInt.isEmpty()) { QList extraIntList; for(QString i : extraInt) { medAbstractInteractor* interactor = factory->createAdditionalInteractor(i, this); connect(this, SIGNAL(orientationChanged()), interactor, SLOT(updateWidgets())); connect(this, SIGNAL(currentLayerChanged()), interactor, SLOT(updateWidgets())); interactor->setInputData(data); extraIntList << interactor; } d->extraInteractorsHash.insert(data, extraIntList); } return true; } bool medAbstractImageView::initialiseNavigators() { // primary medViewFactory* factory = medViewFactory::instance(); QStringList primaryNav = factory->navigatorsAbleToHandle(this->identifier()); if(primaryNav.isEmpty()) { qWarning() << "Unable to find any primary navigator for: " << this->identifier(); return false; } else { d->primaryNavigator = factory->createNavigator(primaryNav.first(), this); connect(this, SIGNAL(orientationChanged()), d->primaryNavigator, SLOT(updateWidgets())); connect(this, SIGNAL(currentLayerChanged()), d->primaryNavigator, SLOT(updateWidgets())); } // extra QStringList extraNav = factory->additionalNavigatorsAbleToHandle(this->identifier()); if(!extraNav.isEmpty()) { for(QString n : extraNav) { medAbstractNavigator* nav = factory->createAdditionalNavigator(n, this); connect(this, SIGNAL(orientationChanged()), nav, SLOT(updateWidgets())); connect(this, SIGNAL(currentLayerChanged()), nav, SLOT(updateWidgets())); d->extraNavigators << nav; } } return true; } void medAbstractImageView::switchToFourViews() { medViewContainer *topLeftContainer = dynamic_cast (this->parent()); medViewContainerSplitter *topLeftContainerSplitter = dynamic_cast (topLeftContainer->parent()); medViewContainer *bottomLeftContainer = topLeftContainer->splitVertically(); medViewContainer *topRightContainer = topLeftContainer->splitHorizontally(); medViewContainer *bottomRightContainer = bottomLeftContainer->splitHorizontally(); topLeftContainerSplitter->adjustContainersSize(); for(medDataIndex index : this->dataList()) { medAbstractData *data = medDataManager::instance()->retrieveData(index); if (data) { topRightContainer->addData(data); bottomLeftContainer->addData(data); bottomRightContainer->addData(data); } } this->setOrientation(medImageView::VIEW_ORIENTATION_3D); medAbstractImageView *bottomLeftContainerView = dynamic_cast (bottomLeftContainer->view()); medAbstractImageView *topRightContainerView = dynamic_cast (topRightContainer->view()); medAbstractImageView *bottomRightContainerView = dynamic_cast (bottomRightContainer->view()); bottomLeftContainerView->setOrientation(medImageView::VIEW_ORIENTATION_AXIAL); topRightContainerView->setOrientation(medImageView::VIEW_ORIENTATION_SAGITTAL); bottomRightContainerView->setOrientation(medImageView::VIEW_ORIENTATION_CORONAL); QString linkGroupBaseName = "MPR "; unsigned int linkGroupNumber = 1; QString linkGroupName = linkGroupBaseName + QString::number(linkGroupNumber); while (medParameterGroupManagerL::instance()->viewGroup(linkGroupName)) { linkGroupNumber++; linkGroupName = linkGroupBaseName + QString::number(linkGroupNumber); } medViewParameterGroupL *viewGroup = new medViewParameterGroupL(linkGroupName, this); viewGroup->addImpactedView(this); viewGroup->addImpactedView(topRightContainerView); viewGroup->addImpactedView(bottomLeftContainerView); viewGroup->addImpactedView(bottomRightContainerView); viewGroup->setLinkAllParameters(true); viewGroup->removeParameter("Slicing"); viewGroup->removeParameter("Orientation"); for (unsigned int i = 0;i < this->layersCount();++i) { QString linkLayerName = linkGroupBaseName + QString::number(linkGroupNumber) + " Layer " + QString::number(i+1); medLayerParameterGroupL* layerGroup = new medLayerParameterGroupL(linkLayerName, this); layerGroup->setLinkAllParameters(true); layerGroup->removeParameter("Slicing"); layerGroup->addImpactedlayer(this, this->layerData(i)); layerGroup->addImpactedlayer(topRightContainerView, topRightContainerView->layerData(i)); layerGroup->addImpactedlayer(bottomLeftContainerView, bottomLeftContainerView->layerData(i)); layerGroup->addImpactedlayer(bottomRightContainerView, bottomRightContainerView->layerData(i)); } for(medAbstractParameterL* param : this->linkableParameters()) { param->trigger(); } for (unsigned int i = 0;i < this->layersCount();++i) { for(medAbstractParameterL* param : this->linkableParameters(i)) { param->trigger(); } } topLeftContainer->setSelected(true); } void medAbstractImageView::setOrientation(medImageView::Orientation orientation) { medAbstractImageViewNavigator * nav = this->primaryNavigator(); if(!nav) return; nav->setOrientation(orientation); emit orientationChanged(); } /** * Return a composite parameter made of: * QVector3D &position, QVector3D &viewup, QVector3D &focal, double ¶llelScale */ medCompositeParameterL *medAbstractImageView::cameraParameter() { medAbstractImageViewNavigator* pNavigator = this->primaryNavigator(); if(!pNavigator) { return nullptr; } return pNavigator->cameraParameter(); } medAbstractVector3DParameterL *medAbstractImageView::positionBeingViewedParameter() { medAbstractImageViewNavigator* pNavigator = this->primaryNavigator(); if(!pNavigator) { return nullptr; } return pNavigator->positionBeingViewedParameter(); } medDoubleParameterL *medAbstractImageView::opacityParameter(unsigned int layer) { medAbstractImageViewInteractor* pInteractor = this->primaryInteractor(layer); if(!pInteractor) { return nullptr; } return pInteractor->opacityParameter(); } /** * Return a composite parameter made of: * double &window, double level */ medCompositeParameterL *medAbstractImageView::windowLevelParameter(unsigned int layer) { medAbstractImageViewInteractor* pInteractor = this->primaryInteractor(layer); if(!pInteractor) { return nullptr; } return pInteractor->windowLevelParameter(); } medTimeLineParameterL *medAbstractImageView::timeLineParameter() { medAbstractImageViewNavigator* pNavigator = this->primaryNavigator(); if(!pNavigator) { return nullptr; } return pNavigator->timeLineParameter(); } medImageView::Orientation medAbstractImageView::orientation() { medAbstractImageViewNavigator * nav = this->primaryNavigator(); if(!nav) return medImageView::VIEW_ORIENTATION_AXIAL; return nav->orientation(); } bool medAbstractImageView::setRotation(double angle) { int res = false; medAbstractImageViewNavigator *nav = this->primaryNavigator(); if(nav) { // Set view in 3D if not done before if (this->orientation() != medImageView::VIEW_ORIENTATION_3D) { this->setOrientation(medImageView::VIEW_ORIENTATION_3D); } res = nav->setRotationAngle(angle); } return res; } bool medAbstractImageView::setSlice(int slice) { int res = false; medAbstractImageViewNavigator *nav = this->primaryNavigator(); if(nav) { res = nav->setSlice(slice); } return res; }