public void Run() { GenerateStartSegments(); while (queue.Count != 0 && segments.Count < maxSegment) { RoadSegment current = queue[0]; queue.RemoveAt(0); if (!CheckLocalConstraint(current)) { continue; } segments.Add(current); AddToGraph(current); GlobalGoals(current); } if (segments.Count == maxSegment) { Debug.Log("Minor Roads reached maximal amount"); } DeleteSomeNodes(); DeleteInsideLeaves(); DeleteAloneEdges(); DeleteAloneNodes(); }
private void GlobalGoals(RoadSegment segment) { if (segment.EndSegment) { return; } globalGoalsRoads.Clear(); //Generate in the 3 other possible direction var dirVector = segment.getDirVector(); var normalVector1 = new Vector2(dirVector.y, -dirVector.x); var normalVector2 = new Vector2(-dirVector.y, dirVector.x); RoadSegment branchedSegment1 = CalcNewRoadSegment(segment.NodeTo, dirVector, 0); RoadSegment branchedSegment2 = CalcNewRoadSegment(segment.NodeTo, normalVector1, 0); RoadSegment branchedSegment3 = CalcNewRoadSegment(segment.NodeTo, normalVector2, 0); globalGoalsRoads.Add(branchedSegment1); globalGoalsRoads.Add(branchedSegment2); globalGoalsRoads.Add(branchedSegment3); foreach (RoadSegment newSegment in globalGoalsRoads) { queue.Add(newSegment); } }
private void GenerateStartSegments() { foreach (RoadSegment segment in hwSegments) { if (segment.EndSegment) { continue; } var dirVector = segment.getDirVector(); var normalVector1 = new Vector2(dirVector.y, -dirVector.x); var normalVector2 = new Vector2(-dirVector.y, dirVector.x); RoadSegment branchedSegment2 = CalcNewRoadSegment(segment.NodeTo, normalVector1, 0); RoadSegment branchedSegment3 = CalcNewRoadSegment(segment.NodeTo, normalVector2, 0); queue.Add(branchedSegment2); queue.Add(branchedSegment3); if (hwSegments.IndexOf(segment) == 0) //We also branch out from the very first Node! { RoadSegment branchedSegment4 = CalcNewRoadSegment(segment.NodeFrom, normalVector1, 0); RoadSegment branchedSegment5 = CalcNewRoadSegment(segment.NodeFrom, normalVector2, 0); queue.Add(branchedSegment4); queue.Add(branchedSegment5); } } }
private RoadSegment GetContinuingRoadSegment(RoadSegment segment) { var dirVector = segment.getDirVector(); if (maxLean < 1) { return(CalcNewRoadSegment(segment.NodeTo, dirVector, 0)); } if (segment.LeanIteration == 3) //Check if we need a new lean. If yes, calculate the next RoadSegment { var randomNumber = rand.Next(0, 3); if (randomNumber == 1) { dirVector = RotateVector(dirVector, GetRandomAngle(2, maxLean * 2)); RoadSegment newSegment = CalcNewRoadSegment(segment.NodeTo, dirVector, 0); newSegment.LeanLeft = true; return(newSegment); } else if (randomNumber == 2) { dirVector = RotateVector(dirVector, GetRandomAngle(-2, -maxLean * 2)); RoadSegment newSegment = CalcNewRoadSegment(segment.NodeTo, dirVector, 0); newSegment.LeanRight = true; return(newSegment); } else { return(CalcNewRoadSegment(segment.NodeTo, dirVector, 0)); } } else //if not, grow the new segment following the lean { if (segment.LeanLeft) { dirVector = RotateVector(dirVector, GetRandomAngle(2, maxLean)); RoadSegment segment1 = CalcNewRoadSegment(segment.NodeTo, dirVector, segment.LeanIteration + 1); segment1.LeanLeft = true; return(segment1); } else if (segment.LeanRight) { dirVector = RotateVector(dirVector, GetRandomAngle(-2, -maxLean)); RoadSegment segment1 = CalcNewRoadSegment(segment.NodeTo, dirVector, segment.LeanIteration + 1); segment1.LeanRight = true; return(segment1); } else { return(CalcNewRoadSegment(segment.NodeTo, dirVector, segment.LeanIteration + 1)); } } }
private void AddToGraph(RoadSegment road) { if (!graph.MajorNodes.Contains(road.NodeFrom) && !graph.MinorNodes.Contains(road.NodeFrom)) { graph.MinorNodes.Add(road.NodeFrom); } if (!graph.MajorNodes.Contains(road.NodeTo) && !graph.MinorNodes.Contains(road.NodeTo)) { graph.MinorNodes.Add(road.NodeTo); } graph.MinorEdges.Add(new Edge(road.NodeFrom, road.NodeTo)); }
private bool CheckLocalConstraint(RoadSegment segment) { foreach (RoadSegment road in segments) { //If the new segment end is close to another segments Node, Fix it's end to it if (IsClose(segment.NodeTo, road.NodeTo)) { segment.NodeTo = road.NodeTo; segment.EndSegment = true; } if (segment.IsCrossing(road)) { return(false); //Check if segment is crossing an other road } } //Check if segment is out of border if (segment.NodeFrom.X > border || segment.NodeFrom.X < -border || segment.NodeFrom.Y > border || segment.NodeFrom.Y < -border) { return(false); } //Check if segment would come into itself if (segment.NodeFrom.X == segment.NodeTo.X && segment.NodeFrom.Y == segment.NodeTo.Y) { return(false); } //nodeTo or nodeFrom has more than 4 edges if (segment.NodeTo.Edges.Count >= 4 || segment.NodeFrom.Edges.Count >= 4) { return(false); } foreach (Edge edge in segment.NodeTo.Edges) { //NodeTo already connected to NodeFrom if (edge.NodeA == segment.NodeFrom || edge.NodeB == segment.NodeFrom) { return(false); } } return(true); }
private void GlobalGoals(RoadSegment segment) { if (segment.EndSegment) { return; } globalGoalsRoads.Clear(); var dirVector = segment.getDirVector(); //BRANCHING int branchRandom = rand.Next(0, 40); //Branching chance is 3 out of 40 if (branchRandom == 4) //At every 40th points approx. the road branches out to the RIGHT { var normalVector = new Vector2(dirVector.y, -dirVector.x); RoadSegment branchedSegment = CalcNewRoadSegment(segment.NodeTo, normalVector, 0); globalGoalsRoads.Add(branchedSegment); } else if (branchRandom == 5) //At every other 40th points approx. the road branches out to the LEFT { var normalVector = new Vector2(-dirVector.y, dirVector.x); RoadSegment branchedSegment = CalcNewRoadSegment(segment.NodeTo, normalVector, 0); globalGoalsRoads.Add(branchedSegment); } else if (branchRandom == 6) //At every another 40th points approx. the road branches out to BOTH DIRECTIONS { var normalVector1 = new Vector2(dirVector.y, -dirVector.x); var normalVector2 = new Vector2(-dirVector.y, dirVector.x); RoadSegment branchedSegment1 = CalcNewRoadSegment(segment.NodeTo, normalVector1, 0); RoadSegment branchedSegment2 = CalcNewRoadSegment(segment.NodeTo, normalVector2, 0); globalGoalsRoads.Add(branchedSegment1); globalGoalsRoads.Add(branchedSegment2); } //ROAD CONTINUE globalGoalsRoads.Add(GetContinuingRoadSegment(segment)); foreach (RoadSegment newSegment in globalGoalsRoads) { queue.Add(newSegment); } }
public bool IsCrossing(RoadSegment road) //Check if the given road intersects with this road { //if (NodeFrom == road.NodeFrom || NodeFrom == road.NodeTo && NodeTo == road.NodeFrom || NodeTo == road.NodeTo) return true; //Two roadSegment is overlapping each other if (NodeFrom == road.NodeFrom || NodeFrom == road.NodeTo || NodeTo == road.NodeFrom || NodeTo == road.NodeTo) { return(false); //One of the Nodes is the same (it doesnt count as an intersection now) } int o1 = Orientation(NodeFrom, NodeTo, road.NodeTo); int o2 = Orientation(NodeFrom, NodeTo, road.NodeFrom); int o3 = Orientation(road.NodeFrom, road.NodeTo, NodeFrom); int o4 = Orientation(road.NodeFrom, road.NodeTo, NodeTo); //General case if (o1 != o2 && o3 != o4) { return(true); } //Special case (rare, but need to handle) - happens if two segments are collinear - we need to check if they are overlap or not if (o1 == 0 && o2 == 0 && o3 == 0 && o4 == 0) { if (o1 == 0 && OnSegment(NodeFrom, NodeTo, road.NodeTo)) { return(true); } if (o2 == 0 && OnSegment(NodeFrom, NodeTo, road.NodeFrom)) { return(true); } if (o3 == 0 && OnSegment(road.NodeFrom, road.NodeTo, NodeFrom)) { return(true); } if (o4 == 0 && OnSegment(road.NodeFrom, road.NodeTo, NodeTo)) { return(true); } } return(false); }
private void GenerateStartSegments() { //First Generate a number nearby the middle quarter of the map int sampleX = rand.Next(0, (border * 100)); int sampleY = rand.Next(0, (border * 100)); float starterX = (sampleX / 100.0f) - (float)border / 3; float starterY = (sampleY / 100.0f) - (float)border / 3; var startNode = new Node(starterX, starterY); //Secondly Generate a vector which determines the two starting directions int randomDirX = rand.Next(-100, 100); int randomDirY = rand.Next(-100, 100); var startDir = new Vector2(randomDirX, randomDirY); var starterNodeTo1 = new Node(startNode.X + startDir.normalized.x * RoadLength, starterY + startDir.normalized.y * RoadLength); var starterNodeTo2 = new Node(startNode.X - startDir.normalized.x * RoadLength, starterY - startDir.normalized.y * RoadLength); //Thirdly We make two starting RoadSegment from these var starterSegment1 = new RoadSegment(startNode, starterNodeTo1, 0); var starterSegment2 = new RoadSegment(startNode, starterNodeTo2, 0); queue.Add(starterSegment1); queue.Add(starterSegment2); }
private bool CheckLocalConstraint(RoadSegment segment) { //TRANSFORMATION bool stretched = false; foreach (RoadSegment road in hwSegments) //first check majorNodes { if (IsClose(segment.NodeTo, road.NodeTo)) { segment.NodeTo = road.NodeTo; segment.EndSegment = true; stretched = true; break; } } if (!stretched) { foreach (RoadSegment road in segments) //then check minorNodes { if (IsClose(segment.NodeTo, road.NodeTo)) { segment.NodeTo = road.NodeTo; segment.EndSegment = true; break; } } } //CHECKING CROSSING foreach (RoadSegment road in hwSegments) //first check majorNodes { if (segment.IsCrossing(road)) { return(false); } } foreach (RoadSegment road in segments) //then check minorNodes { if (segment.IsCrossing(road)) { return(false); } } //CHECKING OTHER CONSTRAINTS //Check if segment is out of border if (segment.NodeFrom.X > border || segment.NodeFrom.X < -border || segment.NodeFrom.Y > border || segment.NodeFrom.Y < -border) { return(false); } //Check if segment would come into itself if (segment.NodeFrom.X == segment.NodeTo.X && segment.NodeFrom.Y == segment.NodeTo.Y) { return(false); } //nodeTo or nodeFrom has more than 4 edges if (segment.NodeTo.Edges.Count >= 4 || segment.NodeFrom.Edges.Count >= 4) { return(false); } if (!segment.NodeFrom.IsFree( Mathf.Atan2(segment.NodeTo.Y - segment.NodeFrom.Y, segment.NodeTo.X - segment.NodeFrom.X) )) { return(false); //direction is not free from NodeFrom } if (!segment.NodeTo.IsFree( Mathf.Atan2(segment.NodeFrom.Y - segment.NodeTo.Y, segment.NodeFrom.X - segment.NodeTo.X) )) { return(false); //direction is not free from NodeTo } return(true); }