Function changes the values of variables given as input.

PVector[] dots = new PVector[3];

void setup() {
  dots[0] = new PVector(100, 10);
  dots[1] = new PVector(10, 10);
  dots[2] = new PVector(10, 50);
  size(200, 200);
  fill(255);
}

void draw() {

  background(0);
  ellipse(dots[0].x, dots[0].y, 10, 10);
  ellipse(dots[1].x, dots[1].y, 10, 10);
  ellipse(dots[2].x, dots[2].y, 10, 10);
  printArray(dots);
  println(getAcute(dots[0], dots[1], dots[2]));

}

float getAcute(PVector a, PVector b, PVector c) {

  return degrees(PVector.angleBetween(a.sub(b), c.sub(b))); //Problematic line.

}

When using this basic function of finding angle using 3 points, the values of 'dots[0]' and 'dots[2]' are reduced by 'dots[1]' every time the getAcute function is called. I don't understand why it does this because my understanding is that the function creates 3 temporary variables, "a, b, c", and is restricted to that function. How do I make it so the dots[] values aren't changed at all? I could make new variables and set them to equal dots[] every time, but I feel like there is a simpler solution and my code should be working.

Answers

  • edited September 2018 Answer ✓

    I don't understand why it does this because my understanding is that the function creates 3 temporary variables, "a, b, c", and is restricted to that function.

    • Indeed getAcute()'s parameters a, b & c only exists within it.
    • However, they're initialized by the memory addresses of the 3 PVector passed arguments.
    • Therefore, if the object received by parameter a is mutated, those changes are gonna be "felt" by dots[0] too; b/c dots[0] points to the same PVector object!
    • That is, both argument dots[0] & parameter a are alias to the same PVector object.

    How do I make it so the dots[] values aren't changed at all?

    • Notice that the overloaded PVector::sub() method w/ just 1 parameter mutates the PVector which had invoked it: :-SS
      https://Processing.org/reference/PVector_sub_.html
    • In order to steer from mutating PVector objects, we need to use their overloaded static methods:
    • You can make getAcute() request a 4th PVector argument to be used as a temporary calculation object: *-:)

    static final float getAcute(final PVector a, final PVector b, final PVector c, final PVector d) {
      return RAD_TO_DEG * PVector.angleBetween(PVector.sub(a, b, d), PVector.sub(c, b, d));
    }
    
    • Or if you don't mind instantiating 1 each time getAcute() is invoked, simply create that 4th PVector inside getAcute(): :-\"

    static final float getAcute(final PVector a, final PVector b, final PVector c) {
      final PVector d = new PVector();
      return RAD_TO_DEG * PVector.angleBetween(PVector.sub(a, b, d), PVector.sub(c, b, d));
    }
    
  • So, is this a call by reference or a call by value?

    float getAcute(PVector a, PVector b, PVector c) {

  • @Chrisir You are working with references. If the reference is changed inside the function, say a is assigned a new PVector using new, then a new memory address is created and assigned to a. However, the original object used to call by a is not affected. Also notice that the new created object assigned to a inside the function will not be available after the function ends. It will be lost. Does this answer your question?

    Kf

Sign In or Register to comment.