¿Controlar la superposición de formas en la tortuga de Python?

2

Estoy escribiendo un programa que toma la entrada del usuario para (1) la cantidad de lados de la forma que se dibujará, (2) qué tan grande dibujarla, (3) cuántos dibujar y (4) cuántos colores usar. Luego, la tortuga espacia muchas de esas formas en un círculo, todos compartiendo un vértice en el centro del círculo.

Lo que me molesta es que si las formas se superponen al final, las últimas formas estarán encima de todo, mientras que me gustaría que estuvieran escondidas detrás de las formas delante de ellas como el resto.

Me las arreglé para determinar que la cantidad de formas que se superponen incorrectamente depende de la cantidad de lados de la forma; para un triángulo, por ejemplo, no hay superposición con 1-6 formas. Con 7-12, una forma se superpone incorrectamente. Con 13-18, dos formas se superponen incorrectamente. Etcétera.

Hasta ahora, he escrito para que considere el primer y último grupo de formas como cosas propias, poly1 y poly2, y para empezar, al menos me gustaría poder decirle que dibuje poly2 detrás de poly1.

Lo principal: ¿es esto posible con la tortuga? Y luego, si es así, ¿cómo puedo hacerlo? (usando 3.5)

Editar: Creo que esto probablemente sea imposible. Todo lo que escucho es que la tortuga solo puede dibujar sobre las formas existentes. Pero también se sugirió que incluyera una captura de pantalla en caso de que agregue claridad; aquí hay una imagen de lo que dibuja la tortuga (cuando se le dice que dibuje 9 triángulos con 3 colores diferentes).

ingrese la descripción de la imagen aquí

Mi objetivo es hacer ese triángulo completo escondido debajo del de las 12 en punto, pero aún sobre el anterior, como se dibujó originalmente.

1
  • Eso es porque turtlepone cada forma encima de la anterior. De alguna manera tendría que volver a dibujar parte de la primera forma para superponer la última forma. (Además: es posible que su publicación no sea completamente clara para todos, podría ayudar si publicara algunas capturas de pantalla) 31 de mayo de 2016 a las 23:00
1

I'm thinking this is probably impossible.

Subestimas el coraje de las tortugas. Aquí está mi ejemplo inicial que muestra el problema asimétrico que desea solucionar:

import math
from itertools import cycle
from turtle import Turtle, Screen

COLORS = cycle(['red', 'green', 'blue', 'yellow'])

def rotate_polygon(polygon, angle):

    theta = math.radians(angle)
    sin, cos = math.sin(theta), math.cos(theta)

    return [(x * cos - y * sin, x * sin + y * cos) for x, y in polygon]

def fill_polygon(turtle, polygon, color):

    turtle.color(color)

    for vertex in polygon:
        turtle.goto(vertex)

        if not turtle.filling():
            turtle.begin_fill()

    turtle.end_fill()

# triangle cursor 5x in size and X translated 50 pixels
polygon = ((100, -28.85), (50, 57.75), (0, -28.85))

screen = Screen()

yertle = Turtle(visible=False)
yertle.penup()

for angle in range(0, 360, 30):
    rotated_polygon = rotate_polygon(polygon, angle)
    color = next(COLORS)
    fill_polygon(yertle, rotated_polygon, color)

screen.exitonclick()

PRODUCCIÓN

ingrese la descripción de la imagen aquí

Realmente queremos que el triángulo amarillo final esté bien metido debajo del rojo inicial, como una escalera de Escher en constante ascenso. Elegí esta ilustración porque tiene múltiples superposiciones, el triángulo amarillo final, en teoría, no solo debería superponerse al rojo, sino tanto al verde como al azul que siguen al rojo. Del mismo modo, el azul y el verde que preceden al amarillo final deben superponerse al rojo. Etc.

ingrese la descripción de la imagen aquí

Mi código anterior es más complejo de lo necesario para dibujar esta ilustración en particular, pero necesita una estructura adicional para admitir la siguiente mejora:

Un enfoque sería calcular la intersección y no dibujar esa parte del triángulo más nuevo. Otro enfoque es dibujar el nuevo triángulo, pero cambiar el color de la intersección del triángulo que debe superponerse. Este último enfoque es lo que implemento a continuación, utilizando una función de Python existente para obtener la intersección a través del algoritmo de recorte de polígonos de Sutherland-Hodgman:

import math
from itertools import cycle
from turtle import Turtle, Screen

COLORS = cycle(['red', 'green', 'blue', 'yellow'])

def clip(subjectPolygon, clipPolygon):

    # obtain this code from:
    # https://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping#Python

    return outputList

def rotate_polygon(polygon, angle):

    theta = math.radians(angle)
    sin, cos = math.sin(theta), math.cos(theta)

    return [(x * cos - y * sin, x * sin + y * cos) for x, y in polygon]

def fill_polygon(turtle, polygon, color):

    turtle.color(color)

    for vertex in polygon:
        turtle.goto(vertex)

        if not turtle.filling():
            turtle.begin_fill()

    turtle.end_fill()

# triangle cursor 5x in size and X translated 50 pixels
polygon = ((100, -28.85), (50, 57.75), (0, -28.85))

screen = Screen()

yertle = Turtle(visible=False)
yertle.speed('slowest')  # slowly so we can see redrawing
yertle.penup()

polygons = []
POLYGON, COLOR = 0, 1

for angle in range(0, 360, 30):
    rotated_polygon = rotate_polygon(polygon, angle)
    color = next(COLORS)
    fill_polygon(yertle, rotated_polygon, color)
    polygons.append((rotated_polygon, color))

    # The -3 here is empirical and really should be calculated, an exercise for the reader
    for forward, backward in enumerate(range(-3, 1 - len(polygons), -1)):
        if polygons[forward] != polygons[backward]:
            try:
                intersection_polygon = clip(rotated_polygon, polygons[forward][POLYGON])
            except (IndexError, ZeroDivisionError):
                break  # because clip() can throw an error when no intersection

            if intersection_polygon:
                fill_polygon(yertle, intersection_polygon, polygons[forward][COLOR])
            else:
                break  # if no intersection, don't look any further
        else:
            break  # avoid testing against polygons clockwise from this one (needs work)

screen.exitonclick()

PRODUCCIÓN

ingrese la descripción de la imagen aquí