Shapeworks Studio  2.1
Shape analysis software suite
itkPSMPointTree.hxx
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef __itkPSMPointTree_hxx
19 #define __itkPSMPointTree_hxx
20 #include "itkPSMPointTree.h"
21 
22 #include <cmath>
23 
24 namespace itk
25 {
26 
27  template <unsigned int VDimension>
28  void PSMPointTreeNode<VDimension>
29  ::PrintSelf(std::ostream& os, Indent indent) const
30  {
31  os << indent << "PSMPointTreeNode: ";
32  os << "m_LowerBound = " << m_LowerBound;
33  os << "\tm_UpperBound = " << m_UpperBound;
34  os << "\tBranchesPerNode = " << BranchesPerNode;
35  os << "\tIsLeaf() = " << this->IsLeaf() << std::endl;
36  os << "\tm_List: ";
37  for (typename PointListType::const_iterator it = m_List.begin();
38  it != m_List.end(); it++)
39  { os << "\t (" << it->Index << ", " << it->Point << ")" << std::endl; }
40  os << std::endl;
41  for (unsigned int i = 0; i < BranchesPerNode; i++)
42  {
43  if (m_Branches[i].GetPointer() != 0) m_Branches[i]->PrintSelf(os, indent);
44  }
45  }
46 
47  template <unsigned int VDimension>
49  ::Overlap(const NodePointerType &node, const PointType &lowerbound,
50  const PointType &upperbound) const
51  {
52  // Check for overlap in all dimensions. If any one dimension has no overlap,
53  // these two regions do not overlap.
54  for (unsigned int i = 0; i < Dimension; i++)
55  {
56  // Does this region contain either node endpoint or does the node region
57  // contain both of this region's endpoints?
58  if (! ((node->GetLowerBound()[i] >= lowerbound[i] && node->GetLowerBound()[i] <= upperbound[i])
59  || (node->GetUpperBound()[i] >= lowerbound[i] && node->GetUpperBound()[i] <= upperbound[i])
60  || (node->GetLowerBound()[i] <= lowerbound[i] && node->GetUpperBound()[i] >= upperbound[i] ) ))
61  return false;
62  }
63  return true;
64  }
65 
66  template <unsigned int VDimension>
67  typename PSMPointTree<VDimension>::PointIteratorListType
69  FindPointsInRegion(const PointType &lowerbound, const PointType &upperbound) const
70  {
71  PointIteratorListType pointlist;
72  NodePointerType it = this->m_Root;
73 
74  // If no overlap with the root node exists, then return an empty list...
75  if ( this->Overlap(it, lowerbound, upperbound) && ! it->IsLeaf() )
76  {
77  // otherwise, descend into the child nodes and compile the list.
78  for (unsigned int i = 0; i < BranchesPerNode; i++)
79  {
80  this->FindOneNodeInRegion(it->GetBranch(i), lowerbound, upperbound, pointlist);
81  }
82  }
83 
84  return pointlist;
85  }
86 
87  template <unsigned int VDimension>
88  void
90  FindOneNodeInRegion(const NodePointerType &it, const PointType &lowerbound,
91  const PointType &upperbound,
92  PointIteratorListType &pointlist) const
93  {
94  // If this node is a leaf node, then add to the list if there is overlap.
95  if (it ->IsLeaf())
96  {
97  if ( this->Overlap(it, lowerbound, upperbound) )
98  {
99  // Add all node's points to the list that are within the given region.
100  for (typename PointListType::const_iterator pit = it->GetList().begin();
101  pit != it->GetList().end(); pit++)
102  {
103  if (this->RegionContains(pit->Point, lowerbound, upperbound) )
104  {
105  pointlist.push_back(pit);
106  }
107  }
108  }
109  }
110  else // Otherwise, call this method on each branch.
111  {
112  for (unsigned int i = 0; i < BranchesPerNode; i++)
113  {
114  this->FindOneNodeInRegion(it->GetBranch(i), lowerbound, upperbound, pointlist);
115  }
116  }
117  }
118 
119  template <unsigned int VDimension>
122  unsigned int idx,
123  NodePointerType &node)
124  {
125  NodePointerType it = this->m_Root;
126 
127  if ( ! it->Contains(point))
128  {
129  itkExceptionMacro("Point " << point << " is not contained within tree domain " << it->GetLowerBound() << " - " << it->GetUpperBound());
130  }
131 
132  while (! it->IsLeaf() )
133  {
134  for (unsigned int i = 0; i < BranchesPerNode; i++)
135  {
136  if (it->GetBranch(i)->Contains(point))
137  {
138  it = it->GetBranch(i);
139  break;
140  }
141  }
142  }
143  node = it;
144  return it->InsertElement( PSMPointIndexPair<VDimension>(point, idx) );
145  }
146 
147  template <unsigned int VDimension>
149  const PointType &upperbound, unsigned int depth)
150  {
151  m_Depth = depth;
152 
153  NodePointerType n = NodeType::New();
154  n->SetLowerBound(lowerbound);
155  n->SetUpperBound(upperbound);
156 
157  this->SetRoot(n);
158  this->BranchNode(n, 1);
159  }
160 
161  template <unsigned int VDimension>
163  unsigned int level)
164  {
165  // Called from a leaf node.
166  if (level > m_Depth) return;
167 
168  PointType midpoint, upper, lower;
169  int thresh[VDimension];
170  for (unsigned int dim = 0; dim < VDimension; dim++)
171  {
172  thresh[dim] = 1;
173  midpoint[dim] = ( parent->GetLowerBound()[dim] + parent->GetUpperBound()[dim] ) / 2.0;
174  }
175 
176  for (unsigned int b = 0; b < BranchesPerNode; b++)
177  {
178  for (unsigned int dim = 0; dim < VDimension; dim++)
179  {
180  // toggle use low/high lower and upper bounds
181  if ( b % ( static_cast<unsigned int>(pow(2.0, (int)dim)) ) == 0 )
182  { thresh[dim] = 1 - thresh[dim]; }
183 
184  if ( thresh[dim] == 0 )
185  {
186  lower[dim] = parent->GetLowerBound()[dim];
187  upper[dim] = midpoint[dim];
188  }
189  else
190  {
191  lower[dim] = midpoint[dim];
192  upper[dim] = parent->GetUpperBound()[dim];
193  }
194  }
195 
196  NodePointerType newNode = NodeType::New();
197  newNode->SetLowerBound(lower);
198  newNode->SetUpperBound(upper);
199 
200  parent->SetBranch(b, newNode);
201 
202  this->BranchNode(newNode, level+1);
203  }
204  }
205 
206  template <unsigned int VDimension>
207  void PSMPointTree<VDimension>::PrintSelf(std::ostream& os, Indent indent) const
208  {
209  os << indent << "BranchesPerNode = " << BranchesPerNode << std::endl;
210  os << indent << "m_Depth = " << m_Depth << std::endl;
211  os << indent << "m_Root: ";
212  m_Root->PrintSelf(os, indent);
213  Superclass::PrintSelf(os, indent);
214  }
215 
216 } // end namespace itk
217 #endif
void BranchNode(NodePointerType &, unsigned int)
Struct containing a Point and an index value associated with a point. This object is used mainly by P...
NodeType::Pointer NodePointerType
void FindOneNodeInRegion(const NodePointerType &, const PointType &, const PointType &, PointIteratorListType &) const
PointListType::iterator AddPoint(const PointType &, unsigned int, NodePointerType &)
void ConstructTree(const PointType &, const PointType &, unsigned int)
PointIteratorListType FindPointsInRegion(const PointType &, const PointType &) const