简体   繁体   中英

Get new x,y coordinates of a point in a rotated image

I have Google Maps icons which I need to rotate by certain angles before drawing on the map using MarkerImage . I do the rotation on-the-fly in Python using PIL, and the resulting image is of the same size as the original - 32x32. For example, with the following default Google Maps marker: 旋转前的图标 , a 30 degrees conter-clockwise rotation is achieved using the following python code:

# full_src is a variable holding the full path to image
# rotated is a variable holding the full path to where the rotated image is saved
image = Image.open(full_src)
png_info = image.info
image = image.copy()
image = image.rotate(30, resample=Image.BICUBIC)
image.save(rotated, **png_info)

The resulting image is 图标逆时针旋转30度

The tricky bit is getting the new anchor point to use when creating the MarkerImage using the new rotated image. This needs to be the pointy end of the icon. By default, the anchor point is the bottom middle [defined as (16,32) in x,y coordinates where (0,0) is the top left corner]. Can someone please explain to me how I can easily go about this in JavaScript?

Thanks.

Update 22 Jun 2011: Had posted the wrong rotated image (original one was for 330 degrees counter-clockwise). I've corrected that. Also added resampling (Image.BICUBIC) which makes the rotated icon clearer.

To calculate the position of a rotated point you can use a rotation matrix .

Converted into JavaScript, this calculates the rotated point:

function rotate(x, y, xm, ym, a) {
    var cos = Math.cos,
        sin = Math.sin,

        a = a * Math.PI / 180, // Convert to radians because that is what
                               // JavaScript likes

        // Subtract midpoints, so that midpoint is translated to origin
        // and add it in the end again
        xr = (x - xm) * cos(a) - (y - ym) * sin(a)   + xm,
        yr = (x - xm) * sin(a) + (y - ym) * cos(a)   + ym;

    return [xr, yr];
}

rotate(16, 32, 16, 16, 30); // [8, 29.856...]

The formula for rotations about 0,0 is:

x1 = cos(theta) x0 - sin(theta) y0
y1 = sin(theta) x0 + cos(theta) y0

But that's for regular axes, and rotation about 0,0. The PIL rotation is clockwise with "graphics" axes. Plus, it's around the center of the image. The final confusing thing is that the size of the image can change, which needs to be accounted for in the final result.

Procedure: take original point, subtract off center of image, apply "graphics axes" corrected rotation, find new size of image, add back center position of new image.

Rotation using graphics axes is:

x1 = cos(theta) x0 + sin(theta) y0
y1 = -sin(theta) x0 + cos(theta) y0

16,32 - 16,16 is 0, 16. Rotate 30 degrees clockwise rotation (based on your images) gives a point cos(-30)*0+sin(-30)*16, -sin(-30)*0+cos(-30)*16 = -8, 13.86. The final step is adding back the center position of the rotated position.

In an image, downwards is positive Y and rightwards is positive X. However, to apply the rotation formula , we need upwards as positive Y. Therefore, step 1 would be to apply f(x,y) = f(x,hy) , where 'h' is the height of the image. Let's say the image is rotated with respect to x0,y0. You'd then need to transform your origin to this point. Therefore, step 2 would be f(x,y) = f(x-x0,y-y0) . At this stage (ie after the two steps), your new co-ordinates would be x-x0 , hy-y0 . You're now ready to apply the rotation formula

x1 = x*cos(theta) - y*sin(theta) 

y1 = xsin(theta) + ycos(theta) 

Use the values of x and y obtained after step two. You'd get

x1 = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) 

y1 = (x-x0)*sin(theta) + (h-y-y0)*cos(theta)

Now, undo transformations done in step 2 and step 1 (in that order).

After undoing step2: xNew = x1 + x0 and yNew = y1 + y0

After undoing step1: xNew = x1 + x0 and yNew = h - (y1 + y0)

This gives you:

xNew = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) + x0

yNew = -(x-x0)*sin(theta) - (h-y-y0)*cos(theta) + (h-y0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM