/// <summary> /// This method continuously creates nodes when certain conditions are met and also removes parrallel lines along the way. /// </summary> private void CreateNodes(Node node, int xDirection, int yDirection) { bool HitWall = false, Done = false, DontSave = false, Found = false, InNodes = false; int AmountOfNodes = 1, XPos = node.XCoordinate, YPos = node.YCoordinate; CreateNodesStackElement Iteration; List <Node> Temp = new List <Node>(); // Storage for nodes, before it's known if they have to be saved Stack <CreateNodesStackElement> IterationStorage = new Stack <CreateNodesStackElement>(); IterationStorage.Push(new CreateNodesStackElement(node, xDirection, yDirection)); while (IterationStorage.Count > 0) { HitWall = false; Done = false; DontSave = false; Found = false; InNodes = false; AmountOfNodes = 1; Iteration = IterationStorage.Pop(); node = Iteration.Node; xDirection = Iteration.XDirection; yDirection = Iteration.YDirection; Temp.Clear(); Temp.Add(node); XPos = node.XCoordinate; YPos = node.YCoordinate; // Prevents a parallel line from being created if (ParallelLineCheck(Temp.ElementAt(0), xDirection, yDirection)) { Done = true; DontSave = true; } while (!HitWall && !Done) { //Console.WriteLine("[DEBUG] Im at: [" + XPos + ", " + YPos + "]"); DEBUG PRINT XPos = XPos + xDirection; YPos = YPos + yDirection; // Prevents outofindex error if (OutofBounds(XPos, xDirection, YPos, yDirection)) { Done = true; DontSave = true; } // Stops the creation of nodes, if it hits a wall while still inside a door else if (Img.GetPixel(XPos, YPos) == Standards.Wall && Standards.IsDoorColor(Img.GetPixel(XPos - xDirection, YPos - yDirection))) { Done = true; DontSave = true; } else if (Img.GetPixel(XPos, YPos) == Standards.Wall) { // Prevents the creating of new nodes, if the funtion was started to close to a wall if (MinPixelSizeDoor > AmountOfNodes) { Done = true; } else { HitWall = true; } } //Checks if the next tile is a door or staircase else if (Standards.IsDoorColor(Img.GetPixel(XPos + xDirection, YPos + yDirection)) || Img.GetPixel(XPos + xDirection, YPos + yDirection) == Standards.StairColor) { // If nodes are hitting a new door, it creates a new node and connects to the node in the door if (!Standards.IsDoorColor(Img.GetPixel(XPos, YPos)) && Img.GetPixel(XPos, YPos) != Standards.StairColor) { CreateNewConnectionNode(Temp, XPos, YPos); AmountOfNodes++; Done = true; ConnectNodes(Temp.Last(), FindClosestDoorNode(XPos, YPos)); } } else if (Standards.IsDoorColor(Img.GetPixel(XPos, YPos)) || Img.GetPixel(XPos, YPos) == Standards.StairColor) { // Prevents parallellines from being created, when leaving a door with a width of more than 1 pixel if (ParallelLineCheck(new Node(XPos + xDirection, YPos + yDirection), xDirection, yDirection)) { Done = true; DontSave = true; } } // If it hits a another node, it will create a new node and connect to it else if (Img.GetPixel(XPos + xDirection, YPos + yDirection) == Standards.NodeColor) { CreateNewConnectionNode(Temp, XPos, YPos); AmountOfNodes++; //Tries to find the node, it hits in the nodes list, gets null if node not found Node target = GetNodeFromList(Nodes, XPos + xDirection, YPos + yDirection); if (target != null) { ConnectNodes(Temp.Last(), target); Found = true; } if (!Found) { target = GetNodeFromList(ConnectionNodes, XPos + xDirection, YPos + yDirection); ConnectNodes(Temp.Last(), target); Nodes.Add(target); ConnectionNodes.Remove(target); } Done = true; } // Creates a new node and continues else if (Img.GetPixel(XPos, YPos) != Standards.Wall) { CreateNewConnectionNode(Temp, XPos, YPos); AmountOfNodes++; } } // Moves the nodes over in connectionNodes, if the nodes has to be saved and colors the nodes on the image if (!DontSave) { ConnectionNodes.AddRange(Temp); for (int i = 1; i < Temp.Count; i++) { // Colors all the new nodes on the map, with the node color Img.SetPixel(Temp.ElementAt(i).XCoordinate, Temp.ElementAt(i).YCoordinate, Standards.NodeColor); } } if (HitWall) { // Rotates the line direction 90deegres and creates a new line of nodes, if there arent any parallellines if (!ParallelLineCheck(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor)), yDirection * (-1), xDirection)) { Nodes.Add(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor))); InNodes = true; IterationStorage.Push(new CreateNodesStackElement(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor)), yDirection * (-1), xDirection)); } // same as above but rotates the other direction if (!ParallelLineCheck(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor)), yDirection, xDirection * (-1))) { if (!InNodes) { Nodes.Add(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor))); InNodes = true; } IterationStorage.Push(new CreateNodesStackElement(Temp.ElementAt(Temp.Count() - (MinPixelSizeDoor)), yDirection, xDirection * (-1))); } } } return; }
/// <summary> /// This method targets a specific node from which it searches the Xcoordinate and Ycoordinate coordinates in all four directions. /// When the search hits an obstacle (e.g. a wall, another important node, door or staircase) it evaluates the length from the node to the obstacle. /// The method detects an obstacle by a pixel color comparison. /// The length between two important nodes is divided by two, to share the distance equally between the nodes. /// When the search is done, the area of the node is calculated by multiplying the two lengths (xLength, yLength). /// </summary> /// <param name="n"> Target node. </param> public void CreateSquare(Bitmap Img, double PixelsPerMeter) { bool HittingSomething = false; int xPos = this.XCoordinate, yPos = this.YCoordinate; // Placeholders for width and height. Will be reevaluated later double xLength = 0, yLength = 0; // Increases the Xcoordinate and Ycoordinate coordinates. for (int i = -1; i < 2; i += 2) { if (!(this is Door) && !(this is Staircase)) { // Searching Xcoordinate coordinates while (!HittingSomething) { xPos += i; // check if we hit a wall if (Img.GetPixel(xPos, yPos) == Standards.Wall) { xLength += Math.Abs(this.XCoordinate - xPos); HittingSomething = true; } // check if we hit a door or staircase else if (Standards.IsDoorOrStaircaseColor(Img.GetPixel(xPos, yPos))) { xLength += Math.Abs(this.XCoordinate - xPos); HittingSomething = true; } // check if we hit another node. In this case, devide the length by two else if (Img.GetPixel(xPos, yPos) == Standards.ImportantNodeColor) { xLength += Convert.ToDouble(Math.Abs(this.XCoordinate - xPos) / 2); HittingSomething = true; } } HittingSomething = false; xPos = this.XCoordinate; // Searching Ycoordinate coordinates while (!HittingSomething) { yPos += i; // check if we hit a wall if (Img.GetPixel(xPos, yPos) == Standards.Wall) { yLength += Math.Abs(this.YCoordinate - yPos); HittingSomething = true; } // check if we hit a door or staircase else if (Standards.IsDoorOrStaircaseColor(Img.GetPixel(xPos, yPos))) { yLength += Math.Abs(this.YCoordinate - yPos); HittingSomething = true; } // check if we hit another node. In this case, devide the length by two else if (Img.GetPixel(xPos, yPos) == Standards.ImportantNodeColor) { yLength += Convert.ToDouble(Math.Abs(this.YCoordinate - yPos) / 2); HittingSomething = true; } } HittingSomething = false; yPos = this.YCoordinate; } } if (!(this is Door) && !(this is Staircase)) { // Set the width and height for the node SetAreaForNode(xLength, yLength, PixelsPerMeter); } }