public float?GetAverageHeightFromNeighbourhood(int pKernelSizeMultiplier) { int pKernelSize = CGroundArray.GetKernelSize(); pKernelSize *= pKernelSizeMultiplier; int defined = 0; float heightSum = 0; for (int x = -pKernelSize; x < pKernelSize; x++) { for (int y = -pKernelSize; y < pKernelSize; y++) { int xIndex = indexInField.Item1 + x; int yIndex = indexInField.Item2 + y; CField el = GetFieldWithOffset(x, y); if (el != null && el.IsDefined()) { defined++; heightSum += (float)el.GetHeight(); } } } if (defined == 0) { return(null); } return(heightSum / defined); }
/// <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> /// Sets SmoothHeight based on average from neighbourhood /// </summary> public void CalculateSmoothHeight(double[,] pGaussKernel) { if (!IsDefined()) { return; } //int defined = 0; float heightSum = 0; float midHeight = (float)GetHeight(); int kernelSize = CGroundArray.GetKernelSize(); float gaussWeightSum = 0; for (int x = 0; x < kernelSize; x++) { for (int y = 0; y < kernelSize; y++) { int xIndex = indexInField.Item1 + x - kernelSize / 2; int yIndex = indexInField.Item2 + y - kernelSize / 2; CField el = CProjectData.Points.groundArray.GetField(xIndex, yIndex); float? elHeight = el?.GetHeight(); //if element is not defined, use height from the middle element float definedHeight = midHeight; if (elHeight != null) { definedHeight = (float)elHeight; } float gaussWeight = (float)pGaussKernel[x, y]; gaussWeightSum += gaussWeight; heightSum += definedHeight * gaussWeight; } } SmoothHeight = heightSum; }
/// <summary> /// Finds closest defined fields in direction based on pDiagonal parameter. /// Returns average of 2 found heights considering their distance from this field. /// </summary> public float?GetAverageHeightFromClosestDefined(int pMaxSteps, bool pDiagonal, EHeight pType) { if (IsDefined()) { return(GetHeight(pType)); } CField closestFirst = null; CField closestSecond = null; CField closestLeft = GetClosestDefined(pDiagonal ? EDirection.LeftTop : EDirection.Left, pMaxSteps); CField closestRight = GetClosestDefined(pDiagonal ? EDirection.RightBot : EDirection.Right, pMaxSteps); CField closestTop = GetClosestDefined(pDiagonal ? EDirection.RightTop : EDirection.Top, pMaxSteps); CField closestBot = GetClosestDefined(pDiagonal ? EDirection.LeftBot : EDirection.Bot, pMaxSteps); closestFirst = closestLeft; closestSecond = closestRight; if ((closestFirst == null || closestSecond == null) && closestTop != null && closestBot != null) { closestFirst = closestTop; closestSecond = closestBot; } if (closestFirst != null && closestSecond != null) { CField smaller = closestFirst; CField higher = closestSecond; if (closestSecond.GetHeight(pType) < closestFirst.GetHeight(pType)) { higher = closestFirst; smaller = closestSecond; } int totalDistance = smaller.GetStepCountTo(higher); float?heightDiff = higher.GetHeight(pType) - smaller.GetHeight(pType); if (heightDiff != null) { float?smallerHeight = smaller.GetHeight(); float distanceToSmaller = GetStepCountTo(smaller); return(smallerHeight + distanceToSmaller / totalDistance * heightDiff); } } else if (!HasAllNeighbours()) { if (closestLeft != null) { return(closestLeft.GetHeight(pType)); } if (closestTop != null) { return(closestTop.GetHeight(pType)); } if (closestRight != null) { return(closestRight.GetHeight(pType)); } if (closestBot != null) { return(closestBot.GetHeight(pType)); } } if (!pDiagonal) { return(GetAverageHeightFromClosestDefined(pMaxSteps, true, pType)); } return(null); }