Draw lines on click

edited July 2017 in Questions about Code

I have this code I have written that is a simple drawing program using arrays to store points where the mouse was clicked, and functions that modify the array in different ways. Other than the keyPressed(), everything else is complete, but the program is not working properly and I'm not sure where I went wrong.

final int START_POINTS = 5;

int[] x = new int[START_POINTS];
int[] y = new int[START_POINTS];
int pointCount = 0;
int red = int(random(255));
int green = int(random(255));
int blue = int(random(255));
color clr = color(red, green, blue);

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

void draw()
{
  background(0);
  stroke(255);
  drawLines(x, y, pointCount);
}

/********************
*  Adds the given x, y point to the corresponding array. curSize corresponds to the
*  existing data entries in the array and the fucntion returns the new number of points
*  in the array.
********************/
int addPoint(int x, int y, int[] pointsX, int[] pointsY, int curSize)
{
  for (int c = 0; c < curSize; c++)
  {
    pointsX[c] = x;
    pointsY[c] = y;
  }
  return curSize++;
}

/********************
*  Draws lines between consecutive pairs of points in the arrays, forming a continuous
*  line.
********************/
void drawLines(int[] x, int[] y, int curSize)
{
  for (int p = 1; p < curSize; p++)
  {
    line(x[p-1], y[p-1], x[p], y[p]);
  }
}

/********************
*  Add the value in delta to every value in the array.
********************/
void addToData(int[] data, int curSize, int delta)
{
  for (int d = 0; d < curSize; d++)
  {
    data[d] = data[d] + delta;
  }
}

/********************
*  Multiplies the value in rate to every value in the array.
********************/
void multiplyData(int[] data, int curSize, float rate)
{
  for (int d = 0; d < curSize; d++)
  {
    data[d] = int(data[d] * rate);
  }
}

/********************
*  Creates and returns a new array that is double the size of the old array, with all
*  data in oldArray copied into the new one. 
********************/
int[] doubleArray(int[] oldArray)
{
  int[] newArray = expand(oldArray);
  arrayCopy(oldArray,newArray);
  return newArray;
}

/********************
*  Removes half the data from a given array, and returns the new array size. Data from
*  the even numbered positions are kept, odd positons are thrown out
********************/
int shrinkData(int[] data, int curSize)
{
  for (int s = 0; s < curSize; s++)
  {
    if (s % 2 == 0)
    {
      data[s] = data[s/2];
    }
  }
  int newSize = data.length/2;
  return newSize;
}

/********************
*  Averages all data in the array.
********************/
int averagePoints(int[] data, int curSize)
{
  int sum = 0;
  for (int s = 0; s < curSize; s++)
  {
    sum += data[s];
  }
  int average = sum/curSize;
  return average;
}

/********************
*  Modifies all values in the array so they get closer to/further from the offset value
*  by a factor of scale.
********************/
void scaleAroundOffset(int[] data, int curSize, int offset, float scale)
{
  addToData(data, curSize, -offset);
  multiplyData(data, curSize, scale);
  addToData(data, curSize, offset);
}

/********************
*  Add current mouse location to the array using addPoint. If not enough space use
*  doubleArray to make the array larger.
********************/
void mousePressed()
{
  addPoint(mouseX, mouseY, x, y, pointCount);
  if (x.length > START_POINTS)
  {
    doubleArray(x);
    doubleArray(y);
  }
}

/********************
*  Erase, shift, zoom, change colour or delete every second point depending which key
*  is pressed.
********************/
void keyPressed()
{
  if (keyPressed)
  {
    if (key == 'w')
    {
      scaleAroundOffset(y, pointCount, 5, 0.5);
    }
    if (key == 'a')
    {
      scaleAroundOffset(x, pointCount, 5, -0.5);
    }
    if (key == 's')
    {
      scaleAroundOffset(y, pointCount, 5, -0.5);
    }
    if (key == 'd')
    {
      scaleAroundOffset(x, pointCount, 5, 0.5);
    }
    if (key == 'q')
    {
      background(0);
    }
    if (key == '!')
    {
      red = int(random(255));
      green = int(random(255));
      blue = int(random(255));
    }
    if (key == 'c')
    {
      shrinkData(x, pointCount);
      shrinkData(y, pointCount);
    }
    if (key == '+')
    {
      multiplyData(x, averagePoints(x, pointCount), 1.5);
      multiplyData(y, averagePoints(y, pointCount), 1.5);
    }
    if (key == '-')
    {
      multiplyData(x, averagePoints(x, pointCount), -2.0);
      multiplyData(y, averagePoints(y, pointCount), -2.0);
    }
  }
}

Answers

  • @albobz -- regarding:

    int[] newArray = expand(oldArray);
    

    What is "expand" supposed to do? How does it work, and where is it defined?

  • Expand doubles the size of the old array, when the array is full the function is called upon.

  • Answer ✓

    The double problem happens right here:

    int addPoint(int x, int y, int[] pointsX, int[] pointsY, int curSize)
    {
      for (int c = 0; c < curSize; c++)
      {
        pointsX[c] = x;
        pointsY[c] = y;
      }
      return curSize++;
    }
    

    When you pass a variable to a function, you pass a reference. For example, curSize above is a reference to your (global) variable pointCount. However, if you modify this variable inside the function, a new memory space is allocated where the new value is kept. When the function ends and returns, pointCount will have never seen the change and it will read zero. One solution will be to do the following:

    pointCount=addPoint(mouseX, mouseY, x, y, pointCount);

    and problem averted.... well, not so fast. The line return curSize++; returns the value of curSize before it is incremented. What you really want is: return ++curSize;

    Before I forget, I believe you need to consider the next change in the following code:

    int shrinkData(int[] data, int curSize)
    {
      for (int s = 0; s < curSize; s++)
      {
        if (s % 2 == 0)
        { 
          //Here s is even, so divide by 2 AND take the current value of the array (at s)
          data[s/2] = data[s];
        }
      }
      int newSize = data.length/2;
      return newSize;
    }
    

    Kf

Sign In or Register to comment.