我正试图渲染一个可爱的小直角三角形,带有斜边,我想围绕它的质心旋转。为此,我使用cairocffi在python中工作,cairocffi是cairo C库的python实现。
为了达到这个目的,我使用了3个从边缘定向并指向质心的线性渐变。通过这样做,我实现了以下目标:
http://i.imgur.com/WswcCg6.png
此图像显示左侧的最终产品,以及我用于在右侧实现的构造线和阴影三角形线段。
我遇到的问题是在不同旋转角度下渐变的渲染行为不一致,因此当我将动画的图像串在一起时,渐变"抖动"在三角形内。您可以在以下链接中找到演示此行为的视频。如您所见,三角形边缘平滑流动,只有渐变抖动。
我用来实现此目的的代码如下。非常感谢任何有关可能出现问题的帮助。
import math
import cairocffi as cairo
import array
def prism90(size, angle):
DIMENSION = size
height = 0.44
data = array.array('c', chr(0) * DIMENSION * DIMENSION * 4)
stride = DIMENSION * 4
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, DIMENSION, DIMENSION, data, stride)
# Context
ctx = cairo.Context(surface)
ctx.scale (DIMENSION, DIMENSION)
# black background for .png
ctx.rectangle (0, 0, 1, 1)
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0)
ctx.fill ()
ctx.translate(0.5, 0.5)
ctx.rotate(math.radians(angle))
ctx.set_operator(cairo.OPERATOR_ADD)
trigons = [
[(0,0),(0,-height+height/2),( height,height/2)],
[(0,0),(0,-height+height/2),(-height,height/2)],
[(0,0),(height, height/2),(-height,height/2)],
]
gradients = [
( height/2, 0, 0, height-height/2),
(-height/2, 0, 0, height-height/2),
( 0, height-height/2, 0, 0),
]
steps = 3
stop_start = 0.01
stop_inc = 0.025
alpha_start = 0.3
alpha_inc = 0.15
shade = 0.6
for index, (points, gradient) in enumerate(zip(trigons, gradients)):
if index == 2: # deeper gradient for hypotenuse trigon
steps = steps*2-1
alpha_start = 0.4
alpha_inc = 0.05
gradient = cairo.LinearGradient(*gradient)
for step in xrange(0, steps, 1):
stop = stop_start+stop_inc*step
alpha = alpha_start+alpha_inc*step
gradient.add_color_stop_rgba(stop, shade, shade, shade, alpha)
ctx.set_source(gradient)
ctx.move_to(*points[0])
ctx.line_to(*points[1])
ctx.line_to(*points[2])
ctx.close_path()
ctx.fill()
shade = shade +0.1
cols = [(1,0,0), (0,1,0), (0,0,1)]
for grad, col in zip(gradients, cols):
ctx.set_line_width(1./size*1)
ctx.set_source_rgb(*col)
ctx.move_to(grad[0], grad[1])
ctx.line_to(grad[2], grad[3])
ctx.stroke()
surface.flush()
surface.write_to_png ("prism90_"+str(angle)+".png")
surface.finish()
return data.tostring()
angle = 0
prism = prism90(250,angle)