private bool ConsiderRoute( RoadCellLong pointA, RoadCellLong pointB) { try { if (pointA.Previous == pointB) { return(false); //We've backtracked completely } if ((int)pointB.DistanceFromOrigin == 0) { pointB.DistanceFromOrigin = GetDirectLineDistance(_origin, pointB); } if (pointB != _destination && pointB.DistanceFromOrigin <= pointA.DistanceFromOrigin) { return(false); //We're circling back } //_logger.Info($"At [{pointB.X},{pointB.Z}] {pointB.DistanceFromOrigin} from Origin"); var costFromOrigin = pointA.CostFromOrigin + _getPathCost(pointA, pointB); if (costFromOrigin > _destination.CostFromOrigin) { return(false); } // PointB has already been hit on different route, only redirect when the // cost is lower. if (pointB.Previous != null && pointB.CostFromOrigin <= costFromOrigin) { return(false); } // PointA already has a route assigned, only update it when the cost is lower if (pointA.Next != null && pointA.Next.CostFromOrigin <= costFromOrigin) { return(false); } pointB.Previous = pointA; pointA.Next = pointB; pointB.CostFromOrigin = costFromOrigin; if (pointB == _destination) { _maximumCost = costFromOrigin; //_logger.Warn($"Found a faster route to destination [{pointA.X},{pointA.Z}] Cost: {_maximumCost}"); return(false); } return(pointA != pointB); } catch (Exception exp) { _logger.Error(exp); throw; } }
private ulong GetUnitRouteCost(RoadCellLong pointA, RoadCellLong pointB) { var heightDifference = Math.Abs((long)pointA.Avg - (long)pointB.Avg); if (heightDifference > 512) { return((ulong)heightDifference << 4); } return((ulong)heightDifference); }
public async Task <RoadCellLong> BuildPath(RoadCellLong from, RoadCellLong to) { _origin = from; _destination = to; _getPathCost = (cell, roadCell) => WalkDirectEstimate(cell, roadCell, GetUnitRouteCost); _destination.CostFromOrigin = long.MaxValue; _maximumCost = _getPathCost(_origin, _destination); _getNeighbours = Get4RadiusNeighbours; await PathFindingUsingLinkedCells(from); return(to); }
private Vector2 <float> GetWalkerFactors(RoadCellLong origin, RoadCellLong destination) { var xDistance = destination.X - origin.X; var zDistance = destination.Z - origin.Z; var factors = new Vector2 <float>(Math.Sign(xDistance), Math.Sign(zDistance)); if (Math.Abs(xDistance) > Math.Abs(zDistance)) { factors.Z = (float)zDistance / (float)Math.Abs(xDistance); } if (Math.Abs(zDistance) > Math.Abs(xDistance)) { factors.X = (float)xDistance / (float)Math.Abs(zDistance); } return(factors); }
private IEnumerable <RoadCellLong> GetRadiusNeighbours(RoadCellLong origin, List <Vector2 <int> > offSets, double backTrackDistanceCheck) { try { var neighbours = offSets .Select(vector2 => new Vector2 <int>(vector2.X + origin.X, vector2.Z + origin.Z)); return(neighbours .Where(vector2 => vector2.X > 0 && vector2.X < _size && vector2.Z > 0 && vector2.Z < _size) .Select(vector2 => _map[vector2.X, vector2.Z])); } catch (Exception exp) { _logger.Error(exp); throw; } }
public RoadCellLong GetCellMetrics(int x, int z) { var mapX = x * _cellSize; var mapZ = z * _cellSize; var cellBoundary = _cellSize - 1; var metrics = new RoadCellLong() { Avg = (ushort)(( _heightMap[mapX + cellBoundary, mapZ] + _heightMap[mapX + cellBoundary, mapZ + cellBoundary] + _heightMap[mapX, mapZ + cellBoundary] + _heightMap[mapX, mapZ]) / 4f), X = x, Z = z }; return(metrics); }
private IEnumerable <RoadCellLong> Get8Neighbours(RoadCellLong fromCell) { var neighbours = new List <RoadCellLong>(); if (fromCell.X > 0) { neighbours.Add(_map[fromCell.X - 1, fromCell.Z]); if (fromCell.Z > 0) { neighbours.Add(_map[fromCell.X - 1, fromCell.Z - 1]); } if (fromCell.Z < _size - 1) { neighbours.Add(_map[fromCell.X - 1, fromCell.Z + 1]); } } if (fromCell.X < _size - 1) { neighbours.Add(_map[fromCell.X + 1, fromCell.Z]); if (fromCell.Z > 0) { neighbours.Add(_map[fromCell.X + 1, fromCell.Z - 1]); } if (fromCell.Z < _size - 1) { neighbours.Add(_map[fromCell.X + 1, fromCell.Z + 1]); } } if (fromCell.Z > 0) { neighbours.Add(_map[fromCell.X, fromCell.Z - 1]); } if (fromCell.Z < _size - 1) { neighbours.Add(_map[fromCell.X, fromCell.Z + 1]); } return(neighbours); }
public async Task PathFindingUsingLinkedCells( RoadCellLong waypoint ) { try { if (waypoint.CostFromOrigin > _maximumCost) { _logger.Info("Too Costly - Bailing out"); } else if (GetDirectLineDistance(waypoint, _destination) < distanceFactor) { ConsiderRoute(waypoint, _destination); } else { var neighbors = _getNeighbours(waypoint).ToList(); foreach (var neighbor in neighbors) { if (neighbor != null) { if (ConsiderRoute(waypoint, neighbor)) { await PathFindingUsingLinkedCells(neighbor); } } else { _logger.Info("Neighbor is null?"); } } } } catch (Exception exp) { _logger.Error(exp); throw; } }
private ulong WalkDirectEstimate(RoadCellLong arg, RoadCellLong destination, Func <RoadCellLong, RoadCellLong, ulong> getRouteCost) { try { var walker = new Vector2 <int>(arg.X, arg.Z); var previousCell = arg; var factors = GetWalkerFactors(arg, destination); ulong totalWalkingCost = 0; int stepCounter = 1; do { walker.X = previousCell.X + (int)Math.Round(factors.X * stepCounter, 0); walker.Z = previousCell.Z + (int)Math.Round(factors.Z * stepCounter, 0); totalWalkingCost += getRouteCost(previousCell, _map[walker.X, walker.Z]); stepCounter++; } while (walker.X != destination.X && walker.Z != destination.Z); return(totalWalkingCost); } catch (Exception exp) { _logger.Error(exp); } return(long.MaxValue); }
private IEnumerable <RoadCellLong> Get12RadiusNeighbours(RoadCellLong origin) { return(GetRadiusNeighbours(origin, PathFinding.TwelveRadius16Points, 23)); }