# 问一个代码问题。

``````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))

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)
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)
``````

``````(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
``````

``````    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)
self.P[i] = t
``````

Hi @virgilwjj , 你期待的处理方法是可以的。只是需要注意两点：

1. 在class中使用Taichi相关的功能，需要在class之前添加修饰器 `@ti.data_oriented`
2. 在Taichi的function之前添加对应的修饰器，`ti.kernel` 或者 `ti.func`，需要注意`ti.kernel`中的参数是需要指定数据类型的。

``````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

@ti.data_oriented
class Pentagram:
def __init__(self, C, R):
self.C = C
self.R = R
self.P = Point.field(shape=(5))

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])

@ti.kernel
def Rotate(self, angle:  ti.f32):
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] = t

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)
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()
``````
2 Likes