import taichi as ti
import math
ti.init(ti.cpu)
Color = ti.types.vector(3, ti.f32)
Point = ti.types.vector(2, ti.i32)
width = 1024
height = 1024
pixels = Color.field(shape=(width, height))
center = Point([width // 2, height // 2])
def BresenhamLine(P0, P1):
dx = ti.abs(P1.x - P0.x)
dy = ti.abs(P1.y - P0.y)
bInterchange = False
signX = 1 if P1.x > P0.x else -1 if P1.x < P0.x else 0
signY = 1 if P1.y > P0.y else -1 if P1.y < P0.y else 0
if dy >= dx:
dx, dy = dy, dx
bInterchange = True
e = -dx
x = P0.x
y = P0.y
color = Color([0.0, 0.0, 0.0])
for i in range(1, int(dx) + 1):
pixels[x, y] = color
if not bInterchange:
x += signX
else:
y += signY
e += 2 * dy
if e >= 0:
if not bInterchange:
y += signY
else:
x += signX
e -= 2 * dx
class Pentagram:
def __init__(self, C, R):
self.C = C
self.R = R
self.P = Point.field(shape=(5))
def ReadPoint(self):
Theta = 2 * math.pi / 5
Alpha = math.pi / 2 - Theta
for i in range(5):
x = self.R * ti.cos(i * Theta + Alpha)
y = self.R * ti.sin(i * Theta + Alpha)
self.P[i] = self.C + Point([x, y])
def Rotate(self, angle):
M = ti.Matrix([
[ti.cos(angle * math.pi / 180), -ti.sin(angle * math.pi / 180)],
[ti.sin(angle * math.pi / 180), ti.cos(angle * math.pi / 180)],
])
for i in range(5):
t = M @ (self.P[i] - self.C) + self.C
self.P[i].x = int(t.x)
self.P[i].y = int(t.y)
def Draw(self):
BresenhamLine(self.P[0], self.P[2])
BresenhamLine(self.P[1], self.P[3])
BresenhamLine(self.P[2], self.P[4])
BresenhamLine(self.P[3], self.P[0])
BresenhamLine(self.P[4], self.P[1])
C = Point([0, -200]) + center
R = 150
pentagram = Pentagram(C, R)
pentagram.ReadPoint()
gui = ti.GUI("15", (width, height))
while gui.running:
pixels.fill(Color([1.0, 1.0, 1.0]))
P0 = Point([-100, 0]) + center
P1 = Point([100, 0]) + center
BresenhamLine(P0, P1)
P3 = Point([0, 0]) + center
BresenhamLine(P3, C)
pentagram.Rotate(5.0)
pentagram.Draw()
gui.set_image(pixels)
gui.show()
其中,
def Rotate(self, angle):
M = ti.Matrix([
[ti.cos(angle * math.pi / 180), -ti.sin(angle * math.pi / 180)],
[ti.sin(angle * math.pi / 180), ti.cos(angle * math.pi / 180)],
])
for i in range(5):
t = M @ (self.P[i] - self.C) + self.C
self.P[i].x = int(t.x)
self.P[i].y = int(t.y)
给P不能直接赋值,错误信息:
(taichi) ➜ KLD-40 git:(master) ✗ /opt/miniconda3/envs/taichi/bin/python /Users/jiajiewu/Projects/KLD-40/算法15:二维几何变换算法/main.py
[Taichi] version 0.8.11, llvm 10.0.0, commit 9d0973e5, osx, python 3.9.7
[Taichi] Starting on arch=x64
Traceback (most recent call last):
File "/Users/jiajiewu/Projects/KLD-40/算法15:二维几何变换算法/main.py", line 88, in <module>
pentagram.Rotate(5.0)
File "/Users/jiajiewu/Projects/KLD-40/算法15:二维几何变换算法/main.py", line 66, in Rotate
self.P[i] = t
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/util.py", line 224, in wrapped
return func(*args, **kwargs)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/matrix.py", line 1244, in __setitem__
self[key].set_entries(value)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/util.py", line 224, in wrapped
return func(*args, **kwargs)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/matrix.py", line 393, in set_entries
self[i, j] = value[i][j]
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/util.py", line 224, in wrapped
return func(*args, **kwargs)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/matrix.py", line 374, in __setitem__
self.set_entry(i, j, item)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/matrix.py", line 254, in set_entry
self.entries[idx].accessor.setter(e, *self.entries[idx].key)
File "/opt/miniconda3/envs/taichi/lib/python3.9/site-packages/taichi/lang/field.py", line 307, in setter
snode.write_int(key, value)
TypeError: write_int(): incompatible function arguments. The following argument types are supported:
1. (self: taichi._lib.core.taichi_core.SNode, arg0: List[int], arg1: int) -> None
Invoked with: <taichi._lib.core.taichi_core.SNode object at 0x7fc973e935f0>, (0, 0, 0, 0, 0, 0, 0, 0), 649.4504829626355
我感觉是类型问题,所以重新cast,再写上去。就ok了。
有个疑问,我把Point的定义改为ti.f32也是不可以,为什么呢?