7 #include "imstkFastMarch.h" 8 #include "imstkLogger.h" 9 #include "imstkVecDataArray.h" 17 std::shared_ptr<AbstractDataArray> abstractScalars = m_imageData->getScalars();
18 if (abstractScalars->getScalarType() != IMSTK_DOUBLE || abstractScalars->getNumberOfComponents() != 1)
20 LOG(WARNING) <<
"fastMarch only works with single component double images";
23 auto scalars = std::dynamic_pointer_cast<DataArray<double>>(abstractScalars);
24 double* imgPtr = scalars->getPointer();
25 m_dim = m_imageData->getDimensions();
26 m_spacing = m_imageData->getSpacing();
27 m_indexShift = m_dim[0] * m_dim[1];
32 m_visited = std::unordered_set<int>();
34 m_distances = std::unordered_map<int, double>();
36 m_queue = std::priority_queue<Node, std::vector<Node>, NodeComparator>();
39 for (
size_t i = 0; i < m_seedVoxels.size(); i++)
41 const Vec3i& coord = m_seedVoxels[i];
42 if (coord[0] < 0 || coord[0] >= m_dim[0]
43 || coord[1] < 0 || coord[1] >= m_dim[1]
44 || coord[2] < 0 || coord[2] >= m_dim[2])
48 const int index =
static_cast<int>(m_imageData->getScalarIndex(coord));
49 m_distances[index] = imgPtr[m_imageData->getScalarIndex(coord)];
50 m_queue.push(Node(index, 0.0, coord));
54 while (!m_queue.empty())
56 Node node = m_queue.top();
59 const Vec3i& coord = node.m_coord;
60 const int& nodeId = node.m_nodeId;
64 || getDistance(nodeId) >= m_distThreshold)
70 m_visited.insert(nodeId);
74 int neighborId = nodeId + 1;
75 Vec3i neighborCoord = coord + Vec3i(1, 0, 0);
76 if (neighborCoord[0] < m_dim[0] && !isVisited(neighborId))
78 solveNode(neighborCoord, neighborId);
81 neighborId = nodeId - 1;
82 neighborCoord = coord - Vec3i(1, 0, 0);
83 if (neighborCoord[0] >= 0 && !isVisited(neighborId))
85 solveNode(neighborCoord, neighborId);
89 neighborId = nodeId + m_dim[0];
90 neighborCoord = coord + Vec3i(0, 1, 0);
91 if (neighborCoord[1] < m_dim[1] && !isVisited(neighborId))
93 solveNode(neighborCoord, neighborId);
96 neighborId = nodeId - m_dim[0];
97 neighborCoord = coord - Vec3i(0, 1, 0);
98 if (neighborCoord[1] >= 0 && !isVisited(neighborId))
100 solveNode(neighborCoord, neighborId);
104 neighborId = nodeId + m_indexShift;
105 neighborCoord = coord + Vec3i(0, 0, 1);
106 if (neighborCoord[2] < m_dim[2] && !isVisited(neighborId))
108 solveNode(neighborCoord, neighborId);
111 neighborId = nodeId - m_indexShift;
112 neighborCoord = coord - Vec3i(0, 0, 1);
113 if (neighborCoord[2] >= 0 && !isVisited(neighborId))
115 solveNode(neighborCoord, neighborId);
120 for (
auto i : m_distances)
122 imgPtr[i.first] = i.second;
127 FastMarch::solveNode(Vec3i coord,
int index)
130 const double dists[6] =
132 coord[0] - 1 >= 0 ? getDistance(index - 1) : IMSTK_DOUBLE_MAX,
133 coord[0] + 1 < m_dim[0] ? getDistance(index + 1) : IMSTK_DOUBLE_MAX,
134 coord[1] - 1 >= 0 ? getDistance(index - m_dim[0]) : IMSTK_DOUBLE_MAX,
135 coord[1] + 1 < m_dim[1] ? getDistance(index + m_dim[0]) : IMSTK_DOUBLE_MAX,
136 coord[2] - 1 >= 0 ? getDistance(index - m_indexShift) : IMSTK_DOUBLE_MAX,
137 coord[2] + 1 < m_dim[2] ? getDistance(index + m_indexShift) : IMSTK_DOUBLE_MAX
139 const double minDist[3] =
141 std::min(dists[0], dists[1]),
142 std::min(dists[2], dists[3]),
143 std::min(dists[4], dists[5])
147 int dimReorder[3] = { 0, 1, 2 };
148 for (
int i = 0; i < 3; i++)
150 for (
int j = i + 1; j < 3; j++)
152 const int dim1 = dimReorder[i];
153 const int dim2 = dimReorder[j];
154 if (minDist[dim1] > minDist[dim2])
156 std::swap(dimReorder[i], dimReorder[j]);
166 double solution = IMSTK_DOUBLE_MAX;
167 double discrim = 0.0;
169 for (
unsigned int i = 0; i < 3; i++)
171 const double value = minDist[dimReorder[i]];
172 if (solution >= value)
174 const double spaceFactor = std::sqrt(1.0 / m_spacing[dimReorder[i]]);
176 bb += value * spaceFactor;
177 cc += value * value * spaceFactor;
179 discrim = bb * bb - aa * cc;
186 solution = (std::sqrt(discrim) + bb) / aa;
194 if (solution < IMSTK_DOUBLE_MAX)
197 m_distances[index] = solution;
198 m_queue.push(Node(index, solution, coord));