首页 > 编程问答 >如何增加五边形不规则四面体的深度?

如何增加五边形不规则四面体的深度?

时间:2024-07-21 16:00:55浏览次数:15  
标签:python shapes python-turtle

我只有一点使用海龟的经验。

形状无意中看起来像一种视错觉,这不是我想要的效果。我不知道最好的方法是什么。我想用阴影添加一些深度,但我不知道这是否可能。任何建议将不胜感激。

import turtle
import math

# Setup 
screen = turtle.Screen()
screen.bgcolor("light blue")  # Set background
screen.title("Spinning Diamond")
t = turtle.Turtle()
t.speed(0)
t.hideturtle()

# vertices 
vertices = [
    [0, 0, 150],  # Top vertex
    [math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, 50],
    [math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, 50],
    [math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, 50],
    [math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, 50],
    [math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, 50],
    [math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, -50],
    [math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, -50],
    [math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, -50],
    [math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, -50],
    [math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, -50],
    [0, 0, -150]  # Bottom vertex
]

faces = [
    [0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1],
    [6, 7, 11], [7, 8, 11], [8, 9, 11], [9, 10, 11], [10, 6, 11],
    [1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 5, 10, 9], [5, 1, 6, 10]
]

# Define colors 
colors = [
    "red", "green", "blue", "yellow", "cyan",
    "magenta", "orange", "purple", "lime", "pink",
    "brown", "gray", "violet", "navy", "gold"
]

# Rotate around X-axis
def rotateX(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    y = point[1] * cosA - point[2] * sinA
    z = point[1] * sinA + point[2] * cosA
    return [point[0], y, z]

# Rotate around Y-axis
def rotateY(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    x = point[0] * cosA + point[2] * sinA
    z = -point[0] * sinA + point[2] * cosA
    return [x, point[1], z]

# Rotate around Z-axis
def rotateZ(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    x = point[0] * cosA - point[1] * sinA
    y = point[0] * sinA + point[1] * cosA
    return [x, y, point[2]]

def project(point):
    distance = 300
    factor = distance / (distance - point[2])
    x = point[0] * factor
    y = point[1] * factor
    return [x, y]

# Draw Shape
def draw_polyhedron():
    t.clear()
    # Rotation
    rotated_vertices = [rotateX(rotateY(rotateZ(v, angleZ), angleY), angleX) for v in vertices]
    projected_vertices = [project(v) for v in rotated_vertices]

    # Calculate the avg Z value 
    face_depths = []
    for i, face in enumerate(faces):
        z_sum = sum(rotated_vertices[vertex][2] for vertex in face)
        face_depths.append((z_sum / len(face), i))

    # Sort depth
    face_depths.sort(reverse=True)

    # Draw faces 
    for depth, i in face_depths:
        face = faces[i]
        t.penup()
        t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
        t.pendown()
        t.begin_fill()
        t.color(colors[i % len(colors)])
        for vertex in face:
            t.goto(projected_vertices[vertex][0], projected_vertices[vertex][1])
        t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
        t.end_fill()

    screen.update()

# rotation angles
angleX = 0
angleY = 0
angleZ = 0

# Animation loop
def animate():
    global angleX, angleY, angleZ
    angleX += 2
    angleY += 3
    angleZ += 1
    draw_polyhedron()
    screen.ontimer(animate, 50)

# Initialize animation
screen.tracer(0)
animate()
screen.mainloop()

你可以通过在代码中实现简单的光照模型来为五角星形反棱镜添加深度。下面是如何操作:

  1. 了解光照模型: 我们将使用一种名为环境光和漫反射照明的基本光照模型。这涉及到根据表面朝向假想光源的方向来计算表面的亮度。
  2. 计算表面法线: 对于每个面,我们需要计算表面法线向量。该向量垂直于表面,指示表面的“朝向”。
  3. 计算漫反射光: 我们将使用光向量和表面法线之间的点积来计算每个面的光照量。点积表示两个向量之间的对齐程度。如果法线直接指向光线,则表面会更亮。
  4. 应用阴影: 为了简单起见,我们将假设一个恒定的环境光照水平,并且不考虑阴影。

下面是更新后的代码:

import turtle
import math

# Setup
screen = turtle.Screen()
screen.bgcolor("light blue")
screen.title("Spinning Diamond")
t = turtle.Turtle()
t.speed(0)
t.hideturtle()

# vertices
vertices = [
    [0, 0, 150],
    [math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, 50],
    [math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, 50],
    [math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, 50],
    [math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, 50],
    [math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, 50],
    [math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, -50],
    [math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, -50],
    [math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, -50],
    [math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, -50],
    [math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, -50],
    [0, 0, -150]
]

faces = [
    [0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1],
    [6, 7, 11], [7, 8, 11], [8, 9, 11], [9, 10, 11], [10, 6, 11],
    [1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 5, 10, 9], [5, 1, 6, 10]
]

# 定义颜色
colors = [
    "red", "green", "blue", "yellow", "cyan",
    "magenta", "orange", "purple", "lime", "pink",
    "brown", "gray", "violet", "navy", "gold"
]

# 光照方向
light_dir = [1, 1, 1]  # 假设光源在该方向上

# 旋转矩阵
def rotateX(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    y = point[1] * cosA - point[2] * sinA
    z = point[1] * sinA + point[2] * cosA
    return [point[0], y, z]

def rotateY(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    x = point[0] * cosA + point[2] * sinA
    z = -point[0] * sinA + point[2] * cosA
    return [x, point[1], z]

def rotateZ(point, angle):
    rad = math.radians(angle)
    cosA = math.cos(rad)
    sinA = math.sin(rad)
    x = point[0] * cosA - point[1] * sinA
    y = point[0] * sinA + point[1] * cosA
    return [x, y, point[2]]

# 投影函数
def project(point):
    distance = 300
    factor = distance / (distance - point[2])
    x = point[0] * factor
    y = point[1] * factor
    return [x, y]

# 计算法向量
def calculate_normal(face, vertices):
    p1 = vertices[face[0]]
    p2 = vertices[face[1]]
    p3 = vertices[face[2]]
    v1 = [p2[i] - p1[i] for i in range(3)]
    v2 = [p3[i] - p1[i] for i in range(3)]
    normal = [
        v1[1] * v2[2] - v1[2] * v2[1],
        v1[2] * v2[0] - v1[0] * v2[2],
        v1[0] * v2[1] - v1[1] * v2[0]
    ]
    return normalize(normal)

# 归一化向量
def normalize(v):
    norm = math.sqrt(sum(i * i for i in v))
    return [i / norm for i in v]

# 计算点积
def dot_product(v1, v2):
    return sum(v1[i] * v2[i] for i in range(3))

# 绘制形状
def draw_polyhedron():
    t.clear()
    # 旋转
    rotated_vertices = [rotateX(rotateY(rotateZ(v, angleZ), angleY), angleX) for v in vertices]
    projected_vertices = [project(v) for v in rotated_vertices]

    # 计算平均 Z 值
    face_depths = []
    for i, face in enumerate(faces):
        z_sum = sum(rotated_vertices[vertex][2] for vertex in face)
        face_depths.append((z_sum / len(face), i))

    # 按深度排序
    face_depths.sort(reverse=True)

    # 绘制面
    for depth, i in face_depths:
        face = faces[i]
        normal = calculate_normal(face, rotated_vertices)  # 计算法向量
        light_intensity = max(0, dot_product(normal, light_dir))  # 计算光照强度
        t.penup()
        t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
        t.pendown()
        t.begin_fill()
        base_color = colors[i % len(colors)]
        r, g, b = turtle.colormode(255)[base_color]
        shaded_color = (int(r * light_intensity), int(g * light_intensity), int(b * light_intensity))
        t.color(shaded_color)
        for vertex in face:
            t.goto(projected_vertices[vertex][0], projected_vertices[vertex][1])
        t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
        t.end_fill()

    screen.update()

# 旋转角度
angleX = 0
angleY = 0
angleZ = 0

# 动画循环
def animate():
    global angleX, angleY, angleZ
    angleX += 2
    angleY += 3
    angleZ += 1
    draw_polyhedron()
    screen.ontimer(animate, 50)

# 初始化动画
screen.tracer(0)
animate()
screen.mainloop()

在这个改进版本中,我们添加了计算法向量和基于光照方向和表面法线之间角度的漫反射分量的函数。这将创建更逼真的 3D 效果,从而增强深度。

标签:python,shapes,python-turtle
From: 78774647

相关文章

  • 用Python实现Cmpp协议的教程
    引言&协议概述(CMPP)是中国移动为实现短信业务而制定的一种通信协议,全称叫做ChinaMobilePointtoPoint,用于在客户端(SP,ServiceProvider)和中国移动短信网关之间传输短消息,有时也叫做移动梦网短信业务。CMPP3.0是该协议的第三个版本,相比于前两个版本,它增加了对长短信的支持、优......
  • Python 请求库无法成功完成 POST(Nanotec 电机控制器)
    我有一个运行RESTWeb服务的电机控制器,我想使用Python对其进行控制。我能够使用Python请求库成功执行GET请求。但是我无法执行POST请求。它给了我以下错误:requests.exceptions.ConnectionError:('Connectionaborted.',RemoteDisconnected('Remoteendclosed......
  • 为什么 exitonclick 在我的 Python Turtle 图形程序中不起作用?
    我正在开发一个PythonTurtle图形程序,我正在尝试使用exitonclick方法在单击窗口时关闭窗口。但是,它似乎不起作用。fromturtleimportTurtle,Screenrem=Turtle()screen=Screen()rem.fd(70)defclear():screen.clearscreen()screen.listen()s......
  • 服务器和本地主机上对相同请求(curl、python aiohttp)的不同响应
    我有一个用Python编写的解析器(aiohttp、bs4)。解析器的功能之一是通过链接访问文件(例如:https://modsfire.com/d/Mwv01aESgj73zx7)。importaiohttpimportyarlimportasynciofrompprintimportpprintMODSFIRE_URL="https://modsfire.com/"COOKIES={......
  • python 中两体问题的集成
    我正在尝试使用python和pygame创建一个二体Sim作为更大项目目标的第一阶段,以在屏幕上显示对象。我目前的主要问题是,轨道卫星在目标行星周围倾斜时它应该处于稳定的320公里圆形轨道上。我为四种不同的集成制作了四种不同的功能。Euler、Leapfrog、Verlet和RK4。......
  • 如何保护Python代码不被用户读取?
    我正在用Python开发一个软件,该软件将分发给我雇主的客户。我的雇主希望使用有时间限制的许可证文件来限制软件的使用。如果我们分发.py文件甚至.pyc文件,则很容易(反编译并)删除检查另一个方面是我的雇主不希望我们的客户读取代码,担心代码可能被窃取或......
  • 无法更新 Python MySQL 中的tinyint
    我无法使用以下代码更新我的Tinyint值(valid_state):importmysql.connectormydb=mysql.connector.connect(host="localhost",user="mahdi",passwd="Abcd@1324",database="mycustomers")mycursor=mydb.cursor()sql="UPDATE`......
  • Cython:将 2D 数组从 Python 传递到 C 并检索它
    我正在尝试使用Cython用C语言构建相机驱动程序的包装器。我是Cython的新手(两周前开始)。经过一番努力,我可以成功开发结构体、一维数组的包装器,但现在我陷入了二维数组的困境。相机的CAPI之一采用2D数组指针作为输入,并将捕获的图像分配给它。该函数需要从Python调......
  • 如何使用python将大文件上传到Onedrive
    importrequestsfrommsalimportPublicClientApplicationfromdotenvimportload_dotenvimportos#Loadenvironmentvariablesload_dotenv()#ConfigurationfromenvironmentvariablesCLIENT_ID=os.getenv('CLIENT_ID')#TENANT_IDisnotused......
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的生日派对座位安排(200分) - 三
    ......