| 198 | } |
| 199 | |
| 200 | void LiTreeFilter::segmentTree(PointView& view, PointIdList& Ui, |
| 201 | int64_t& tree_id, PointId t0) |
| 202 | { |
| 203 | // "The proposed segmentation algorithm isolates trees individually and |
| 204 | // sequentially from the point cloud, from the tallest tree to the |
| 205 | // shortest." |
| 206 | |
| 207 | // "Let Pi denote a set of points that belong to tree i (target), and Ni |
| 208 | // denote a set of points that do not belong to tree i." |
| 209 | PointIdList Pi; |
| 210 | PointIdList Ni; |
| 211 | |
| 212 | log()->get(LogLevel::Debug) << "Classifying points for tree " << tree_id |
| 213 | << " (|Ui| = " << Ui.size() << ")\n"; |
| 214 | |
| 215 | // "During each iteration, only one tree (target) is segmented, and the |
| 216 | // points corresponding to this target tree are removed from the point |
| 217 | // cloud." |
| 218 | |
| 219 | Pi.push_back(t0); |
| 220 | |
| 221 | // "We then insert a dummy point n0 that is far away (e.g., 100m) from t0 |
| 222 | // into Ni." |
| 223 | // |
| 224 | // If the found dummy point is the target point, then the target point is |
| 225 | // geographically isolated. We remove it and return. |
| 226 | PointId n0 = locateDummyPoint(view, Ui, t0); |
| 227 | if (n0 == t0) |
| 228 | { |
| 229 | Utils::remove(Ui, t0); |
| 230 | return; |
| 231 | } |
| 232 | Ni.push_back(n0); |
| 233 | |
| 234 | // "For iteration i, we classify each point in Ui as Pi or Ni." |
| 235 | double tx = view.getFieldAs<double>(Id::X, t0); |
| 236 | double ty = view.getFieldAs<double>(Id::Y, t0); |
| 237 | for (PointId const& ui : Ui) |
| 238 | { |
| 239 | // t0 and n0 are already in Pi or Ni. |
| 240 | if (ui == t0 || ui == n0) |
| 241 | continue; |
| 242 | |
| 243 | double ux = view.getFieldAs<double>(Id::X, ui); |
| 244 | double uy = view.getFieldAs<double>(Id::Y, ui); |
| 245 | //ABELL - This is strange. We've already done a radius search to locate a dummy point |
| 246 | // and the distance used is 100, so we already have the points that are within that |
| 247 | // distance, so there's really no need to do it again, is there? |
| 248 | double d = (ux - tx) * (ux - tx) + (uy - ty) * (uy - ty); |
| 249 | if (d < 100.0) |
| 250 | classifyPoint(ui, view, Ni, Pi); |
| 251 | else |
| 252 | Ni.push_back(ui); |
| 253 | } |
| 254 | |
| 255 | log()->get(LogLevel::Debug3) |
| 256 | << "|Pi| = " << Pi.size() << ", |Ni| = " << Ni.size() << std::endl; |
| 257 | // Use Pi to assign current tree_id to TreeID dimension, only if minimum |