Exemplo n.º 1
0
    StreetTraversal PickNextTraversed(Intersection currentIntersection, StreetTraversal prevTraversed)
    {
        //the float as the key doesnt pose issues because the only way we access anyway is by MaxKey
        Dictionary <float, StreetTraversal> streetsByAngle = new Dictionary <float, StreetTraversal>();

        //picking connected Streets that go counterclockwise, or straight, compared to prevTraversed
        foreach (Street connected in currentIntersection.Connected)
        {
            if (connected == prevTraversed.Street)
            {
                continue;
            }                                                    //we dont want to backtrack, so skipping the one from which we came from
            Vector2 prevDir           = GS.GetPolar(prevTraversed.FromAToB) * prevTraversed.Street.Line.Dir;
            bool    connectedFromAToB = (currentIntersection == connected.InterA);
            Vector2 connectedDir      = GS.GetPolar(connectedFromAToB) * connected.Line.Dir;
            float   angle             = -Vector2.SignedAngle(prevDir, connectedDir);
            if (angle >= -0.01f)
            {
                streetsByAngle.Add(angle, new StreetTraversal(connected, connectedFromAToB));
            }
        }
        if (streetsByAngle.Count > 0)
        {
            return(streetsByAngle[streetsByAngle.MaxKey()]);
        }
        return(null);
    }
Exemplo n.º 2
0
    public IEnumerator ExtractCityBlocks(List <Intersection> inters, List <RimStreetLine> linesWithEndOnRim)
    {
        DB.Log("EXTRACTING CITY BLOCKS", 1);
        Blocks = new List <CityBlock>();
        //extracting city blocks looks like this:
        //From every Intersection the algorithm tries to traverse the Streets connected to it
        //and upon encountering an Intersection on the other end it makes the first clockwise
        //turn available, unless there is no such turn, then it continues in the same direction.
        //When it doesn't encounter an Intersection on the end of a Street, but instead a dead end
        //on the rim of the city circle, it jumps to the next point clockwise along the rim
        //and continues traversal. This way the alg will eventually reach the same Intersection it started
        //from and this way it will save all the Streets encountered as the bounds of the city block.

        //In the case when the traversal gets lost and after a lot of points it still hasn't come back,
        //it is skipped, but I doubt if getting lost is even mathematically possible, it's just an
        //extra precaution.

        for (int i = 0; i < inters.Count; i++)
        {
            foreach (Street startStreet in inters[i].Connected)
            {
                bool                   lost       = false;
                bool                   hasRimSkip = false;
                Intersection           current    = startStreet.GetOtherSide(inters[i]);
                List <StreetTraversal> traversal  = new List <StreetTraversal>();
                bool                   startingTraversedFromAToB = (inters[i] == startStreet.InterA);
                traversal.Add(new StreetTraversal(startStreet, startingTraversedFromAToB));

                while (current != inters[i])
                {
                    if (current == null)
                    {
                        //current Intersection is null meaning we've reached city rim on its end
                        //need to jump along the rim clockwise
                        hasRimSkip = true;
                        Vector2         pointOnRim         = (traversal.Last().FromAToB) ? traversal.Last().Street.B : traversal.Last().Street.A;
                        StreetTraversal traversedAfterSkip = GetTraversalFromSkip(pointOnRim, linesWithEndOnRim);
                        traversal.Add(traversedAfterSkip);
                        current = traversedAfterSkip.FromAToB ? traversedAfterSkip.Street.InterB : traversedAfterSkip.Street.InterA;
                    }
                    else
                    {
                        traversal.Add(PickNextTraversed(current, traversal.Last()));
                        current = traversal.Last().Street.GetOtherSide(current);
                    }
                    if (traversal.Count > 50)
                    {
                        lost = true; DB.Log("traversal got lost."); break;
                    }
                }

                if (!lost)
                {
                    CityBlock block = new CityBlock(traversal, hasRimSkip);
                    if (!BlockIsADuplicate(block))
                    {
                        Blocks.Add(block);
                        block.DebugDraw(300f);
                        //DB.Log(block.ToString());
                        //yield return new WaitForSeconds(1f);
                    }
                }
            }
            yield return(null);
        }
        DB.Log($"{Blocks.Count} CITY BLOCKS EXTRACTED", 1);
    }