2012-04-05 33 views
6

Đây là một câu hỏi xuất hiện nhiều lần trong sự nghiệp của tôi, và điều này chia tách tôi và đồng nghiệp của tôi thành hai trại. Tôi nghĩ rằng nó có thể được trả lời tốt nhất trên trang web này, một lần và cho tất cả.Xác định hình chữ nhật là hai điểm hoặc nguồn gốc/kích thước?

Hầu như tất cả các thư viện giao diện người dùng đồ họa thực hiện một cấu trúc hình chữ nhật, nhưng cách họ làm điều đó thường chia cùng hai tùy chọn có thể:

  1. Hình chữ nhật được định nghĩa là hai điểm 2D trong hệ tọa độ cùng, thường là tên p0 và p1, hoặc với các thành phần riêng lẻ, như x0, y0, x1, y1.
  2. Hình chữ nhật được định nghĩa là vector gốc và kích thước 2D, thường được đặt tên theo vị trí và kích thước, hoặc, riêng lẻ, x, y, chiều rộng, chiều cao.

Bây giờ, giả sử tôi đã viết thư viện giao diện người dùng, tôi nên chọn hai lựa chọn nào?

Cập nhật: Câu hỏi liên quan đến việc triển khai chứ không phải giao diện. Tất nhiên giao diện của hình chữ nhật cũng có thể hỗ trợ cả hai cách tiếp cận, nhưng làm cách nào bạn lưu trữ dữ liệu trong hình chữ nhật?

+3

Tôi nghĩ câu hỏi này sẽ nhận được câu trả lời dứt khoát khi chúng tôi quyết định a) trong đó các dấu ngoặc nhọn sẽ chuyển sang, và b) có sử dụng vi hoặc emacs hay không. – molbdnilo

Trả lời

8

Tại sao không chọn cả hai?

Thực sự, điều duy nhất quan trọng là giao diện giữa thư viện và nội bộ của thư viện. Hoặc, cách người dùng của bạn sẽ sử dụng thư viện. Bạn có thể lưu trữ thông tin cho một hình chữ nhật tuy nhiên bạn muốn, nhưng nó phải được gói gọn, cách xa người dùng để chúng không cần phải lo lắng về cách hình chữ nhật của chúng được lưu trữ, chỉ là nó thực sự là một hình chữ nhật.

Nói cách khác là chọn cả hai, nếu bạn đang viết mã hướng đối tượng, bạn có thể lưu hình chữ nhật theo ý muốn và sau đó cho phép người dùng tạo hình chữ nhật bằng cách sử dụng một trong hai phương pháp.

Ví dụ, tuyên bố của bạn có thể trông giống như thế này:

class Rectangle 
{ 
public: 
    Rectangle(Point p1, Point p2); 
    Rectangle(Point origin, int width, int height); 
    ... 
}; 

(C++, kể từ khi bạn gắn thẻ đó)

đâu Point là một số lớp:

class Point 
{ 
public: 
    Point(int x, int y) : mX(x), mY(y) {} 
private: 
    int mX; 
    int mY; 
}; 

Bằng cách này, thư viện của bạn không bị giới hạn chỉ hỗ trợ một loại đặc điểm kỹ thuật để tạo hình chữ nhật.

Theo như triển khai cụ thể, nó thực sự không quan trọng. Cả hai đều làm việc và có thể dễ dàng được chuyển đổi với nhau và sử dụng cùng một lượng bộ nhớ, và do đó sẽ không có tác động hiệu suất lớn của việc sử dụng một trong những khác.

Để dễ dàng phát triển đơn giản, hãy xem xét trường hợp sử dụng hình chữ nhật của bạn là gì. Hãy xem xét từng chức năng của thành viên mà bạn sẽ cần phải viết cho lớp đó và suy nghĩ về định dạng nào sẽ dễ dàng hơn để viết các hàm đó.

Nếu đó là tôi, tôi có thể thực hiện nó với hai điểm.

Chỉnh sửa: Cách tiếp cận học tập tại sao tôi nghĩ triển khai theo cách này sẽ hoàn toàn không có sự khác biệt trong hầu hết các trường hợp.

Cho phép có chức năng thành viên hoặc thao tác trên lớp Hình chữ nhật hoạt động trên hình chữ nhật của chúng tôi hoặc thực hiện một số phép tính. Giả sử một phương pháp thực hiện (chiều rộng/chiều cao/nguồn gốc hoặc hai điểm) sẽ thực hiện thao tác này nhanh hơn đáng kể so với thực hiện khác.

Chúng ta có thể chuyển đổi từ thực hiện chiều rộng/chiều cao/nguồn gốc như sau:

// assuming x0,y0 is top left and x1,y1 is bottom right 
x0 = originX; 
y0 = originY; 
x1 = originX + width; 
y1 = originY + height; 

Và chúng ta có thể chuyển đổi từ thực hiện hai điểm như sau:

// assuming x0,y0 is top left and x1,y1 is bottom right 
originX = x0; 
originY = y0; 
width = x1 - x0; 
height = y1 - y0; 

Do đó, việc thực hiện, thực hiện hoạt động này chậm hơn/tồi tệ hơn so với việc triển khai khác có thể được chuyển đổi sang triển khai khác trong O (1) thời gian chạy, do đó việc triển khai khác không thể là rằng tốt hơn nhiều so với thực hiện đầu tiên. Trừ khi bạn đang thực hiện thao tác này vài nghìn lần trong một giây hoặc trên một thiết bị có hiệu năng cực kỳ hạn chế, tôi rất thuyết phục rằng sẽ không có sự khác biệt về hiệu suất. Không có sự khác biệt về bộ nhớ bởi vì cả hai triển khai thực hiện khá nhiều chỉ lưu trữ 4 float/ints.

Điều này khá nhiều lá thuận tiện của mã hóa, và như tôi đã nói ở trên trong bài viết ban đầu của tôi, bạn chỉ có thể "xem xét những gì các trường hợp sử dụng của hình chữ nhật của bạn. Hãy xem từng chức năng thành viên bạn sẽ cần phải viết cho lớp đó và suy nghĩ về định dạng nào sẽ giúp viết các hàm đó dễ dàng hơn. "

+1

Điều này chỉ đưa ra gợi ý về giao diện trông như thế nào và tôi đồng ý. Tuy nhiên câu hỏi là về việc thực hiện. Tôi đang mở rộng câu hỏi ban đầu để làm cho điều này rõ ràng hơn. – paniq

+0

Ba khối văn bản cuối cùng không trả lời câu hỏi của bạn về việc triển khai? Tôi sẽ giữ một mắt lột cho câu hỏi của bạn được cập nhật. –

+0

Ồ vâng, tôi đã bỏ qua điều đó, xin lỗi. Tôi không tin rằng nó không quan trọng, mặc dù. – paniq

1

Nếu không có bất kỳ câu hỏi nào, điều này tất nhiên chỉ phụ thuộc vào vấn đề bạn đang gặp phải.

Thuật toán vẽ đồ họa tùy chọn thứ 2 dường như có một lợi thế rất nhỏ IMHO. Trong khi các thuật toán "hình học" chung được xác định trên mặt phẳng euclidian - tùy chọn thứ nhất có phần thuận tiện hơn.

Ngoài ra, khi tôi đang làm việc trên một thuật toán được xác định trên bề mặt Trái Đất. Có nghĩa là, x, y tọa độ đại diện cho kinh độ/vĩ độ tương ứng. Tọa độ x rõ ràng là cyclic. Trong trường hợp cụ thể này để xác định một (loại) rect - không đủ để xác định các góc, bạn cũng cần một hướng . Điều này có thể được xử lý bởi quy ước rằng điểm thứ nhất (p0) là điểm ngoài cùng bên trái, trong khi điểm thứ 2 (p1) - điểm cực đại nhất. Nhưng tôi thích chuyển sang quy ước thứ 2 thay vào đó, nơi bạn có một góc tự nhiên và một vector bù trừ.

+0

Đó là một điểm thú vị mà bạn đang thực hiện. – paniq

Các vấn đề liên quan