<jupyter_start><jupyter_text>Parameters<jupyter_code>WIDTH = 2
HEIGHT = 2
MAJOR_R = 1
# 360 has to be divisible by this value
NUM_POINTS = 12
STROKE_WIDTH = 0.02
SEPARATION = 7.5
INNER_P_DETECT = MAJOR_R / 6
OUTER_P_DETECT = MAJOR_R / 1.3
MAX_SEPARATION = 360 / NUM_POINTS
# Template Size
EXT_WIDTH = 5
EXT_HEIGHT = 5
# Has to be 0 <= x < 1
X_OFFSET = 0
Y_OFFSET = 0
# Helpers

def get_line_string(sx,sy,ex,ey):
    return LineString([(sx,sy), (ex,ey)])

# Draw Construction Lines

def add_line_to_svg(ps, color, stroke_width, label):
    l = draw.Line(*ps, stroke=color, stroke_width=stroke_width)
    l.shape = get_line_string(*ps)
    l.label = label
    SVG.append(l)
    

def draw_inner_squares(color, stroke_width):
    for t in range(0, 360, round(360/NUM_POINTS)):
        rad = np.deg2rad(t)
        # sx, sy, ex, ey
        ps = np.array((math.cos(rad + math.pi/2),
                       math.sin(rad + math.pi/2), 
                       math.cos(rad), 
                       math.sin(rad)))*MAJOR_R
        add_line_to_svg(ps, color, stroke_width, 'inner_square')
        
def draw_inner_parallel_lines(color, stroke_width):
    t_offset = np.deg2rad(SEPARATION)
    for t in range(0, 180, round(360/NUM_POINTS)):
        rad = np.deg2rad(t)
        ps = np.array((math.cos(rad + math.pi + t_offset),
                       math.sin(rad + math.pi + t_offset), 
                       math.cos(rad - t_offset), 
                       math.sin(rad - t_offset)))*MAJOR_R
        add_line_to_svg(ps, color, stroke_width, 'inner_parallel')


        ps = np.array((math.cos(rad + math.pi - t_offset),
                       math.sin(rad + math.pi - t_offset), 
                       math.cos(rad + t_offset), 
                       math.sin(rad + t_offset)))*MAJOR_R
        add_line_to_svg(ps, color, stroke_width, 'inner_parallel')

def draw_shape():
    global SVG
    SVG = draw.Drawing(WIDTH, HEIGHT, origin='center')
    # Draw another shape to fill with the same gradient
    p = draw.Circle(fill='transparent',cx=0,cy=0, r=MAJOR_R,stroke='red', stroke_width=STROKE_WIDTH)
    SVG.append(p)

    draw_inner_squares('red', STROKE_WIDTH/4)
    draw_inner_parallel_lines('blue', STROKE_WIDTH/4)
    return SVG.setRenderSize(w=600)
# Helpers

def create_line(sx, sy, ex, ey):
    return LineString([(sx,sy), (ex,ey)])

def draw_inner_squares():
    r = []
    corners = []
    for t in range(0, 360, round(360/NUM_POINTS)):
        rad = np.deg2rad(t)
        # sx, sy, ex, ey
        ps = np.array((math.cos(rad + math.pi/2),
                       math.sin(rad + math.pi/2), 
                       math.cos(rad), 
                       math.sin(rad)))*MAJOR_R
        corners.append(ps)
        r.append(create_line(*ps))
    return r, corners
        
def draw_inner_parallel_lines():
    r = []
    t_offset = np.deg2rad(SEPARATION)
    for t in range(0, 180, round(360/NUM_POINTS)):
        rad = np.deg2rad(t)
        ps = np.array((math.cos(rad + math.pi + t_offset),
                       math.sin(rad + math.pi + t_offset), 
                       math.cos(rad - t_offset), 
                       math.sin(rad - t_offset)))*MAJOR_R
        r.append(create_line(*ps))

        ps = np.array((math.cos(rad + math.pi - t_offset),
                       math.sin(rad + math.pi - t_offset), 
                       math.cos(rad + t_offset), 
                       math.sin(rad + t_offset)))*MAJOR_R
        r.append(create_line(*ps))
    return r

def get_skeleton():
    r_elements = []
    r, corners = draw_inner_squares()
    r_elements += r
    r_elements += draw_inner_parallel_lines()
    return r_elements, corners

def get_adjusted_angle(x, y):
    return round(np.arctan2(y, x), 6)
        

def get_base_element(tx, ty):
    SVG = draw.Drawing(WIDTH, HEIGHT, origin='center')
    lines, corners = get_skeleton()
    center = Point(0,0)
    ps_dict = defaultdict(list)
    for i in range(len(lines)):
        l1 = lines[i]
        for j in range(i+1, len(lines)):
            l2 = lines[j]
            p = l1.intersection(l2)
            r = round(p.distance(center), 4)
            if p and INNER_P_DETECT < r < OUTER_P_DETECT:
                p.r = r
                p.theta = get_adjusted_angle(p.x, p.y)

                ps_dict[p.r].append(p)
    distances = sorted(ps_dict.keys())
    # Inner star
    ps = sorted(ps_dict[distances[2]] + ps_dict[distances[3]] + ps_dict[distances[4]], key=lambda p: p.theta)
    x = sum(([p.x + tx, p.y + ty] for p in ps), [])
    SVG.append(draw.Lines(*x, fill='transparent', stroke='green', stroke_width=0.015, close=True))

    # Middle star
    ps = sorted(ps_dict[distances[1]] + ps_dict[distances[2]], key=lambda p: p.theta)
    x = sum(([p.x + tx, p.y + ty] for p in ps), [])
    SVG.append(draw.Lines(*x, fill='transparent', stroke='green', stroke_width=0.015, close=True))

    # Outer star
    ps = sorted(ps_dict[distances[0]] + ps_dict[distances[1]], key=lambda p: p.theta)
    x = sum(([p.x + tx, p.y + ty] for p in ps), [])
    SVG.append(draw.Lines(*x, fill='transparent', stroke='green', stroke_width=0.015, close=True))
    
    return SVG.elements[-3:], ps_dict[distances[-1]]
def draw_star(SVG, x, y):
    tx, ty = x, y
    elements, corners = get_base_element(tx, ty)
    SVG.elements += elements
    for p in corners:
        SVG.append(draw.Circle(p.x + tx, p.y + ty, 0.025, fill='black'))
    SVG.setRenderSize(500,500)
    star_d = max(c.distance(corners[0]) for c in corners[1:])
    return star_d, corners
SVG = draw.Drawing(EXT_WIDTH, EXT_HEIGHT, origin='center')
D, _ = draw_star(SVG, 0, 0)
SVG = draw.Drawing(EXT_WIDTH, EXT_HEIGHT, origin='center')
R = D / 2

shift = False

x = D * X_OFFSET - EXT_WIDTH / 2
while x + R <= EXT_WIDTH:
    y = D * Y_OFFSET - EXT_HEIGHT / 2
    while y + R <= EXT_HEIGHT:
        if shift:
            _, corners = draw_star(SVG, x, y)
        else:
            _, corners = draw_star(SVG, x - R, y)
        shift = not shift
        y += math.sin(math.pi/2 - (2*math.pi/NUM_POINTS)) * D
    x += D
SVG
SVG2 = draw.Drawing(2, 2, origin='center')
D, corners = draw_star(SVG2, 0, 0)

_ = SVG2.setRenderSize(500)
d_theta = math.pi/NUM_POINTS
r = 0.5
for i in range(-1, len(corners) - 1):
    dx = r 
    dy = r * math.tan(d_theta)
    dx = dx * math.cos(i * d_theta) - dx * math.sin(i * d_theta)
    dy = dy * math.sin(i * d_theta) + dy * math.cos(i * d_theta) 
    print(dx, dy)
    SVG2.append(draw.Line(corners[i].x, corners[i].y, corners[i].x + dx, corners[i].y + dy, stroke='red', stroke_width=0.01))
    #SVG2.append(draw.Line(corners[i].x, corners[i].y, corners[i].x + 0.1, corners[i].y + math.tan(td_theta), stroke='blue', stroke_width=0.01))
SVG2
corners[i]
corners[0].x<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1470326409495549, 'fraction_numerical': 0.02166172106824926, 'mean_word_length': 2.446319018404908, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '206121', 'license': 'MIT', 'n_tokens_mistral': 2651, 'n_tokens_neox': 2522, 'n_words': 528, 'path': '.ipynb_checkpoints/Untitled-checkpoint.ipynb', 'repo_name': 'amehina/islamic_svg_pattern_generator', 'size': '6740'}