Làm thế nào để tính diện tích của một hình dạng không đều?


17

Tôi có một đối tượng phòng được xác định bởi một tập hợp các phân đoạn dòng lặp mà tôi cần tính diện tích cho. Các lớp có thể được mô tả như sau (bằng mã giả):

class Point {
    float x; 
    float y;
    ...
    float distanceFrom(Point p);
}

class Segment {
    Point start;
    Point end;
    ...
    float length();
}

class Room {
    List<Segment> walls;
    ...
    float area();
}

Các bức tường của một căn phòng không bao giờ có thể giao nhau ở bất cứ đâu, nhưng tại các điểm cuối của các phân khúc và bất kỳ "vòng lặp phụ" nào được tạo ra cũng sẽ được tách thành một phòng mới. Giải pháp không cần phải hoàn toàn chính xác (tỷ lệ sai số 10% là chấp nhận được) và cũng không được tính toán thường xuyên (<1 / s).


7
Sẽ có ý nghĩa hơn Roomkhi chứa một danh sách các Points, và sau đó lấy các phân đoạn bằng cách kết nối từng điểm với nhau và sau đó lặp lại xung quanh. Mặt khác, với thiết lập hiện tại của bạn, sẽ rất đông để nhận các giá trị không chính xác (ví dụ: phòng không được tiết lộ, phòng có tường ở giữa, v.v.). Đây sẽ là lựa chọn tốt nhất.
MCM Abbey

Một tùy chọn khác là hình tam giác trên cùng và tính diện tích của mỗi hình tam giác. Phần khó là tam giác. Có thể làm được, nhưng không phải lúc nào cũng đẹp. Câu trả lời dây giày vẫn còn cách tốt hơn.
Draco18

@MCM Abbey Giải pháp đó sẽ không hiệu quả, vì nó đòi hỏi Roomphải luôn luôn hoàn thành và đó có thể không phải là trường hợp nếu tôi có người chơi xây dựng Rooms bằng cách sử dụng Segments. Ngoài ra, một chức năng phòng kín rất dễ xác định (chỉ cần lặp qua các Segments và đảm bảo rằng chúng tạo ra một phòng).

Câu trả lời:


31

Bạn có thể sử dụng công thức dây giày của Gauss :

Bạn cần lấy tọa độ x của mọi điểm, nhân chúng với tọa độ y của điểm tiếp theo, sau đó trừ tọa độ y của điểm hiện tại nhân với tọa độ x của điểm tiếp theo từ kết quả và thêm chúng vào tổng diện tích. Sau khi bạn làm điều này cho mọi điểm, giảm một nửa tổng diện tích để có được diện tích thực của đa giác. Nếu điểm hiện tại là điểm cuối cùng, thì điểm tiếp theo là điểm đầu tiên.

A = 0

for (i = 0; i < points.length; i++) do

    A += points[i].x * points[(i + 1) % points.length].y - points[i].y * points[(i + 1) % points.length].x

end

A /= 2

2
Tôi luôn sử dụng nó để tính tích của hai vectơ không bao giờ biết nó được gọi là thuật toán dây giày
Sidar

3
Lưu ý rằng điều này có thể được mở rộng để tính toán thể tích của một vật thể 3D không đều được tạo thành từ các hình tam giác, và nó có thể được coi là một trường hợp tầm thường của định lý cơ bản của phép tính.
Dietrich Epp

5
Khu vực ở đây được ký kết. Đi qua các điểm theo hướng khác và trận chung kết Abị phủ định. Tùy thuộc vào mục tiêu, một A = |A|có thể cần thiết. Với mã vùng âm có thể tìm thấy vùng trên một chiếc bánh rán không đều bằng cách sử dụng danh sách các điểm bên trong và bên ngoài (một thứ tự ngược lại).
chux - Phục hồi Monica

6
Bởi vì tất nhiên hoặc Gauss hoặc Euler có một công thức cho nó.
corsiKa

0

Chúng ta cũng có thể sử dụng phương pháp Monte Carlo.

Vẽ một hình chữ nhật xung quanh hình dạng tùy ý. Lấy một nguồn PRNG phân phối đồng đều, ví dụ. mersenne twister, sau đó ràng buộc đầu ra bằng độ dài X, Y của hình chữ nhật bằng hàm modulo. Đếm số không. điểm ngẫu nhiên đáp xuống bên trong hình dạng của bạn. Chia cho tổng số điểm được tạo. Nhân số thương đó với diện tích của hình chữ nhật. Với mỗi lần lặp, bạn sẽ hội tụ đến khu vực thực sự. Thuật toán có thể song song hóa một cách lố bịch và có thể được sử dụng để tính toán 'khối lượng' hình dạng tùy ý, miễn là bạn có thể xác định xem tọa độ R ^ N có nằm trong ranh giới R ^ N của hình dạng hay không.

.

Ở đây ai đó đang sử dụng phương pháp này tìm diện tích vòng tròn, sau đó sử dụng diện tích đó để tính pi https://www.youtube.com/watch?v=VJTFfIqO4TU


2
-1: Bạn không muốn sử dụng modulo để đưa nó vào phạm vi, bạn muốn sử dụng phân phối thống nhất hoặc phân phối khác, thực hiện theo cách modulo có tất cả các loại vấn đề thống kê.
dùng1997744

12
Phương pháp này có thể có ích khi chúng ta không có một đa giác đơn giản, nhưng thay vào đó là một loại hình dạng ngầm có đường viền khó thể hiện, như một hình chữ nhật hoặc hình chữ nhật. Đối với trường hợp của một đa giác như trong câu hỏi, có vẻ như nó sẽ không cần thiết đắt tiền.
DMGregory

Như @DMGregory đã chỉ ra, đây không phải là thứ tôi đang tìm kiếm. Tuy nhiên, tôi nghĩ rằng nó xứng đáng được +1 trong trường hợp người khác cần nó.

Điều này rất thú vị nhưng chi phí cho các bài kiểm tra hòa nhập có bị cấm không? Tức là nếu bạn có một hình dạng đủ phức tạp để đảm bảo phương pháp này, thì các bài kiểm tra bao gồm cũng có thực sự tốn kém vì vậy bạn sẽ không muốn thực hiện hàng tấn chúng? (giả sử đa giác)
Mattia

Ok modulo thực sự có vấn đề, nhưng đó là một giải pháp đơn giản. Những gì chúng ta thực sự nhận được là P = 1/2 bit 0/1 ngẫu nhiên, vì vậy những gì chúng ta nhận được là một phân phối số thống nhất, ví dụ. cho 3 bit từ 0 đến 7. Thực hiện rand% 5, nếu một số ngẫu nhiên lấy giá trị 6 hoặc 7, được ánh xạ thành 1 hoặc 2, làm tăng tần số 1,2 làm cho phân phối không đồng đều. Để tránh điều đó, bạn cần một cái gì đó giống như một máy trạng thái xoay bản đồ, vd. 6,7 bản đồ thành 1,2 rồi đến 3,4 rồi 5,0 và nó tiếp tục. Chúng tôi cũng có thể vứt đi 6,7 bất cứ khi nào họ đến. Dù sao đó là một vấn đề thực hiện thư viện.
FranG

-1

Một cách tiếp cận khác: Đừng.

Thay thế:

while (Segments.Count > 3)
{
    Segment A = Segments[Segments.Count - 2];
    Segment B = Segments[Segments.Count - 1];
    Segment C = new Segment(B.End, A.Start);
    Triangle T = new Triangle(A, B, C);
    Segments[Segments.Count - 2] = C;
    Segments.RemoveAt(Segments.Count - 1);
    if (B is inside the new shape Segments)
        Area -= T.Area;
    else
        Area += T.Area;
}
Area += new Triangle(Segments[0], Segments[1], Segments[2]).Area;

Về cơ bản, lop ra một hình tam giác. Diện tích của một hình tam giác là đơn giản và để làm như vậy, chúng tôi đã giảm số phần còn lại của một phần còn lại. Lặp lại cho đến khi những gì còn lại là một hình tam giác.


2
Công thức dây giày của Gauss là một tốc ký cho việc này giảm một nửa hoặc một phần ba số lượng tính toán. Giải quyết.
Pieter Geerkens
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.