/// <summary>
    /// Goes road by road to create sidewalks
    /// Once a side of the road (designated by a road and the intersection it comes from) is used, don't try to use it again
    /// </summary>
    private IEnumerator GenerateBlock()
    {
        GameObject parentObject = new GameObject();

        parentObject.name     = "Block";
        parentObject.isStatic = true;

        HashSet <SidewalkCheckHelper> usedRoads = new HashSet <SidewalkCheckHelper>();
        List <Sidewalk>     sidewalks           = new List <Sidewalk>();
        SidewalkCheckHelper check = new SidewalkCheckHelper();

        // TODO: Add list of all roads to city info to optimize this
        for (int i = 0; i < city.Nodes.Count; i++)
        {
            for (int j = 0; j < city.Nodes[i].Roads.Count; j++)
            {
                check.Intersection = city.Nodes[i];
                check.Road         = city.Nodes[i].Roads[j];

                if (!usedRoads.Contains(check))
                {
                    usedRoads.Add(check);
                    sidewalks.Add(CreateSidewalk(city.Nodes[i], city.Nodes[i].Roads[j], usedRoads, parentObject));
                }
            }
        }

        // Create buildings
        // Use collisions to make sure buildings don't collide with roads
        // TODO: Add list of all roads to city info to optimize this
        GameObject buildingObject = new GameObject();

        buildingObject.name             = "Buildings";
        buildingObject.transform.parent = parentObject.transform;
        buildingObject.isStatic         = true;

        HashSet <RoadSegment> roads = new HashSet <RoadSegment>();

        for (int i = 0; i < city.Nodes.Count; i++)
        {
            for (int j = 0; j < city.Nodes[i].Roads.Count; j++)
            {
                if (!roads.Contains(city.Nodes[i].Roads[j]))
                {
                    roads.Add(city.Nodes[i].Roads[j]);
                    yield return(EditorCoroutineUtility.StartCoroutine(CreateBuildings(city.Nodes[i].Roads[j], buildingObject), this));
                }
            }
        }

        // After buildings are created, create the infill mesh
        for (int i = 0; i < sidewalks.Count; i++)
        {
            if (!sidewalks[i].IsSurroundingSidewalk())
            {
                sidewalks[i].CreateFillMesh();
            }
        }
    }
    /// <summary>
    /// Gets all the points that will form a sidewalk
    /// </summary>
    /// <param name="startIntersection"></param>
    /// <param name="roadSegment"></param>
    /// <param name="checks"></param>
    /// <param name="parent"></param>
    private Sidewalk CreateSidewalk(Intersection startIntersection, RoadSegment roadSegment, HashSet <SidewalkCheckHelper> checks, GameObject parent)
    {
        Intersection current     = startIntersection;
        Intersection next        = roadSegment.GetOtherSide(startIntersection);
        RoadSegment  nextSegment = null;

        GameObject go = new GameObject();

        go.name = "Sidewalk Mesh";
        Sidewalk sidewalk = go.AddComponent <Sidewalk>();

        sidewalk.OriginalVertices.Add(roadSegment.GetVertexWorldPosition(startIntersection, false));
        SidewalkCheckHelper check = new SidewalkCheckHelper();

        while (next != startIntersection)
        {
            int nextIndex = (next.Roads.IndexOf(roadSegment) + 1) % (next.Roads.Count);
            nextSegment = next.Roads[nextIndex];

            check.Intersection = next;
            check.Road         = nextSegment;

            checks.Add(check);

            if (next.Roads.Count == 1)
            {
                sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, true));
                sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false));
            }
            else if (!(Mathf.Approximately(roadSegment.GetVertexWorldPosition(next, true).x, nextSegment.GetVertexWorldPosition(next, false).x) &&
                       Mathf.Approximately(roadSegment.GetVertexWorldPosition(next, true).z, nextSegment.GetVertexWorldPosition(next, false).z)))
            {
                sidewalk.OriginalVertices.Add(roadSegment.GetVertexWorldPosition(next, true));
                sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false));
            }
            else
            {
                sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false));
            }

            current     = next;
            next        = nextSegment.GetOtherSide(next);
            roadSegment = nextSegment;
        }

        if (nextSegment != null &&
            !(Mathf.Approximately(sidewalk.OriginalVertices[0].x, nextSegment.GetVertexWorldPosition(next, true).x) &&
              Mathf.Approximately(sidewalk.OriginalVertices[0].z, nextSegment.GetVertexWorldPosition(next, true).z)))
        {
            sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, true));
        }


        Vector3 sum = Vector3.zero;

        for (int i = 0; i < sidewalk.OriginalVertices.Count; i++)
        {
            sum += sidewalk.OriginalVertices[i];
        }

        go.transform.position     = sum / sidewalk.OriginalVertices.Count;
        sidewalk.SidewalkMaterial = city.SidewalkMaterial;
        sidewalk.InnerMaterial    = city.InnerBlockMaterial;
        sidewalk.FixMeshOffset();
        sidewalk.FindDirection();
        sidewalk.CalculateVertices();
        sidewalk.CreateMesh();
        go.transform.parent = parent.transform;
        go.isStatic         = true;
        return(sidewalk);
    }