Я не верю, что запуск алгоритма окружности средней точки на каждом слое даст желаемые результаты, когда вы достигнете полюсов, так как у вас будут зазоры на поверхности, где светодиоды не горят. Тем не менее, это может дать желаемый результат, и это будет зависеть от эстетики. Этот пост основан на использовании алгоритма круга средней точки для определения радиуса слоев через два средних вертикальных октанта, а затем при рисовании каждого из этих кругов также устанавливает точки для полярных октантов.
Я думаю, что на основе комментария @Nick Udall и ответа здесь Использование кругового алгоритма для определения радиуса вашего горизонтального среза будет работать с модификацией, которую я предложил в комментарии к его ответу. Алгоритм круга должен быть изменен, чтобы принимать в качестве входных данных исходную ошибку, а также рисовать дополнительные точки для полярных октантов.
- Нарисуйте стандартные точки алгоритма круга в точках
y0 + y1
и y0 - y1
: x0 +/- x, z0 +/- z, y0 +/- y1
, x0 +/- z, z0 +/- x, y0 +/- y1
, всего 16 точек. Это составляет основную часть вертикали сферы.
- Дополнительно нарисуйте точки
x0 +/- y1, z0 +/- x, y0 +/- z
и x0 +/- x, z0 +/- y1, y0 +/- z
, всего 16 точек, которые сформируют полярные шапки для сферы.
Путем передачи ошибки внешнего алгоритма в алгоритм круга он позволяет выполнять субвоксельную корректировку круга каждого слоя. Без передачи ошибки во внутренний алгоритм, экватор круга будет аппроксимирован цилиндром, а каждая аппроксимированная грань сферы по осям x, y и z будет образовывать квадрат. С учетом ошибки каждая грань с достаточно большим радиусом будет аппроксимирована как закрашенная окружность.
Следующий код является изменением алгоритма среднего круга Википедии. В алгоритме DrawCircle
номенклатура изменена для работы в плоскости xz, добавлены третья начальная точка y0
, смещение по оси y y1
и начальная ошибка error0
. DrawSphere
был изменен из той же функции, чтобы взять третью начальную точку y0
и вызывать DrawCircle
, а не 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);
}
}
}
Для сферы с радиусом 4 (что на самом деле требует 9x9x9), это запустит три итерации процедуры DrawCircle
, при этом первая будет рисовать типичный круг радиуса 4 (три шага), вторая рисовать круг радиуса 4 с начальной ошибкой 0 ( также три шага), а затем третий рисунок круга радиуса 3 с начальной ошибкой 0 (также три шага). В итоге получается девять расчетных точек по 32 пикселя каждая. Это составляет 32 (точек на круг) x 3 (операций сложения или вычитания на точку) + 6 (операций сложения, вычитания, сдвига на итерацию) = 102 операций сложения, вычитания или сдвига на вычисленную точку. В этом примере это 3 точки для каждого круга = 306 операций на слой. Алгоритм радиуса также добавляет 6 операций на слой и повторяется 3 раза, поэтому 306 + 6 * 3 = 936
базовых арифметических операций для примера с радиусом 4. Стоимость здесь состоит в том, что вы будете повторно устанавливать некоторые пиксели без дополнительных проверок условий (т.е. x = 0, y = 0 , или z = 0), поэтому, если ваш ввод-вывод медленный, вам может быть лучше добавить проверки условий. Предполагая, что все светодиоды были сброшены в начале, в круге примера будет установлено 288 светодиодов, в то время как количество светодиодов, которые на самом деле будут гореть, будет намного меньше из-за повторяющихся наборов.
Похоже, что это будет работать лучше, чем метод грубой силы для всех сфер, которые вписываются в сетку 8x8x8, но метод грубой силы будет иметь согласованную синхронизацию независимо от радиуса, в то время как этот метод будет замедляться при рисовании сфер большого радиуса, где будет только часть отображается. Однако по мере увеличения разрешения куба дисплея время этого алгоритма будет оставаться неизменным, в то время как брутфорс будет увеличиваться.
person
rjp
schedule
04.12.2013
Solid - Erode(Solid)
должен помочь. - person japreiss   schedule 01.02.2012