加工中的谢尔宾斯基地毯

Sierpinski carpet in processing

所以我在处理过程中使用 Square 数据类型制作了 Sierpinski 地毯分形,该数据类型绘制一个正方形并具有一个函数 generate() 可以从自身生成 9 个相等的正方形并且 returns一个 (9-1)=8 正方形的 ArrayList 移除中间的正方形(它不会添加到返回的 ArrayList 中)以生成 Sierpinski 地毯.

这里是class广场-

class Square {

  PVector pos;
  float r;

  Square(float x, float y, float r) {
    pos = new PVector(x, y);
    this.r = r;
  }
  void display() {
    noStroke();
    fill(120,80,220);
    rect(pos.x, pos.y, r, r);
  }
  ArrayList<Square> generate() {

    ArrayList<Square> rects = new ArrayList<Square>();

    float newR = r/3;

    for (int i=0; i<3; i++) {
      for (int j=0; j<3; j++) {
        if (!(i==1 && j==1)) {
          Square sq = new Square(pos.x+i*newR, pos.y+j*newR, newR);
          rects.add(sq);
        }
      }
    }

    return rects;
  }
}

这是主草图,鼠标单击时向前移动生成 -

ArrayList<Square> current;

void setup() {
  size(600, 600);
  current = new ArrayList<Square>();

  current.add(new Square(0, 0, width));
}

void draw() {
  background(255);
  for (Square sq : current) {
    sq.display();
  }
}

void mousePressed() {
  ArrayList<Square> next = new ArrayList<Square>();

  for(Square sq: current) {
    ArrayList<Square> rects = sq.generate();
    next.addAll(rects);
  }
  current = next;
}

问题:

我得到的输出有非常细的白线,这些白线不应该存在:

第一代 -

二代 -

第三代-

我的猜测是,这些线条只是由于 generate() 中的计算偏离一两个像素而出现的白色背景。但是我不确定如何摆脱这些。如有任何帮助,我们将不胜感激!

这里有一个更小的例子来说明你的问题:

size(1000, 100);
noStroke();
background(0);

float squareWidth = 9.9;
for(float squareX = 0; squareX < width; squareX += squareWidth){
 rect(squareX, 0, squareWidth, height); 
}

请注意,黑色背景透过方块显示出来。请尝试 post 这种最小的例子,而不是你以后的整个草图。

无论如何,可以通过三种方法解决此问题:

选项 1: 调用 noSmooth() 函数。

默认情况下,Processing 使用抗锯齿功能使您的绘图看起来更平滑。通常这是一件好事,但它也会给形状的边缘增加一些模糊度。如果您禁用抗锯齿,您的形状会更清晰并且您不会看到伪影。

选项 2:使用与填充颜色相同的描边。

正如您已经发现的那样,这会在形状周围绘制轮廓。

选项 3: 使用 int 值而不是 float 值。

您在 float 值中存储您的坐标和大小,这些值可以包含小数位。问题是,屏幕(显示器上的实际像素)没有小数位(没有半个像素这样的东西),因此它们由 int 值表示。因此,当您将 float 值转换为 int 时,小数部分会被删除,这可能会导致形状出现小间隙。

如果您只是改用 int 值,问题就会消失:

size(1000, 100);
noStroke();
background(0);

int squareWidth = 10;
for(int squareX = 0; squareX < width; squareX += squareWidth){
 rect(squareX, 0, squareWidth, height); 
}