/// <summary> /// Add new tree to tree arrays /// </summary> public void OnTreeCreated(CTree pNewTree, Vector3 pFirstPoint) { CVegeField vegeField = vegeDetailArray.GetFieldContainingPoint(pFirstPoint); CTreeField treeDetailField = treeDetailArray.GetFieldContainingPoint(pFirstPoint); CTreeField treeNormalField = treeNormalArray.GetFieldContainingPoint(pFirstPoint); if (vegeField == null) { CDebug.Error($"Cant create tree. point {pFirstPoint} is OOB!"); return; } treeDetailField.AddDetectedTree(pNewTree, true); treeNormalField.AddDetectedTree(pNewTree, true); pNewTree.peakDetailField = treeDetailField; pNewTree.peakNormalField = treeNormalField; }
/// <summary> /// Merges all trees, whose peak has good AddFactor to another tree /// </summary> private static void MergeGoodAddFactorTrees(bool pOnlyInvalid) { DateTime mergeStart = DateTime.Now; DateTime previousMergeStart = DateTime.Now; int iteration = 0; int maxIterations = Trees.Count; for (int i = Trees.Count - 1; i >= 0; i--) { if (CProjectData.backgroundWorker.CancellationPending) { return; } if (i >= Trees.Count) { //CDebug.WriteLine("Tree was deleted"); continue; } CTree treeToMerge = Trees[i]; if (treeToMerge.treeIndex == 48 || treeToMerge.treeIndex == 1001) { CDebug.WriteLine(""); } if (pOnlyInvalid && !treeToMerge.isValid && treeToMerge.IsAtBorder()) { //CDebug.Warning(treeToMerge + " is at border"); continue; } //dont merge tree if it is local maximum //if some tree is very close (in neighbouring detail field) //merge it with the highest one if (detectMethod == EDetectionMethod.AddFactor2D) { if (treeToMerge.Equals(22)) { CDebug.WriteLine(); } if (treeToMerge.IsLocalMaximum()) { continue; } CTreeField f = CProjectData.Points.treeDetailArray.GetFieldContainingPoint(treeToMerge.peak.Center); List <CTree> treesInHood = f.GetDetectedTreesFromNeighbourhood(); foreach (CTree tree in treesInHood) { if (tree.Equals(treeToMerge)) { continue; } MergeTrees(tree, treeToMerge); break; } continue; } List <CTree> possibleTrees = GetPossibleTreesToMergeWith(treeToMerge, EPossibleTreesMethod.ClosestHigher); Vector3 pPoint = treeToMerge.peak.Center; float bestAddPointFactor = 0; CTree selectedTree = null; foreach (CTree possibleTree in possibleTrees) { bool isFar = false; bool isSimilarHeight = false; if (possibleTree.isValid && treeToMerge.isValid) { float mergeFactor = GetMergeValidFacor(treeToMerge, possibleTree); if (mergeFactor > 0.9f) { selectedTree = possibleTree; break; } } if (pOnlyInvalid && possibleTree.isValid && treeToMerge.isValid) { continue; } if (treeToMerge.isValid) { //treeToMerge is always lower float possibleTreeHeight = possibleTree.GetTreeHeight(); float treeToMergeHeight = treeToMerge.GetTreeHeight(); const float maxPeaksDistance = 1; float peaksDist = CUtils.Get2DDistance(treeToMerge.peak, possibleTree.peak); if (peaksDist > maxPeaksDistance) { isFar = true; } const float maxPeakHeightDiff = 1; if (possibleTreeHeight - treeToMergeHeight < maxPeakHeightDiff) { isSimilarHeight = true; } } float addPointFactor = possibleTree.GetAddPointFactor(pPoint, treeToMerge); float requiredFactor = 0.5f; if (isFar) { requiredFactor += 0.1f; } if (isSimilarHeight) { requiredFactor += 0.1f; } if (pOnlyInvalid) { requiredFactor -= 0.2f; } if (addPointFactor > requiredFactor && addPointFactor > bestAddPointFactor) { selectedTree = possibleTree; bestAddPointFactor = addPointFactor; if (bestAddPointFactor > 0.9f) { break; } } } if (selectedTree != null) { float dist = CUtils.Get2DDistance(treeToMerge.peak.Center, selectedTree.peak.Center); treeToMerge = MergeTrees(ref treeToMerge, ref selectedTree, pOnlyInvalid); } CDebug.Progress(iteration, maxIterations, 50, ref previousMergeStart, mergeStart, "merge"); iteration++; } }