/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkUpdateWhitakerSparseLevelSet_hxx #define itkUpdateWhitakerSparseLevelSet_hxx #include "itkConnectedImageNeighborhoodShape.h" namespace itk { template UpdateWhitakerSparseLevelSet::UpdateWhitakerSparseLevelSet() : m_TimeStep(NumericTraits::OneValue()) , m_RMSChangeAccumulator(LevelSetOutputType{}) , m_CurrentLevelSetId(IdentifierType{}) , m_MinStatus(LevelSetType::MinusThreeLayer()) , m_MaxStatus(LevelSetType::PlusThreeLayer()) { this->m_Offset.Fill(0); this->m_TempLevelSet = LevelSetType::New(); this->m_OutputLevelSet = LevelSetType::New(); } template void UpdateWhitakerSparseLevelSet::SetUpdate( const LevelSetLayerType & update) { this->m_Update = update; } template void UpdateWhitakerSparseLevelSet::Update() { if (this->m_InputLevelSet.IsNull()) { itkGenericExceptionMacro("m_InputLevelSet is nullptr"); } if (this->m_Update.empty()) { itkGenericExceptionMacro("m_Update is empty"); } this->m_Offset = this->m_InputLevelSet->GetDomainOffset(); // copy input to output. Will not use input again // store modified output in this->m_TempLevelSet this->m_OutputLevelSet->SetLayer(LevelSetType::MinusTwoLayer(), this->m_InputLevelSet->GetLayer(LevelSetType::MinusTwoLayer())); this->m_OutputLevelSet->SetLayer(LevelSetType::MinusOneLayer(), this->m_InputLevelSet->GetLayer(LevelSetType::MinusOneLayer())); this->m_OutputLevelSet->SetLayer(LevelSetType::ZeroLayer(), this->m_InputLevelSet->GetLayer(LevelSetType::ZeroLayer())); this->m_OutputLevelSet->SetLayer(LevelSetType::PlusOneLayer(), this->m_InputLevelSet->GetLayer(LevelSetType::PlusOneLayer())); this->m_OutputLevelSet->SetLayer(LevelSetType::PlusTwoLayer(), this->m_InputLevelSet->GetLayer(LevelSetType::PlusTwoLayer())); this->m_OutputLevelSet->SetDomainOffset(this->m_Offset); this->m_TempLevelSet->SetDomainOffset(this->m_Offset); this->m_OutputLevelSet->SetLabelMap(this->m_InputLevelSet->GetModifiableLabelMap()); auto labelMapToLabelImageFilter = LabelMapToLabelImageFilterType::New(); labelMapToLabelImageFilter->SetInput(this->m_InputLevelSet->GetLabelMap()); labelMapToLabelImageFilter->Update(); this->m_InternalImage = labelMapToLabelImageFilter->GetOutput(); this->m_InternalImage->DisconnectPipeline(); this->m_TempPhi.clear(); // TODO: ARNAUD: Why is 2 not included here? // Arnaud: Being iterated upon later, so no need to do it here. // Here, we are adding all pairs of indices and levelset values to a map for (LevelSetLayerIdType status = LevelSetType::MinusOneLayer(); status < LevelSetType::PlusTwoLayer(); ++status) { const LevelSetLayerType layer = this->m_InputLevelSet->GetLayer(status); auto it = layer.begin(); while (it != layer.end()) { this->m_TempPhi[it->first] = it->second; ++it; } } /** todo: put neighborhood creation in protected method */ ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); const LevelSetLayerType & layerMinus2 = this->m_InputLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); auto it = layerMinus2.begin(); while (it != layerMinus2.end()) { const LevelSetInputType currentIndex = it->first; this->m_TempPhi[currentIndex] = LevelSetType::MinusTwoLayer(); neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator nIt = neighIt.Begin(); !nIt.IsAtEnd(); ++nIt) { if (nIt.Get() == LevelSetType::MinusThreeLayer()) { const LevelSetInputType neighborIndex = neighIt.GetIndex(nIt.GetNeighborhoodOffset()); this->m_TempPhi[neighborIndex] = LevelSetType::MinusThreeLayer(); } } ++it; } LevelSetLayerType layerPlus2 = this->m_InputLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); it = layerPlus2.begin(); while (it != layerPlus2.end()) { LevelSetInputType currentIndex = it->first; this->m_TempPhi[currentIndex] = LevelSetType::PlusTwoLayer(); neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator nIt = neighIt.Begin(); !nIt.IsAtEnd(); ++nIt) { if (nIt.Get() == LevelSetType::PlusThreeLayer()) { LevelSetInputType neighborIndex = neighIt.GetIndex(nIt.GetNeighborhoodOffset()); this->m_TempPhi[neighborIndex] = LevelSetType::PlusThreeLayer(); } } ++it; } this->UpdateLayerZero(); this->UpdateLayerMinus1(); this->UpdateLayerPlus1(); this->UpdateLayerMinus2(); this->UpdateLayerPlus2(); this->MovePointIntoZeroLevelSet(); this->MovePointFromMinus1(); this->MovePointFromPlus1(); this->MovePointFromMinus2(); this->MovePointFromPlus2(); auto labelImageToLabelMapFilter = LabelImageToLabelMapFilterType::New(); labelImageToLabelMapFilter->SetInput(this->m_InternalImage); labelImageToLabelMapFilter->SetBackgroundValue(LevelSetType::PlusThreeLayer()); labelImageToLabelMapFilter->Update(); this->m_OutputLevelSet->GetModifiableLabelMap()->Graft(labelImageToLabelMapFilter->GetOutput()); this->m_TempPhi.clear(); } template void UpdateWhitakerSparseLevelSet::UpdateLayerZero() { TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & outputLayer0 = this->m_OutputLevelSet->GetLayer(LevelSetType::ZeroLayer()); LevelSetLayerType & layerMinus1 = this->m_TempLevelSet->GetLayer(LevelSetType::MinusOneLayer()); LevelSetLayerType & layerPlus1 = this->m_TempLevelSet->GetLayer(LevelSetType::PlusOneLayer()); itkAssertInDebugAndIgnoreInReleaseMacro(this->m_Update.size() == outputLayer0.size()); auto nodeIt = outputLayer0.begin(); auto nodeEnd = outputLayer0.end(); auto upIt = this->m_Update.begin(); ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); LevelSetInputType inputIndex; while (nodeIt != nodeEnd) { itkAssertInDebugAndIgnoreInReleaseMacro(nodeIt->first == upIt->first); LevelSetInputType currentIndex = nodeIt->first; inputIndex = currentIndex + this->m_Offset; LevelSetOutputType currentValue = nodeIt->second; LevelSetOutputType tempUpdate = this->m_TimeStep * static_cast(upIt->second); if (tempUpdate > 0.5) { // what about 0.5 - itk::NumericTraits< LevelSetOutputType >::epsilon(); ? tempUpdate = 0.499; } else if (tempUpdate < -0.5) { // what about - ( 0.5 - itk::NumericTraits< LevelSetOutputType >::epsilon(); ) ? tempUpdate = -0.499; } LevelSetOutputType tempValue = currentValue + tempUpdate; this->m_RMSChangeAccumulator += tempUpdate * tempUpdate; if (tempValue > 0.5) { // is there any point moving in the opposite direction? bool samedirection = true; neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { if (it.Get() == LevelSetType::ZeroLayer()) { LevelSetInputType tempIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto tit = this->m_TempPhi.find(tempIndex); if (tit != this->m_TempPhi.end()) { if (tit->second < -0.5) { samedirection = false; } } } } if (samedirection) { auto tit = this->m_TempPhi.find(currentIndex); if (tit != this->m_TempPhi.end()) { termContainer->UpdatePixel(inputIndex, tit->second, tempValue); tit->second = tempValue; } else { // Kishore: Never comes here? this->m_TempPhi.insert(NodePairType(currentIndex, tempValue)); } auto tempIt = nodeIt; ++nodeIt; ++upIt; // remove p from Lz outputLayer0.erase(tempIt); // add p to Sp1 layerPlus1.insert(NodePairType(currentIndex, tempValue)); } else // samedirection == false { ++nodeIt; ++upIt; } } // end of if( tempValue > 0.5 ) else if (tempValue < -0.5) { bool samedirection = true; neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { if (it.Get() == LevelSetType::ZeroLayer()) { LevelSetInputType tempIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto tit = this->m_TempPhi.find(tempIndex); if (tit != this->m_TempPhi.end()) { if (tit->second > 0.5) { samedirection = false; } } } } if (samedirection) { auto tit = this->m_TempPhi.find(currentIndex); if (tit != this->m_TempPhi.end()) { // change values termContainer->UpdatePixel(inputIndex, tit->second, tempValue); tit->second = tempValue; } else { // Kishore: Can this happen? this->m_TempPhi.insert(NodePairType(currentIndex, tempValue)); } auto tempIt = nodeIt; ++nodeIt; ++upIt; outputLayer0.erase(tempIt); layerMinus1.insert(NodePairType(currentIndex, tempValue)); } else // samedirection == false { ++nodeIt; ++upIt; } } else // -0.5 <= temp <= 0.5 { auto it = this->m_TempPhi.find(currentIndex); if (it != this->m_TempPhi.end()) { // change values termContainer->UpdatePixel(inputIndex, it->second, tempValue); it->second = tempValue; } nodeIt->second = tempValue; ++nodeIt; ++upIt; } } // while( nodeIt != nodeEnd ) } template void UpdateWhitakerSparseLevelSet::UpdateLayerMinus1() { TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); LevelSetLayerType & outputlayerMinus1 = this->m_OutputLevelSet->GetLayer(LevelSetType::MinusOneLayer()); LevelSetLayerType & layerMinusTwo = this->m_TempLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); LevelSetLayerType & layerZero = this->m_TempLevelSet->GetLayer(LevelSetType::ZeroLayer()); auto nodeIt = outputlayerMinus1.begin(); auto nodeEnd = outputlayerMinus1.end(); LevelSetInputType inputIndex; while (nodeIt != nodeEnd) { LevelSetInputType currentIndex = nodeIt->first; inputIndex = currentIndex + this->m_Offset; neighIt.SetLocation(currentIndex); bool thereIsAPointWithLabelEqualTo0 = false; LevelSetOutputType max = NumericTraits::NonpositiveMin(); // compute M and check if point with label 0 exists in the neighborhood for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { LevelSetInputType tempIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); LevelSetLayerIdType label = it.Get(); if (label >= LevelSetType::ZeroLayer()) { if (label == LevelSetType::ZeroLayer()) { thereIsAPointWithLabelEqualTo0 = true; } auto phiIt = this->m_TempPhi.find(tempIndex); itkAssertInDebugAndIgnoreInReleaseMacro(phiIt != this->m_TempPhi.end()); max = std::max(max, phiIt->second); } } // end for if (thereIsAPointWithLabelEqualTo0) { auto phiIt = this->m_TempPhi.find(currentIndex); max = max - 1.; if (phiIt != this->m_TempPhi.end()) { // change value termContainer->UpdatePixel(inputIndex, phiIt->second, max); phiIt->second = max; nodeIt->second = max; } else { // Kishore: Can this happen? this->m_TempPhi.insert(NodePairType(currentIndex, max)); } if (max >= -0.5) { // change layers only auto tempIt = nodeIt; ++nodeIt; outputlayerMinus1.erase(tempIt); layerZero.insert(NodePairType(currentIndex, max)); } else if (max < -1.5) { // change layers only auto tempIt = nodeIt; ++nodeIt; outputlayerMinus1.erase(tempIt); layerMinusTwo.insert(NodePairType(currentIndex, max)); } else { ++nodeIt; } } else // !thereIsAPointWithLabelEqualTo0 { // change layers only auto tempIt = nodeIt; LevelSetOutputType t = tempIt->second; ++nodeIt; outputlayerMinus1.erase(tempIt); layerMinusTwo.insert(NodePairType(currentIndex, t)); } } } template void UpdateWhitakerSparseLevelSet::UpdateLayerPlus1() { ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & layerPlus2 = this->m_TempLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); LevelSetLayerType & layerZero = this->m_TempLevelSet->GetLayer(LevelSetType::ZeroLayer()); LevelSetLayerType & outputLayerPlus1 = this->m_OutputLevelSet->GetLayer(LevelSetType::PlusOneLayer()); auto nodeIt = outputLayerPlus1.begin(); auto nodeEnd = outputLayerPlus1.end(); while (nodeIt != nodeEnd) { const LevelSetInputType currentIndex = nodeIt->first; const LevelSetInputType inputIndex = currentIndex + this->m_Offset; neighIt.SetLocation(currentIndex); bool thereIsAPointWithLabelEqualTo0 = false; LevelSetOutputType max = NumericTraits::max(); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { LevelSetLayerIdType label = it.Get(); if (label <= LevelSetType::ZeroLayer()) { if (label == LevelSetType::ZeroLayer()) { thereIsAPointWithLabelEqualTo0 = true; } const LevelSetInputType neighborIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto phiIt = this->m_TempPhi.find(neighborIndex); if (phiIt != this->m_TempPhi.end()) { max = std::min(max, phiIt->second); } else { itkDebugMacro(<< neighborIndex << "is not in this->m_TempPhi" << std::endl); } } } // end for if (thereIsAPointWithLabelEqualTo0) { auto phiIt = this->m_TempPhi.find(currentIndex); max = max + 1.; if (phiIt != this->m_TempPhi.end()) { // change in value termContainer->UpdatePixel(inputIndex, phiIt->second, max); phiIt->second = max; nodeIt->second = max; } else { // Kishore: can this happen? this->m_TempPhi.insert(NodePairType(currentIndex, max)); } if (max <= 0.5) { // change layers only auto tempIt = nodeIt; ++nodeIt; outputLayerPlus1.erase(tempIt); layerZero.insert(NodePairType(currentIndex, max)); } else if (max > 1.5) { // change layers only auto tempIt = nodeIt; ++nodeIt; outputLayerPlus1.erase(tempIt); layerPlus2.insert(NodePairType(currentIndex, max)); } else { ++nodeIt; } } else { // change layers only auto tempIt = nodeIt; LevelSetOutputType t = tempIt->second; ++nodeIt; outputLayerPlus1.erase(tempIt); layerPlus2.insert(NodePairType(currentIndex, t)); } } } template void UpdateWhitakerSparseLevelSet::UpdateLayerMinus2() { ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & outputLayerMinus2 = this->m_OutputLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); LevelSetLayerType & layerMinus1 = this->m_TempLevelSet->GetLayer(LevelSetType::MinusOneLayer()); auto nodeIt = outputLayerMinus2.begin(); const LevelSetLayerIterator nodeEnd = outputLayerMinus2.end(); while (nodeIt != nodeEnd) { const LevelSetInputType currentIndex = nodeIt->first; const LevelSetInputType inputIndex = currentIndex + this->m_Offset; neighIt.SetLocation(currentIndex); bool thereIsAPointWithLabelEqualToMinus1 = false; LevelSetOutputType max = NumericTraits::NonpositiveMin(); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { const LevelSetLayerIdType label = it.Get(); if (label >= LevelSetType::MinusOneLayer()) { if (label == LevelSetType::MinusOneLayer()) { thereIsAPointWithLabelEqualToMinus1 = true; } const LevelSetInputType neighborIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); const LevelSetLayerIterator phiIt = this->m_TempPhi.find(neighborIndex); itkAssertInDebugAndIgnoreInReleaseMacro(phiIt != this->m_TempPhi.end()); max = std::max(max, phiIt->second); } } // end for if (thereIsAPointWithLabelEqualToMinus1) { const LevelSetLayerIterator phiIt = this->m_TempPhi.find(currentIndex); max = max - 1.; if (phiIt != this->m_TempPhi.end()) { // change values termContainer->UpdatePixel(inputIndex, phiIt->second, max); phiIt->second = max; nodeIt->second = max; } else { // Kishore: can this happen? this->m_TempPhi.insert(NodePairType(currentIndex, max)); } if (max >= -1.5) // change layers only { auto tempIt = nodeIt; ++nodeIt; outputLayerMinus2.erase(tempIt); layerMinus1.insert(NodePairType(currentIndex, max)); } else if (max < -2.5) // change layers only { auto tempIt = nodeIt; ++nodeIt; outputLayerMinus2.erase(tempIt); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::MinusThreeLayer()); termContainer->UpdatePixel(inputIndex, max, LevelSetType::MinusThreeLayer()); this->m_TempPhi.erase(currentIndex); } else { ++nodeIt; } } else // change value { auto tempIt = nodeIt; ++nodeIt; this->m_InternalImage->SetPixel(currentIndex, LevelSetType::MinusThreeLayer()); termContainer->UpdatePixel(inputIndex, tempIt->second, LevelSetType::MinusThreeLayer()); outputLayerMinus2.erase(tempIt); this->m_TempPhi.erase(currentIndex); } } } template void UpdateWhitakerSparseLevelSet::UpdateLayerPlus2() { ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & outputLayerPlus2 = this->m_OutputLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); LevelSetLayerType & layerPlusOne = this->m_TempLevelSet->GetLayer(LevelSetType::PlusOneLayer()); auto nodeIt = outputLayerPlus2.begin(); const LevelSetLayerIterator nodeEnd = outputLayerPlus2.end(); while (nodeIt != nodeEnd) { const LevelSetInputType currentIndex = nodeIt->first; const LevelSetInputType inputIndex = currentIndex + this->m_Offset; neighIt.SetLocation(currentIndex); bool thereIsAPointWithLabelEqualToPlus1 = false; LevelSetOutputType max = NumericTraits::max(); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { LevelSetLayerIdType label = it.Get(); if (label <= LevelSetType::PlusOneLayer()) { if (label == LevelSetType::PlusOneLayer()) { thereIsAPointWithLabelEqualToPlus1 = true; } const LevelSetInputType neighborIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto phiIt = this->m_TempPhi.find(neighborIndex); if (phiIt != this->m_TempPhi.end()) { max = std::min(max, phiIt->second); } else { itkDebugMacro(<< neighborIndex << " is not in this->m_TempPhi" << std::endl); } } } if (thereIsAPointWithLabelEqualToPlus1) { auto phiIt = this->m_TempPhi.find(currentIndex); max = max + 1.; if (phiIt != this->m_TempPhi.end()) // change values { termContainer->UpdatePixel(inputIndex, phiIt->second, max); phiIt->second = max; nodeIt->second = max; } else // todo: remove dead code { // Kishore: can this happen? this->m_TempPhi.insert(NodePairType(currentIndex, max)); } if (max <= 1.5) // change layers { auto tempIt = nodeIt; ++nodeIt; outputLayerPlus2.erase(tempIt); layerPlusOne.insert(NodePairType(currentIndex, max)); } else if (max > 2.5) // change layers { auto tempIt = nodeIt; ++nodeIt; outputLayerPlus2.erase(tempIt); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::PlusThreeLayer()); termContainer->UpdatePixel(inputIndex, max, LevelSetType::PlusThreeLayer()); this->m_TempPhi.erase(currentIndex); } else { ++nodeIt; } } else // change values { auto tempIt = nodeIt; ++nodeIt; this->m_InternalImage->SetPixel(currentIndex, LevelSetType::PlusThreeLayer()); termContainer->UpdatePixel(inputIndex, tempIt->second, LevelSetType::PlusThreeLayer()); outputLayerPlus2.erase(tempIt); this->m_TempPhi.erase(currentIndex); } } } template void UpdateWhitakerSparseLevelSet::MovePointIntoZeroLevelSet() { LevelSetLayerType & layer0 = this->m_TempLevelSet->GetLayer(LevelSetType::ZeroLayer()); LevelSetLayerType & outputLayer0 = this->m_OutputLevelSet->GetLayer(LevelSetType::ZeroLayer()); auto nodeIt = layer0.begin(); auto nodeEnd = layer0.end(); while (nodeIt != nodeEnd) { outputLayer0.insert(NodePairType(nodeIt->first, nodeIt->second)); this->m_InternalImage->SetPixel(nodeIt->first, LevelSetType::ZeroLayer()); auto tempIt = nodeIt; ++nodeIt; layer0.erase(tempIt); } } template void UpdateWhitakerSparseLevelSet::MovePointFromMinus1() { ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & layerMinus1 = this->m_TempLevelSet->GetLayer(LevelSetType::MinusOneLayer()); LevelSetLayerType & layerMinus2 = this->m_TempLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); LevelSetLayerType & outputlayerMinus1 = this->m_OutputLevelSet->GetLayer(LevelSetType::MinusOneLayer()); auto nodeIt = layerMinus1.begin(); auto nodeEnd = layerMinus1.end(); while (nodeIt != nodeEnd) { LevelSetInputType currentIndex = nodeIt->first; LevelSetOutputType currentValue = nodeIt->second; outputlayerMinus1.insert(NodePairType(currentIndex, currentValue)); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::MinusOneLayer()); auto tempIt = nodeIt; ++nodeIt; layerMinus1.erase(tempIt); neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { LevelSetInputType tempIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto phiIt = this->m_TempPhi.find(tempIndex); if (phiIt != this->m_TempPhi.end()) { if (Math::ExactlyEquals(phiIt->second, -3.)) // change values { phiIt->second = currentValue - 1; layerMinus2.insert(NodePairType(tempIndex, currentValue - 1)); termContainer->UpdatePixel(tempIndex + m_Offset, LevelSetType::MinusThreeLayer(), phiIt->second); } } } } } template void UpdateWhitakerSparseLevelSet::MovePointFromPlus1() { ZeroFluxNeumannBoundaryCondition spNBC; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(1); NeighborhoodIteratorType neighIt(radius, this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion()); neighIt.OverrideBoundaryCondition(&spNBC); neighIt.ActivateOffsets(GenerateConnectedImageNeighborhoodShapeOffsets()); TermContainerPointer termContainer = this->m_EquationContainer->GetEquation(this->m_CurrentLevelSetId); LevelSetLayerType & layerPlus1 = this->m_TempLevelSet->GetLayer(LevelSetType::PlusOneLayer()); LevelSetLayerType & layerPlus2 = this->m_TempLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); LevelSetLayerType & outputLayerPlus1 = this->m_OutputLevelSet->GetLayer(LevelSetType::PlusOneLayer()); auto nodeIt = layerPlus1.begin(); auto nodeEnd = layerPlus1.end(); while (nodeIt != nodeEnd) { LevelSetInputType currentIndex = nodeIt->first; LevelSetOutputType currentValue = nodeIt->second; outputLayerPlus1.insert(NodePairType(currentIndex, currentValue)); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::PlusOneLayer()); auto tempIt = nodeIt; ++nodeIt; layerPlus1.erase(tempIt); neighIt.SetLocation(currentIndex); for (typename NeighborhoodIteratorType::Iterator it = neighIt.Begin(); !it.IsAtEnd(); ++it) { LevelSetInputType tempIndex = neighIt.GetIndex(it.GetNeighborhoodOffset()); auto phiIt = this->m_TempPhi.find(tempIndex); if (phiIt != this->m_TempPhi.end()) { if (phiIt->second == 3.) { // change values here phiIt->second = currentValue + 1; layerPlus2.insert(NodePairType(tempIndex, currentValue + 1)); termContainer->UpdatePixel(tempIndex + m_Offset, 3, phiIt->second); } } } } } template void UpdateWhitakerSparseLevelSet::MovePointFromMinus2() { LevelSetLayerType & layerMinus2 = this->m_TempLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); LevelSetLayerType & outputLayerMinus2 = this->m_OutputLevelSet->GetLayer(LevelSetType::MinusTwoLayer()); auto nodeIt = layerMinus2.begin(); auto nodeEnd = layerMinus2.end(); while (nodeIt != nodeEnd) { const LevelSetInputType currentIndex = nodeIt->first; outputLayerMinus2.insert(NodePairType(currentIndex, nodeIt->second)); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::MinusTwoLayer()); auto tempIt = nodeIt; ++nodeIt; layerMinus2.erase(tempIt); } } template void UpdateWhitakerSparseLevelSet::MovePointFromPlus2() { LevelSetLayerType & layerPlus2 = this->m_TempLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); LevelSetLayerType & outputLayerPlus2 = this->m_OutputLevelSet->GetLayer(LevelSetType::PlusTwoLayer()); auto nodeIt = layerPlus2.begin(); auto nodeEnd = layerPlus2.end(); while (nodeIt != nodeEnd) { const LevelSetInputType currentIndex = nodeIt->first; outputLayerPlus2.insert(NodePairType(currentIndex, nodeIt->second)); this->m_InternalImage->SetPixel(currentIndex, LevelSetType::PlusTwoLayer()); auto tempIt = nodeIt; ++nodeIt; layerPlus2.erase(tempIt); } } } // namespace itk #endif // itkUpdateWhitakerSparseLevelSet_hxx