2011-06-21 55 views
11

Tôi có các biểu tượng Google Maps mà tôi cần xoay theo các góc nhất định trước khi vẽ trên bản đồ bằng cách sử dụng MarkerImage. Tôi thực hiện phép xoay vòng trong Python bằng PIL và hình ảnh kết quả có cùng kích thước với bản gốc - 32x32. Ví dụ, với mặc định marker Google Maps sau: icon before rotation , một 30 độ conter chiều kim đồng hồ xoay được thực hiện bằng cách sử dụng mã python sau:Nhận tọa độ x, y mới của một điểm trong hình ảnh được xoay

# 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) 

Hình ảnh kết quả là icon rotated 30 degrees counter-clockwise

Các chút khéo léo là nhận điểm neo mới để sử dụng khi tạo MarkerImage bằng hình ảnh xoay mới. Điều này cần phải là đầu nhọn của biểu tượng. Theo mặc định, điểm neo là đáy ở giữa [được định nghĩa là (16,32) theo toạ độ x, y trong đó (0,0) là góc trên cùng bên trái]. Ai đó có thể vui lòng giải thích cho tôi làm thế nào tôi có thể dễ dàng đi về điều này trong JavaScript?

Cảm ơn.

Cập nhật ngày 22 tháng 6 năm 2011: Đã đăng sai hình ảnh được xoay (ảnh gốc là 330 độ ngược chiều kim đồng hồ). Tôi đã sửa chữa điều đó. Ngoài ra thêm resampling (Image.BICUBIC) mà làm cho biểu tượng xoay rõ ràng hơn.

+0

@Trufa: cảm ơn cho lời khuyên. –

Trả lời

20

Để tính vị trí của điểm xoay bạn có thể sử dụng rotation matrix.

Chuyển Đổi thành JavaScript, này tính toán điểm xoay:

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...] 
+0

Cảm ơn. Đây chính xác là những gì tôi cần. –

+0

@Simon Kagwi: Cảm ơn bạn đã sửa, không chắc điều gì đã xảy ra ở đó ... – pimvdb

6

Công thức cho phép quay về 0,0 là:

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

Nhưng đó là đối với trục thường xuyên, và luân chuyển khoảng 0,0. Xoay PIL theo chiều kim đồng hồ với các trục "đồ họa". Ngoài ra, nó nằm xung quanh trung tâm của hình ảnh. Điều khó hiểu cuối cùng là kích thước của hình ảnh có thể thay đổi, cần được tính toán trong kết quả cuối cùng.

Thủ tục: lấy điểm gốc, trừ trung tâm của hình ảnh, áp dụng xoay trục đồ họa "xoay đúng, tìm kích thước hình ảnh mới, thêm lại vị trí trung tâm của hình ảnh mới.

Rotation sử dụng đồ họa trục là:

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

16,32 - 16,16 là 0, 16. Xoay 30 độ theo chiều kim đồng xoay (dựa trên hình ảnh của bạn) đưa ra một cos điểm (-30) * 0 + sin (-30) * 16, -sin (-30) * 0 + cos (-30) * 16 = -8, 13,86. Bước cuối cùng là thêm lại vị trí trung tâm của vị trí xoay.

+0

Bạn có thể giải thích sự khác biệt giữa các trục "đồ họa" và "đồ họa" không? Sự khác biệt chính có vẻ là phối hợp nào có phép trừ, nhưng tôi không hiểu tại sao. – Michael

0

Trong một hình ảnh, xuống dưới là dương Y và sang phải là dương tính X. Tuy nhiên, để áp dụng các rotation formula, chúng ta cần Y. lên như dương Do đó , bước 1 sẽ áp dụng f(x,y) = f(x,h-y), trong đó 'h' là chiều cao của hình ảnh. Giả sử hình ảnh được xoay theo x0, y0. Sau đó bạn sẽ cần phải chuyển đổi nguồn gốc của bạn đến thời điểm này. Do đó, bước 2 sẽ là f(x,y) = f(x-x0,y-y0). Ở giai đoạn này (tức là sau hai bước), các tọa độ mới của bạn sẽ là x-x0, h-y-y0. Bây giờ bạn đã sẵn sàng để áp dụng công thức xoay

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

y1 = xsin(theta) + ycos(theta) 

Sử dụng giá trị của x và y thu được sau bước hai. Bạn sẽ nhận được

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

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

Bây giờ, hoàn tác các chuyển đổi được thực hiện ở bước 2 và bước 1 (theo thứ tự đó).

Sau khi hoàn tác bước 2: xNew = x1 + x0yNew = y1 + y0

Sau khi hoàn tác bước 1: xNew = x1 + x0yNew = h - (y1 + y0)

này mang đến cho bạn:

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

yNew = -(x-x0)*sin(theta) - (h-y-y0)*cos(theta) + (h-y0) 
Các vấn đề liên quan