问题描述
使用PyCairo,我希望有一种方法可以在上下文中放置,调整给定ImageSurface的大小并旋转它,但是可以旋转图像中心(而不是左上角)
好的,我尝试了在这里找到的示例,但是没有成功。 让我们详细介绍“上下文”。
我有一个“ finale” ImageSurface(例如A),上面写有一些其他图像和文本。 我想在指定位置上放置另一个ImageSurface(例如B),该位置是将B放在A上的左上角。然后我需要调整B的大小(减小其大小)并旋转它 ,而不是其左上角。
我尝试了以下方法,但没有成功:
def draw_rotated_image(ctx,image_surface,left,top,width,height,angle):
ctx.save()
w = image_surface.get_width()
h = image_surface.get_height()
cl = left / (width/w)
ct = top / (height/h)
ctx.rotate(angle*3.1415927/180)
ctx.scale(width/w,height/h)
ctx.translate(cl + (-0.5*w),ct + (-0.5*h) )
ctx.set_source_surface(image_surface,0)
ctx.paint()
ctx.restore()
return
非常感谢您的帮助:)
解决方法
好吧,我终于做到了! (感谢我的14岁儿子让我修改了三角函数)
我试图在这里解释我的解决方案。 首先,我不是数学家。因此,可能是最好的方法,当然我的解释肯定有错误,但是我只是在解释我用来获得良好结果的逻辑方法。
最好的方法是首先在矩形周围绘制一个圆,因为我们需要根据所需的角度围绕该矩形的圆移动该矩形的左上角。 因此,要获取矩形圆的半径,我们需要计算其假设,然后除以2:
hypothenuse = math.hypot(layerWidth,layerHeight)
radius = hypothenuse / 2
然后我们将能够在矩形周围绘制一个圆。
第二,我们需要知道在该圆上哪个角度是矩形的实际左上角。 因此,我们需要计算矩形的反正切值,即arc-tan(height / width)。 但是因为我们想知道距0°的距离是多少度,所以我们需要计算相反的arc-tan(width / height)。
最后,另一个奇点是开罗0°实际上是90°,因此我们将不得不再次旋转。
那么,最后,需要了解什么? 如果要以某个角度绘制一个图层,并以其中心旋转,则左上角的点将根据所需角度在圆周围移动。 给定角度为0的左上角位置必须为“参考”。
因此,我们需要获得新的X-Y位置,在该位置开始放置图层以使其能够旋转:
现在,我们可以编写一个函数,该函数将返回左上角矩形的X-Y pos,以给定角度绘制该矩形:
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 getTopLeftForRectangleAtAngle(layerLeft,pointY)