예제 #1
0
        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();
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        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));
                }
            }
        }
예제 #5
0
 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));
 }
예제 #6
0
        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);
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }