float WallCWOrthoOffset(List <Vector3> innerWall, int wallSegment)
    {
        int l       = perimeter.Count;
        int idPerim = perimeter.IndexOf(innerWall[wallSegment]);

        if (idPerim >= 0)
        {
            Vector3 pt  = perimeter[idPerim];
            Vector3 rhs = pt - perimeter[(l + idPerim - 1) % l];
            Vector3 lhs = perimeter[(idPerim + 1) % l] - pt;
            if (ProcGenHelpers.XZRotation(lhs, rhs) == -1)
            {
                if (ProcGenHelpers.XZRotation(rhs, innerWall[wallSegment + 1] - innerWall[wallSegment]) == 0)
                {
                    return(0);
                }
                else
                {
                    return(1);
                }
            }
        }
        else if (wallSegment == l - 2)
        {
            idPerim = perimeter.IndexOf(innerWall[wallSegment]);
            if (idPerim >= 0)
            {
                Vector3 pt  = perimeter[idPerim];
                Vector3 rhs = pt - perimeter[(l + idPerim - 1) % l];
                Vector3 lhs = perimeter[(idPerim + 1) % l] - pt;
                if (ProcGenHelpers.XZRotation(lhs, rhs) == -1)
                {
                    if (ProcGenHelpers.XZRotation(rhs, innerWall[wallSegment - 1] - innerWall[wallSegment]) == 0)
                    {
                        return(1);
                    }
                    else
                    {
                        return(0);
                    }
                }
            }
        }
        return(0.5f);
    }
    IEnumerator <WaitForSeconds> _Build()
    {
        //TODO: Best way to remove convex points
        //TODO: Instert point in next wall behind current rather than far wall
        //TODO: Have points of interest (non concave) and use for corners too?
        //TODO: Linear points to wall building.
        //TODO: Allow inner wall free building.

        gizmoWalls.Clear();
        int rooms = Mathf.Clamp(Random.Range(1, 3) + Random.Range(1, 4) + Random.Range(2, 4), 4, 7);

        perimeter.Clear();
        perimeter.AddRange(ProcGenHelpers.Simplify(floor.GetCircumferance(false).Select(v => transform.InverseTransformPoint(v)).ToList()));

        yield return(new WaitForSeconds(0.05f));

        for (int i = 0, l = perimeter.Count; i < l; i++)
        {
            Vector3 pt       = perimeter[i];
            Vector3 rhs      = pt - perimeter[(l + i - 1) % l];
            Vector3 lhs      = perimeter[(i + 1) % l] - pt;
            int     rotation = ProcGenHelpers.XZRotation(lhs, rhs);
            if (rotation == -1)
            {
                //Debug.Log(string.Format("{0}: convex", i));
                convex.Add(pt);
            }
            else if (rotation == 1)
            {
                //Debug.Log(string.Format("{0}: concave", i));
                nonConcave.Add(pt);
            }
        }


        yield return(new WaitForSeconds(0.01f));

        int attempts = 0;

        while (rooms > 0 && attempts < 300)
        {
            bool          addedRoom = false;
            RoomBuildType nextRoom  = NextRoomType;
            if (nextRoom == RoomBuildType.ConvexCornerToStraightToWall)
            {
                if (MapCornerStraightWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }
            else if (nextRoom == RoomBuildType.ConvexCornerToConvexCorner)
            {
                if (MapCornerToCornerWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }
            else if (nextRoom == RoomBuildType.WallStraightToWall)
            {
                if (MapWallToWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }

            attempts++;
            yield return(new WaitForSeconds(addedRoom ? 0.05f : 0.01f));
        }

        Debug.LogWarning(string.Format("Ended with remaining {0} rooms after {1} attempts", rooms, attempts));

        foreach (List <Vector3> innerWall in wallLines)
        {
            ConstructInnerWall(innerWall);
            yield return(new WaitForSeconds(0.05f));

            innerWall.Reverse();
            ConstructInnerWall(innerWall);
            yield return(new WaitForSeconds(0.05f));
        }


        mCol.sharedMesh = null;
        mCol.sharedMesh = mesh;

        generated  = true;
        generating = false;
    }