public WeightedLocation(Location loc, double weight, Floorplan floorplan)
 {
     Location = loc;
     Weight = weight;
     Floorplan = floorplan;
 }
        /// <summary>
        /// Fullfills pathfinding requests by returning a Route object.
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="endX"></param>
        /// <param name="startY"></param>
        /// <param name="endY"></param>
        /// <param name="startFloor"></param>
        /// <param name="endFloor"></param>
        /// <returns></returns>
        public RouteDto getPath(int startX, int startY, int endX, int endY, Floorplan startFloorPlan, Floorplan endFloorPlan)
        {
            int startFloor = startFloorPlan.Floor;
            int endFloor = endFloorPlan.Floor;

            // The route object will contain the final route, if one exists
            RouteDto route = new RouteDto();

            if (_bluePrint == null)
            {
                return route.pathfindingError();
            }

            // Get map of start floor through api.
            // If something goes wrong, return a fail-code route
            bool[,] startFloorMap = getFloorMap(startFloor, _bluePrint);
            if (startFloorMap == null)
            {
                return route.pathfindingError();
            }

            // API call for endFloor map
            // (needed in places of different scope below)
            bool[,] endFloorMap = null;
            if (startFloor != endFloor)
            {
                endFloorMap = getFloorMap(endFloor, _bluePrint);

                if (endFloorMap == null)
                {
                    return route.pathfindingError();
                }
            }

            // BEGIN PATHFINDING /////////////////

            if (startFloor == endFloor)
            {
                AStarSearch searchPath = new AStarSearch(startFloorMap).run(startX, startY, endX, endY);

                if (searchPath.hasSolution())
                {
                    // Create the event for the path and add it to our route
                    lastFloorGridWidth = searchPath.gridLengthX;
                    lastFloorGridHeight = searchPath.gridLengthY;
                    return route.addPath(startFloor, searchPath.Solution.ToList());
                }

                // falls out to third-tier search
            }
            else
            {
                if (endFloorMap == null)
                {
                    return route.pathfindingError();
                }

                // API call searching for all "vertical paths" (VPs) from startFloor directly to endFloor
            //				var directPois = _bluePrint.NavigationalPois
            //					.Where(v => v.Locations.Any(l => l.FloorPlan.Floor == startFloor) && v.Locations.Any(asd => asd.FloorPlan.Floor == endFloor))
            //					.ToList();
                var directPois = _bluePrint.GetDirectNavPois(startFloor, endFloor);

                if (directPois != null && directPois.Count > 0)
                {
                    // Create the search objs here to be reused. Prevents duplicatoin of weighted-grid work.
                    AStarSearch search1 = new AStarSearch(startFloorMap);
                    AStarSearch search2 = new AStarSearch(endFloorMap);

                    // Here we are looking for a valid path using only one stairs, elevator, etc.
                    foreach (var v in directPois)
                    {
                        // start floor
                        var fp1 = v.Location;
            //						FloorPlanLocation fp1 = v.Locations.Where(x => x.FloorPlan.Floor == startFloor).FirstOrDefault();
                        int vertX1 = (int) (fp1.X*startFloorPlan.ImageDataWidth);
                        int vertY1 = (int) (fp1.Y*startFloorPlan.ImageDataHeight);

                        // find path from user position to the "stairs"
                        search1.run(startX, startY, vertX1, vertY1);

                        // if we can't get to the "stairs" from here, lets try the next way up
                        if (!search1.hasSolution())
                        {
                            continue;
                        }

                        // end floor
                        var fp2 = v.Location;
            //						FloorPlanLocation fp2 = v.Locations.Where(x => x.FloorPlan.Floor == endFloor).FirstOrDefault();
                        int vertX2 = (int) (fp2.X*endFloorPlan.ImageDataWidth);
                        int vertY2 = (int) (fp2.Y*endFloorPlan.ImageDataHeight);

                        // find path from "stairs" to the ending position
                        search2.run(vertX2, vertY2, endX, endY);

                        // if we can't get to the "stairs" from here, we do not want to get to the return statement
                        if (!search2.hasSolution())
                        {
                            continue;
                        }

                        lastFloorGridWidth = search2.gridLengthX;
                        lastFloorGridHeight = search2.gridLengthY;

                        // Create solution
                        return route
                            .addPath(startFloor, search1.Solution.ToList())
                            .addVerticalTransisiton(v.Type, new CoordinateDto(vertX1, vertY1, search1.gridLengthX, search1.gridLengthY),
                                startFloor, endFloor)
                            .addPath(endFloor, search2.Solution.ToList());

                    }

                    // falls out to third-tier search
                }
            }

            // the infamous third-tier search

            return route;
        }