【问题标题】:How to create an image of a triangle with sides and angles如何创建具有边和角的三角形图像
【发布时间】:2023-03-08 04:02:01
【问题描述】:

正如问题所说,我如何创建一个三角形的图像文件,其中输入了边和角度。

我目前使用的解决方案是使用海龟库

forward(s1)
left(180-c)
forward(s2)
left(180-a)
forward(s3)
ts = turtle.getcanvas()
ts.postscript(file="file.ps")

现在这可以工作了,但它会在 ps 文件中输出图像。由于我希望它以图像形式(如 png/jpg/pil 图像),我需要将其转换为它。所以我发现这样做你可以使用

img = Image.open("file.ps")
img.save("file.png")

但这表示它“无法在路径上找到 Ghostscript” 但由于我无法在我的设备上安装 ghostscript(由于原因),我无法将其转换为图像格式。 所以我的问题是,是否有任何库或任何方法可以仅使用边和角度来创建三角形的图像文件。 不知道如何在 PIL 中做到这一点,因为我需要顶点的坐标,而且我不知道如何获取顶点的坐标。 Turtle 的另一个问题是它创建了一个新窗口来制作图像。所以最好是,我希望图像创建在后台发生。有什么办法吗?

编辑:我目前用来制作文件的代码:

def trianglesss(s1,s2,s3):
    a = s1
    b = s2
    c = s3
    a1 = round(math.degrees(math.acos(((b**2)+(c**2)-(a**2))/(2*b*c))))
    b1 = round(math.degrees(math.acos(((c**2)+(a**2)-(b**2))/(2*a*c))))
    c1 = round(math.degrees(math.acos(((b**2)+(a**2)-(c**2))/(2*a*b))))
    turtle.tracer(0,0)
    turtle.pendown()
    turtle.speed('fastest')
    hideturtle()
    forward(s1)
    left(180-c1)
    forward(s2)
    left(180-a1)
    forward(s3)
    turtle.update()
    ts = turtle.getcanvas()
    ts.postscript(file="file.eps")
    bye()
    trisssimg = Image.open("file.eps")
    trisssimg.save("Trisss.jpg")
trianglesss(20,20,20)
#Calculating angles using the formula from:
#https://www.mathsisfun.com/algebra/trig-solving-sss-triangles.html

【问题讨论】:

  • 请提供更完整的海龟图形绘制代码。
  • 好的,差不多了。

标签: python image python-imaging-library


【解决方案1】:

您可以使用 Image 和 ImageDraw 在图像上画线。 在这里,按照乌龟概念的一部分给出画线的命令。

from math import cos, sin, pi, ceil
from PIL import Image, ImageDraw

def draw(commands, filename=None, size=None, show=True):

    x0, y0 = 0, 0
    direction = 0
    line_width, line_color = 1, 'black'
    pen_down = False
    points = []

    for command, value in commands:
        cmd = command.strip().lower()
        if cmd == "color":
            line_color = value
        elif cmd == "width":
            line_width = value
        elif cmd in ("forward", "fd", "backward", "bk"):
            distance = value
            radian = direction/180*pi if cmd in ("forward", "fd") else (direction+180)/180*pi
            x1, y1 = x0 + distance * cos(radian), y0 + distance * sin(radian)
            if pen_down:
                points.append([(x0, y0), (x1, y1), line_color, line_width])
            x0, y0 = x1, y1
        elif cmd == "left":
            direction -= value
        elif cmd == "right":
            direction += value
        elif cmd in ("penup", "pu"):
            pen_down = False
        elif cmd in ("pendown", "pd"):
            pen_down = True

    xs, ys = [], []
    for point1, point2, color, width in points:
        xs += [point1[0], point2[0]]
        ys += [point1[1], point2[1]]
    x_min, x_max, y_min, y_max = min(xs), max(xs), min(ys), max(ys)
    w, h = ceil(x_max - x_min + 1), ceil(y_max - y_min + 1)

    width, height = size if size else (w, h)
    dx, dy = (width - w)/2 - x_min, (height - h)/2 - y_min
    im = Image.new(mode="RGBA", size=(width, height), color=(0, 0, 0, 0))
    draw = ImageDraw.Draw(im, mode="RGBA")

    for point1, point2, line_color, line_width in points:
        p1, p2 = (point1[0]+dx, point1[1]+dy), (point2[0]+dx, point2[1]+dy)
        draw.line([p1, p2], fill=line_color, width=line_width)
    if filename:
        im.save(filename)
    if show:
        im.show()

commands = [("PenDown", None), ("Width", 5), ("Color", "blue"),
    ("FD", 100), ("Left", 120), ("FD", 100), ("left", 120), ("FD", 100)]

draw(commands, "Triangle.png", (200, 200))

【讨论】:

    【解决方案2】:

    由于 turtle 模块基于 tkinter,您可以使用 PIL 来执行类似以下操作。

    import math
    from PIL import ImageGrab
    import tkinter as tk
    import tkinter.messagebox as tkMessageBox
    from tkinter.constants import *
    import turtle
    
    WIDTH, HEIGHT = 500, 400
    IMG_FILENAME = 'turtlescreen.png'  # Extension determines file format.
    
    def trianglesss(t, s1, s2, s3):
        a = s1
        b = s2
        c = s3
        a1 = round(math.degrees(math.acos(((b**2)+(c**2)-(a**2)) / (2*b*c))))
        b1 = round(math.degrees(math.acos(((c**2)+(a**2)-(b**2)) / (2*a*c))))
        c1 = round(math.degrees(math.acos(((b**2)+(a**2)-(c**2)) / (2*a*b))))
        t.pendown()
        t.forward(s1)
        t.left(180-c1)
        t.forward(s2)
        t.left(180-a1)
        t.forward(s3)
    
    def draw_stuff(canvas):
        screen = turtle.TurtleScreen(canvas)
        t = turtle.RawTurtle(screen.getcanvas())
        t.speed(0)  # Fastest.
        t.pencolor('black')
        t.hideturtle()
        trianglesss(t, 200, 200, 200)
    
    def image_grab(root, widget):
        x = root.winfo_rootx() + widget.winfo_x()
        y = root.winfo_rooty() + widget.winfo_y()
        x1 = x + widget.winfo_width()
        y1 = y + widget.winfo_height()
        return ImageGrab.grab().crop((x, y, x1, y1))
    
    def save_file(root, canvas, filename):
        """ Convert the Canvas widget into an image file. """
        # Get image of Canvas and save it to a file.
        img = image_grab(root, canvas)
        img.save(IMG_FILENAME)  # Save image file.
    
        tkMessageBox.showinfo("Info", "Image saved as %r" % filename, parent=root)
    
    
    # Main
    root = tk.Tk()
    canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT,
                       borderwidth=0, highlightthickness=0)
    canvas.pack()
    
    btn_frame = tk.Frame(root)
    btn_frame.pack()
    btn1 = tk.Button(btn_frame, text='Draw', command=lambda: draw_stuff(canvas))
    btn1.pack(side=LEFT)
    btn2 = tk.Button(btn_frame, text='Save',
                     command=lambda: save_file(root, canvas, IMG_FILENAME))
    btn2.pack(side=LEFT)
    btn3 = tk.Button(btn_frame, text='Quit', command=root.quit)
    btn3.pack(side=LEFT)
    
    root.mainloop()
    

    运行截图:

    【讨论】:

    • 谢谢,它有效。我还删除了用于绘图和保存的按钮,只在主程序中调用绘图和保存功能,因为我希望这是自动化的。你能告诉如何在绘图和保存后执行退出命令吗?由于按钮有效,但我希望它在绘制和保存后自动退出。再次感谢您的帮助。
    • 另外,是否可以在后台进行保存工作和三角形的创建?谢谢
    • 您可以致电root.quit() 终止mainloop()。我认为您不能在背景中创建三角形,尽管我不完全确定您的意思。这是通过对turtle 制作的绘图进行截图来实现的,因此屏幕必须是可见的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    相关资源
    最近更新 更多