2009-08-06 67 views
14

Tôi có một chương trình trong C# (Windows Forms) để vẽ một số hình chữ nhật trên hình tượng. Chúng có thể được vẽ ở một góc quá (xoay).Kiểm tra xem một điểm có nằm trong một hình chữ nhật xoay (C#)

Tôi biết từng điểm bắt đầu của hình chữ nhật (góc trên bên trái), kích thước của chúng (chiều rộng + chiều cao) và góc của chúng. Vì xoay vòng, điểm bắt đầu không nhất thiết là góc trên bên trái, nhưng điều đó không quan trọng ở đây. Sau đó, khi tôi nhấp vào hình tượng, tôi cần kiểm tra hình chữ nhật nào (nếu có) tôi đã nhấp vào.

Vì vậy, tôi cần một số cách để kiểm tra xem một điểm có nằm trong hình chữ nhật hay không, nhưng tôi cũng cần tính đến vòng quay của mỗi hình chữ nhật. Có ai biết cách để làm điều này trong C#?

+0

Các hình chữ nhật có xoay quanh nguồn gốc, góc trên bên trái hoặc một điểm tùy ý khác không? – outis

Trả lời

18

Có thể áp dụng cùng một vòng xoay được áp dụng cho hình chữ nhật với điểm ngược lại không? Ví dụ: Hình chữ nhật A được xoay 45 độ theo chiều kim đồng hồ từ gốc (góc trên bên trái), sau đó bạn chỉ cần xoay điểm B xung quanh cùng một gốc 45 độ theo chiều kim đồng hồ, sau đó kiểm tra xem nó có nằm trong Rectangle A trước hay không -rotation

+0

Đây chắc chắn là con đường để đi, nhưng tôi dường như không thể có được toán học của tôi ngay lúc này. Cảm ơn bạn. – Ove

+0

Tôi nghĩ giải pháp lý tưởng phụ thuộc vào khung bạn đã thiết lập trong ứng dụng của bạn. Trong một số trường hợp, tôi nghĩ rằng ý tưởng của Outis về một bộ đệm z là lý tưởng hơn. Hãy nhớ rằng giải pháp của anh ấy giống như cách render của GPU trong 3D. –

+1

Để công bằng, bạn đã đưa "z-" vào ý tưởng đệm. – outis

5

Bạn có thể giữ một hình ảnh thứ hai, chưa được hiển thị nơi bạn vẽ các bản sao của hình chữ nhật, mỗi hình chữ nhật có màu duy nhất. Khi người dùng nhấp vào hình tượng hình, tìm màu của pixel tương ứng trong hình ảnh thứ 2, sẽ xác định hình chữ nhật nào được nhấp vào.

+1

Đó sẽ là một sự lãng phí bộ nhớ và nó sẽ chậm. – Ove

+1

Giải pháp Outis 'không hoạt động.Tôi đang sử dụng nó trong dự án CF ngay bây giờ để làm một số thử nghiệm hit đặc biệt phức tạp. Nhưng hãy kiểm tra: http://msdn.microsoft.com/en-us/library/system.drawing.rectangle.contains(VS.80).aspx Lớp Rectangle có phương pháp Chứa có thể được sử dụng để kiểm tra điểm ngăn chặn. –

+0

+1 cho giải pháp phi toán – JeffH

1

Các hình chữ nhật có được phép chồng lên nhau không? Nếu vậy, bạn có muốn tất cả các hình chữ nhật trong một điểm hay chỉ một hình chữ nhật trong lớp trên cùng?

2

Tôi biết điều này đã được trả lời nhưng tôi đã phải làm điều gì đó tương tự như trước đây. Tôi tạo ra một phương pháp mở rộng cho lớp System.Windows.Point đã giúp thực hiện chính xác những gì Neil gợi ý:

public static double GetAngle(this Point pt) 
    { 
     return Math.Atan2(pt.X, -pt.Y) * 180/Math.PI; 
    } 

    public static Point SetAngle(this Point pt, double angle) 
    { 
     var rads = angle * (Math.PI/180); 
     var dist = Math.Sqrt(pt.X * pt.X + pt.Y * pt.Y); 
     pt.X = Math.Sin(rads) * dist; 
     pt.Y = -(Math.Cos(rads) * dist); 
     return pt; 
    } 

Điều này sẽ cho phép tôi làm việc với các góc của điểm khoảng 0, 0. Vì vậy, nếu bạn biết trung tâm của rect mà bạn đang thử nghiệm, bạn sẽ bù đắp điểm bằng âm của giá trị này (ví dụ: pt.X - = 32; pt.Y - = 32) Và sau đó bạn sẽ áp dụng phép quay âm của hình chữ nhật (như được gợi ý bởi Neil: pt.SetAngle (-45);) ...

Bây giờ nếu điểm nằm trong phạm vi 64, 64 bạn biết bạn đã nhấn vào hình chữ nhật. Cụ thể hơn, tôi đã kiểm tra một điểm ảnh của một hình ảnh được xoay để đảm bảo rằng tôi đã đạt được một điểm ảnh của một màu cụ thể.

0

Tôi đã rối tung này trong một thời bây giờ và đã tìm thấy một vài câu trả lời, không ai trong số họ thực sự làm việc. Đây là một chức năng C# thực hiện chính xác như OP mô tả, nếu không cho OP thì những người khác Googling như tôi.

Thật là đau đầu khi tìm ra điều này. Rất nhiều phỏng đoán điển hình.

bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation) 
    { 
     Matrix rotMat = Matrix.CreateRotationZ(-rotation); 
     Vector2 Localpoint = P - (rect.Location).ToVector2(); 
     Localpoint = Vector2.Transform(Localpoint, rotMat); 
     Localpoint += (rect.Location).ToVector2(); 

     if (rect.Contains(Localpoint)) { return true; } 
     return false; 
    } 

Và tại đây nó nằm trong một dòng mã. Có lẽ nhanh hơn để sử dụng.

bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation) 
    { 
     if (
      rect.Contains(Vector2.Transform(P - (rect.Location).ToVector2(), Matrix.CreateRotationZ(-rotation)) + (rect.Location).ToVector2()) 
      ) { return true; } 
     return false; 
    } 
Các vấn đề liên quan