Ну наконец-то я сделал это! (спасибо моему 14-летнему сыну, который заставил меня пересмотреть мою тригонометрию)
Я пытаюсь объяснить здесь свое решение. Во-первых, я НЕ МАТЕМАТИК. Так что, вероятно, есть лучший способ, и, конечно же, в моем объяснении есть ошибки, но я просто объясняю логический способ, которым я воспользовался для получения хорошего результата.
Лучшая идея для этого - сначала нарисовать круг вокруг прямоугольника, потому что нам нужно переместить верхний левый угол этого прямоугольника вокруг его собственного круга в соответствии с желаемым углом. Итак, чтобы получить радиус прямоугольного круга, нам нужно вычислить его гипотенузу, а затем разделить на 2:
hypothenuse = math.hypot(layerWidth,layerHeight)
radius = hypothenuse / 2
Тогда мы сможем нарисовать круг вокруг прямоугольника.
Во-вторых, нам нужно знать, под каким углом на этом круге находится фактический верхний левый угол прямоугольника. Итак, для этого нам нужно вычислить арктангенс прямоугольника, который равен arc-tan (высота/ширина). Но поскольку мы хотим знать, на сколько градусов мы далеки от 0°, нам нужно вычислить противоположное значение, так что arc-tan(width/height).
Наконец, еще одна особенность заключается в том, что Каир 0° на самом деле находится под углом 90°, так что нам придется снова повернуться.
Это можно показать на этом простом графике: ![введите здесь описание изображения](https://i.stack. imgur.com/jCOZa.png)
Итак, наконец, что необходимо понять? Если вы хотите нарисовать слой с углом, повернутым вокруг его центра, верхняя левая точка будет перемещаться по кругу в соответствии с желаемым углом. Верхнее левое положение с заданным углом 0 должно быть эталоном.
Итак, нам нужно получить новую позицию X-Y, где начать размещать слой, чтобы иметь возможность его вращать: ![введите здесь описание изображения](https://i.stack.imgur.com/DNfY1.png)
Теперь мы можем написать функцию, которая будет возвращать позицию X-Y верхнего левого прямоугольника, где его можно нарисовать под заданным углом:
def getTopLeftForRectangleAtAngle(layerLeft,layerTop,layerWidth,layerHeight,angleInDegrees):
# now we need to know the angle of the top-left corner
# for that, we need to compute the arc tangent of the triangle-rectangle:
layerAngleRad = math.atan((layerWidth / layerHeight))
layerAngle = math.degrees(layerAngleRad)
# 0° is 3 o'clock. So we need to rotate left to 90° first
# Then we want that 0° will be the top left corner which is "layerAngle" far from 0
if (angleInDegrees >= (90 + layerAngle)):
angleInDegrees -= (90 + layerAngle)
else:
angleInDegrees = 360 - ((90 + layerAngle) - angleInDegrees)
angle = (angleInDegrees * math.pi / 180.0)
centerLeft = layerLeft + (layerWidth / 2)
centerTop = layerTop + (layerHeight / 2)
# hypothenuse will help us knowing the circle radius
hypothenuse = math.hypot(layerWidth,layerHeight)
radius = hypothenuse / 2
pointX = centerLeft + radius * math.cos(angle)
pointY = centerTop + radius * math.sin(angle)
return (pointX,pointY)
И, наконец, вот как использовать его с изображением, которое мы хотим изменить, повернуть и написать в контексте:
def draw_rotated_image(ctx, image_surface, left, top, width, height, angle=0.0, alpha=1.0):
ctx.save()
w = image_surface.get_width()
h = image_surface.get_height()
# get the new top-left position according to the given angle
newTopLeft = getTopLeftForRectangleAtAngle(left, top, width, height, angle)
# translate
ctx.translate(newTopLeft[0], newTopLeft[1])
# rotate
ctx.rotate(angle * math.pi / 180)
# scale & write
ctx.scale(width/w, height/h)
ctx.set_source_surface(image_surface, 0, 0)
ctx.paint_with_alpha(alpha)
ctx.restore()
return
person
CutMaster Prod
schedule
04.09.2020