Skip to content

Commit

Permalink
DemoBadPatchRealImage working.
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddoria committed Feb 20, 2012
1 parent 6982d0f commit 369159c
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 109 deletions.
14 changes: 9 additions & 5 deletions ClassicalImageInpainting.cpp
Expand Up @@ -157,18 +157,22 @@ int main(int argc, char *argv[])
typedef std::less<float> PriorityCompareType;
PriorityCompareType lessThanFunctor;

typedef boost::d_ary_heap_indirect<VertexDescriptorType, 4, IndexInHeapMap, PriorityMapType, PriorityCompareType> BoundaryNodeQueueType;
typedef boost::d_ary_heap_indirect<VertexDescriptorType, 4, IndexInHeapMap, PriorityMapType, PriorityCompareType>
BoundaryNodeQueueType;
BoundaryNodeQueueType boundaryNodeQueue(priorityMap, index_in_heap, lessThanFunctor);

// Create the descriptor visitor
typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType> ImagePatchDescriptorVisitorType;
typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType>
ImagePatchDescriptorVisitorType;
ImagePatchDescriptorVisitorType imagePatchDescriptorVisitor(image, mask, imagePatchDescriptorMap, patch_half_width);

// Create the inpainting visitor
typedef InpaintingVisitor<VertexListGraphType, ImageType, BoundaryNodeQueueType, FillStatusMapType,
ImagePatchDescriptorVisitorType, PriorityType, PriorityMapType, BoundaryStatusMapType> InpaintingVisitorType;
ImagePatchDescriptorVisitorType, PriorityType, PriorityMapType, BoundaryStatusMapType>
InpaintingVisitorType;
InpaintingVisitorType inpaintingVisitor(image, mask, boundaryNodeQueue, fillStatusMap,
imagePatchDescriptorVisitor, priorityMap, &priorityFunction, patch_half_width, boundaryStatusMap);
imagePatchDescriptorVisitor, priorityMap, &priorityFunction, patch_half_width,
boundaryStatusMap);

InitializePriority(mask, boundaryNodeQueue, priorityMap, &priorityFunction, boundaryStatusMap);

Expand All @@ -186,7 +190,7 @@ int main(int argc, char *argv[])
// Perform the inpainting
inpainting_loop(graph, inpaintingVisitor, boundaryStatusMap, boundaryNodeQueue, linearSearchBest, patchInpainter);

HelpersOutput::WriteImage<ImageType>(image, outputFilename);
OutputHelpers::WriteImage<ImageType>(image, outputFilename);

return EXIT_SUCCESS;
}
4 changes: 2 additions & 2 deletions Concepts/DescriptorVisitorConcept.hpp
Expand Up @@ -27,8 +27,8 @@ struct DescriptorVisitorConcept

BOOST_CONCEPT_USAGE(DescriptorVisitorConcept)
{
vis.initialize_vertex(u);// Function called on all vertices during the initialization phase.
vis.discover_vertex(u); // Function called when a live vertex is taken out of the priority-queue.
vis.InitializeVertex(u);// Function called on all vertices during the initialization phase.
vis.DiscoverVertex(u); // Function called when a live vertex is taken out of the priority-queue.
};

};
Expand Down
86 changes: 49 additions & 37 deletions Demos/CMakeLists.txt
@@ -1,8 +1,8 @@
add_executable(DemoBoundaryNormals DemoBoundaryNormals.cpp)
target_link_libraries(DemoBoundaryNormals PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})

add_executable(DemoBoundaryNormals2 DemoBoundaryNormals2.cpp)
target_link_libraries(DemoBoundaryNormals2 PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
# add_executable(DemoBoundaryNormals DemoBoundaryNormals.cpp)
# target_link_libraries(DemoBoundaryNormals PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})
#
# add_executable(DemoBoundaryNormals2 DemoBoundaryNormals2.cpp)
# target_link_libraries(DemoBoundaryNormals2 PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
#
# add_executable(DemoClusterColors DemoClusterColors.cpp)
# target_link_libraries(DemoClusterColors PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})
Expand All @@ -16,42 +16,54 @@ target_link_libraries(DemoBoundaryNormals2 PatchBasedInpainting ${VTK_LIBRARIES}
# add_executable(DemoColorImageByScore DemoColorImageByScore.cpp)
# target_link_libraries(DemoColorImageByScore PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES})

add_executable(DemoCreateImage DemoCreateImage.cpp)
target_link_libraries(DemoCreateImage PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})
# add_executable(DemoCreateImage DemoCreateImage.cpp)
# target_link_libraries(DemoCreateImage PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})

# add_executable(DemoCreateMask DemoCreateMask.cpp)
# target_link_libraries(DemoCreateMask PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})

add_executable(DemoDerivatives DemoDerivatives.cpp)
target_link_libraries(DemoDerivatives PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})

add_executable(DemoErroneousGradient DemoErroneousGradient.cpp)
target_link_libraries(DemoErroneousGradient PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)

add_executable(DemoFindPixelAcrossHole DemoFindPixelAcrossHole.cpp)
target_link_libraries(DemoFindPixelAcrossHole PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)

add_executable(DemoFollowIsophotesAcrossBoundary DemoFollowIsophotesAcrossBoundary.cpp ${ROOT_SOURCE_DIR}/ImageProcessing/MaskOperations.cpp)
target_link_libraries(DemoFollowIsophotesAcrossBoundary PatchBasedInpainting
${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoGradient DemoGradient.cpp)
target_link_libraries(DemoGradient PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoInnerOuterBoundary DemoInnerOuterBoundary.cpp)
target_link_libraries(DemoInnerOuterBoundary PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})

add_executable(DemoIsophotes DemoIsophotes.cpp ${ROOT_SOURCE_DIR}/ImageProcessing/MaskOperations.cpp)
target_link_libraries(DemoIsophotes PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoPatchDifference DemoPatchDifference.cpp)
target_link_libraries(DemoPatchDifference PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
# add_executable(DemoDerivatives DemoDerivatives.cpp)
# target_link_libraries(DemoDerivatives PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})
#
# add_executable(DemoErroneousGradient DemoErroneousGradient.cpp)
# target_link_libraries(DemoErroneousGradient PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
#
# add_executable(DemoFindPixelAcrossHole DemoFindPixelAcrossHole.cpp)
# target_link_libraries(DemoFindPixelAcrossHole PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
#
# add_executable(DemoFollowIsophotesAcrossBoundary DemoFollowIsophotesAcrossBoundary.cpp
# ${ROOT_SOURCE_DIR}/ImageProcessing/MaskOperations.cpp)
# target_link_libraries(DemoFollowIsophotesAcrossBoundary PatchBasedInpainting
# ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoPatchImageDifference DemoPatchImageDifference.cpp)
target_link_libraries(DemoPatchImageDifference PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
# add_executable(DemoGradient DemoGradient.cpp)
# target_link_libraries(DemoGradient PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
#
# add_executable(DemoInnerOuterBoundary DemoInnerOuterBoundary.cpp)
# target_link_libraries(DemoInnerOuterBoundary PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES})
#
# add_executable(DemoIsophotes DemoIsophotes.cpp ${ROOT_SOURCE_DIR}/ImageProcessing/MaskOperations.cpp)
# target_link_libraries(DemoIsophotes PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
#
# add_executable(DemoPatchDifference DemoPatchDifference.cpp)
# target_link_libraries(DemoPatchDifference PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
#
# add_executable(DemoPatchImageDifference DemoPatchImageDifference.cpp)
# target_link_libraries(DemoPatchImageDifference PatchBasedInpainting ${VTK_LIBRARIES} ${ITK_LIBRARIES} libHelpers)
#
# add_executable(DemoPatchSearchFunction DemoPatchSearchFunction.cpp)
# target_link_libraries(DemoPatchSearchFunction PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
#
# add_executable(DemoSelfPatchCompare DemoSelfPatchCompare.cpp)
# target_link_libraries(DemoSelfPatchCompare PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoPatchSearchFunction DemoPatchSearchFunction.cpp)
target_link_libraries(DemoPatchSearchFunction PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
add_executable(DemoBadPatchComparison DemoBadPatchComparison.cpp)
target_link_libraries(DemoBadPatchComparison PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)

add_executable(DemoSelfPatchCompare DemoSelfPatchCompare.cpp)
target_link_libraries(DemoSelfPatchCompare PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
QT4_WRAP_UI(DemoBadPatchRealImageUISrcs ${ROOT_SOURCE_DIR}/Interactive/TopPatchesDialog.ui)
QT4_WRAP_CPP(DemoBadPatchRealImageMOCSrcs ${ROOT_SOURCE_DIR}/Interactive/TopPatchesDialog.h
${ROOT_SOURCE_DIR}/Interactive/Delegates/PixmapDelegate.h)
add_executable(DemoBadPatchRealImage DemoBadPatchRealImage.cpp
${ROOT_SOURCE_DIR}/Interactive/Delegates/PixmapDelegate.cpp
${DemoBadPatchRealImageUISrcs} ${DemoBadPatchRealImageMOCSrcs})
target_link_libraries(DemoBadPatchRealImage PatchBasedInpainting ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} libHelpers)
5 changes: 3 additions & 2 deletions Demos/DemoBadPatchComparison.cpp
Expand Up @@ -71,8 +71,9 @@ int main(int argc, char *argv[])
++shiftedImageIterator;
}

ImageType::PixelType averagePixel = ITKHelpers::AverageInRegion(noisyImage, noisyImage->GetLargestPossibleRegion());
ITKHelpers::SetRegionToConstant(averageImage, averageImage->GetLargestPossibleRegion(), averagePixel);
ImageType::PixelType averagePixel = ITKHelpers::AverageInRegion(noisyImage.GetPointer(),
noisyImage->GetLargestPossibleRegion());
ITKHelpers::SetRegionToConstant(averageImage.GetPointer(), averageImage->GetLargestPossibleRegion(), averagePixel);

return EXIT_SUCCESS;
}
135 changes: 84 additions & 51 deletions Demos/DemoBadPatchRealImage.cpp
Expand Up @@ -37,6 +37,77 @@
#include "itkImage.h"
#include "itkImageFileReader.h"

typedef itk::VectorImage<float, 2> ImageType;

struct DemoDriver
{

typedef boost::grid_graph<2> VertexListGraphType;
typedef boost::graph_traits<VertexListGraphType>::vertex_descriptor VertexDescriptorType;
typedef ImagePatchPixelDescriptor<ImageType> ImagePatchPixelDescriptorType;
typedef boost::property_map<VertexListGraphType, boost::vertex_index_t>::const_type IndexMapType;
typedef boost::vector_property_map<ImagePatchPixelDescriptorType, IndexMapType> ImagePatchDescriptorMapType;
typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType> VisitorType;
typedef LinearSearchKNNProperty<ImagePatchDescriptorMapType,
ImagePatchDifference<ImagePatchPixelDescriptorType> > KNNSearchType;
VertexListGraphType* graph;

unsigned int PatchRadius;

ImageType* Image;
Mask* MaskImage;

VisitorType* Visitor;

KNNSearchType* KNNSearch;

ImagePatchDescriptorMapType* ImagePatchDescriptorMap;

DemoDriver(ImageType* const image, Mask* const mask) : graph(NULL), PatchRadius(15), Image(image), MaskImage(mask)
{
boost::array<std::size_t, 2> graphSideLengths = { { image->GetLargestPossibleRegion().GetSize()[0],
image->GetLargestPossibleRegion().GetSize()[1] } };
//VertexListGraphType graph(graphSideLengths);
graph = new VertexListGraphType(graphSideLengths);

// Get the index map
IndexMapType indexMap(get(boost::vertex_index, *graph));

// Create the descriptor map. This is where the data for each pixel is stored.
ImagePatchDescriptorMap = new ImagePatchDescriptorMapType(num_vertices(*graph), indexMap);

Visitor = new VisitorType(Image, MaskImage, *ImagePatchDescriptorMap, PatchRadius);

InitializeFromMaskImage<VisitorType, VertexDescriptorType>(MaskImage, Visitor);

// Create the nearest neighbor finders
KNNSearch = new KNNSearchType(*ImagePatchDescriptorMap, 1000);
}

void DisplayTopPatches(VertexDescriptorType targetNode)
{
Visitor->DiscoverVertex(targetNode);

std::vector<VertexDescriptorType> bestSourceNodes;
typename boost::graph_traits<VertexListGraphType>::vertex_iterator vi,vi_end;
tie(vi,vi_end) = vertices(*graph);
(*KNNSearch)(vi, vi_end, targetNode, bestSourceNodes);

std::cout << "There are " << bestSourceNodes.size() << " bestSourceNodes." << std::endl;

TopPatchesDialog<ImageType>* topPatchesDialog = new TopPatchesDialog<ImageType>(Image, MaskImage, PatchRadius);
topPatchesDialog->SetQueryNode(targetNode);
topPatchesDialog->SetSourceNodes(bestSourceNodes);
//topPatchesDialog->exec();
topPatchesDialog->show();

// Return the node to an invalid state
ImagePatchPixelDescriptorType& descriptor = get(*ImagePatchDescriptorMap, targetNode);
descriptor.SetStatus(PixelDescriptor::INVALID);
}

};

int main(int argc, char *argv[])
{
if(argc != 3)
Expand All @@ -48,7 +119,6 @@ int main(int argc, char *argv[])
std::string imageFileName = argv[1];
std::string maskFileName = argv[2];

typedef itk::VectorImage<float, 2> ImageType;
typedef itk::ImageFileReader<ImageType> ImageReaderType;
ImageReaderType::Pointer imageReader = ImageReaderType::New();
imageReader->SetFileName(imageFileName);
Expand All @@ -62,60 +132,23 @@ int main(int argc, char *argv[])
maskReader->SetFileName(maskFileName);
maskReader->Update();

itk::Index<2> centerGood = {{503,156}};
itk::Index<2> centerBad = {{503,146}};

const unsigned int patchRadius = 15;
itk::ImageRegion<2> regionGood = ITKHelpers::GetRegionInRadiusAroundPixel(centerGood, patchRadius);
itk::ImageRegion<2> regionBad = ITKHelpers::GetRegionInRadiusAroundPixel(centerBad, patchRadius);


typedef ImagePatchPixelDescriptor<ImageType> ImagePatchPixelDescriptorType;

// Create the graph
typedef boost::grid_graph<2> VertexListGraphType;
boost::array<std::size_t, 2> graphSideLengths = { { imageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0],
imageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] } };
VertexListGraphType graph(graphSideLengths);
typedef boost::graph_traits<VertexListGraphType>::vertex_descriptor VertexDescriptorType;

// Get the index map
typedef boost::property_map<VertexListGraphType, boost::vertex_index_t>::const_type IndexMapType;
IndexMapType indexMap(get(boost::vertex_index, graph));

// Create the descriptor map. This is where the data for each pixel is stored.
typedef boost::vector_property_map<ImagePatchPixelDescriptorType, IndexMapType> ImagePatchDescriptorMapType;
ImagePatchDescriptorMapType imagePatchDescriptorMap(num_vertices(graph), indexMap);

typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType> VisitorType;
VisitorType visitor(imageReader->GetOutput(), maskReader->GetOutput(), imagePatchDescriptorMap, patchRadius);

InitializeFromMaskImage<VisitorType, VertexDescriptorType>(maskReader->GetOutput(), &visitor);

// Create the nearest neighbor finders
typedef LinearSearchKNNProperty<ImagePatchDescriptorMapType,
ImagePatchDifference<ImagePatchPixelDescriptorType> > KNNSearchType;
KNNSearchType knnSearch(imagePatchDescriptorMap, 100);

VertexDescriptorType goodTargetNode = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(centerGood);
//VertexDescriptorType badTargetNode = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(centerBad);

VertexDescriptorType targetNode = goodTargetNode;
// Setup the GUI system
QApplication app( argc, argv );

std::vector<VertexDescriptorType> bestSourceNodes;
typename boost::graph_traits<VertexListGraphType>::vertex_iterator vi,vi_end;
tie(vi,vi_end) = vertices(graph);
knnSearch(vi, vi_end, goodTargetNode, bestSourceNodes);
DemoDriver demoDriver(imageReader->GetOutput(), maskReader->GetOutput());

std::cout << "There are " << bestSourceNodes.size() << " bestSourceNodes." << std::endl;
itk::Index<2> centerGood = {{503,156}};
DemoDriver::VertexDescriptorType goodTargetNode = Helpers::ConvertFrom<DemoDriver::VertexDescriptorType,
itk::Index<2> >(centerGood);
demoDriver.DisplayTopPatches(goodTargetNode);

// Setup the GUI system
QApplication app( argc, argv );
// itk::Index<2> centerBad = {{503,146}}; // The top 1000 matches to this patch are completely wrong
itk::Index<2> centerBad = {{503,147}};
DemoDriver::VertexDescriptorType badTargetNode = Helpers::ConvertFrom<DemoDriver::VertexDescriptorType,
itk::Index<2> >(centerBad);
demoDriver.DisplayTopPatches(badTargetNode);

TopPatchesDialog<ImageType> topPatchesDialog(imageReader->GetOutput(), maskReader->GetOutput(), patchRadius);
topPatchesDialog.SetQueryNode(targetNode);
topPatchesDialog.SetSourceNodes(bestSourceNodes);
topPatchesDialog.exec();
app.exec();

return EXIT_SUCCESS;
}
2 changes: 2 additions & 0 deletions DifferenceFunctions/ImagePatchDifference.hpp
Expand Up @@ -45,6 +45,7 @@ struct ImagePatchDifference

float totalDifference = 0.0f;

// If both nodes are source nodes, compare them fully.
if(a.GetStatus() == ImagePatchType::SOURCE_NODE && b.GetStatus() == ImagePatchType::SOURCE_NODE)
{
itk::Offset<2> offsetAToB = b.GetCorner() - a.GetCorner();
Expand All @@ -70,6 +71,7 @@ struct ImagePatchDifference
++patchAIterator;
}
}
// If one of the nodes is a target node, only compare in it's list of valid offset pixels.
else if(a.GetStatus() == ImagePatchType::TARGET_NODE || b.GetStatus() == ImagePatchType::TARGET_NODE)
{
const std::vector<itk::Offset<2> >* validOffsets;
Expand Down
2 changes: 1 addition & 1 deletion Helpers/ITKHelpers.hxx
Expand Up @@ -718,7 +718,7 @@ typename TImage::PixelType AverageOfPixelsAtIndices(const TImage* const image, c
template<typename TImage>
typename TImage::PixelType AverageInRegion(const TImage* const image, const itk::ImageRegion<2>& region)
{
typename itk::ImageRegionIterator<TImage> imageIterator(image, region);
typename itk::ImageRegionConstIterator<TImage> imageIterator(image, region);
std::vector<typename TImage::PixelType> pixels;
while(!imageIterator.IsAtEnd())
{
Expand Down
5 changes: 5 additions & 0 deletions Interactive/TopPatchesDialog.h
Expand Up @@ -37,7 +37,9 @@ Q_OBJECT

public slots:

/** Ideally this would be templated on the node type, but since it is a slot it cannot be templated. */
virtual void SetSourceNodes(const std::vector<Node>& sourceNodes) = 0;

virtual void SetQueryNode(const Node& queryNode) = 0;
virtual void slot_Selected(const QModelIndex & index) = 0;
};
Expand Down Expand Up @@ -78,6 +80,9 @@ class TopPatchesDialog : public TopPatchesDialogParent
/** Set the source nodes from which the user can choose. */
void SetSourceNodes(const std::vector<Node>& nodes);

template <typename TNode>
void SetSourceNodes(const std::vector<TNode>& sourceNodes);

/** Set the query node that the user will choose the best match to. */
void SetQueryNode(const Node& node);

Expand Down
13 changes: 13 additions & 0 deletions Interactive/TopPatchesDialog.hpp
Expand Up @@ -50,6 +50,19 @@ void TopPatchesDialog<TImage>::SetSourceNodes(const std::vector<Node>& nodes)
this->PatchesModel->SetNodes(nodes);
}

template <typename TImage>
template <typename TNode>
void TopPatchesDialog<TImage>::SetSourceNodes(const std::vector<TNode>& sourceNodes)
{
std::vector<Node> nodes;
for(unsigned int i = 0; i < sourceNodes.size(); ++i)
{
Node node = Helpers::ConvertFrom<Node, TNode>(sourceNodes[i]);
nodes.push_back(node);
}
SetSourceNodes(nodes);
}

template <typename TImage>
void TopPatchesDialog<TImage>::SetQueryNode(const Node& queryNode)
{
Expand Down
5 changes: 5 additions & 0 deletions Node.h
Expand Up @@ -60,6 +60,11 @@ class Node
return coord[component];
}

int& operator[](const unsigned int& component)
{
return coord[component];
}

template <typename T>
void CreateFromObject(const T& object)
{
Expand Down

0 comments on commit 369159c

Please sign in to comment.