2

我喜欢最大限度地控制屏幕,所以我必须控制每个像素,这有利有弊。一个缺点是我真的没有任何内置函数的帮助。所以我不知道如何画一条线。我试图制作一个函数来处理线条画,但我无法让它工作!这是我用来画线的代码

  int startX;
  int startY;
  int deltaX = x1/x2;
  int deltaY = y1/y2;
  float deltaPixl = deltaX/deltaY;
  for(int i=0;i<deltaY;i=i+1){
    if(x1>x2){ startX = x2;}else{ startX=x1;}
    if(y1>y2){ startY = y2;}else{ startY=y1;}
    pixl(startX+i,round(startY+(deltaPixl*i)),0);
  }

它使用了一个名为 pixl 的函数,因此它可以轻松地将一个像素绘制到像素数组中,只是为了澄清为什么在代码中有一个名为 pixl 的函数。

当我尝试使用此代码时,它不会崩溃,就像处理通常在出现错误时那样!它只是不起作用,而是什么都不做!

我想在这个问题上得到一些帮助,拜托。

4

2 回答 2

2

你可以简单地使用PGraphics。这个想法是,一旦你有了一个 PGraphics 实例,你就可以使用点符号来访问以前使用的绘图函数(只要它们在.beginDraw()and之间调用.endDraw())。

使用noSmooth()你可以让它看起来像素完美。

这是一个基本草图来说明这个想法:

// disable anti-aliasing
noSmooth();
// create a PGraphics layer
PGraphics layer = createGraphics(25, 25);
// render a line
layer.beginDraw();
layer.line(0, 24, 24, 0);
layer.endDraw();
// render the line at 100%
image(layer, 0, 0);
// render the line scaled up
image(layer, 0, 0, width, height);

100% 和 400% 比例的光栅化线条图,没有平滑(锯齿)

这应该适用于大多数情况。(只有具有非常小的值和透明度的更棘手的情况可能会让您头疼)

如果由于某种原因您需要更多的控制,您总是可以实现自己的光栅化方法。您可能可以从Bresenham 的线算法开始的地方

关于您的代码,有一些可能出错的地方:

  • float deltaPixl = deltaX/deltaY;:如果 deltaY 为零,您将遇到异常
  • 您正在为deltaXand进行整数除法deltaY(可能使其对于任何一个值都可能为 0)
  • 您应该println()在 for 循环之前尝试一个带有开始/结束值的语句,以了解该循环是否会实际执行。此外,在for循环中,您可以println(i)查看是否获得了您期望的值。

总的来说,我建议查看Kevin Workman 的如何调试指南

此外,您可以使用lerp()来计算线的起点和终点之间的线性插值位置。传递每个坐标和一个标准化(0.0、1.0 之间)值,其中 0.0 = 在起点,1.0 = 在终点,中间的任何值都在线上(例如 0.5 = 沿线的 50%)。

这是一个基本示例:

void drawLinePoints(int x1, int y1, int x2, int y2, int numberOfPoints){
    // for each point  
    for(int i = 0; i < numberOfPoints; i++){
      // map the counter to a normalized (0.0 to 1.0) value for lerp
      // 0.0 = 0 % along the line, 0.5 = 50% along the line, 1.0 = 100% along the line
      float t = map(i, 0, numberOfPoints, 0.0, 1.0);
      // linearly interpolate between the start / end points (and snap to whole pixels (casting to integer type))
      int x = (int)lerp(x1, x2, t);
      int y = (int)lerp(y1, y2, t);
      // render the point
      point(x, y);
    }
  
}

void setup(){
  // render points are large squares
  strokeWeight(6);
  strokeCap(PROJECT);
}

void draw(){
  // clear frame
  background(255);
  // calculate distance
  float distance = dist(10, 10, mouseX, mouseY);
  // map distance the number of points to illustrate interpolation (more points = continuous line)
  int numPoints = (int)distance / 8;
  // render points along the line
  drawLinePoints(10, 10, mouseX, mouseY, numPoints);
}

沿垂直线的插值点呈现为白色背景上的黑色方块

沿对角线的插值点呈现为白色背景上的黑色方块

为了完整起见,这里使用了上面的代码片段pixels[]

void drawLinePoints(int x1, int y1, int x2, int y2, int numberOfPoints){
    // for each point  
    for(int i = 0; i < numberOfPoints; i++){
      // map the counter to a normalized (0.0 to 1.0) value for lerp
      // 0.0 = 0 % along the line, 0.5 = 50% along the line, 1.0 = 100% along the line
      float t = map(i, 0, numberOfPoints, 0.0, 1.0);
      // linearly interpolate between the start / end points (and snap to whole pixels (casting to integer type))
      int x = (int)lerp(x1, x2, t);
      int y = (int)lerp(y1, y2, t);
      // convert the x, y coordinate to pixels array index and render the point in black
      pixels[x + (y * width)] = color(0);
    }
  
}

void setup(){
  noSmooth();
}

void draw(){
  // clear frame
  loadPixels();
  java.util.Arrays.fill(pixels, color(255));
  // calculate distance
  float distance = dist(10, 10, mouseX, mouseY);
  // map distance the number of points to illustrate interpolation (more points = continuous line)
  int numPoints = (int)distance;
  // render points along the line
  drawLinePoints(10, 10, mouseX, mouseY, numPoints);
  // update pixels
  updatePixels();
}

在 100x100 栅格中的捕捉像素处渲染的插值线

于 2020-09-18T20:28:28.553 回答
2

我有点晚了,但我在这个网站上找到了一个非常简单的画线到像素阵列的方法。这是我在 Monogame 中制作的一个简单实现(顺便说一句,抱歉它没有使用处理 - 我从未使用过它):

public void drawLine(int x1, int y1, int x2, int y2)
{
    //this will store the colour data of the canvas pixels
    Color[] canvasData = new Color[canvas.Width * canvas.Height];
    //store the pixel data of the canvas in canvasData
    canvas.GetData<Color>(canvasData);

    //drawing line starts here
    int dx = x2 - x1;
    int dy = y2 - y1;

    for (int x = x1; x < x2; x++)
    {
        int y = y1 + dy * (x - x1) / dx;
        //[y*canvas.Width+x] converts the 2d array index to a 1d array index
        canvasData[y * canvas.Width + x] = Color.Black;
    }
    //line drawing ended

    //setting the canvas' pixels to the modified pixels with the line
    canvas.SetData<Color>(canvasData);
}
于 2021-08-17T10:51:50.947 回答