2023-10-05 Roaming Rectangles
Description
Series of rectangles where one is connected to the next one, of varying colors and sizes.
Images
Plotter Preview
Code
from random import randint, choice
from gcode2dplotterart import Plotter2D
BLACK_LAYER = 'thin_black'
COLOR_LAYERS=['thick_red', 'thick_yellow', 'thick_blue']
plotter = Plotter2D(
title="Roaming Rectangles",
x_min = 0,
x_max = 220,
y_min = -150, # Note - My plotting goes from -150 to 0.
y_max = 0,
feed_rate=10000,
output_directory="./output",
handle_out_of_bounds='Warning' # Some points will be out of bounds for this, that's ok.
)
for layer in COLOR_LAYERS:
plotter.add_layer(layer)
plotter.add_layer(BLACK_LAYER)
# Min movement is 10% of the total width/height
MIN_MOVEMENT_X = round((plotter.x_max - plotter.x_min) * 0.10)
MIN_MOVEMENT_Y = round((plotter.y_max - plotter.y_min) * 0.10)
# Max movement is 20% of the total width/height
MAX_MOVEMENT_X = round((plotter.x_max - plotter.x_min) * 0.20)
MAX_MOVEMENT_Y = round((plotter.y_max - plotter.y_min) * 0.20)
def calculate_next_move(start_point, end_point):
# Don't start the next rectangle where the current rectangle started, don't include (start_point[0], start_point[1])
next_point_start_options = [
(start_point[0], end_point[1]),
(end_point[0], start_point[1]),
(end_point[0], end_point[1]),
]
next_point_start = choice(next_point_start_options)
# Future improvement - Could optimize here so that choice([-1,1]) factors in the previous rectangle and doesn't plot on top.
movement_x = randint(MIN_MOVEMENT_X, MAX_MOVEMENT_X) * choice([-1, 1])
movement_y = randint(MIN_MOVEMENT_Y, MAX_MOVEMENT_Y) * choice([-1, 1])
next_point_end = (next_point_start[0] + movement_x, next_point_start[1] + movement_y)
return [next_point_start, next_point_end]
# Starting rectangle is a rectangle plotted around the center point.
CENTER_POINT = [(plotter.x_max + plotter.x_min) / 2, (plotter.y_max + plotter.y_min) / 2]
start_point = [CENTER_POINT[0] - plotter.width * 0.05, CENTER_POINT[1] - plotter.height * 0.05]
end_point = [CENTER_POINT[0] + (plotter.x_max - plotter.x_min) * 0.05, CENTER_POINT[1] + (plotter.y_max - plotter.y_min) * 0.05 ]
current_layer_index = 0
plotter.layers[COLOR_LAYERS[current_layer_index]].add_rectangle(start_point[0], start_point[1], end_point[0], end_point[1])
plotter.layers[BLACK_LAYER].add_rectangle(start_point[0], start_point[1], end_point[0], end_point[1])
TOTAL_RECTANGLES = 100
current_rectangle_count = 0
while True:
# With 3 colors being plotted, the next rectangle plotted should not be the same color as the previous.
current_layer_index_choices = [index for [index, value] in enumerate(COLOR_LAYERS) if index != current_layer_index]
current_layer_index = choice(current_layer_index_choices)
while True:
# Lazy solution to prevent plotter from going out of bounds
[next_start_point, next_end_point] = calculate_next_move(start_point, end_point)
if plotter.is_point_in_bounds(next_start_point[0], next_start_point[1]) and plotter.is_point_in_bounds(next_end_point[0], next_end_point[1]):
break
plotter.layers[COLOR_LAYERS[current_layer_index]].add_rectangle(next_start_point[0], next_start_point[1], next_end_point[0], next_end_point[1])
plotter.layers[BLACK_LAYER].add_rectangle(next_start_point[0], next_start_point[1], next_end_point[0], next_end_point[1])
start_point = next_start_point
end_point = next_end_point
current_rectangle_count += 1
if current_rectangle_count == TOTAL_RECTANGLES:
break
plotter.preview()
plotter.save()