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> /// Add points of given class to the partitions /// </summary> public static void AddPoints(EClass pClass) { for (int x = 0; x < CProjectData.Points.groundArray.arrayXRange; x += partitionStepSize) { for (int y = 0; y < CProjectData.Points.groundArray.arrayYRange; y += partitionStepSize) { List <Vector3> points = new List <Vector3>(); for (int _x = x; _x < x + partitionStepSize; _x++) { for (int _y = y; _y < y + partitionStepSize; _y++) { CField element = CProjectData.Points.GetField(pClass, _x, _y); //CField element = CProjectData.Points.groundArray.GetField(_x, _y); if (element != null) { points.AddRange(element.points); } } } Obj pointsObj = new Obj(GetPointsObjName(pClass)); CObjExporter.AddPointsToObj(ref pointsObj, points); pointsObj.UseMtl = CMaterialManager.GetPointsMaterial(pClass).Name; AddObj(x, y, pointsObj); } } }
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)); }
/// <summary> /// Finds the closest neighbour in given direction which doesnt contain any of the given points /// </summary> public CField GetClosestNeighbourWithout(List <Vector3> pPoints, EDirection pDirection) { CField current = GetNeighbour(pDirection); while (current != null && current.Contains(pPoints, false)) { current = current.GetNeighbour(pDirection); } return(current); }
public static EDirection GetDirection(CField pFrom, CField pTo) { Vector3 dir = pTo.Center - pFrom.Center; dir = Vector3.Normalize(dir); const float angle_limit = 0.35f; if (dir.X > angle_limit) { if (dir.Y > angle_limit) { return(EDirection.RightTop); } else if (dir.Y < -angle_limit) { return(EDirection.RightBot); } else { return(EDirection.Right); } } else if (dir.X < -angle_limit) { if (dir.Y > angle_limit) { return(EDirection.LeftTop); } else if (dir.Y < -angle_limit) { return(EDirection.LeftBot); } else { return(EDirection.Left); } } else { if (dir.Y > angle_limit) { return(EDirection.Top); } else if (dir.Y < -angle_limit) { return(EDirection.Bot); } else { return(EDirection.None); } } }
public override bool Equals(object obj) { // Check for null values and compare run-time types. if (obj == null || GetType() != obj.GetType()) { return(false); } CField e = (CField)obj; return((indexInField.Item1 == e.indexInField.Item1) && (indexInField.Item2 == e.indexInField.Item2)); }
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> /// 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); }
public List <CField> GetPerpendicularNeighbours(EDirection pToDirection) { List <CField> neigh = new List <CField>(); CField n1 = null; CField n2 = null; switch (pToDirection) { case EDirection.Top: case EDirection.Bot: n1 = GetNeighbour(EDirection.Left); n2 = GetNeighbour(EDirection.Right); break; case EDirection.RightTop: case EDirection.LeftBot: n1 = GetNeighbour(EDirection.LeftTop); n2 = GetNeighbour(EDirection.RightBot); break; case EDirection.Right: case EDirection.Left: n1 = GetNeighbour(EDirection.Top); n2 = GetNeighbour(EDirection.Bot); break; case EDirection.RightBot: case EDirection.LeftTop: n1 = GetNeighbour(EDirection.RightTop); n2 = GetNeighbour(EDirection.LeftBot); break; } if (n1 != null) { neigh.Add(n1); } if (n2 != null) { neigh.Add(n2); } return(neigh); }
public List <CField> GetFieldsInDistance(int pSteps) { List <CField> fields = new List <CField>(); for (int x = -pSteps; x <= pSteps; x++) { for (int y = -pSteps; y <= pSteps; y++) { CField field = GetFieldWithOffset(x, y); if (field != null) { fields.Add(field); } } } fields.Sort((a, b) => CUtils.Get2DDistance(Center, a.Center).CompareTo( CUtils.Get2DDistance(Center, b.Center))); return(fields); }
protected List <TypeField> GetPathFrom(TypeField pFieldFrom, TypeField pFieldTo, float pMaxPathLength = int.MaxValue) { //todo: check if generated path is valid TypeField current = pFieldFrom; List <TypeField> path = new List <TypeField>() { current }; float pathLength = 0; while (!current.Equals(pFieldTo) && pathLength < pMaxPathLength) { EDirection dir = CField.GetDirection(current, pFieldTo); TypeField newCurrent = (TypeField)current.GetNeighbour(dir); pathLength += CUtils.Get2DDistance(current, newCurrent); current = newCurrent; path.Add(current); } return(path); }
/// <summary> /// Returnd point with given local position to this point /// </summary> private CField GetFieldWithOffset(int pIndexOffsetX, int pIndexOffsetY) { CField el = this; for (int x = 0; x < Math.Abs(pIndexOffsetX); x++) { el = pIndexOffsetX > 0 ? el.Right : el.Left; if (el == null) { return(null); } } for (int y = 0; y < Math.Abs(pIndexOffsetY); y++) { el = pIndexOffsetY > 0 ? el.Top : el.Bot; if (el == null) { return(null); } } return(el); }
/// <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> /// Returns neighbour using 8-neighbourhood /// </summary> /// <param name="pIncludeThis"></param> /// <returns></returns> public List <CField> GetNeighbours(bool pIncludeThis = false) { if (neighbours != null) { if (pIncludeThis) { List <CField> neighbourCopy = new List <CField>(); neighbourCopy.Add(this); foreach (CField n in neighbours) { neighbourCopy.Add(n); } return(neighbourCopy); } return(neighbours); } neighbours = new List <CField>(); if (pIncludeThis) { neighbours.Add(this); } var directions = Enum.GetValues(typeof(EDirection)); foreach (EDirection d in directions) { CField neighour = GetNeighbour(d); if (neighour != null) { neighbours.Add(neighour); } } return(neighbours); }
/// <summary> /// Returns number of steps required to reach 'pField' in 4-neighbourhood stepping /// </summary> public int GetStepCountTo(CField pField) { return(Math.Abs(indexInField.Item1 - pField.indexInField.Item1) + Math.Abs(indexInField.Item2 - pField.indexInField.Item2)); }
/// <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); }
public float GetDistanceTo(CField pField) { return(this.GetDistanceTo(pField.Center)); }