私は、重心を中心に回転させたい、面取りされたエッジを持つかわいい小さな直角三角形をレンダリングしようとしています。これを行うために、カイロ C ライブラリの Python 実装である cairocffi を使用して 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)