<jupyter_start><jupyter_text>division<jupyter_code># make page
paper_size = '17x11 inches'
border:float=20
paper = Paper(paper_size)

drawbox = paper.get_drawbox(border)
states = geopandas.read_file('/mnt/c/data/side/maps/cb_2018_us_state_20m/cb_2018_us_state_20m.shp')

continental = ~states['NAME'].isin(['Hawaii', 'Alaska', 'Puerto Rico'])

cnt = states.loc[continental,:].unary_union.centroid


states['geometry'] = states['geometry'].scale(xfact=1.3, yfact=-1.5, origin=cnt)
us_poly = gp.make_like(states.loc[continental,:].unary_union, drawbox)
start_poly = us_poly.buffer(50)
border_pts = [start_poly.boundary.interpolate(i, normalized=True) for i in np.linspace(0, 1, 10)]
trcp = gp.RecursiveCirclePacker(start_poly, rad_seq_start=0.18,
    rad_seq_end=0.18, min_allowed_rad=2, n_rads=10, )
trcp.run(1)
vertices = MultiPoint([c.centroid for c in trcp.unfilled_circles] + border_pts)
tris = so.triangulate(vertices)
def choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters, n_per_iter=None):
    if valid.sum() > 0:
        p = df[valid].area / df[valid].area.sum()
        if n_per_iter==None:
            n_per_iter = len(df[valid])
        id_choices = np.random.choice(df.loc[valid, 'id'], size=n_per_iter, p=p, replace=False)
        index = np.flatnonzero(df['id'].isin(id_choices))
        
        
        if n_iters == 0:
            return df
        elif n_iters > 0:
            df = subdivide_rows(df, index, distances)
            n_iters -= 1
            valid = (df['generation'] < max_generation) & (df['parent'].isin(id_choices))
            return choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters)
    else:
        return df

ids =[id(tri) for tri in tris]
df = geopandas.GeoDataFrame({
    'geometry': tris,
    'id': ids,
    'distances': [[None]] * len(tris),
    'generation': [0] * len(tris),
    'subdivided': [False] * len(tris),
    'parent': [None] * len(tris),
    },
)
max_generation = 7
n_subdivisions = 200
distances = [0.3, 0.7, 0.3]
valid = (df['generation'] < max_generation) & ~df['subdivided']
df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=1, n_per_iter=None)
for i in range(n_subdivisions):
    valid = (df['generation'] < max_generation) & ~df['subdivided']
    df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=np.random.randint(1,4), n_per_iter=1)
# valid = (df['generation'] < max_generation) & ~df['subdivided']
# df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=3, n_per_iter=2)

layers = []
bottom = df.query('subdivided == False')
for gen, group in bottom.groupby('generation'):
    layer = gp.merge_LineStrings([ls for ls in group.boundary if ls is not None])
    layers.append(layer)

sk = vsketch.Vsketch()
sk.size(paper.page_format_mm)
sk.scale('1mm')
sk.penWidth('0.1mm')
for i, layer in enumerate(layers):
    sk.stroke(i+1)
    sk.geometry(layer)
sk.display()
for i in df['id']:
    # top level
    valid = (df['generation'] < max_generation) & ~df['subdivided']
    df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=1, id_choice=i)
        
    
valid = (df['generation'] < max_generation) & ~df['subdivided']
df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=3)
layers = []
bottom = df.query('subdivided == False')
for gen, group in bottom.groupby('generation'):
    layer = gp.merge_LineStrings([ls for ls in group.boundary if ls is not None])
    diff_layer = layer.intersection(us_poly)
    layers.append(diff_layer)
sk = vsketch.Vsketch()
sk.size(paper.page_format_mm)
sk.scale('1mm')
sk.penWidth('0.1mm')
for i, layer in enumerate(layers):
    sk.stroke(i+1)
    sk.geometry(layer)
sk.display()
tolerance=0.1
sk.vpype(f'splitall linemerge --tolerance {tolerance}mm linemerge --tolerance {tolerance}mm linesort')
sk.save('/mnt/c/code/side/plotter_images/oned_outputs/162_subdivision.svg')<jupyter_output><empty_output><jupyter_text>circle<jupyter_code>class PolygonGrowth(object):
    
    def __init__(self, polygon):
        self.polygons = [polygon]
        self.growth = polygon
        self.growth = Polygon(self.growth.exterior)
        self.obj_func = None
        
    def _repr_svg_(self):
        return self.growth._repr_svg_()
        
    @property
    def lines(self):
        lss = []
        for p in self.polygons:
            b = p.boundary
            if b.type == 'LineString':
                lss.append(b)
            elif b.type == 'MultiLineString':
                lss += list(b)
        return MultiLineString(lss)
        
    def calc_polygon_diff(self, polygon):
        return polygon.difference(self.growth)
        
    def add_polygon_diff(self, polygon):
        polygon_diff = self.calc_polygon_diff(polygon)
        self.polygons.append(polygon_diff)
        self.growth = so.unary_union([self.growth, polygon_diff])
        self.growth = Polygon(self.growth.boundary)
        
    def get_boundary_point(self, boundary_loc=None):
        if boundary_loc is None:
            boundary_loc = np.random.rand()
        return self.growth.boundary.interpolate(boundary_loc, normalized=True)
    
    def get_random_boundary_points(self, n):
        return MultiPoint([self.get_boundary_point() for i in range(n)])
    
    def get_boundary_points(self, boundary_locs):
        return MultiPoint([self.get_boundary_point(b) for b in boundary_locs])
    
    def grow_random_circle_diff(self, rad):
        self.add_polygon_diff(self.get_boundary_point().buffer(rad))
        
    def buffer_growth(self, d):
        self.growth = self.growth.buffer(d)
        self.growth = Polygon(self.growth.exterior)
        
    def filter_points_by_distance(self, points, target_point, descending=True, n_filtered_points=1):
        dists = [target_point.distance(p) for p in points]
        if descending:
            ordered = np.argsort(dists)
        else:
            ordered = np.argsort(-dists)
        return MultiPoint([points[i] for i in ordered[:n_filtered_points]])
    
    def get_LineFactory(self):
        lf = LineFactory()
        for line in self.lines:
            lf.add_line(np.asarray(line.xy))
        return lf
    
    
class TargetPointGrowth(PolygonGrowth):
    
    def grow_circle_diff(self, target_point, rad, n_checks, **kwargs):
        points = self.get_random_boundary_points(n=n_checks)
        fps = self.filter_points_by_distance(points, target_point, **kwargs)
        for fp in fps:
            self.add_polygon_diff(fp.buffer(rad))
            
            
target_point = drawbox.centroid
max_rads = [40, ]
min_rads = [1,]
circles_per_wave = [100, ]
check_ns_per_wave = [ 250, ]
tps = [target_point ]

rads = []
check_ns = []

for max_rad, min_rad, n_circles, check_n in zip(max_rads, min_rads, circles_per_wave, check_ns_per_wave):
    rads.append(np.logspace(np.log10(max_rad), np.log10(min_rad), int(n_circles)))
    check_ns.append(np.repeat(check_n, n_circles))


target_points = []
for tp, n_circles_per_wave in zip(tps, circles_per_wave):
    target_points += [tp] * n_circles_per_wave

rads = np.concatenate(rads)
check_ns = np.concatenate(check_ns)
init_rad = rads[0]
## initialize
start_circle = drawbox.centroid.buffer(init_rad)
main_orb = TargetPointGrowth(start_circle)
for i, rad in enumerate(tqdm(rads)):
    n_checks = check_ns[i]
    target_point = target_points[i]
    try:
        main_orb.grow_circle_diff(target_point=target_point, rad=rad, n_checks=n_checks)
    except:
        pass

main_orb_triangles = so.triangulate(MultiPoint([l.centroid for l in main_orb.lines]), edges=False)
# main_orb_triangles = MultiPolygon([t.buffer((t.bounds[1] - t.bounds[0]) * -0.000 - 0.00 ) for t in main_orb_triangles if t.within(main_orb.growth)])
# # function dis
# main_orb_hatches = []
# for t in main_orb_triangles:
#     h = hatch.hatchbox(t, (t.bounds[1] - t.bounds[0]) * 90, 0.02)
#     if h.length > 0:
#         if h.type == 'MultiLineString':
#             h = merge_MultiLineStrings(hatch.connect_hatchlines(h, 0.025))
#         main_orb_hatches.append(h)
# main_orb_hatches = merge_MultiLineStrings(main_orb_hatches)
tris = main_orb_triangles

ids =[id(tri) for tri in tris]
df = geopandas.GeoDataFrame({
    'geometry': tris,
    'id': ids,
    'distances': [[None]] * len(tris),
    'generation': [0] * len(tris),
    'subdivided': [False] * len(tris),
    'parent': [None] * len(tris),
    },
)
max_generation=7
distances = [0.3, 0.5, 0.3]
n_subdivisions = 340

for i in tqdm(range(n_subdivisions)):
    try:
        valid = (df['generation'] < max_generation) & ~df['subdivided']
        df = choose_among_valid_and_subdivide_recursive(df, valid, distances, n_iters=np.random.randint(1,4), n_per_iter=1)
    except:
        pass
layers = []
for gen, group in df.groupby('generation'):
    layer = gp.merge_Polygons([ls for ls in group.geometry if ls is not None]).buffer(-0.2, cap_style=2, join_style=2).boundary
    layers.append(layer)
layers = []
for gen, group in df.groupby('generation'):
    layer = gp.merge_LineStrings([ls for ls in group.boundary if ls is not None])
    layers.append(layer)
sk = vsketch.Vsketch()
sk.size(paper.page_format_mm)
sk.scale('1mm')
sk.penWidth('0.1mm')
for i, layer in enumerate(layers):
    sk.stroke(i+1)
    sk.geometry(layer)

# tolerance=0.5
# sk.vpype(f'linemerge --tolerance {tolerance}mm linesort')

sk.display()
sk.vpype(f'splitall linemerge --tolerance 0.05mm linemerge --tolerance 0.05mm linemerge --tolerance 0.05mm linesort')
sk.save('/mnt/c/code/side/plotter_images/oned_outputs/166_triangle_subdivision.svg')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.132952776336274, 'fraction_numerical': 0.015153087701089777, 'mean_word_length': 3.7142857142857144, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 12, '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': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '442340', 'license': 'MIT', 'n_tokens_mistral': 3682, 'n_tokens_neox': 3480, 'n_words': 650, 'path': 'scratch/015_triangle_subdivision.ipynb', 'repo_name': 'ANaka/genpen', 'size': '9635'}