Home > OS >  Simultaneously iterating through sequences of coordinate values, drawing lines between pairs of them
Simultaneously iterating through sequences of coordinate values, drawing lines between pairs of them

Time:10-22

In Python 3.10, I'm using Turtle graphics to write a program that currently only draws a random amount of polygonal shapes (2-5) with a random amount of points/sides (3-8) that appear on the screen in random places. To complete the program, I want it to be able to draw connecting lines from the points of the first/preceding polygon created to the points of the next/succeeding polygon, kind of like joints on a worm-like body of polygons.

So far, I have a list, grouped_joints, of lists of tuples, which holds the points (or joints) for every polygon in the order both it and its points/sides were drawn. The list would look like this if a triangle succeeded by a heptagon was drawn (the first point of the first polygon drawn always starts at 0.00, 0.00/the middle of the screen):

[[(0.00,0.00), (100.00,0.00), (50.00,-86.60)], [(112.00,151.00), (12.86,137.91), (-59.19,207.25), (-49.89,306.82), (33.75,361.63), (128.75,330.41), (163.58,236.67)]].

So, the first three points are the triangle's, the next are the heptagon's. This is then taken by a connect_joints function that I'm not sure what to do with.

How would I go about taking the contents of grouped_joints and drawing a line from, in this case, (0.00,0.00) to (112.00,151.00), (100.00,0.00) to (12.86,137.91), (50.00,-86.60) to (-59.19,207.25)?

I understand that I would use a combination of my_pen.goto(), my_pen.down() and my move_pen() function to actually make the lines, but I can't figure out the best logic for moving through a list of lists (of varying sizes) of tuples in such a way as to take the sequence of the coordinates in each sub-list and logically pair them within a looping structure... I haven't had the time to try to even begin to figure out how to do this recursively...

For now, I don't care that not every point is connected up in some orderly way. Until I get a better grasp on the problem, I just want to be able to connect each polygon by the most immediate number of lines. All 3 points of a triangle to 3 points of a heptagon is ugly, but fine with me. Same for the other way around, if the heptagon were to have been drawn before the triangle, it's fine if it's 3 of the 7 points to all 3 points of the triangle.

Would it be easier if I used a dictionary to map each list of points to a key value and looped that way? My apologies for being so helpless, I just started working in python...

TLDR; [any strong text]

Below is the whole working program (76 lines) without my previous attempts at making connect joints work. If you run it, you'll be able to see how the polygons are drawn. Click to exit.

Thanks a lot if you've the time to take a look at this.

import turtle
import random
from itertools import islice

WIN_TITLE = "Summoning Wonderful Polygonal Creature..."
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BLACK = 1, 0, 0
WHITE = 0, 0, 0


def quick_setup():
    new_screen = turtle.Screen()
    new_screen.bgcolor(WHITE)
    new_screen.title(WIN_TITLE)
    new_screen.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
    new_pen = turtle.Turtle()
    return new_screen, new_pen


def move_pen(x=random.randint(-350, 350), y=random.randint(-300, 300)):
    my_pen.goto(x, y)


def rotate_pen():
    my_pen.right(random.random()*360)


def randomize_pen_color():
    random_rgb_values = (random.random(), random.random(), random.random())
    my_pen.color(random_rgb_values)


def draw_polygon(pen, length=100):
    polygon_count = random.randint(2, 5)
    all_side_counts = []
    body_joints = []
    for polygon in range(polygon_count):
        sides = random.randint(3, 8)
        all_side_counts.append(sides)
        exterior_angle = 360.0/sides
        pen.begin_fill()
        for side in range(sides):
            randomize_pen_color()
            pen.down()
            body_joints.append(pen.position())
            pen.forward(length)
            pen.right(exterior_angle)
            pen.up()
        pen.end_fill()
        rotate_pen()
        move_pen()
    return body_joints, all_side_counts


def group_joints(body_joints, all_side_counts):
    joint_slices = iter(body_joints)

    grouped_joints = [list(islice(joint_slices, each_polygon))
                      for each_polygon in all_side_counts]
    return grouped_joints


def connect_joints(grouped_joints):
    print(grouped_joints[0][0])  # How to connect in a looping structure
    print(grouped_joints[1][0])  # to this, and so on...
    print(grouped_joints)


if __name__ == "__main__":
    screen, my_pen = quick_setup()
    my_pen.speed(0)
    body_joints, all_side_counts = draw_polygon(my_pen)
    grouped_joints = group_joints(body_joints, all_side_counts)
    connect_joints(grouped_joints)
    screen.exitonclick()

CodePudding user response:

I am not positive that this is what you mean, but you can try this.

this iterates through the shapes 2 at a time and collects one point from each shape and connects them.

from itertools import pairwise

def connect_joints(grouped_joints):
    for shape1, shape2 in pairwise(grouped_joints):
        for point1, point2 in zip(shape1, shape2):
            (x1,y1), (x2,y2) = point1, point2
            my_pen.penup()
            my_pen.goto(x1,y1)
            my_pen.pendown()
            my_pen.goto(x2,y2)
  • Related