Я пытаюсь нарисовать некоторые базовые фигуры с применением преобразований перемещения, поворота и масштабирования.
Однако линии сужаются при уменьшении системы координат (и я хочу, чтобы она оставалась постоянной):
См. Прилагаемый блок кода ниже, который иллюстрирует то, что я уже пробовал.
Официальный учебник Cairo предоставляет такой способ обновления ширины линии:
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)
Во время итерации он начинает давать отрицательные значения. Это приводит к странному и глючному результату: .
Чтобы нарисовать исходное изображение, на которое я ссылался в начале, нужно просто закомментировать строки с настройкой ширины линии внутри цикла.
Где я ошибаюсь? Заранее спасибо.