赞
踩
'''本程序由 @自旋子 (qq:3431773550)独立开发,所有内容秉承开源的精神完全开源
本人技术不湛,还望各路高手明确指点或者帮忙修改
接下来是使用教程:
import pygamefrom PPy3D import ppy3d
screen=pygame.display.set_mode([1000,600]) #这里先创建了pygame幕布
run=ppy3d.py3D(screen,[1000,600]) #实例化ppy3d
run.Sight3D([-90,-90,130]) #嗯设置点坐标。run.Spot3D('nn',[100,100,100],(0,255,0),True) #输入点的名称,坐标,颜色,布尔值
run.Draw(90,90,90,[0,0,0]) #前三位是视野宽度,相机旋转角,后一位是相机坐标
'''
import pygame
import math
import time
from multiprocessing import Process, Pipe
class py3D():
def __init__(self,screen,size_2D):
self.WHITE = (255, 255, 255) #定义白色幕布
self.BLACK = (0,0,0) #定义黑色幕布
self.size_3D=[500,500,500] #顶你三体空间尺寸
self.size_2D=size_2D #接收用户提供的2d屏幕大小
self.Point={} #创建全局字典去储存乱序下的点所有信息,包括点的name信息和Date信息,具体date信息请见Spot3D,Text,Line函数
self.Point_list=[]#创建点坐标缓存,包含点 名称 和 坐标信息,每一个点用一个列表点内有一个字符串,即为名称,和一个列表为点坐标信息
#这里由于大量的点可能占用大量的储存资源后期将考虑使用字典代替,由列表表示的点坐标信息后期也考虑使用元组代替
#如果您想更改的话,我们十分支持,万分感谢
self.Clickc=[] #此为后期更新所留的预订设置
self.Cache=[] #此为后期更新所留的预订设置
self.sightSpot=[0,0,0] #相机坐标,这里为初始默认坐标,如果用户没有输入相机坐标,这就为当前相机坐标
pygame.init() #对pygame进行实例化
self.screen = screen
pygame.display.set_caption("3D CL")
self.font = pygame.font.Font(None, 36) # 使用默认字体,大小为36
def model(self,spot): #终于处理不规则的self.Point_list,你保证它能被堆排算法排序
list=[]
for spot1 in spot:
spot2=spot1[0]
list.append(math.sqrt(spot2[0]**2+spot2[1]**2+spot2[2]**2))
return list
#>>>>>此处是堆排算法,为保证性能,有条件的可以使用gpu加速,具体方法可自行修改
def bubble_sort(self,numbers):
n = len(numbers)
num=self.model(numbers)
for i in range(n):
for j in range(0, n-i-1):
if num[j] < num[j+1]:
numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
num[j], num[j+1] = num[j+1], num[j]
return numbers
def quick_sort(self, array_s):
array = self.model(array_s)
n = len(array)
# 创建最小堆
for i in range(n // 2 - 1, -1, -1):
self.heapify(array, array_s, i, n)
# 逐个取出堆顶元素,放到末尾,并调整堆
for i in range(n - 1, 0, -1):
array[i], array[0] = array[0], array[i]
array_s[i], array_s[0] = array_s[0], array_s[i]
self.heapify(array, array_s, 0, i)
#return list(reversed(array_s))
return array_s
def heapify(self, array, array_s, i, n):
smallest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and array[l] < array[smallest]:
smallest = l
if r < n and array[r] < array[smallest]:
smallest = r
if smallest != i:
array[i], array[smallest] = array[smallest], array[i]
array_s[i], array_s[smallest] = array_s[smallest], array_s[i]
self.heapify(array, array_s, smallest, n)
#<<<<<<<堆排到此结束。
#此处为啊用户能够使用的系统提供的方法创建模型,模型包括点、文本、线,如有需要可自行添加
#下方我请对Spot3D做出明确解释
def Spot3D(self,name,spot,color,bool_): #信息包括点的名称、坐标、颜色、布尔值,其中,布尔值用于后期更新
pass
Date=[spot,'Spot',color,bool_] #在date数据中所拥有的点信息
self.Point[name]=Date #在此字典中仅包含Date列表
list=[spot,name] #List列表包含点的坐标和名称,其中坐标用于堆排
self.Point_list.append(list)#[[[],''] , [[],'']] self.Point:list结构。
def Text(self,text,name,spot,color):
Date=[spot,'Text',color,text]
self.Point[name]=Date
list=[spot,name]
self.Point_list.append(list)#[[[],'']]
def Line(self,name,line_list,color):
Date=[line_list,'Line',color]
self.Point[name]=Date
new_list=[line_list[1][0] - line_list[0][0],line_list[1][1] - line_list[0][1],line_list[1][2] - line_list[0][2]]
#New list的作用是计算这条线的中点坐标,以中点坐标抽象为标准坐标
list=[new_list,name]
self.Point_list.append(list)
pass
def Sight3D(self,spot): #此函数用于修改相机坐标位置,提供方便的API
self.sightSpot=spot
def Draw(self,sightAN,UDangles,LRangles,sxyz): #此函数用于调用这里的大部分函数去做一个总的驱动,去绘制图像
self.screen.fill((self.WHITE))
self.Point_list=self.quick_sort(self.Point_list) #使用堆牌对Point:list进行排序
self.sightSpot=sxyz #此处s xyz可能多于以后将会删除或者删除Sight3D函数。
for Sname1 in self.Point_list: #开始历遍Point_list列表
Sname=Sname1[1] #获得点的名称
Point_list=self.Point[Sname] #利用获得的点的名称,从字典中获得其他数据,这里的Point_list是局部变量
NAME_spot=Point_list[1] #这里具体的数据含义看 line 82,此处因为点名称
CLOCK_spot=Point_list[2] #此处应为点颜色
if NAME_spot=='Spot': #如果本次模型为spot,也即是点
list=self.sight(sightAN,UDangles,LRangles,sxyz,Sname1[0])
pygame.draw.circle(self.screen, CLOCK_spot, (list[0],list[1]), 3) #这里规定了点的一些信息,最后一个三代表点的尺寸,如果你希望自行修改或者你希望用户改变他,自行添加。
pass
elif NAME_spot=='Text':
list=self.sight(sightAN,UDangles,LRangles,sxyz,Sname1[0])
text =self.font.render(Point_list[3]+str((int(list[0]),int(list[1]))), True, CLOCK_spot)
self.screen.blit(text,(list[0],list[1]))
elif NAME_spot=='Line':
list=[]
for i in range(2):
sname=self.Point[Sname][0][i]
list.append(self.sight(sightAN,UDangles,LRangles,sxyz,sname))
pygame.draw.line(self.screen, CLOCK_spot, (list[0][0],list[0][1]), (list[1][0],list[1][1]), 5)
pygame.display.flip()
#此处为坐标转换算法,具体算法已经忘记,可尝试询问人工智能
def sight(self,sightAN,UDangles,LRangles,sxyz,SPOT_list): #这里面包含需要的信息有
#视野宽度,视野上下旋转角,视野左右旋转角,无用信息,点的三维坐标
Sx=self.sightSpot[0]
Sy=self.sightSpot[1]
Sz=self.sightSpot[2]
spot_l=(SPOT_list[1]-Sy)**2+(SPOT_list[0]-Sx)**2
spot_l=math.sqrt(abs(spot_l))*((spot_l>0)-(spot_l<0))
spot_r=(SPOT_list[1]-Sy)**2+(SPOT_list[0]-Sx)**2+SPOT_list[2]-Sz
spot_r=math.sqrt(abs((SPOT_list[1]-Sy)**2+(SPOT_list[0]-Sx)**2+SPOT_list[2]-Sz))*((spot_r>0)-(spot_r<0))
if spot_l!=0:
if abs(Sz-SPOT_list[2])/spot_l<1 and abs(Sx-SPOT_list[0])/spot_l<1 :
S_a=math.degrees(math.asin((Sz-SPOT_list[2])/spot_l))##
S_b=math.degrees(math.asin((Sx-SPOT_list[0])/spot_l))##
S_a_2=90-S_a-UDangles+UDangles//360*360+sightAN#########
S_b_2=90-S_b-LRangles+LRangles//360*360+sightAN
S_a_3=sightAN*2-S_a_2
S_b_3=sightAN*2-S_b_2
Spot_end_x=S_b_3/(2*sightAN)*self.size_2D[0]
Spot_end_y=S_a_3/(2*sightAN)*self.size_2D[1]
list_=[Spot_end_x,Spot_end_y]
return list_
else:
return [0,0] #如果点不在视野中,则返回视野中点坐标为(0,0)
else:
return [0,0] #如果点与相机重合,则返回视野中点坐标为(0,0)
###
pygame.draw.line(self.screen, self.BLACK, (0, 0), (self.size_2D[0],0), 20)
pygame.draw.line(self.screen, self.BLACK, (self.size_2D[0],0), (self.size_2D[0],self.size_2D[1]+10), 20)
pygame.draw.line(self.screen, self.BLACK, (0, 0), (0,self.size_2D[1]), 20)
pygame.draw.line(self.screen, self.BLACK, (0, self.size_2D[1]), (self.size_2D[0],self.size_2D[1]), 10)
#此段代码无用,后期删除或者优化
def fill(self):
self.Point={} #清除所有点信息
self.Point_list=[] #清除已排序好后的点
pygame.display.flip() #清除pygame图像缓存
self.screen.fill((self.WHITE)) #更新幕布
以下有自己写的一些使用案例
import pygame
import math
from PPy3D import ppy3d
screen=pygame.display.set_mode([1000,600])
run=ppy3d.py3D(screen,[1000,600])
run.Sight3D([-90,-90,130])
n2=0
radius=150
num_points=200
'''win=ppy3d.py3D(screen,(1000,500))
win.Sight3D([-90,-90,130])'''
un=100
rf=120
while True:
run.fill()
'''win.fill()
for i in range(100):
win.Spot3D('win1'+str(i),[10+i*2,10,10],(0,255,0),True)
for i in range(10):
win.Spot3D('win2'+str(i),[10,10+i*2,10],(0,255,0),True)
for i in range(10):
win.Spot3D('win3'+str(i),[10,10,10+i*2],(0,255,0),True)'''
n2+=1
run.Spot3D('nn'+str(n2),[250,n2*5,n2*5],(0,255,0),True)
run.Text(str([250,n2*5,n2*5]),'Text',[250,n2*5,n2*5],(0,0,255))
run.Spot3D('point',[100,100,100],(255,255,0),True)
for i in range(num_points):
angle = i * (2 * math.pi / num_points) # 计算角度
x = int(radius * math.cos(angle)) + 100# 根据角度计算 x 坐标
y = int(radius * math.sin(angle)) + 100# 根据角度计算 y 坐标
run.Spot3D('n'+str(n2),[x,100,y],(255,255,0),True)
run.Spot3D('n2'+str(n2),[x,y,100],(255,0,0),True)
run.Draw(90,un,rf,[-90+n2,-90+n2,130+n2])#视野,上下旋转角,左右旋转角
#win.Draw(180,0,0,[-90,-90,130])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。