Как я могу оптимизировать этот ковер Серпинского, который я сделал, используя рекурсию?

Я следовал руководству Шиффмана о рекурсии, чтобы получить следующее: Ковер Серпинского, который я сделал

Как видите, он не идеален, и я думаю, что код можно оптимизировать. Как избавиться от толстых линий, которых не должно быть? И если у вас есть идея, как я могу оптимизировать этот код, скажите мне, пожалуйста!

Это было сделано с обработкой 3.3.6, и код выглядит следующим образом:

void setup() {
  size(800, 800);
}

void draw() {
  background(255);
  fill(0);
  noStroke();

  rectMode(CENTER);
  Serpinski(width/2, height/2, width/3);
}

void Serpinski(int x, int y, int d) {
  rect(x, y, d, d);
  if (d > 1) {
    Serpinski(int(x+ d), y, d*1/3);
    Serpinski(int(x- d), y, d*1/3);
    Serpinski(x, int(y+ d), d*1/3);
    Serpinski(x, int(y- d), d*1/3);
    Serpinski(int(x+ d), int(y+ d), d*1/3);
    Serpinski(int(x- d), int(y- d), d*1/3);
    Serpinski(int(x+ d), int(y- d), d*1/3);
    Serpinski(int(x- d), int(y+ d), d*1/3);
  }
}

person IgnacioRM    schedule 27.05.2018    source источник
comment
Вы имеете в виду толстые белые линии, которые появляются на границах самой верхней сетки 3x3? Я предполагаю, что они просто из-за ошибок округления: 800/3 = 266,666667 (усечено до 266 для int), 266/3 = 88,6666667 (усечено до 88 для int). Я предполагаю, что параметры функции Sierpinski должны быть float. (Это не ответ, потому что я не могу это проверить, но если вы подтвердите, что это работает, я напишу это как ответ (и, возможно, также попробую...))   -  person Marco13    schedule 27.05.2018
comment
вместо того, чтобы рисовать белые линии, попробуйте вырезать черные прямоугольники.   -  person Will Ness    schedule 27.05.2018


Ответы (2)


Как упоминалось в комментариях, изменение метода Серпинского, чтобы он работал со значениями float вместо int, поможет.

void setup() {
  size(800, 800);
}

void draw() {
  background(255);
  fill(0);
  noStroke();
  rectMode(CENTER);
  Serpinski(width/2, height/2, width/3);
}

void Serpinski(float x, float y, float d) {
  rect(x, y, d, d);
  if (d > 1) {
    Serpinski( x+ d,  y,    d/3);
    Serpinski( x- d,  y,    d/3);
    Serpinski( x,     y+ d, d/3);
    Serpinski( x,     y- d, d/3);
    Serpinski( x+ d,  y+ d, d/3);
    Serpinski( x- d,  y- d, d/3);
    Serpinski( x+ d,  y- d, d/3);
    Serpinski( x- d,  y+ d, d/3);
  }
}

Однако из-за способа обработки информации о пикселях вы обнаружите, что графическое представление все еще не является «точным», когда вы переходите к меньшим прямоугольникам. Один из способов добиться этого — изменить размер скетча на размер, равный степени 3:

size(729, 729);

Что касается оптимизации, вы можете вызвать метод Серпинского в setup(), тогда он будет вычисляться только один раз, а не при каждом вызове draw().

person Julian    schedule 27.05.2018

Как это?

void setup() {
  size(729, 729);
  fill(0);
  background(255);
  centerRectangle(0, 0, width);
  rectangles(width/3, height/3, width/3);
}

void centerRectangle(int x, int y, int s) {
  float delta = s/3;
  noStroke();
  rect(x+delta, y+delta, delta, delta);
}

void rectangles(int x, int y, int s) {
  if (s < 1) return;
  int xc = x-s;
  int yc = y-s;
  for (int row = 0; row < 3; row++) {
    for (int col = 0; col < 3; col++) {
      if (!(row == 1 && col == 1)) {
        int xx = xc+row*s;
        int yy = yc+col*s;
        centerRectangle(xx, yy, s);
        rectangles(xx+s/3, yy+s/3, s/3);
      }
    }
  }
}
person Emmanuel Pil    schedule 21.08.2020