public static void TryMergeAllTrees(bool pOnlyInvalid) { IsMerging = true; DateTime mergeStartTime = DateTime.Now; CDebug.WriteLine("TryMergeAllTrees"); Trees.Sort((a, b) => b.peak.Center.Z.CompareTo(a.peak.Center.Z)); int treeCountBeforeMerge = Trees.Count; if (detectMethod == EDetectionMethod.AddFactor) { MergeGoodAddFactorTrees(pOnlyInvalid); } if (detectMethod == EDetectionMethod.Detection2D) { Merge2DTrees(); } if (pOnlyInvalid) { CAnalytics.secondMergeDuration = CAnalytics.GetDuration(mergeStartTime); } else { CAnalytics.firstMergeDuration = CAnalytics.GetDuration(mergeStartTime); } IsMerging = false; CDebug.Duration("Trees merge", mergeStartTime); CDebug.Count("Number of trees merged", treeCountBeforeMerge - Trees.Count); }
/// <summary> /// Assigns vege poins to trees. Handled in TreeManager /// </summary> private void ProcessVegePoints() { vege.Sort((b, a) => a.Z.CompareTo(b.Z)); //sort descending by height const int debugFrequency = 10000; DateTime processVegePointsStart = DateTime.Now; CDebug.WriteLine("ProcessVegePoints", true); DateTime previousDebugStart = DateTime.Now; int pointsToAddCount = vege.Count; //pointsToAddCount = 12000; for (int i = 0; i < pointsToAddCount; i++) { if (CProjectData.backgroundWorker.CancellationPending) { return; } Vector3 point = vege[i]; CTreeManager.AddPoint(point, i); CDebug.Progress(i, vege.Count, debugFrequency, ref previousDebugStart, processVegePointsStart, "added point"); } CDebug.WriteLine("maxPossibleTreesAssignment = " + CTreeManager.maxPossibleTreesAssignment + " todo: investigate if too high"); CAnalytics.processVegePointsDuration = CAnalytics.GetDuration(processVegePointsStart); CDebug.Duration("ProcessVegePoints", processVegePointsStart); }
/// <summary> /// Classify each point into its according points list. /// Then adds it to its array. /// </summary> public void AddPointsFromLines(List <Tuple <EClass, Vector3> > pParsedLines) { ClassifyPoints(pParsedLines); DateTime processStartTime = DateTime.Now; CDebug.Count("ProcessParsedLines", pParsedLines.Count); //TODO: unite processing all points CDebug.Step(EProgramStep.ProcessUnassignedPoints); ProcessUnassignedPoints(); CDebug.Step(EProgramStep.ProcessBuildingPoints); ProcessBuildingPoints(); CDebug.Step(EProgramStep.ProcessGroundPoints); ProcessGroundPoints(); CDebug.Step(EProgramStep.PreprocessVegePoints); PreprocessVegePoints(); CDebug.Step(EProgramStep.ProcessVegePoints); ProcessVegePoints(); SetAnalytics(); CDebug.Duration("All points added", processStartTime); }
/*public void AddPointInField(Vector3 pPoint, EPointType pType, bool pLogErrorInAnalytics) * { * Tuple<int, int> index = GetPositionInArray(pPoint); * if (!IsWithinBounds(index)) * { * CDebug.Error($"point {pPoint} is OOB {index}", pLogErrorInAnalytics); * return; * } * switch (pType) * { * case EPointType.Ground: * array[index.Item1, index.Item2].AddGroundPoint(pPoint); * break; * case EPointType.Vege: * array[index.Item1, index.Item2].AddVegePoint(pPoint); * break; * case EPointType.Preprocess: * array[index.Item1, index.Item2].AddPreProcessVegePoint(pPoint); * break; * } * }*/ //public void SortPoints() //{ // foreach (CField field in fields) // { // field.SortPoints(); // } //} /// <summary> /// Approximates the height in undefined fields of ground array. /// </summary> public void FillArray() { CDebug.WriteLine("FillArray", true); DateTime fillAllHeightsStart = DateTime.Now; int counter = 1; while (!IsAllDefined()) { if (CProjectData.backgroundWorker.CancellationPending) { return; } DateTime fillHeightsStart = DateTime.Now; CDebug.Count("FillMissingHeights", counter); FillMissingHeights(counter); counter++; const int maxFillArrayIterations = 5; if (counter > maxFillArrayIterations + 1) { CDebug.Error("FillMissingHeights"); CDebug.Count("too many iterations", counter); break; } CDebug.Duration("FillMissingHeights", fillHeightsStart); } CAnalytics.fillAllHeightsDuration = CAnalytics.GetDuration(fillAllHeightsStart); CDebug.Duration("fillAllHeights", fillAllHeightsStart); }
private void AddPointsFromLines(List <Tuple <EClass, Vector3> > pParsedLines) { DateTime addStartTime = DateTime.Now; CDebug.WriteLine("AddPointsFromLines " + pParsedLines.Count); int pointsToAddCount = pParsedLines.Count; pParsedLines.Sort((a, b) => b.Item2.Z.CompareTo(a.Item2.Z)); //lines are sorted. first point is peak for sure Init(pParsedLines[0].Item2, treeIndex, treePointExtent); DateTime lineStartTime = DateTime.Now; for (int i = 1; i < Math.Min(pParsedLines.Count, pointsToAddCount); i++) { Tuple <EClass, Vector3> parsedLine = pParsedLines[i]; Vector3 point = parsedLine.Item2; //all points belong to 1 tree. force add it AddPoint(point); CDebug.Progress(i, pParsedLines.Count, 100000, ref lineStartTime, addStartTime, "added point:"); } CDebug.Duration("All points added", addStartTime); }
public CRefTree(string pFileName, int pTreeIndex, float pTreePointExtent, bool pLoadFromFile) { treeIndex = pTreeIndex; fileName = pFileName; treePointExtent = pTreePointExtent; isValid = true; if (pLoadFromFile) { string[] lines = GetFileLines(pFileName); if (lines.Length == 0) { isValid = false; return; } LoadObj(pFileName); List <Tuple <EClass, Vector3> > parsedLines = CProgramLoader.ParseLines(lines, false); AddPointsFromLines(parsedLines); DateTime processStartTime = DateTime.Now; CDebug.WriteLine("Process"); Process(); CDebug.Duration("Processed", processStartTime); } }
/// <summary> /// If not-tree is very close to some tree then it is probably part of that tree. /// Not-tree will be merged into the closest one. /// </summary> public static void TryMergeNotTrees() { IsMerging = true; DateTime mergeStartTime = DateTime.Now; CDebug.WriteLine("TryMergeNotTrees"); //sort in descending order - trees will be processed from the end NotTrees.Sort((b, a) => b.peak.Center.Z.CompareTo(a.peak.Center.Z)); //TODO: CHECK!!! THIS IS NOT DESCENDING ORDER??? int treeCountBeforeMerge = NotTrees.Count; for (int i = NotTrees.Count - 1; i >= 0; i--) { CTree notTree = NotTrees[i]; //if(notTree.Equals(335)) // CDebug.WriteLine(""); //just debug //List<CTree> closeTrees2 = CProjectData.Points.treeNormalArray. // GetTreesInMaxStepsFrom(notTree.peak.Center, 1); List <CTree> closeTrees = new List <CTree>(); //fisrt try to get a tree on the same detail field CTree t = CProjectData.Points.treeDetailArray. GetFieldContainingPoint(notTree.peak.Center).GetSingleDetectedTree(); if (t != null) { closeTrees.Add(t); } //if no tree is on the same field get some in close distance if (closeTrees.Count == 0) { closeTrees = CProjectData.Points.treeDetailArray. GetTreesInMaxStepsFrom(notTree.peak.Center, 2); } //merge not-tree with the closest tree but only if it is higher. //if not then it is probably some noise above the regular tree if (closeTrees.Count > 0 && closeTrees[0].GetTreeHeight() > notTree.GetTreeHeight() && !notTree.IsLocalMaximum()) { closeTrees[0].MergeWith(notTree); NotTrees.RemoveAt(i); } } IsMerging = false; CDebug.Duration("Not-trees merge", mergeStartTime); CDebug.Count("Number of not-trees merged", treeCountBeforeMerge - Trees.Count); }
/// <summary> /// Assigns all vege points in preprocess arrays. /// Then it calculates the expected average tree height. /// </summary> private void PreprocessVegePoints() { const int debugFrequency = 10000; DateTime PreprocessVegePointsStart = DateTime.Now; CDebug.WriteLine("PreprocessVegePoints", true); DateTime preprocessVegePointsStart = DateTime.Now; DateTime previousDebugStart = DateTime.Now; for (int i = 0; i < vege.Count; i++) { if (CProjectData.backgroundWorker.CancellationPending) { return; } Vector3 point = vege[i]; preprocessDetailArray.AddPointInField(point); preprocessNormalArray.AddPointInField(point); CDebug.Progress(i, vege.Count, debugFrequency, ref previousDebugStart, preprocessVegePointsStart, "preprocessed point"); } //fill missing heigh - will be used in detection process //rank 2 - rank 1 (max) extends local maximas -> unwanted effect preprocessDetailArray.FillMissingHeights(2); preprocessDetailArray.FillMissingHeights(2); CDebug.Duration("PreprocessVegePoints", PreprocessVegePointsStart); //determine average tree height if (CParameterSetter.GetBoolSettings(ESettings.autoAverageTreeHeight)) { //not valid anymore //why not valid??...seems to work fine CTreeManager.AVERAGE_TREE_HEIGHT = preprocessNormalArray.GetAverageZ(); if (float.IsNaN(CTreeManager.AVERAGE_TREE_HEIGHT)) { CDebug.Error("AVERAGE_TREE_HEIGHT = NaN. using input value"); CTreeManager.AVERAGE_TREE_HEIGHT = CParameterSetter.GetIntSettings(ESettings.avgTreeHeigh); } } else { CTreeManager.AVERAGE_TREE_HEIGHT = CParameterSetter.GetIntSettings(ESettings.avgTreeHeigh); } }
private static void LoadTrees(List <string> pFileNames) { DateTime loadTreesStartTime = DateTime.Now; DateTime lastDebugTime = DateTime.Now; CDebug.WriteLine("Load reftrees: "); foreach (string fileName in pFileNames) { CDebug.WriteLine(" - " + fileName); } for (int i = 0; i < pFileNames.Count; i++) { if (CProjectData.backgroundWorker.CancellationPending) { return; } string fileName = pFileNames[i]; CDebug.Progress(i, pFileNames.Count, 1, ref lastDebugTime, loadTreesStartTime, "load reftree"); CRefTree deserializedRefTree = CRefTree.Deserialize(fileName); bool isDeserializedTreeValid = deserializedRefTree != null && deserializedRefTree.IsCurrentVersion(); CRefTree refTree = isDeserializedTreeValid ? deserializedRefTree : new CRefTree(fileName, i, TREE_POINT_EXTENT, true); refTree.RefTreeTypeName = fileName; //GetTypeName(fileName); if (!refTree.isValid) { //this reftree is not valid. case for reftrees in 'ignore' folder CDebug.Warning($"Skipping reftree {fileName}"); continue; } //material set durring assigning to tree //refTree.Obj.UseMtl = CMaterialManager.GetRefTreeMaterial(counter); Trees.Add(refTree); CDebug.WriteLine($"Loaded tree: {fileName}. height = {refTree.GetTreeHeight()}"); } CAnalytics.loadReftreesDuration = CAnalytics.GetDuration(loadTreesStartTime); CDebug.Duration("Load reftrees", loadTreesStartTime); CAnalytics.loadedReftrees = Trees.Count; DebugReftrees(); }
protected override void OnProcess() { string filePath = GetRefTreeFilePath(fileName, fileName + ".reftree"); CDebug.WriteLine("\nfilePath = " + filePath); if (File.Exists(filePath)) { if (!IsCurrentVersion()) { File.Delete(filePath); CDebug.Warning($"deleting old .reftree file ({filePath})"); } else { CDebug.Error(".reftree file already exists ({filePath})"); } //return; } DateTime processStartTime = DateTime.Now; CDebug.WriteLine("Serialization"); List <string> serializedTree = Serialize(); version = CURRENT_REFTREE_VERSION; using (StreamWriter file = new StreamWriter(filePath, false)) { foreach (string line in serializedTree) { file.WriteLine(line); } } CDebug.Duration("Serialized", processStartTime); CDebug.WriteLine("saved to: " + filePath); }
public static void Export(int pTileIndex) { if (!exportBitmap) { return; } //init for each tile treeMarkerSize = GetTreeBrushSize(false); DateTime bitmapStart = DateTime.Now; CVegeArray array = CProjectData.Points.vegeDetailArray; Bitmap bitmap = new Bitmap(array.arrayXRange, array.arrayYRange); int maxValue = 0; for (int x = 0; x < array.arrayXRange; x++) { for (int y = 0; y < array.arrayYRange; y++) { CVegeField element = array.GetField(x, y); int? colorVal = element.GetColorValue(); //from detailed array if (colorVal == null) { continue; } int colorVaInt = (int)colorVal; if (colorVaInt > maxValue) { maxValue = colorVaInt; } int rVal = colorVaInt; //highlight buffer zone bool isAtBufferZone = CTreeMath.IsAtBufferZone(element.Center); if (isAtBufferZone) { rVal = Math.Min(rVal + 30, 255); } Color color = Color.FromArgb(rVal, colorVaInt, colorVaInt); //CDebug.WriteLine($"{x},{y} = {color}"); bitmap.SetPixel(x, y, color); if (exportMain && !isAtBufferZone) { Tuple <int, int> posInMain = GetIndexInMainBitmap(element.Center); if (posInMain == null) { continue; } if (color.R > 255) { CDebug.Error("color.R = " + color.R); } mainMap.SetPixel(posInMain.Item1, posInMain.Item2, color); } } } //StretchColorRange(ref bitmap, maxValue); //FilterBitmap(ref bitmap, GetKernelSize(array.stepSize, .2f), EFilter.Max); if (exportHeightmap) { ExportBitmap(bitmap, "heightmap", pTileIndex); } int bitmapsCount = 3; bool useCheckTree = CParameterSetter.GetBoolSettings(ESettings.useCheckTreeFile); if (useCheckTree) { bitmapsCount++; } CDebug.Progress(1, bitmapsCount, 1, ref bitmapStart, bitmapStart, "bitmap: "); if (exportPositions) { Bitmap bitmapTreePos = new Bitmap(bitmap); AddTreesToBitmap(array, bitmapTreePos, true, false); ExportBitmap(bitmapTreePos, "tree_positions", pTileIndex); if (useCheckTree) { Bitmap bitmapChecktree = new Bitmap(bitmapTreePos); ExportBitmap(bitmapChecktree, "tree_check", pTileIndex); CDebug.Progress(bitmapsCount - 1, bitmapsCount, 1, ref bitmapStart, bitmapStart, "bitmap: "); } } CDebug.Progress(2, bitmapsCount, 1, ref bitmapStart, bitmapStart, "bitmap: "); if (exportBorders) { Bitmap bitmapTreeBorder = new Bitmap(bitmap); AddTreesToBitmap(array, bitmapTreeBorder, true, true); ExportBitmap(bitmapTreeBorder, "tree_borders", pTileIndex); } CDebug.Progress(bitmapsCount, bitmapsCount, 1, ref bitmapStart, bitmapStart, "bitmap: "); CAnalytics.bitmapExportDuration = CAnalytics.GetDuration(bitmapStart); CDebug.Duration("bitmap export", bitmapStart); }
private static EProcessResult ProcessTile(string pTilePath, int pTileIndex) { //has to reinit first for the correct progress output CDebug.ReInit(); DateTime startTime = DateTime.Now; currentTileIndex = pTileIndex; List <Tuple <EClass, Vector3> > parsedLines; if (CRxpParser.IsRxp) { CRxpInfo rxpInfo = CRxpParser.ParseFile(pTilePath); parsedLines = rxpInfo.ParsedLines; //for now we expect only one tile in rxp processing CProjectData.currentTileHeader = rxpInfo.Header; CProjectData.mainHeader = rxpInfo.Header; } else { string[] lines = CProgramLoader.GetFileLines(pTilePath); bool linesOk = lines != null && lines.Length > 0 && !string.IsNullOrEmpty(lines[0]); if (linesOk && CHeaderInfo.HasHeader(lines[0])) { //todo: where to init header? CProjectData.currentTileHeader = new CHeaderInfo(lines); } else { const string noHeaderMsg = "Processed tile has no header"; CDebug.Error(noHeaderMsg); throw new Exception(noHeaderMsg); } parsedLines = CProgramLoader.ParseLines(lines, true); } //has to be called after currentTileHeader is assigned CProjectData.ReInit(pTileIndex); //has to reinit after each tile is processed CTreeManager.Reinit(); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } CProgramLoader.ProcessParsedLines(parsedLines); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } CTreeManager.DebugTrees(); CDebug.Step(EProgramStep.Export3D); CObjPartition.ExportPartition("", "tile" + pTileIndex); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } //has to be called after ExportPartition where final folder location is determined try { CDebug.Step(EProgramStep.Bitmap); CBitmapExporter.Export(pTileIndex); } catch (Exception e) { CDebug.Error("exception: " + e.Message); } CAnalytics.totalDuration = CAnalytics.GetDuration(startTime); CDebug.Duration("total time", startTime); CDebug.Step(EProgramStep.Dart); CDartTxt.ExportTile(); CDebug.Step(EProgramStep.Shp); CShpController.ExportCurrent(); CDebug.Step(EProgramStep.Las); CLasExporter.ExportTile(); CDebug.Step(EProgramStep.Analytics); CAnalytics.Write(true); return(EProcessResult.Done); }
/// <summary> /// Assigns to each of detected trees the most suitable refTree /// </summary> public static void AssignRefTrees() { if (Trees.Count == 0) { //CDebug.Error("no reftrees loaded"); return; } DateTime addTreeObjModelsStart = DateTime.Now; CDebug.WriteLine("Get reftree models"); const int debugFrequency = 10; DateTime assignRefTreesStart = DateTime.Now; CDebug.WriteLine("AssignRefTrees"); DateTime previousDebugStart = DateTime.Now; int counter = 0; float similaritySum = 0; foreach (CTree t in CTreeManager.Trees) { if (CProjectData.backgroundWorker.CancellationPending) { break; } Tuple <CRefTree, STreeSimilarity> suitableRefTree = GetMostSuitableRefTree(t); CRefTree mostSuitableRefTree = suitableRefTree.Item1; if (mostSuitableRefTree == null) { CDebug.Error("no reftrees assigned!"); continue; } SetRefTreeObjTransform(ref mostSuitableRefTree, t, suitableRefTree.Item2.angleOffset); similaritySum += suitableRefTree.Item2.similarity; //CDebug.WriteLine($"similaritySum += {suitableRefTree.Item2.similarity}"); Obj suitableTreeObj = mostSuitableRefTree.Obj.Clone(); suitableTreeObj.Name += "_" + t.treeIndex; t.assignedRefTreeObj = suitableTreeObj; t.assignedRefTree = mostSuitableRefTree; //t.RefTreeTypeName = mostSuitableRefTree.RefTreeTypeName; //copy the type name suitableTreeObj.UseMtl = t.assignedMaterial.Name; CDebug.Progress(counter, CTreeManager.Trees.Count, debugFrequency, ref previousDebugStart, assignRefTreesStart, "Assigned reftree"); counter++; //CDebug.WriteLine("\n mostSuitableRefTree = " + mostSuitableRefTree); } CAnalytics.averageReftreeSimilarity = similaritySum / CTreeManager.Trees.Count; CAnalytics.reftreeAssignDuration = CAnalytics.GetDuration(addTreeObjModelsStart); CDebug.Duration("Assign reftree models", addTreeObjModelsStart); }