Search code examples
pythonmathgeometrycomputational-geometry

Creating an equilateral triangle grid / mesh inside a larger equilateral triangle


I have a list of vertices from a polygon and I'm trying to create an equilateral triangular grid inside a larger triangle centered around the current vertex from the input polygon.

The size of the internal triangle's sides is determined by L which divides the container side to L equal parts. Finally I'd like to store the coordinates of the vertices of all these triangles (including the original larger triangle) in a list in Python.

Desired result

One approach I have come up with is the following:

  • Find equidistant points with respect to L on each side of the large triangle
  • Connect these points to the adjacent larger side
  • Create a Shapely LineString from each of corresponding points
  • Run a for loop that utilizes Shapely's object.intersection() function that returns the coordinates

However I'm open to ideas and other approaches possibly more efficient ones.

Here's my code so far:

import math
import sys


# Constructs the larger, container triangle given the centroid (a vertex from the input polygon)
def construct_eq_triangle(centroid, radius):
    side_length = radius * math.sqrt(3)
    # Calculate three vertices of the container triangle
    a = [centroid[0], centroid[1] + (math.sqrt(3) / 3) * side_length]  # Top vertex
    b = [centroid[0] - (side_length / 2), centroid[1] - (math.sqrt(3) / 6) * side_length]  # Bottom left vertex
    c = [centroid[0] + (side_length / 2), centroid[1] - (math.sqrt(3) / 6) * side_length]  # Bottom right vertex

    return a, b, c


def draw_triangular_grid(vertex, radius, L):

    grid_x = []
    grid_y = []
    
    # contruct the container equilateral triangler around this vertex
    a, b, c = construct_eq_triangle(vertex, radius)
    # Draw the grid here inside a,b,c and fill 'grid_x' and 'grid_y'
   
    # but for now just print the mother triangle
    print("\n Equilateral triangle for vertex " + str(vertex) + ":")
    print((a, b, c))

    return grid_x, grid_y


def main(args):
    # demo data, 4 vertices of a simple square with a length of 8
    vertices = [(2.0, 10.0), (10.0, 10.10), (10.0, 2.0), (2.0, 2.0)]
    radius = 2
    L = 7
    i = 0
    while i <= len(vertices) - 1:
        grid_x, grid_y = draw_triangular_grid(vertices[i], radius, L)
        # process the grid coordinates
        i += 1


# Main entry point
if __name__ == "__main__":
    main(sys.argv[1:])



Solution

  • If you need to calculate triangle vertices:

    import math
    
    ax = 0
    ay = 100
    L = 4
    tri = []
    Size = 100
    dx = 0.5 * Size / L
    dy = - math.sqrt(3) * dx
    
    for i in range(L):
        basex = ax - dx * i
        basey = ay + dy * i
        tri.append([(basex, basey), (basex - dx, basey + dy), (basex + dx, basey + dy)])
        for j in range(i):
            tri[-1].extend([(basex + j * 2 * dx, basey),
                            (basex + j * 2 * dx + dx, basey +   dy),
                            (basex + (j + 1) * 2 * dx, basey)])
            tri[-1].extend([(basex + (j + 1) * 2 * dx, basey),
                            (basex + (j + 1) * 2 * dx - dx, basey + dy),
                            (basex + (j + 1) * 2 * dx + dx, basey + dy)])
    
    for i in range(L):
        print(tri[i])
        print()
    

    Result contains stripes of triangles as triplets of vertex tuples:

    [(0.0, 100.0), (-12.5, 78.34936490538904), (12.5, 78.34936490538904)]
    
    [(-12.5, 78.34936490538904), (-25.0, 56.698729810778076), (0.0, 56.698729810778076),
     (-12.5, 78.34936490538904), (0.0, 56.698729810778076), (12.5, 78.34936490538904), 
     (12.5, 78.34936490538904), (0.0, 56.698729810778076), (25.0, 56.698729810778076)]
    
    [(-25.0, 56.69872981077807), (-37.5, 35.0480947161671), (-12.5, 35.0480947161671), 
     (-25.0, 56.69872981077807), (-12.5, 35.0480947161671), (0.0, 56.69872981077807), 
     (0.0, 56.69872981077807), (-12.5, 35.0480947161671), (12.5, 35.0480947161671), 
     (0.0, 56.69872981077807), (12.5, 35.0480947161671), (25.0, 56.69872981077807), 
     (25.0, 56.69872981077807), (12.5, 35.0480947161671), (37.5, 35.0480947161671)]
    
    [(-37.5, 35.0480947161671), (-50.0, 13.397459621556134), (-25.0, 13.397459621556134), 
     (-37.5, 35.0480947161671), (-25.0, 13.397459621556134), (-12.5, 35.0480947161671), 
     (-12.5, 35.0480947161671), (-25.0, 13.397459621556134), (0.0, 13.397459621556134), 
     (-12.5, 35.0480947161671), (0.0, 13.397459621556134), (12.5, 35.0480947161671), 
     (12.5, 35.0480947161671), (0.0, 13.397459621556134), (25.0, 13.397459621556134), 
     (12.5, 35.0480947161671), (25.0, 13.397459621556134), (37.5, 35.0480947161671), 
     (37.5, 35.0480947161671), (25.0, 13.397459621556134), (50.0, 13.397459621556134)]