/**Move the tool pos / axis pos to a new position given * by the input click position in vp space. */ void ViewWrapper2D::setAxisPos(Vector3D click_vp) { ToolPtr tool = mServices->getToolManager()->getManualTool(); Transform3D sMr = mSliceProxy->get_sMr(); Transform3D rMpr = mServices->getPatientService()->get_rMpr(); Transform3D prMt = tool->get_prMt(); // find tool position in s Vector3D tool_t(0, 0, tool->getTooltipOffset()); Vector3D tool_s = (sMr * rMpr * prMt).coord(tool_t); // find click position in s. Transform3D vpMs = mView->get_vpMs(); Vector3D click_s = vpMs.inv().coord(click_vp); // compute the new tool position in slice space as a synthesis of the plane part of click and the z part of original. Vector3D cross_s(click_s[0], click_s[1], tool_s[2]); // compute the position change and transform to patient. Vector3D delta_s = cross_s - tool_s; Vector3D delta_pr = (rMpr.inv() * sMr.inv()).vector(delta_s); // MD is the actual tool movement in patient space, matrix form Transform3D MD = createTransformTranslate(delta_pr); // set new tool position to old modified by MD: tool->set_prMt(MD * prMt); }
void ViewWrapper2D::samplePoint(Vector3D click_vp) { if(!this->isAnyplane()) return; Transform3D sMr = mSliceProxy->get_sMr(); Transform3D vpMs = mView->get_vpMs(); Vector3D p_s = vpMs.inv().coord(click_vp); Vector3D p_r = sMr.inv().coord(p_s); emit pointSampled(p_r); }
/**Call when viewport size or zoom has changed. * Recompute camera zoom and reps requiring vpMs. */ void ViewWrapper2D::viewportChanged() { if (!mView->getRenderer()->IsActiveCameraCreated()) return; mView->setZoomFactor(mZoom2D->getFactor()); double viewHeight = mView->getViewport_s().range()[1]; mView->getRenderer()->GetActiveCamera()->SetParallelScale(viewHeight / 2); // Heuristic guess for a good clip depth. The point is to show 3D data clipped in 2D // with a suitable thickness projected onto the plane. double clipDepth = 2.0; // i.e. all 3D props rendered outside this range is not shown. double length = clipDepth*10; clipDepth = viewHeight/120 + 1.5; mView->getRenderer()->GetActiveCamera()->SetPosition(0,0,length); mView->getRenderer()->GetActiveCamera()->SetClippingRange(length-clipDepth, length+0.1); mSliceProxy->setToolViewportHeight(viewHeight); double anyplaneViewOffset = settings()->value("Navigation/anyplaneViewOffset").toDouble(); mSliceProxy->initializeFromPlane(mSliceProxy->getComputer().getPlaneType(), false, Vector3D(0, 0, 1), true, viewHeight, anyplaneViewOffset, true); DoubleBoundingBox3D BB_vp = getViewport(); Transform3D vpMs = mView->get_vpMs(); DoubleBoundingBox3D BB_s = transform(vpMs.inv(), BB_vp); PLANE_TYPE plane = mSliceProxy->getComputer().getPlaneType(); mToolRep2D->setViewportData(vpMs, BB_vp); if (mSlicePlanes3DMarker) { mSlicePlanes3DMarker->getProxy()->setViewportData(plane, mSliceProxy, BB_s); } mViewFollower->setView(BB_s); }
void LandmarkRegistrationWidget::cellChangedSlot(int row, int column) { QTableWidgetItem* item = mLandmarkTableWidget->item(row, column); QString uid = item->data(Qt::UserRole).toString(); if (column == 0) { QString name = item->text(); mServices->patient()->setLandmarkName(uid, name); } if (column == 1) { Qt::CheckState state = item->checkState(); mServices->patient()->setLandmarkActive(uid, state == Qt::Checked); this->performRegistration(); // automatic when changing active state (Mantis #0000674)s } if (column == 2) { QString val = item->text(); // remove formatting stuff: val = val.replace('(', " "); val = val.replace(')', " "); val = val.replace(',', " "); Transform3D rMtarget = this->getTargetTransform(); Vector3D p_r = Vector3D::fromString(val); Vector3D p_target = rMtarget.inv().coord(p_r); this->setTargetLandmark(uid, p_target); } }
/**\brief Identical to doFastRegistration_Orientation(), except data does not move. * * When applying a new transform to the patient orientation, all data is moved * the the inverse of that value, thus giving a net zero change along the path * pr...d_i. * */ void RegistrationImplService::applyPatientOrientation(const Transform3D& tMtm, const Transform3D& prMt) { Transform3D rMpr = mPatientModelService->get_rMpr(); //create a marked(m) space tm, which is related to tool space (t) as follows: //the tool is defined in DICOM space such that //the tool points toward the patients feet and the spheres faces the same //direction as the nose Transform3D tMpr = prMt.inv(); // this is the new patient registration: Transform3D tmMpr = tMtm * tMpr; // the change in pat reg becomes: Transform3D F = tmMpr * rMpr.inv(); QString description("Patient Orientation"); QDateTime oldTime = this->getLastRegistrationTime(); // time of previous reg this->applyPatientRegistration(tmMpr, description); // now apply the inverse of F to all data, // thus ensuring the total path from pr to d_i is unchanged: Transform3D delta_pre_rMd = F; // use the same registration time as generated in the applyPatientRegistration() above: RegistrationTransform regTrans(delta_pre_rMd, this->getLastRegistrationTime(), description); std::map<QString,DataPtr> data = mPatientModelService->getData(); // update the transform on all target data: for (std::map<QString,DataPtr>::iterator iter = data.begin(); iter!=data.end(); ++iter) { DataPtr current = iter->second; RegistrationTransform newTransform = regTrans; newTransform.mValue = regTrans.mValue * current->get_rMd(); current->get_rMd_History()->updateRegistration(oldTime, newTransform); report("Updated registration of data " + current->getName()); std::cout << "rMd_new\n" << newTransform.mValue << std::endl; } this->setLastRegistrationTime(regTrans.mTimestamp); reportSuccess("Patient Orientation has been performed"); }
/**Move the tool pos / axis pos to a new position given * by delta movement in vp space. */ void ViewWrapper2D::shiftAxisPos(Vector3D delta_vp) { delta_vp = -delta_vp; ToolPtr tool = mServices->getToolManager()->getManualTool(); Transform3D sMr = mSliceProxy->get_sMr(); Transform3D rMpr = mServices->getPatientService()->get_rMpr(); Transform3D prMt = tool->get_prMt(); Transform3D vpMs = mView->get_vpMs(); Vector3D delta_s = vpMs.inv().vector(delta_vp); Vector3D delta_pr = (rMpr.inv() * sMr.inv()).vector(delta_s); // MD is the actual tool movement in patient space, matrix form Transform3D MD = createTransformTranslate(delta_pr); // set new tool position to old modified by MD: tool->set_prMt(MD * prMt); }
Vector3D ViewFollower::findCenter_r_fromShift_s(Vector3D shift_s) { Transform3D sMr = mSliceProxy->get_sMr(); Vector3D c_s = sMr.coord(mDataManager->getCenter()); Vector3D newcenter_s = c_s + shift_s; Vector3D newcenter_r = sMr.inv().coord(newcenter_s); return newcenter_r; }
/**called when transform is changed * reset it in the prop.*/ void GeometricRep2D::transformChangedSlot() { if (!mSlicer || !mMesh) return; Transform3D rMs = mSlicer->get_sMr().inv(); Transform3D dMr = mMesh->get_rMd().inv(); Transform3D dMs = dMr * rMs; mActor->SetUserMatrix(dMs.inv().getVtkMatrix()); }
void ViewWrapper2D::setSlicePlanesProxy(SlicePlanesProxyPtr proxy) { mSlicePlanes3DMarker = SlicePlanes3DMarkerIn2DRep::New("uid"); PLANE_TYPE plane = mSliceProxy->getComputer().getPlaneType(); mSlicePlanes3DMarker->setProxy(plane, proxy); DoubleBoundingBox3D BB_vp = getViewport(); Transform3D vpMs = mView->get_vpMs(); mSlicePlanes3DMarker->getProxy()->setViewportData(plane, mSliceProxy, transform(vpMs.inv(), BB_vp)); mView->addRep(mSlicePlanes3DMarker); }
/**Perform a fast orientation by setting the patient registration equal to the current active * tool position. * Input is an additional transform tMtm that modifies the tool position. Use this to * define DICOM-ish spaces relative to the tool. * */ void RegistrationImplService::doFastRegistration_Orientation(const Transform3D& tMtm, const Transform3D& prMt) { //create a marked(m) space tm, which is related to tool space (t) as follows: //the tool is defined in DICOM space such that //the tool points toward the patients feet and the spheres faces the same //direction as the nose Transform3D tMpr = prMt.inv(); Transform3D tmMpr = tMtm * tMpr; this->applyPatientRegistration(tmMpr, "Fast Orientation"); // also apply the fast translation registration if any (this frees us form doing stuff in a well-defined order.) this->doFastRegistration_Translation(); }
void LandmarkRegistrationWidget::setManualToolPosition(Vector3D p_r) { Transform3D rMpr = mServices->patient()->get_rMpr(); Vector3D p_pr = rMpr.inv().coord(p_r); // set the picked point as offset tip ToolPtr tool = mServices->tracking()->getManualTool(); Vector3D offset = tool->get_prMt().vector(Vector3D(0, 0, tool->getTooltipOffset())); p_pr -= offset; p_r = rMpr.coord(p_pr); // TODO set center here will not do: must handle mServices->patient()->setCenter(p_r); Vector3D p0_pr = tool->get_prMt().coord(Vector3D(0, 0, 0)); tool->set_prMt(createTransformTranslate(p_pr - p0_pr) * tool->get_prMt()); }
Transform3D ManualImage2ImageRegistrationWidget::getMatrixFromBackend() { if (!this->isValid()) // Check if fixed and moving data are defined return Transform3D::Identity(); Transform3D rMm = mServices->registration()->getMovingData()->get_rMd(); Transform3D rMf = mServices->registration()->getFixedData()->get_rMd(); Transform3D fMm = rMf.inv() * rMm; RegistrationHistoryPtr history = mServices->registration()->getMovingData()->get_rMd_History(); Transform3D init_rMd; if(!history->getData().empty()) // Is vector with RegistrationTransforms empty ? init_rMd = history->getData().front().mValue; else init_rMd = Transform3D::Identity(); Transform3D current_rMd = history->getCurrentRegistration().mValue; fMm = current_rMd * init_rMd.inv(); return fMm; }
void ElastixManager::executionFinishedSlot() { if (mDisableRendering->getValue()) mServices->view()->enableRender(true); bool ok = false; Transform3D mMf = mExecuter->getAffineResult_mMf(&ok); if (!ok) return; // std::cout << "ElastixManager::executionFinishedSlot(), Linear Result mMf: \n" << mMf << std::endl; QStringList parameterFiles = mParameters->getActiveParameterFiles(); QString desc = QString("Image2Image [exe=%1]").arg(QFileInfo(mParameters->getActiveExecutable()->getValue()).fileName()); for (unsigned i=0; i<parameterFiles.size(); ++i) desc += QString("[par=%1]").arg(QFileInfo(parameterFiles[i]).fileName()); // Start with fMr * D * rMm = fMm' // where the lhs is the existing data and the delta that is input to regmanager, // and the rhs is the (inverse of the) output from ElastiX. // This gives // D = rMf * fMm' * mMr // as the input to regmanager applyImage2ImageRegistration() Transform3D delta_pre_rMd = mServices->registration()->getFixedData()->get_rMd() * mMf.inv() * mServices->registration()->getMovingData()->get_rMd().inv(); // std::cout << "ElastixManager::executionFinishedSlot(), delta_pre_rMd: \n" << delta_pre_rMd << std::endl; // std::cout << "ElastixManager::executionFinishedSlot(), expected new rMdm: \n" << mServices->registration()->getFixedData()->get_rMd() * mMf.inv() << std::endl; // mServices->registration()->applyImage2ImageRegistration(mMf.inv(), desc); mServices->registration()->applyImage2ImageRegistration(delta_pre_rMd, desc); // add nonlinear data AFTER registering - we dont want these data to be double-registered! this->addNonlinearData(); }
/** return the bow widget current size in data space */ DoubleBoundingBox3D InteractiveCropper::getBoxWidgetSize() { if (!mImage || !mBoxWidget) { return DoubleBoundingBox3D::zero(); } double bb_hard[6] = { -0.5, 0.5, -0.5, 0.5, -0.5, 0.5 }; DoubleBoundingBox3D bb_unit(bb_hard); vtkTransformPtr transform = vtkTransformPtr::New(); mBoxWidget->GetTransform(transform); Transform3D M(transform->GetMatrix()); Transform3D rMd = mImage->get_rMd(); M = rMd.inv() * M; DoubleBoundingBox3D bb_new_r = cx::transform(M, bb_unit); return bb_new_r; }
void ManualImage2ImageRegistrationWidget::setMatrixFromWidget(Transform3D M) { if (!this->isValid()) // Check if fixed and moving data are defined return; Transform3D rMm = mServices->registration()->getMovingData()->get_rMd(); RegistrationHistoryPtr history = mServices->registration()->getMovingData()->get_rMd_History(); Transform3D init_rMd; if(!history->getData().empty()) // Is vector with RegistrationTransforms empty ? init_rMd = history->getData().front().mValue; else init_rMd = Transform3D::Identity(); Transform3D new_rMd = M * init_rMd; Transform3D delta = new_rMd * rMm.inv(); mServices->registration()->addImage2ImageRegistration(delta, "Manual Image"); this->updateAverageAccuracyLabel(); }