tôi không tin chạy thuật toán vòng tròn trung điểm trên mỗi lớp sẽ cho kết quả mong muốn khi bạn đạt được cực, vì bạn sẽ có những khoảng trống trên bề mặt nơi đèn LED không thắp sáng . Điều này có thể cho kết quả bạn muốn, tuy nhiên, do đó sẽ được lên đến thẩm mỹ. Bài viết này dựa trên việc sử dụng thuật toán vòng tròn giữa để xác định bán kính của các lớp thông qua hai octants thẳng đứng giữa, và sau đó khi vẽ từng vòng tròn đó cũng thiết lập các điểm cho các octants cực.
Tôi nghĩ dựa trên nhận xét và câu trả lời của @Nick Udall here sử dụng thuật toán vòng tròn để xác định bán kính lát ngang của bạn sẽ hoạt động với sửa đổi mà tôi đã đề xuất trong nhận xét về câu trả lời của anh ấy. Thuật toán vòng tròn nên được sửa đổi để lấy làm đầu vào một lỗi ban đầu, và cũng vẽ các điểm bổ sung cho các octants cực.
- Vẽ điểm thuật toán vòng tròn tiêu chuẩn tại
y0 + y1
và y0 - y1
: x0 +/- x, z0 +/- z, y0 +/- y1
, x0 +/- z, z0 +/- x, y0 +/- y1
, tổng 16 điểm. Điều này tạo thành phần lớn dọc của hình cầu.
- Ngoài ra vẽ các điểm
x0 +/- y1, z0 +/- x, y0 +/- z
và x0 +/- x, z0 +/- y1, y0 +/- z
, tổng cộng 16 điểm, sẽ tạo thành các mũ cực cho hình cầu.
Bằng cách chuyển lỗi thuật toán bên ngoài vào thuật toán vòng tròn, nó sẽ cho phép điều chỉnh phụ voxel của vòng tròn của mỗi lớp. Nếu không truyền lỗi vào thuật toán bên trong, đường xích đạo của vòng tròn sẽ được xấp xỉ với một hình trụ và mỗi mặt cầu gần đúng trên trục x, y và z sẽ tạo thành một hình vuông. Với lỗi bao gồm, mỗi khuôn mặt được cung cấp một bán kính đủ lớn sẽ được xấp xỉ như một vòng tròn đầy.
Mã sau đây được sửa đổi từ Midpoint circle algorithm của Wikipedia. Thuật toán DrawCircle
có thuật ngữ thay đổi để hoạt động trong mặt phẳng xz, bổ sung điểm ban đầu thứ ba y0
, độ lệch y y1
và lỗi ban đầu error0
. DrawSphere
đã được sửa đổi từ chức năng tương tự để có những điểm ban đầu thứ ba y0
và gọi DrawCircle
hơn DrawPixel
public static void DrawCircle(int x0, int y0, int z0, int y1, int radius, int error0)
{
int x = radius, z = 0;
int radiusError = error0; // Initial error state passed in, NOT 1-x
while(x >= z)
{
// draw the 32 points here.
z++;
if(radiusError<0)
{
radiusError+=2*z+1;
}
else
{
x--;
radiusError+=2*(z-x+1);
}
}
}
public static void DrawSphere(int x0, int y0, int z0, int radius)
{
int x = radius, y = 0;
int radiusError = 1-x;
while(x >= y)
{
// pass in base point (x0,y0,z0), this algorithm's y as y1,
// this algorithm's x as the radius, and pass along radius error.
DrawCircle(x0, y0, z0, y, x, radiusError);
y++;
if(radiusError<0)
{
radiusError+=2*y+1;
}
else
{
x--;
radiusError+=2*(y-x+1);
}
}
}
Đối với một quả cầu bán kính 4 (mà thực sự đòi hỏi 9x9x9), điều này sẽ chạy ba lần lặp của DrawCircle
thường lệ, với bản vẽ đầu tiên bán kính 4 vòng tròn (ba bước), thứ hai vẽ bán kính 4 vòng tròn với sai số ban đầu là 0 (cũng ba bước), và sau đó vẽ thứ ba bán kính 3 vòng tròn với lỗi ban đầu 0 (cũng ba bước). Điều đó kết thúc lên được chín điểm tính toán, vẽ 32 pixel mỗi. Điều đó làm cho 32 (điểm trên mỗi vòng tròn) x 3 (cộng hoặc trừ các phép toán cho mỗi điểm) + 6 (cộng, trừ, thay đổi hoạt động trên mỗi lần lặp) = 102 cộng, trừ, hoặc thay đổi hoạt động cho mỗi điểm được tính toán. Trong ví dụ này, đó là 3 điểm cho mỗi vòng tròn = 306 hoạt động mỗi lớp.Thuật toán bán kính cũng thêm 6 hoạt động cho mỗi lớp và lặp lại 3 lần, do đó, 306 + 6 * 3 = 936
phép tính số học cơ bản cho bán kính mẫu là 4. Chi phí ở đây là bạn sẽ lặp lại thiết lập một số pixel mà không cần kiểm tra điều kiện bổ sung (tức là x = 0, y = 0, hoặc z = 0), vì vậy nếu I/O của bạn chậm, bạn có thể tốt hơn khi thêm kiểm tra điều kiện. Giả sử tất cả các đèn LED đã bị xóa khi bắt đầu, vòng tròn ví dụ sẽ đặt 288 đèn LED, trong khi có rất ít đèn LED thực sự được chiếu sáng do các bộ lặp lại. Có vẻ như điều này sẽ hoạt động tốt hơn phương pháp bruteforce cho tất cả các hình cầu phù hợp với lưới 8x8x8, nhưng phương pháp bruteforce sẽ có thời gian nhất quán bất kể bán kính, trong khi phương pháp này sẽ chậm lại khi vẽ các bán kính lớn chỉ một phần sẽ được hiển thị. Do khối hiển thị tăng độ phân giải, tuy nhiên, thời gian giải thuật này sẽ vẫn ổn định trong khi bruteforce sẽ tăng lên.
Đánh giá bởi quả cầu LED, chúng ta có nên giả sử bạn cần nội thất của hình cầu được vẽ theo cách nào đó không? – NominSim
@NominSim Tôi không nghĩ vậy. Trong trường hợp này, anh ta sẽ không nói về sự lặp lại vòng tròn của Bresenham và chỉ có thể sử dụng giải pháp sức mạnh vũ phu của japreiss. –
@Christian Trên thực tế, tôi muốn có cả hai tùy chọn. –