我正在尝试通过应用平移,旋转和缩放变换来绘制一些基本形状。
但是,随着坐标系统的缩小,线变得越来越细(我想保持不变):
请参阅下面的代码块,它说明了我已经尝试过的内容。
开罗官方教程提供了一种更新线宽的方法:
double ux=1, uy=1;
cairo_device_to_user_distance (cr, &ux, &uy);
if (ux < uy)
ux = uy;
cairo_set_line_width (cr, ux);
(请参见https://cairographics.org/tutorial/的“技巧和窍门” /“行宽”部分)
import cairo
def rect(ctx, x, y, w, h):
ctx.move_to(x, y)
ctx.rel_line_to(w, 0)
ctx.rel_line_to(0, h)
ctx.rel_line_to(-w, 0)
ctx.close_path()
ctx.stroke()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300)
context = cairo.Context(surface)
context.scale(300, 300)
# background
context.set_source_rgb(0.5, 0.8, 0.8)
context.paint()
# new stroking color is black
context.set_source_rgb(0, 0, 0)
# translating to the center point
context.translate(0.5, 0.5)
# See https://cairographics.org/tutorial/ -> Tips and Tricks -> Line width
context.set_line_width(context.device_to_user_distance(1, 1)[0])
# So far so good, the rect is ok
rect(context, -0.1, -0.1, 0.2, 0.2)
# With each iteration, I rotate the coordinate system 60˚ clockwise,
# translate and scale down a bit
for i in range(6):
scale_factor = 0.5
angle = np.pi/3.
dy = -0.3
context.rotate(angle)
context.translate(0, dy)
context.scale(scale_factor, scale_factor)
old_lw = context.get_line_width()
dist = context.device_to_user_distance(1, 1)
print('{0} Old: {1:2.4f} New: {2:2.4f}'.format(i, old_lw, dist[0]))
context.set_line_width(dist[0])
rect(context, -0.05, -0.05, 0.1, 0.1)
# Scaling and translating back, keeping current rotation cumulative
context.scale(1/scale_factor, 1/scale_factor)
context.translate(0, -dy)
surface.write_to_png('test.png')
打印块产生以下结果:
0 Old: 0.0033 New: 0.0091
1 Old: 0.0091 New: 0.0024
2 Old: 0.0024 New: -0.0067
3 Old: 0.0000 New: -0.0091
4 Old: 0.0000 New: -0.0024
5 Old: 0.0000 New: 0.0067
因此,我认为问题出在这一行:
dist = context.device_to_user_distance(1, 1)
在迭代时,它开始产生负值。这会导致奇怪和错误的结果:。
要绘制我一开始所指的初始图像,只需在循环内设置线宽的注释行即可。
我在哪里弄错了?提前致谢。
最佳答案
更新:device_to_user_distance
返回负值的原因仍然未知,但是问题实际上很容易解决。
在应用任何缩放变换之前,我会根据其当前值来更新线宽,如下所示:
scale_factor = 0.5
current_lw = context.get_line_width()
# so the new line width value is twice as thick as the old one
new_lw = current_lw/scale_factor
context.scale(scale_factor, scale_factor)
context.set_line_width(new_lw)
# do drawing
# restoring back scaling transform and line width
context.set_line_width(new_lw*scale_factor)
context.scale(1./scale_factor, 1./scale_factor)
关于python - 在变换之间保持恒定的线宽,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56949169/