| 182 | } |
| 183 | |
| 184 | void NormalFilter::update( |
| 185 | PointView& view, KD3Index& kdi, std::vector<bool> inMST, |
| 186 | std::priority_queue<Edge, EdgeList, CompareEdgeWeight> edge_queue, |
| 187 | PointId updateIdx) |
| 188 | { |
| 189 | // Add the current PointId to the minimum spanning tree. |
| 190 | inMST[updateIdx] = true; |
| 191 | ++m_count; |
| 192 | |
| 193 | // Consider neighbors of the newly added PointId, adding them to |
| 194 | // the edge queue if they are not already part of the minimum |
| 195 | // spanning tree. The first neighbor is the query point which is |
| 196 | // already part of the minimum spanning tree and can safely be |
| 197 | // skipped. |
| 198 | PointIdList neighbors; |
| 199 | if (m_radiusArg->set()) |
| 200 | neighbors = kdi.radius(updateIdx, m_args->m_radius); |
| 201 | else |
| 202 | neighbors = kdi.neighbors(updateIdx, m_args->m_knn); |
| 203 | |
| 204 | neighbors.erase(neighbors.begin()); |
| 205 | PointRef p = view.point(updateIdx); |
| 206 | Vector3d N0(p.getFieldAs<double>(Id::NormalX), |
| 207 | p.getFieldAs<double>(Id::NormalY), |
| 208 | p.getFieldAs<double>(Id::NormalZ)); |
| 209 | for (PointId const& neighborIdx : neighbors) |
| 210 | { |
| 211 | if (!inMST[neighborIdx]) |
| 212 | { |
| 213 | PointRef q = view.point(neighborIdx); |
| 214 | Vector3d N1(q.getFieldAs<double>(Id::NormalX), |
| 215 | q.getFieldAs<double>(Id::NormalY), |
| 216 | q.getFieldAs<double>(Id::NormalZ)); |
| 217 | double weight = 1.0 - std::fabs(N0.dot(N1)); |
| 218 | edge_queue.emplace(updateIdx, neighborIdx, weight); |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | void NormalFilter::refine(PointView& view, KD3Index& kdi) |
| 224 | { |