【问题标题】:How to Create a Rainbow Triangle Tessellation如何创建彩虹三角形镶嵌
【发布时间】:2019-09-22 12:20:39
【问题描述】:

我正在尝试在 Python 中创建如下所示的三角形镶嵌:

我得到的只是谢尔彭斯基的三角形。我假设它会使用一些相同的代码。

import turtle as t
import math
import colorsys

t.hideturtle()
t.speed(0)
t.tracer(0,0)

h = 0
def draw_tri(x,y,size):
    global h
    t.up()
    t.goto(x,y)
    t.seth(0)
    t.down()
    color = colorsys.hsv_to_rgb(h,1,1)
    h += 0.1
    t.color(color)
    t.left(120)
    t.fd(size)
    t.left(120)
    t.fd(size)
    t.end_fill()

def draw_s(x,y,size,n):
    if n == 0:
        draw_tri(x,y,size)
        return

    draw_s(x,y,size/2,n-1)
    draw_s(x+size/2,y,size/2,n-1)
    draw_s(x+size/4,y+size*math.sqrt(3)/4,size/2,n-1)

draw_s(-300,-250,600,6)
t.update()

【问题讨论】:

  • 你有什么问题?
  • 如何制作三角形镶嵌
  • 如果你看图像,你会看到有三个不同的方向。只需在三个方向上以预先指定的距离绘制直线。

标签: python geometry turtle-graphics tiling


【解决方案1】:

正如@ReblochonMasque 所说,有多种方法可以解决这个问题。这是我想出的使用尽可能少的海龟代码来解决问题的方法:

from turtle import Screen, Turtle

TRIANGLE_SIDE = 60
TRIANGLE_HEIGHT = TRIANGLE_SIDE * 3 ** 0.5 / 2
CURSOR_SIZE = 20

screen = Screen()

width = TRIANGLE_SIDE * (screen.window_width() // TRIANGLE_SIDE)
height = TRIANGLE_HEIGHT * (screen.window_height() // TRIANGLE_HEIGHT)

diagonal = width + height

turtle = Turtle('square', visible=False)
turtle.shapesize(diagonal / CURSOR_SIZE, 1 / CURSOR_SIZE)
turtle.penup()
turtle.sety(height/2)
turtle.setheading(270)

turtle = turtle.clone()
turtle.setx(width/2)
turtle.setheading(210)

turtle = turtle.clone()
turtle.setx(-width/2)
turtle.setheading(330)

for _ in range(int(diagonal / TRIANGLE_HEIGHT)):
    for turtle in screen.turtles():
        turtle.forward(TRIANGLE_HEIGHT)
        turtle.stamp()

screen.exitonclick()

它可能会使用优化,但它可以完成工作。而且观看起来很有趣...

【讨论】:

    【解决方案2】:

    有多种方法;以下示例在引导turtle 在画布上绘制它们之前生成所有线段。

    import turtle as t
    import math
    
    
    WIDTH, HEIGHT = 800, 800
    OFFSET = -WIDTH // 2, -HEIGHT // 2
    
    
    class Point:
        """convenience for point arithmetic
        """
        def __init__(self, x=0, y=0):
            self.x, self.y = x, y
        def __add__(self, other):
            return Point(self.x + other.x, self.y + other.y)
        def __iter__(self):
            yield self.x
            yield self.y
    
    
    def get_line_segments(side_length=50):
        """calculates the coordinates of all vertices
           organizes them by line segment
           stores the segments in a container and returns it
        """
        triangle_height = int(side_length * math.sqrt(3) / 2)
        half_side = side_length // 2
        p0 = Point(0, 0)
        p1 = Point(0, side_length)
        p2 = Point(triangle_height, half_side)
    
        segments = []
    
        for idx, x in enumerate(range(-triangle_height, WIDTH+1, triangle_height)):
            for y in range(-side_length, HEIGHT+1, side_length):
                y += half_side * (idx%2 + 1)
                offset = Point(x, y)
                pa, pb, pc = p0 + offset, p1 + offset,p2 + offset
                segments += [[pa, pb], [pb, pc], [pc, pa]]
    
        return segments
    
    
    def draw_segment(segment):
        p0, p1 = segment
        p0, p1 = p0 + offset, p1 + offset
        t.penup()
        t.goto(p0)
        t.pendown()
        t.goto(p1)
    
    
    def draw_tiling():
        for segment in get_line_segments():
            draw_segment(segment)
    
    
    t.hideturtle()
    t.speed(0)
    t.tracer(0,0)
    offset = Point(*OFFSET)
    
    draw_tiling()
    
    t.update()
    t.exitonclick()
    

    如果您想查看平铺的跟踪方式,可以替换以下行:

    # t.hideturtle()
    t.speed(1)
    # t.tracer(0, 0)
    

    并用鼠标放大画布屏幕以查看平铺的边界(我使其与窗口的标准大小重叠)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 2016-10-05
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多