public Destination Calculate(long callerId, Destination carDestination, Destination endDestination)
        {
            var network   = NodeNetwork.NodeNetwork.GetInstance();
            var startNode = new Node(GPSSystem.FindIntersection(carDestination.Location).Location);
            var endNodes  = AlgorithmTools.IntersectionTupleToNodeTuple(
                AlgorithmTools.GetIntersectionOrderForRoadSide(endDestination.Road, endDestination.Location));

            if (startNode.Equals(endNodes.Item1))
            {
                #if DEBUG
                AlgorithmDebuggerWindow.Instance.AddNetworkResult(_debuggerIndex++.ToString(), network,
                                                                  startNode, endNodes.Item2, endNodes);
                #endif
                return(endDestination);
            }

            AssignNodeValues(ref network, ref startNode);

            var nextNode = FindNextNodeOnBestRoute(ref network, endNodes.Item1);
            #if DEBUG
            AlgorithmDebuggerWindow.Instance.AddNetworkResult("DY" + _debuggerIndex++, network,
                                                              startNode, nextNode, endNodes);
            #endif
            var roadX = (startNode.PositionX - nextNode.PositionX) / 2.0 + nextNode.PositionX;
            var roadY = (startNode.PositionY - nextNode.PositionY) / 2.0 + nextNode.PositionY;
            return(new Destination
            {
                Location = new Vector(nextNode.PositionX, nextNode.PositionY),
                Road = GPSSystem.NearestRoad(new Vector(roadX, roadY))
            });
        }
Exemple #2
0
        public Destination Calculate(long callerId, Destination carDestination, Destination endDestination)
        {
            var network   = NodeNetwork.NodeNetwork.GetInstance();
            var startNode = new Node(GPSSystem.FindIntersection(carDestination.Location).Location);
            var endNodes  = AlgorithmTools.IntersectionTupleToNodeTuple(
                AlgorithmTools.GetIntersectionOrderForRoadSide(endDestination.Road, endDestination.Location));

            Node   nextNode;
            double roadX, roadY;

            if (startNode.Equals(endNodes.Item1))
            {
                #if DEBUG
                AlgorithmDebuggerWindow.Instance.AddNetworkResult(_debuggerIndex++.ToString(), network,
                                                                  startNode, endNodes.Item2, endNodes);
                #endif
                return(endDestination);
            }

            if (_calculationCache.ContainsKey(callerId))
            {
                var tuple = _calculationCache[callerId];
                if (tuple.Item1.Equals(endDestination))
                {
                    var path     = tuple.Item2;
                    var thisNode = path.Single(n => n.Equals(startNode));
                    nextNode = thisNode.ConnectedTo;

                    #if DEBUG
                    AlgorithmDebuggerWindow.Instance.AddNetworkResult(_debuggerIndex++.ToString(), network,
                                                                      startNode, nextNode, endNodes);
                    #endif
                    roadX = (startNode.PositionX - nextNode.PositionX) / 2.0 + nextNode.PositionX;
                    roadY = (startNode.PositionY - nextNode.PositionY) / 2.0 + nextNode.PositionY;
                    return(new Destination
                    {
                        Location = new Vector(nextNode.PositionX, nextNode.PositionY),
                        Road = GPSSystem.NearestRoad(new Vector(roadX, roadY))
                    });
                }

                _calculationCache.Remove(callerId);
            }

            var endNode = endNodes.Item1;
            nextNode = CalculatePathNextNode(callerId, ref network, ref startNode, ref endNode, endDestination);

            #if DEBUG
            AlgorithmDebuggerWindow.Instance.AddNetworkResult("AS" + _debuggerIndex++, network,
                                                              startNode, nextNode, endNodes);
            #endif
            roadX = (startNode.PositionX - nextNode.PositionX) / 2.0 + nextNode.PositionX;
            roadY = (startNode.PositionY - nextNode.PositionY) / 2.0 + nextNode.PositionY;
            return(new Destination
            {
                Location = new Vector(nextNode.PositionX, nextNode.PositionY),
                Road = GPSSystem.NearestRoad(new Vector(roadX, roadY))
            });
        }
        /// <summary>
        /// Calculates the path to the customergroup using Dijkstra algorithm
        /// </summary>
        /// <param name="start">start path</param>
        /// <param name="group">group customers</param>
        /// <returns>list with the roads to take</returns>
        public static List <Road> CalculateRouteToCustomerGroup(Vector start, CustomerGroup group)
        {
            var startRoad = GPSSystem.NearestRoad(start);
            var endRoad   = GPSSystem.NearestRoad(group.Location);
            var hitEnd    = false;

            var listPaths = new List <Path>();

            // if the starroad equals to the endRoad
            if (startRoad == endRoad)
            {
                return(new List <Road> {
                    startRoad
                });
            }
            ;

            //add the first two intersections of the startRoad to the PathList;
            foreach (var item in GPSSystem.FindIntersectionsRoad(startRoad))
            {
                listPaths.Add(new Path(start, group.Location, item));
            }

            // loop until the end is found
            while (hitEnd == false)
            {
                var newListPaths = new List <Path>();
                foreach (var path in listPaths)
                {
                    // new found intersections
                    var lastIntersectionOfPath = path.Intersections.Last();

                    var newFoundIntersections = GPSSystem.FindNextIntersections(lastIntersectionOfPath);

                    // add the path of every new intersetion to the new ListPath
                    foreach (var intersection in newFoundIntersections)
                    {
                        var intersections = new List <Intersection>(path.Intersections);
                        intersections.Add(intersection);
                        var newPath = new Path(start, group.Location, intersection);
                        newListPaths.Add(newPath);

                        // check if endLocation is between these intersections

                        if ((endRoad.End == intersection.Location || endRoad.Start == intersection.Location) && (endRoad.End == lastIntersectionOfPath.Location || endRoad.Start == lastIntersectionOfPath.Location))
                        {
                            return(newPath.PathToRoadList());
                        }
                        else
                        {
                            throw new Exception("roads are not horizontal or vertical");
                        }
                    }
                }
                // set the new list
                listPaths = newListPaths;
            }
            return(null);
        }
        public CustomerGroupController(CustomerGroup group)
        {
            Group = group;
            var road = GPSSystem.NearestRoad(group.Location);

            MoveToNearestRoad(road);
            Group.RoadsNear = GPSSystem.GetRoadsInRange(Group.Location, GroupRadius);
        }
Exemple #5
0
        public override List <Road> CalculatePath(Vector start, CustomerGroup group)
        {
            var startRoad = GPSSystem.NearestRoad(start);
            var endRoad   = GPSSystem.NearestRoad(group.Location);

            var listPaths = new List <Path>();

            // if the startroad equals to the endRoad
            if (startRoad == endRoad)
            {
                return(new List <Road> {
                    startRoad
                });
            }
            ;

            //add the first two intersections of the startRoad to the PathList;
            foreach (var item in GPSSystem.FindIntersectionsRoad(startRoad))
            {
                listPaths.Add(new Path(start, group.Location, item));
            }
            // order list
            orderListByPriority(ref listPaths);

            // loop until the end is found
            while (true)
            {
                // new found intersections
                var lastIntersectionOfPath = listPaths[0].Intersections.Last();

                var newFoundIntersections = GPSSystem.FindNextIntersections(lastIntersectionOfPath);

                // add the path of every new intersetion to the new ListPath
                foreach (var intersection in newFoundIntersections)
                {
                    var intersections = new List <Intersection>(listPaths[0].Intersections);
                    intersections.Add(intersection);
                    var newPath = new Path(start, group.Location, intersection);
                    listPaths.Add(newPath);

                    // check if endLocation is between these intersections

                    if ((endRoad.End == intersection.Location || endRoad.Start == intersection.Location) && (endRoad.End == lastIntersectionOfPath.Location || endRoad.Start == lastIntersectionOfPath.Location))
                    {
                        return(newPath.PathToRoadList());
                    }
                }
                listPaths.RemoveAt(0);
                orderListByPriority(ref listPaths);
            }
        }
Exemple #6
0
        public void NearestRoadTest(int x1b, int y1b, int x1e, int y1e, int x2b, int y2b, int x2e, int y2e, int ex,
                                    int ey)
        {
            var road1 = new Road(new Vector(x1b, y1b), new Vector(x1e, y1e), 20, 100);
            var road2 = new Road(new Vector(x2b, y2b), new Vector(x2e, y2e), 20, 100);

            var city = new CityBuilder()
                       .Road(road1)
                       .Road(road2)
                       .Build();

            var road = GPSSystem.NearestRoad(new Vector(ex, ey));

            Assert.AreEqual(road, road1);
        }
Exemple #7
0
        public List <Road> PathToRoadList()
        {
            var listRoads = new List <Road>();

            foreach (var road in City.Instance.Roads)
            {
                if (Intersections.FindAll(i => i.Location == road.Start)
                    .FindAll(i => i.Location == road.End).Count > 0)
                {
                    listRoads.Add(road);
                }
            }
            listRoads.Add(GPSSystem.NearestRoad(Start));
            listRoads.Add(GPSSystem.NearestRoad(End));

            return(listRoads);
        }
        public void TestLookForNearestRoad(double groupX, double groupY, bool road)
        {
            var building = new Building(new Vector(groupX, groupY), 8);
            var road1    = new Road(new Vector(0, 50), new Vector(10, 50), 10, 100);
            var road2    = new Road(new Vector(0, 20), new Vector(10, 20), 10, 100);
            var city     = new CityBuilder()
                           .Road(road1)
                           .Road(road2)
                           .Building(building)
                           .Build();

            var group = new CustomerGroup(5, building, null);

            var result = GPSSystem.NearestRoad(group.Location);

            Assert.AreEqual(road ? road1 : road2, result);
        }
        public void Update()
        {
            var buitenRange = Group.Customers.Any(c => MathUtil.Distance(c.Location, Group.Location) > GroupRadius);

            if (RequestedCar)
            {
                var car = City.Instance.Cars.Find(c => MathUtil.Distance(c.Location, Group.Location) < 20);
                if (car == null || car.Passengers.Count > 0)
                {
                    return;
                }


                Group.Customers.ForEach(customer => customer.Controller.Destroy());
                MainScreen.AILoop.Unsubscribe(Update);
                car.Passengers.AddRange(Group.Customers);
                var destination = Group.Destination.Location;
                App.Console.Print($"Passengers entered car {car.Id} with destination {destination}", Colors.Blue);
                car.Destination = new Destination {
                    Location = destination, Road = GPSSystem.NearestRoad(destination)
                };
                car.Controller.PassengersReady();
                return;
            }

            if (buitenRange)
            {
                return;
            }
            var road = GPSSystem.NearestRoad(Group.Destination.Location);

            GPSSystem.RequestCar(new CarSystem.Destination {
                Location = Group.Destination.Location, Road = road
            }, Group);
            RequestedCar = true;
        }
Exemple #10
0
        private static Node CalculatePathNextNode(long callerId, ref NodeNetworkCopy network, ref Node startNode, ref Node endNode, Destination endDestination)
        {
            var openNodes = new List <ConnectedNode> {
                new ConnectedNode(endNode)
            };
            var           closedNodes = new List <ConnectedNode>();
            ConnectedNode lastNode    = null;

            var updateIndex = 0;

            while (true)
            {
                // propogate
                var thisNode = openNodes.First();
                openNodes.Remove(thisNode);
                closedNodes.Add(thisNode);

                var neighbours = network.Links
                                 .Where(l => l.NodeA.Equals(thisNode) || l.NodeB.Equals(thisNode))
                                 .Select(l => l.NodeA.Equals(thisNode) ? new ConnectedNode(l.NodeB) : new ConnectedNode(l.NodeA))
                                 .ToList();

                // calculate
                var foundEnd = false;
                foreach (var n in neighbours)
                {
                    if (closedNodes.SingleOrDefault(cn => cn.Equals(n)) != null)
                    {
                        continue;
                    }

                    if (n.Equals(startNode))
                    {
                        foundEnd = true;
                        lastNode = n;
                    }

                    n.ConnectedTo = thisNode;
                    n.Value       = Math.Sqrt(Math.Pow((n.PositionX - startNode.PositionX), 2) + Math.Pow((n.PositionY - startNode.PositionY), 2));
                    network.Nodes.Single(nn => nn.Equals(n)).Value = n.Value;
                    #if DEBUG
                    AlgorithmDebuggerWindow.Instance.AddNodeUpdateResult($"AS{_debuggerIndex}${updateIndex++}", network,
                                                                         n, thisNode);
                    #endif
                    openNodes.Add(n);
                }

                if (foundEnd)
                {
                    break;
                }

                // sort
                openNodes = openNodes.OrderBy(n => n.Value).ToList();

                // info
                #if DEBUG
                AlgorithmDebuggerWindow.Instance.AddNetworkResult($"AS{_debuggerIndex}#{openNodes.First().Value}", network,
                                                                  thisNode, openNodes.First());
                #endif
            }

            var roadX  = (startNode.PositionX - lastNode.ConnectedTo.PositionX) / 2.0 + lastNode.ConnectedTo.PositionX;
            var roadY  = (startNode.PositionY - lastNode.ConnectedTo.PositionY) / 2.0 + lastNode.ConnectedTo.PositionY;
            var result = new Destination
            {
                Location = new Vector(lastNode.ConnectedTo.PositionX, lastNode.ConnectedTo.PositionY),
                Road     = GPSSystem.NearestRoad(new Vector(roadX, roadY))
            };

            if (_calculationCache.ContainsKey(callerId))
            {
                _calculationCache.Remove(callerId);
            }
            _calculationCache.Add(callerId, new Tuple <Destination, List <ConnectedNode> >(endDestination, closedNodes));

            // find next node
            return(lastNode.ConnectedTo);
        }
Exemple #11
0
        public Car SpawnCar(int id, Destination finalDestination)
        {
            if (!hasDirection)
            {
                var nearest = GPSSystem.NearestRoad(Location);
                Direction    = nearest.IsXRoad() ? DirectionCar.East : DirectionCar.North;
                hasDirection = true;
            }

            if (AvailableCars <= 0)
            {
                return(null);
            }

            foreach (var cityCar in City.Instance.Cars)
            {
                if (MathUtil.Distance(Location, cityCar.Location) < 100)
                {
                    var thread = new Thread(() =>
                    {
                        Thread.Sleep(1000);
                        SpawnCar(id, finalDestination);
                    });
                    thread.Start();
                    return(null);
                }
            }

            var road = GPS.GPSSystem.NearestRoad(Location);

            double x;
            double y;

            if (road.IsXRoad())
            {
                x = Location.X;
                y = Direction == DirectionCar.East ? road.Start.Y + road.Width / 3d : road.Start.Y - road.Width / 3d;
            }
            else
            {
                y = Location.Y;
                x = Direction == DirectionCar.South ? road.Start.X - road.Width / 3d : road.Start.X + road.Width / 3d;
            }

            var    location = new Vector(x, y);
            var    car      = Model.CreateCar(id, location, this, Direction);
            Vector destination;

            switch (Direction)
            {
            case DirectionCar.North:
                destination = new Vector(road.Start.X, Math.Min(road.Start.Y, road.End.Y));
                break;

            case DirectionCar.South:
                destination = new Vector(road.Start.X, Math.Max(road.Start.Y, road.End.Y));
                break;

            case DirectionCar.East:
                destination = new Vector(Math.Max(road.Start.X, road.End.X), road.Start.Y);
                break;

            case DirectionCar.West:
                destination = new Vector(Math.Min(road.Start.X, road.End.X), road.Start.Y);
                break;

            default:
                throw new ArgumentException("Unknown direction");
            }
            car.Destination = new Destination
            {
                Location = destination,
                Road     = road
            };
            car.CurrentTarget = destination;
            City.Instance.Cars.Add(car);
            AvailableCars--;
            car.Destination = finalDestination;
            return(car);
        }
Exemple #12
0
        /// <summary>
        /// Runs the main car logic. Needs to be subscribed to the MainLoop.
        /// </summary>
        public void Update()
        {
            // If we're not initialized, initialize!
            if (!initialized)
            {
                Init();
            }

            // Update the passenger count.
            Car.PassengerCount = Car.Passengers.Count;

            // Update the current road with the road at our location.
            Car.CurrentRoad         = GPSSystem.GetRoad(Car.Location);
            Car.CurrentIntersection = GPSSystem.FindIntersection(Car.Location);

            if (Car.CurrentRoad == null && Car.CurrentIntersection == null)
            {
                if (!resetTarget)
                {
                    resetTarget = true;
                    var closestRoad = GPSSystem.NearestRoad(Car.Location);
                    if (closestRoad != null && Car != null)
                    {
                        Car.CurrentTarget =
                            MathUtil.Distance(closestRoad.End, Car.Location) >
                            MathUtil.Distance(closestRoad.Start, Car.Location)
                                ? closestRoad.Start
                                : closestRoad.End;
                        App.Console.Print($"[C{Car.Id}] Lost road, trying to get back on, targeting {Car.CurrentTarget}", Colors.Blue);
                    }
                    ;
                }
            }
            else if (resetTarget)
            {
                App.Console.Print($"[C{Car.Id}] Road found again", Colors.Blue);
                resetTarget = false;
            }

            // Calculate the distance to the local target (usually the next intersection).
            var distanceToTarget = MathUtil.Distance(Car.Location, Car.CurrentTarget);
            // Calculate the distance to the destination.
            var distanceToDestination = MathUtil.Distance(Car.Location, Car.Destination.Location);
            // Calculate the relative yaw (in degrees).
            var yaw = MathUtil.VectorToAngle(Car.Rotation, Car.Direction);
            // Get the current velocity of the car.
            var velocity = Car.Velocity;
            // Create a variable to store the added rotation in this update call.
            var addedRotation      = 0.0;
            var closeToDestination = CloseToDestination();

            // Check if we're close to our target but not the destination.
            if (distanceToTarget < 20 && !closeToDestination && !resetTarget)
            {
                // Check if we've not obtained a new target yet.
                if (!obtainedNewTarget)
                {
                    // Find the nearest intersection.
                    var intersection = GPSSystem.FindIntersection(GetClosestRoadPoint(Car.Location));
                    if (intersection == null)
                    {
                        return;
                    }

                    App.Console.Print($"[C{Car.Id}] Requesting new target from intersection {intersection.Location}...", Colors.Blue);

                    // Request the next target from the GPSSystem.
                    var target = GPSSystem.GetDirection(Car, intersection);

                    // Update our target.
                    newTarget         = target.Location;
                    obtainedNewTarget = true;

                    var distance = Math.Round(MathUtil.Distance(newTarget, Car.Location));
                    App.Console.Print($"[C{Car.Id}] Obtained a new target {newTarget} ({distance}m away)", Colors.Blue);
                }
            }
            else
            {
                obtainedNewTarget = false;
            }

            // Check if we are turning.
            if (turning > 0)
            {
                turning--;

                // Check if we locked on the new target yet.
                if (newTarget.X > -1)
                {
                    // Lock on the new target and reset newTarget.
                    Car.CurrentTarget = newTarget;
                    newTarget         = new Vector(-1, -1);
                    App.Console.Print($"[C{Car.Id}] Locked on to target", Colors.Blue);
                }

                // Call the handle function to turn.
                HandleTurn(ref velocity, ref yaw, ref addedRotation);
            }
            // Check if we're still turning around.
            else if (flipping)
            {
                // Stop turning around.
                flipping = false;
                App.Console.Print($"[C{Car.Id}] Turn-around done", Colors.Blue);
            }

            // Check if we're on an intersection.
            if (Car.CurrentIntersection != null)
            {
                // Reset our turn timer.
                turning = 20;
            }
            else
            {
                // Check if we're not close to the destination.
                if (!closeToDestination)
                {
                    // If we're still approaching, stop approaching.
                    if (approach)
                    {
                        approach = false;
                        App.Console.Print($"[C{Car.Id}] Approach done", Colors.Blue);
                    }

                    // Call the handle functions to stay in the lane and accelerate/deccelerate.
                    HandleStayInLane(ref velocity, ref yaw, ref addedRotation);
                    HandleAccelerate(ref velocity, ref distanceToTarget);
                }
                else
                {
                    // If we're not approaching, start approaching.
                    if (!approach)
                    {
                        approach = true;
                        App.Console.Print($"[C{Car.Id}] Initiating approach", Colors.Blue);
                    }

                    // Call the handle function to approach the target.
                    HandleApproachTarget(ref velocity, ref yaw, ref addedRotation, ref distanceToDestination);
                }
            }

            // Update the car's velocity with the result of the handle functions:
            // Temporarily store the current speed.
            var speed = velocity.Length;

            // Rotate the velocity based on the addedRotation this tick.
            velocity = MathUtil.RotateVector(velocity, -addedRotation);
            // Normalize the velocity and multiply with the speed to make sure it stays the same.
            velocity.Normalize();
            velocity = Vector.Multiply(velocity, speed);
            // Actually update the car's velocity.
            Car.Velocity = velocity;

            // Calculate the rotation by normalizing the velocity.
            var rotation = new Vector(velocity.X, velocity.Y);

            rotation.Normalize();

            // If the rotation vector is invalid or the car is not moving, set the rotation to the absolute direction.
            if (rotation.Length < 0.9 || double.IsNaN(rotation.Length) || velocity.Length < 0.1)
            {
                rotation = Car.Direction.GetVector();
            }

            // Actually update the rotation and update the absolute direction.
            Car.Rotation  = rotation;
            Car.Direction = DirectionCarMethods.Parse(rotation);

            // Update the car's location by adding the velocity to it.
            Car.Location          = Vector.Add(Car.Location, Car.Velocity);
            Car.DistanceTraveled += Car.Velocity.Length;
        }