/// <summary> /// Returns true if tree was added /// </summary> public bool AddDetectedTree(CTree pTree, bool pIsPeak) { //if tree is not peak, dont set IsPeak to false, could be a peak from previous tree if (pIsPeak) { IsPeak = true; } if (this.indexInField.Item1 == 171 && this.indexInField.Item1 == 144) { CDebug.WriteLine(); } if (!DetectedTrees.Contains(pTree)) { if (IsDetail && DetectedTrees.Count > 0) { CDebug.Error($"Adding tree to detail field {this} where tree {DetectedTrees[0]} altready is"); } DetectedTrees.Add(pTree); pTree.AddField(this); return(true); } return(false); }
private void LoadObj(string pFileName) { Obj = new Obj(pFileName); string refTreePath = GetRefTreeFilePath(pFileName, pFileName + ".obj"); bool useReducedReftreeModels = CParameterSetter.GetBoolSettings(ESettings.useReducedReftreeModels); if (useReducedReftreeModels || !File.Exists(refTreePath)) { Obj.Name += "_reduced"; string reducedObjFileName = pFileName + "_reduced.obj"; if (!useReducedReftreeModels) { CDebug.WriteLine("Reftree " + refTreePath + " OBJ does not exist."); CDebug.WriteLine("Try reduced file: " + reducedObjFileName); } refTreePath = GetRefTreeFilePath(pFileName, reducedObjFileName); if (!File.Exists(refTreePath)) { CDebug.Error("No ref tree OBJ found!"); return; } } Obj.LoadObj(refTreePath); }
/// <summary> /// Assigns ground points into arrays (main and detailed for precess and later bitmap generation). /// Fills missing heights in the array and applies smoothing. /// </summary> private void ProcessGroundPoints() { if (CRxpParser.IsRxp) { return; } for (int i = 0; i < ground.Count; i++) { if (CProjectData.backgroundWorker.CancellationPending) { return; } Vector3 point = ground[i]; groundArray.AddPointInField(point); //some points can be at border of detail array - not error -> dont log //detailArray?.AddPointInField(point, CGroundArray.EPointType.Ground, false); } if (groundArray == null) { CDebug.Error("No array defined"); CDebug.WriteLine("setting height to " + lowestHeight); //CDebugData.DefineArray(true, lowestHeight); } groundArray.FillArray(); groundArray?.SmoothenArray(1); }
public virtual void AddPoint(Vector3 pPoint) { if (IsPointOutOfField(pPoint)) { CDebug.Error($"point {pPoint} is too far from center {Center}"); } float height = pPoint.Z; //todo test points.Add(pPoint); //null checks are neccessary! if (SumZ != null) { SumZ += height; } else { SumZ = height; } if (height > MaxZ || MaxZ == null) { MaxZ = height; } if (height < MinZ || MinZ == null) { MinZ = height; } }
public TypeField GetFieldContainingPoint(Vector3 pPoint) { Tuple <int, int> index = GetIndexInArray(pPoint); if (!IsWithinBounds(index)) { if (index.Item1 == -1) { index = new Tuple <int, int>(0, index.Item2); } if (index.Item2 == -1) { index = new Tuple <int, int>(index.Item1, 0); } if (index.Item1 == arrayXRange) { index = new Tuple <int, int>(arrayXRange - 1, index.Item2); } if (index.Item2 == arrayYRange) { index = new Tuple <int, int>(index.Item1, arrayYRange - 1); } if (!IsWithinBounds(index)) { return(null); } else { //todo: some points are 1 index away from the range CDebug.Error($"pPoint {pPoint} was OOB and was moved to {index}", false); } } return(array[index.Item1, index.Item2]); }
public static void AddRefTrees() { List <CTree> trees = new List <CTree>(); foreach (CTreeField f in CProjectData.Points.treeNormalArray.fields) { foreach (CTree tree in f.DetectedTrees) { if (!tree.isValid) { continue; } if (!trees.Contains(tree)) { trees.Add(tree); } } } foreach (CTree tree in trees) { if (tree.assignedRefTreeObj == null) { //not error if reftrees were not loaded if (CReftreeManager.Trees.Count > 0) { CDebug.Error($"{tree} has no reftree assigned"); } return; } AddObj(CProjectData.Points.treeNormalArray.GetIndexInArray(tree.peak.Center), tree.assignedRefTreeObj); } }
public static string[] GetHeaderLines(string pSourceFilePath, string pOutputFilePath) { if (!File.Exists(pSourceFilePath)) { CDebug.Error($"file: {pSourceFilePath} not found"); return(null); } //string infoFileName = Path.GetFileNameWithoutExtension(pSourceFilePath) + "_i.txt"; //string infoFilePath = currentTmpFolder + infoFileName; string info = "lasinfo " + pSourceFilePath + " -o " + pOutputFilePath; try { CCmdController.RunLasToolsCmd(info, pOutputFilePath); } catch (Exception e) { CDebug.Error($"Exception {e}"); } return(CProgramLoader.GetFileLines(pOutputFilePath, HEADER_FILE_LINES)); }
public override void FillMissingHeight(EFillMethod pMethod, int pKernelMultiplier) { if (MinZ != null) { ExpectedGroundZ = (float)MinZ; return; } int maxSteps = 1; switch (pMethod) { case EFillMethod.ClosestDefined: float?avgMinZ = GetAverageHeightFromClosestDefined(10 * maxSteps, false, EHeight.MinZ); if (avgMinZ != null) { ExpectedGroundZ = (float)avgMinZ; } break; case EFillMethod.FromNeighbourhood: CDebug.Error("Unsupported method"); break; } }
/// <summary> /// Scale¨color values in bitmap so that max value = 255 (MAX_COLOR_VALUE) /// </summary> private static void StretchColorRange(ref Bitmap pBitmap, int pMaxValue) { //if no value was not assigned (its error, but just to prevent exception) pMaxValue = Math.Max(1, pMaxValue); float scale = MAX_COLOR_VALUE / pMaxValue; //skip process if change is not significant if (scale - 1 < 0.1f) { return; } for (int x = 0; x < pBitmap.Width; x++) { for (int y = 0; y < pBitmap.Height; y++) { Color color = pBitmap.GetPixel(x, y); int origVal = color.R; int scaledVal = Math.Min((int)(origVal * scale), 255); Color newColor = Color.FromArgb(scaledVal, scaledVal, scaledVal); if (newColor.R > 255) { CDebug.Error("color.R = " + newColor.R); } pBitmap.SetPixel(x, y, newColor); } } }
public static void DeleteTree(CTree pTree) { if (pTree.treeIndex == 169) { bool i = true; } if (!Trees.Contains(pTree)) { CDebug.Error("Trees dont contain " + pTree); return; } pTree.peakDetailField.RemoveTree(pTree); pTree.peakNormalField.RemoveTree(pTree); foreach (CTreeField field in pTree.detailFields) { field.RemoveTree(pTree); } foreach (CTreeField field in pTree.normalFields) { field.RemoveTree(pTree); } //shouldnt be neccessary //pTree.peakDetailField.RemoveTree(pTree); //pTree.peakNormalField.RemoveTree(pTree); Trees.Remove(pTree); //if(!pTree.treeDetailField.GetDetectedTrees().Contains(pTree)) //{ // CDebug.Error("element " + pTree.treeDetailField + " doesnt contain " + pTree); // return; //} }
/*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); }
/// <summary> /// Calculates rigid transformations between all permutations of pSetA and pSetB /// and returns the best one (having the smallest offset). /// This is done due to the expected indexing in function CalculateRigidTransform /// </summary> public static CRigidTransform GetRigidTransform(List <Vector3> pSetA, List <Vector3> pSetB) { CDebug.WriteLine($"GetRigidTransform from set : {CDebug.GetString(pSetA)} to {CDebug.GetString(pSetB)}"); if (pSetA.Count != pSetB.Count) { CDebug.Error("Sets copunt dont match"); return(null); } IEnumerable <IEnumerable <Vector3> > setApermutations = pSetA.Permute(); List <CRigidTransform> rigTransforms = new List <CRigidTransform>(); foreach (var permutation in setApermutations) { CRigidTransform rigTransform = CalculateRigidTransform(permutation.ToList(), pSetB); rigTransforms.Add(rigTransform); //CDebug.WriteLine($"{rigTransform}"); if (rigTransform.offset < MAX_OFFSET) { break; } } CRigidTransform minOffsetRigTransform = rigTransforms.Aggregate( (curMin, x) => x.offset < curMin.offset ? x : curMin); CDebug.WriteLine($"Selected {minOffsetRigTransform}", true, true); return(minOffsetRigTransform); }
public static float Get2DDistance(CField pField1, CField pField2) { if (pField1 == null || pField2 == null) { CDebug.Error("Field is null"); return(0); } return(Get2DDistance(pField1.Center, pField2.Center)); }
public static void AddObj(int pArrayIndexX, int pArrayIndexY, Obj pObj) { if (pObj == null) { CDebug.Error("AddObj is null!"); } Tuple <int, int> index = GetIndexInArray(pArrayIndexX, pArrayIndexY); AddToPartition(pObj, index); }
public CTree GetSingleDetectedTree() { if (DetectedTrees.Count == 0) { return(null); } if (DetectedTrees.Count > 1) { CDebug.Error($"User requested single tree but field {this} contains more"); } return(DetectedTrees[0]); }
public void CheckBranch() { for (int i = 1; i < TreePoints.Count; i++) { CTreePoint previousTp = TreePoints[i - 1]; CTreePoint tp = TreePoints[i]; if (tp.minHeight.Z > previousTp.maxHeight.Z) { CDebug.Error("- CheckBranch. tree " + tree.treeIndex + ": " + tp + " is higher than " + previousTp); } } }
public Tuple <int, int> GetIndexInArray(Vector3 pPoint) { Tuple <int, int> pos = GetIndexInArray(pPoint, topLeftCorner, stepSize); CField el = GetField(pos.Item1, pos.Item2); if (el != null && el.IsPointOutOfField(pPoint)) { CDebug.Error($"point {pPoint} is too far from center {el.Center}"); } return(pos); }
/// <summary> /// Deletes the lower tree and merges it into the higher one. /// important! delete has to be done before the merge to prevent deadlock by adding points to new tree during merging /// </summary> public static void MergeTrees(CTree pHigherTree, CTree pLowerTree) { float higherTreeZ = pHigherTree.peak.maxHeight.Z; float lowerTreeZ = pLowerTree.peak.minHeight.Z; if (lowerTreeZ > higherTreeZ) { CDebug.Error("given pHigherTree is lower!"); return; } DeleteTree(pLowerTree); pHigherTree.MergeWith(pLowerTree); }
public static float GetOverlapRatio(CBoundingBoxObject pOfObject, CBoundingBoxObject pWithObject) { float overlapVolume = GetOverlapVolume(pOfObject, pWithObject); float ofObjectVolume = pOfObject.Volume; if (ofObjectVolume == 0) { CDebug.Error("object " + pWithObject + " has no volume"); return(0); } float ratio = overlapVolume / ofObjectVolume; return(ratio); }
/// <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); } }
public static void AddPoint(Vector3 pPoint, int pPointIndex) { //index < 0 = the point was re-added during the tree merging process //(where the index is not passed) - use the last index if (pPointIndex < 0) { pPointIndex = currentPointIndex; } currentPointIndex = pPointIndex; ProcessDebug(pPoint, pPointIndex); pointCounter++; CProjectData.Points.vegeArray.AddPointInField(pPoint); CProjectData.Points.vegeDetailArray.AddPointInField(pPoint); List <CTree> possibleTrees = GetPossibleTreesFor(pPoint, EPossibleTreesMethod.ClosestHigher, false); CTree selectedTree = SelectBestPossibleTree(possibleTrees, pPoint, true); /*if(selectedTree == null && detectMethod == EDetectionMethod.AddFactor2D) * { * CTreeField f = CProjectData.Points.treeDetailArray.GetFieldContainingPoint(pPoint); * List<CTree> treesInHood = f.GetDetectedTreesFromNeighbourhood(); * foreach(CTree tree in treesInHood) * { * selectedTree = tree; * break; * } * }*/ if (selectedTree != null) { selectedTree.AddPoint(pPoint, pPointIndex); } else if (CProjectData.Points.treeDetailArray.GetFieldContainingPoint(pPoint).DetectedTrees.Count > 0) { //new tree cant be created on field where another tree was already detected - shouldnt happen CDebug.Error("trying to create tree on a field where a tree already is"); return; } else { CreateNewTree(pPoint); } }
public static double[,] CalculateGaussKernel(int lenght, double weight) { if (lenght % 2 == 0) { CDebug.Error("CalculateGaussKernel - lenght cant be even. " + lenght); } double[,] Kernel = new double[lenght, lenght]; double sumTotal = 0; int kernelRadius = lenght / 2; double distance = 0; double calculatedEuler = 1.0 / (2.0 * Math.PI * Math.Pow(weight, 2)); for (int filterY = -kernelRadius; filterY <= kernelRadius; filterY++) { for (int filterX = -kernelRadius; filterX <= kernelRadius; filterX++) { distance = ((filterX * filterX) + (filterY * filterY)) / (2 * (weight * weight)); Kernel[filterY + kernelRadius, filterX + kernelRadius] = calculatedEuler * Math.Exp(-distance); sumTotal += Kernel[filterY + kernelRadius, filterX + kernelRadius]; } } for (int y = 0; y < lenght; y++) { for (int x = 0; x < lenght; x++) { double finalVal = Kernel[y, x] * (1.0 / sumTotal); //CDebug.WriteLine(finalVal.ToString("0.00000")); Kernel[y, x] = finalVal; } } return(Kernel); }
private static void AddToPartition(Obj pObj, Tuple <int, int> pIndex) { //TODO: error, incorrect partition if (pIndex.Item1 >= partitionXRange) { CDebug.Error($"obj {pObj.Name} has partition index {pIndex} OOB"); pIndex = new Tuple <int, int>(partitionXRange - 1, pIndex.Item2); } if (pIndex.Item2 >= partitionYRange) { CDebug.Error($"obj {pObj.Name} has partition index {pIndex} OOB"); pIndex = new Tuple <int, int>(pIndex.Item1, partitionYRange - 1); } objPartition[pIndex.Item1, pIndex.Item2].Add(pObj); }
/// <summary> /// Returns the interpolated height. /// Interpolation = bilinear. /// </summary> public float?GetHeight(Vector3 pPoint) { if (!HasAllNeighbours() || !HasAllNeighboursDefined(true)) { if (!IsDefined()) { return(null); } return(GetHeight()); } //return GetHeight(); //uncomment to cancel interpolation //http://www.geocomputation.org/1999/082/gc_082.htm //3.4 Bilinear interpolation List <CField> bilinearFields = GetBilinearFieldsFor(pPoint); CField h1 = bilinearFields[0]; CField h2 = bilinearFields[1]; CField h3 = bilinearFields[2]; CField h4 = bilinearFields[3]; float a00 = (float)h1.GetHeight(); float a10 = (float)h2.GetHeight() - (float)h1.GetHeight(); float a01 = (float)h3.GetHeight() - (float)h1.GetHeight(); float a11 = (float)h1.GetHeight() - (float)h2.GetHeight() - (float)h3.GetHeight() + (float)h4.GetHeight(); float step = CParameterSetter.groundArrayStep; float x = pPoint.X - Center.X; x += step / 2; x = x / step; float y = Center.Y - pPoint.Y; y += step / 2; y = y / step; if (x < 0 || x > 1 || y < 0 || y > 1) { CDebug.Error("field " + this + " interpolation is incorrect! x = " + x + " z = " + y); } //pPoint space coords are X and Z, Y = height float hi = a00 + a10 * x + a01 * y + a11 * x * y; return(hi); }
/// <summary> /// Transforms given point from world coordinates to index in main bitmap /// </summary> private static Tuple <int, int> GetIndexInMainBitmap(Vector3 pPoint) { Tuple <int, int> posInMain = CGroundArray.GetIndexInArray( pPoint, CProjectData.mainHeader.TopLeftCorner, mainMapStepSize); //todo: error posInMain is OOB CUtils.TransformArrayIndexToBitmapIndex(ref posInMain, CProjectData.mainHeader, mainMapStepSize, mainMap); if (!CUtils.IsInBitmap(posInMain, mainMap)) { CDebug.Error($"cant write to bitmap {posInMain.Item1}, {posInMain.Item2}"); return(null); } return(posInMain); }
/// <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; }
private static Material GetTreeMaterial(int pIndex) { if (!useTreeMaterial) { return(null); } List <int> treeIndexes = materialSet[EMaterial.Tree]; int matIndex = (pIndex % treeIndexes.Count + treeIndexes.Count) % treeIndexes.Count; if (matIndex < 0 || matIndex > treeIndexes.Count - 1) { CDebug.Error("matIndex OOR"); matIndex = 0; } return(materials.MaterialList[treeIndexes[matIndex]]); }
/// <summary> /// Returns field from array (of normal step size) of the given class on the given index /// </summary> public CField GetField(EClass pClass, int pX, int pY) { switch (pClass) { case EClass.Unassigned: return(unassignedArray.GetField(pX, pY)); case EClass.Ground: return(groundArray.GetField(pX, pY)); case EClass.Vege: return(vegeArray.GetField(pX, pY)); case EClass.Building: return(buildingArray.GetField(pX, pY)); } CDebug.Error($"array from class {pClass} not defined"); return(null); }
private static float GetRangeSettings(ESettings pRangeSetting) { switch (pRangeSetting) { case ESettings.rangeXmax: return(GetIntSettings(ESettings.rangeXmax) / 10f); case ESettings.rangeXmin: return(GetIntSettings(ESettings.rangeXmin) / 10f); case ESettings.rangeYmax: return(GetIntSettings(ESettings.rangeYmax) / 10f); case ESettings.rangeYmin: return(GetIntSettings(ESettings.rangeYmin) / 10f); } CDebug.Error("GetRange - invalid arg"); return(0); }
private void CheckAddedPoint() { if (TreePoints[0].minHeight.Z > tree.peak.Z) { //not error, can happen after merging when peak is expanded //CDebug.Error($"CheckAddedPoint. tree {tree.treeIndex} : first point {TreePoints[0]} is higher than peak {tree.peak}"); } if (TreePoints.Count < 2) { return; } CTreePoint previousTp = TreePoints[TreePoints.Count - 2]; CTreePoint tp = TreePoints[TreePoints.Count - 1]; if (tp.minHeight.Z > previousTp.maxHeight.Z) { CDebug.Error("CheckAddedPoint. tree " + tree.treeIndex + ": " + tp + " is higher than " + previousTp); } }