Search code examples
processing

What is the problem with my midpoint algorithm?


I just started to learn processing and I have a few problems that I couldn't solve. I hope someone could help me. This should draw lines where i could choose the starting and finishing points with mousePressed(), but I failed before trying implementing that.

//int x1, x2, y1, y2;

void setup() {
  size(640, 480);
}
void draw() {
  midpoint(0, 0, 100, 100);
}

//void mousePressed() {
//  pmouseX =x1;
//  pmouseY =y1;
//  mouseX =x2;
//  mouseY =y2;
//}

void midpoint(int x1, int y1, int x2, int y2) {
  int dx, dy, d, x, y;
  dx = x2-x1;
  dy = y2-y1;
  d = 2*dy-dx;
  x = x1;
  y = y1;
  for (int i = 1; i <dx; i++) {
    point(x, y);
    if (d>0) {
      y++;
      d+=2*(dy-dx);
    } else {
      d+=2*dy;
    }
    x++;
  }
}

My problem is that it will not always draw the line. e.g.

midpoint(0,0,100,100);

it will draw it

midpoint(100,100,0,0);

it draws nothing.

It should draw the same line if I exchange the points coordinates, or draw a single point if the coordinates are the same.


Solution

  • In Bresenham's midpoint line algorithm you have to be careful with the gradient of the line drawn, the base algorithm you described only works for gradients between 0 and 1. In order to deal with gradients that are steeper (m > 1 or m < -1), you have to switch the roles of the x and y values, therefore you have to step in y and then calculate x. Also to deal with negative steps just switch the point order.

    void midpoint(int x1, int y1, int x2, int y2) {
      // Is gradient of line greater than 1
      boolean steep = abs(y2-y1) > abs(x2-x1);
      int temp;
    
      if (steep) {   // If gradient > 1
        // Swap roles of x and y components to step in y instead
        temp = y1;
        y1 = x1;
        x1 = temp;
    
        temp = y2;
        y2 = x2;
        x2 = temp;
      }
    
      if (x2 < x1) {  
        // Swap points such that step in x is positive
        temp = x1;
        x1 = x2;
        x2 = temp;
    
        temp = y1;
        y1 = y2;
        y2 = temp;
      }
    
      // Change in x and y which are now both positive
      int dx = x2 - x1;
      int dy = abs(y2 - y1);
    
      // Step in y
      int sy = y2 > y1 ? 1 : -1;
      int y = y1;
    
      // Decision variable
      int d = 2*dy-dx;
    
      // Small step in x
      for (int x=x1; x<=x2; x++) {
        // Depending on gradient plot x and y
        if (steep) {
          point(y, x);
        } else {
          point(x, y);
        }
    
        // Update decision parameter
        if (d>0) {
          y += sy;
          d+=2*(dy-dx);
        }else{
          d+=2*dy;
        }
      }
    }