| 221 | } |
| 222 | |
| 223 | void NormalFilter::refine(PointView& view, KD3Index& kdi) |
| 224 | { |
| 225 | log()->get(LogLevel::Debug) |
| 226 | << "Refining normals using minimum spanning tree\n"; |
| 227 | |
| 228 | std::priority_queue<Edge, EdgeList, CompareEdgeWeight> edge_queue; |
| 229 | std::vector<bool> inMST(view.size(), false); |
| 230 | PointId nextIdx(0); |
| 231 | while (m_count < view.size()) |
| 232 | { |
| 233 | // Find the PointId of the next point not currently part of the minimum |
| 234 | // spanning tree. |
| 235 | while (inMST[nextIdx]) |
| 236 | ++nextIdx; |
| 237 | |
| 238 | update(view, kdi, inMST, edge_queue, nextIdx); |
| 239 | |
| 240 | // Iterate on the edge queue until empty (or all points have been added |
| 241 | // to the minimum spanning tree). |
| 242 | while (!edge_queue.empty() && (m_count < view.size())) |
| 243 | { |
| 244 | // Retrieve the edge with the smallest weight. |
| 245 | Edge edge(edge_queue.top()); |
| 246 | edge_queue.pop(); |
| 247 | |
| 248 | // Record the PointId and normal of the PointId (if one exists) |
| 249 | // that is not already in the minimum spanning tree. |
| 250 | PointId newIdx(0); |
| 251 | Vector3d normal; |
| 252 | PointRef p = view.point(edge.m_v0); |
| 253 | Vector3d N0(p.getFieldAs<double>(Id::NormalX), |
| 254 | p.getFieldAs<double>(Id::NormalY), |
| 255 | p.getFieldAs<double>(Id::NormalZ)); |
| 256 | PointRef q = view.point(edge.m_v1); |
| 257 | Vector3d N1(q.getFieldAs<double>(Id::NormalX), |
| 258 | q.getFieldAs<double>(Id::NormalY), |
| 259 | q.getFieldAs<double>(Id::NormalZ)); |
| 260 | if (!inMST[edge.m_v0]) |
| 261 | { |
| 262 | newIdx = edge.m_v0; |
| 263 | normal = N0; |
| 264 | } |
| 265 | else if (!inMST[edge.m_v1]) |
| 266 | { |
| 267 | newIdx = edge.m_v1; |
| 268 | normal = N1; |
| 269 | } |
| 270 | else |
| 271 | continue; |
| 272 | |
| 273 | // Where the dot product of the normals is less than 0, invert the |
| 274 | // normal of the selected PointId. |
| 275 | if (N0.dot(N1) < 0) |
| 276 | { |
| 277 | normal *= -1; |
| 278 | view.setField(Id::NormalX, newIdx, normal(0)); |
| 279 | view.setField(Id::NormalY, newIdx, normal(1)); |
| 280 | view.setField(Id::NormalZ, newIdx, normal(2)); |