你如何在像素阵列中画一条线

问题描述

我喜欢对屏幕进行最大程度的控制,因此我必须控制每个像素,这有其优点和缺点。缺点之一是我并没有任何内置函数的帮助。所以我不知道如何划界线。 我试图制作一个处理线条绘制的函数,但是我无法使其正常工作! 这是我用来画线的代码

  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的函数

,当我尝试使用此代码时,它不会崩溃,就像处理出错时一样! 只是不起作用,而是什么也不做!

请给我一些帮助。

解决方法

您只需使用PGraphics就可以摆脱困境。 这个想法是,一旦有了PGraphics实例,就可以使用点表示法来访问用于的绘图函数(只要在.beginDraw().endDraw()之间调用它们)。

使用noSmooth()可以使它看起来很完美。

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

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

rasterised line drawing at 100% and 400% scale with no smoothing (aliased)

在大多数情况下都应该这样做。 (只有very small values and transparency的棘手案例可能会让您头痛)

如果出于某些原因需要更多控制,则可以始终实施自己的栅格化方法。一旦找到您可以开始的地方,Bresenham's line algorithm

关于您的代码,可能会出错:

  • float deltaPixl = deltaX/deltaY;:如果deltaY为零,则会遇到exception
  • 您正在对deltaXdeltaY进行整数除法(有可能使这两个值都可能获得0)
  • 您应该在for循环之前尝试使用{/ {1}}语句,并使用开始/结束值来了解该循环是否实际执行。此外,在println()循环中,您可以for查看是否获得了期望的价值。

总体上,我建议检查Kevin Workman's How to Debug guide

此外,您可以使用lerp()计算线的起点和终点之间的线性插值位置。传递每个坐标和一个规范化的值(介于0.0、1.0之间),其中0.0 =起始点,1.0 =终止点,并且中间的任何内容都在直线上(例如,直线上的0.5 = 50%)。

这是一个基本示例:

println(i)

interpolated points along a vertical line rendered as black squares on a white background

interpolated points along a diagonal line rendered as black squares on a white background

为了完整起见,以下是使用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,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,mouseY,numPoints); } 的上述代码段:

pixels[]

interpolated line rendered at snapped pixels in a 100x100 raster