Null Pointers that shouldnt be null

Hello guys, i am getting a really weird error… And I hope you can help me.

  void show(int c) {
    noFill();
    stroke(c);
    strokeWeight(2);
    ellipse(center.x, center.y, 2*r, 2*r);

    this.a.show(255);
    this.b.show(255);
    this.c.show(255);
    // center.show(255);
    new Point2D(center.x, center.y).show(255);
    noStroke();
  }

That is my method show() for my Class Circle. Each circle is defined with 3 points (a, b, c). And the center is calculated with a method I have on a static Class.

And each Point is also a Class called Point2D with attributes x and y. And with its own show() that consists on drawing an ellipse.

The code I pasted works, but you can see the commented line is the same as the non-commented, but if I try to show the center, it causes a null pointer, while showing a new Point2D, doesnt. Also, points a, b and c are being shown without any problem.

Please, I wanna know what is causing a null pointer. If you need more code please, reply this post asking for it.

Hi! Could you show the Point2D class? Maybe its .show() method is trying to access something that is null?

That CAN’T be possible, because points a, b and c are also called with .show() and they raise no error.

This is my Point2D Class. The show is at the end, and is basically a point.

class Point2D {
 
  float x, y;
 
  Point2D(float x, float y) {
    this.x = x;
    this.y = y;
  }
 
  float[] polar(Point2D center) {
    float mod = center.dist1(this);
    float x = this.x - center.x;
    float y = this.y - center.y;
    float angle = abs(atan(y/x));
    if (x < 0 && y >= 0) angle = PI - angle;
    else if (x < 0 && y < 0) angle += PI;
    else if (x >= 0 && y < 0) angle = TWO_PI - angle;    
    return new float[]{mod, angle};
  }
 
  Point2D plus(Point2D A) {
    return new Point2D(this.x + A.x, this.y + A.y);
  }
 
  Point2D minus(Point2D A) {
    return new Point2D(this.x - A.x, this.y - A.y);
  }
 
  float dist1(Point2D A) {
    return sqrt(pow(A.x - this.x, 2) + pow(A.y - this.y, 2));
  }
 
  float dist2(Point2D A) {
    return pow(A.x - this.x, 2) + pow(A.y - this.y, 2);
  }
 
  float distLine(Line line) {
    if (util.sarea(line.a, line.b, this) == 0) return 0;
    else {
      Matrix matrix = new Matrix(new float [][] {{line.b.x - line.a.x, line.b.y - line.a.y}, {this.x - line.a.x, this.y - line.a.y}});
      float den = sqrt(pow(line.b.x - line.a.x, 2) + pow(line.b.y - line.a.y, 2));
      return abs(matrix.det()/den);
    }
  }
 
  float dotProd(PVector v) {
    return this.x * v.x + this.y * v.y;
  }
 
  Point2D midPoint(Point2D A) {
    return new Point2D((this.x + A.x)/2, (this.y + A.y)/2);
  }
 
  void update(float x, float y) {
    this.x = x;
    this.y = y;
  }
 
  String toString() {
    return "(" + x + "," + y + ")";
  }
 
  boolean equals(Object obj) {
    if (obj == this) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Point2D p = (Point2D) obj;
    return this.x == p.x && this.y == p.y;
  }
 
  void show(int c) {
    stroke(c);
    strokeWeight(10);
    point(x, y);
    strokeWeight(2);
    noStroke();
  }
 
  void show(int c, int alpha) {
    stroke(c, alpha);
    strokeWeight(10);
    point(x, y);
    strokeWeight(2);
    noStroke();
  }
 
  void show(int red, int green, int blue) {
    stroke(red, green, blue);
    strokeWeight(10);
    point(x, y);
    strokeWeight(2);
    noStroke();
  }
 
  void show(int red, int green, int blue, int alpha) {
    stroke(red, green, blue, alpha);
    strokeWeight(10);
    point(x, y);
    strokeWeight(2);
    noStroke();
  }
}

Also, take a look at this screen shoot. I put a breakpoint on the show(), where the null pointer is raised.

https://gyazo.com/94c1fc25ed870e8fa699ae6179682441

You’ve got me stumped. Would you mind posting all the code for the Circle class? It’s unlikely but the bug could be in how you’re creating the points.

I think with this all u can run the same code as me

class Circle {

  Point2D center, a, b, c;
  float r;

  Circle(Point2D a, Point2D b, Point2D c) {
    this.a = a;
    this.b = b;
    this.c = c;
    center = util.circumcenter(a, b, c);
    r = center.dist1(a);
  }

  Circle(Point2D center, float r) {
    this.center = center;
    this.r = r;
  }

  boolean inCircle(Point2D P) {
    return P.dist1(this.center) <= r;
  }

  void show(int col) {
    noFill();
    stroke(col);
    strokeWeight(2);
    ellipse(center.x, center.y, 2*r, 2*r);

    a.show(255);
    text("A", this.a.x+10, this.a.y-20);
    b.show(255);
    text("B", this.b.x+10, this.b.y-20);
    c.show(255);
    text("C", this.c.x+10, this.c.y-20);
    //center.show(255);
    new Point2D(center.x, center.y).show(255);
    noStroke();
  }

  void show(int red, int green, int blue) {
    noFill();
    stroke(red, green, blue);
    strokeWeight(2);
    ellipse(center.x, center.y, 2*r, 2*r);

    a.show(255);
    text("A", this.a.x+10, this.a.y-20);
    b.show(255);
    text("B", this.b.x+10, this.b.y-20);
    c.show(255);
    text("C", this.c.x+10, this.c.y-20);
    //center.show(255);
    new Point2D(center.x, center.y).show(255);
    noStroke();
  }
}
  static Point2D circumcenter(Point2D A, Point2D B, Point2D C) throws IllegalArgumentException {
    if (util.sarea(A, B, C) == 0) {
      throw new IllegalArgumentException("Points do not define a Circle");
      //return gtc.new Point2D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
    } else {

      Point2D AB = B.minus(A);
      Point2D AC = C.minus(A);

      Point2D ortoab = gtc.new Point2D(-AB.y, AB.x);
      Point2D ortoac = gtc.new Point2D(-AC.y, AC.x);

      Point2D midab = A.midPoint(B);
      Point2D midac = A.midPoint(C);

      Line r = gtc.new Line(midab, midab.plus(ortoab));
      Line s = gtc.new Line(midac, midac.plus(ortoac));

      return r.intersection(s);
    }
  }
  Point2D intersection(Line l) {
    // Line AB represented as a1x + b1y = c1
    float a1 = l.b.y - l.a.y;
    float b1 = l.a.x - l.b.x;
    float c1 = a1*(l.a.x) + b1*(l.a.y);

    // Line CD represented as a2x + b2y = c2
    float a2 = this.b.y - this.a.y;
    float b2 = this.a.x - this.b.x;
    float c2 = a2*(this.a.x) + b2 * (this.a.y);

    Matrix temp = new Matrix(new float[][] {{a1, b1}, {a2, b2}});
    float determinant = temp.det();

    if (determinant == 0) {
      // The lines are parallel
      //return new Point2D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
      return null;
    } else {
      float x = (b2*c1 - b1*c2)/determinant;
      float y = (a1*c2 - a2*c1)/determinant;

      return new Point2D(x, y);
    }
  }

The answer is in the Line class intersection can return null therefore circumcenter can return null. It means that after

center = util.circumcenter(a, b, c);

center could be null.

2 Likes

Yeah, thats why new Point2D(center.x, center.y).show(255) does not throw any null pointer…

If center was null, center.x will throw a NPE also

And also, 3 points that are not collinears always define a circle, and a circle always has a center. and if the 3 points were collinears, an IllegalArgumentException would be thrown, not a NPE

But without entering on maths details, if center is null (and it is not; look the screenshoot of the variables), center.x and center.y shoule be null too

And also if I do println(center) just above the center.show(255), I got the center coordinates printed on the console

I don’t think so!

Can you post the entire code or make it available some other way because I am having serious problems trying to trace your code thorugh these posts.

Well, I have many different files, so I will try to make this work without the not necessary files.

This is the main Sketch.

void setup() {
  size(600, 500);
  background(100);
  mouse = new Point2D(0,0);
  Point2D a, b, c;
  a = new Point2D(random(0, width), random(0, height));
  b = new Point2D(random(0, width), random(0, height));
  c = new Point2D(random(0, width), random(0, height));
  circle = new Circle(a, b, c);
}

void draw(){
  mouse.update(mouseX, mouseY);
  circle.show(255);
  mouse.show(255);
  if (circle.inCircle(mouse)) {
    circle.show(255, 0, 0);
    mouse.show(255, 0, 0);
  }
}

This is the Point2D Class

class Point2D {

  float x, y, size;

  Point2D(float x, float y) {
    this.x = x;
    this.y = y;
    size = 10;
  }

  float[] polar(Point2D center) {
    float mod = center.dist1(this);
    float x = this.x - center.x;
    float y = this.y - center.y;
    float angle = abs(atan(y/x));
    if (x < 0 && y >= 0) angle = PI - angle;
    else if (x < 0 && y < 0) angle += PI;
    else if (x >= 0 && y < 0) angle = TWO_PI - angle;    
    return new float[]{mod, angle};
  }

  Point2D plus(Point2D A) {
    return new Point2D(this.x + A.x, this.y + A.y);
  }

  Point2D minus(Point2D A) {
    return new Point2D(this.x - A.x, this.y - A.y);
  }

  float dist1(Point2D A) {
    return sqrt(pow(A.x - this.x, 2) + pow(A.y - this.y, 2));
  }

  float dist2(Point2D A) {
    return pow(A.x - this.x, 2) + pow(A.y - this.y, 2);
  }

  float distLine(Line line) {
    if (util.sarea(line.a, line.b, this) == 0) return 0;
    else {
      Matrix matrix = new Matrix(new float [][] {{line.b.x - line.a.x, line.b.y - line.a.y}, {this.x - line.a.x, this.y - line.a.y}}); 
      float den = sqrt(pow(line.b.x - line.a.x, 2) + pow(line.b.y - line.a.y, 2));
      return abs(matrix.det()/den);
    }
  }

  float dotProd(PVector v) {
    return this.x * v.x + this.y * v.y;
  }

  Point2D midPoint(Point2D A) {
    return new Point2D((this.x + A.x)/2, (this.y + A.y)/2);
  }

  void update(float x, float y) {
    this.x = x;
    this.y = y;
  }

  String toString() {
    return "(" + x + "," + y + ")";
  }

  boolean equals(Object obj) {
    if (obj == this) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Point2D p = (Point2D) obj;
    return this.x == p.x && this.y == p.y;
  }
  
  void size(int i){
    size = i;
  }

  void show(int col) {
    stroke(col);
    strokeWeight(size);
    point(x, y);
    noStroke();
  }

  void show(int col, int alpha) {
    stroke(col, alpha);
    strokeWeight(size);
    point(x, y);
    noStroke();
  }

  void show(int red, int green, int blue) {
    stroke(red, green, blue);
    strokeWeight(size);
    point(x, y);
    noStroke();
  }

  void show(int red, int green, int blue, int alpha) {
    stroke(red, green, blue, alpha);
    strokeWeight(size);
    point(x, y);
    noStroke();
  }
}

This is the Circle Class

class Circle {

  Point2D center, a, b, c;
  float r;

  Circle(Point2D a, Point2D b, Point2D c) {
    this.a = a;
    this.b = b;
    this.c = c;
    center = util.circumcenter(a, b, c);
    r = center.dist1(a);
  }

  Circle(Point2D center, float r) {
    this.center = center;
    this.r = r;
  }

  boolean inCircle(Point2D P) {
    return P.dist1(this.center) <= r;
  }

  void show(int col) {
    noFill();
    stroke(col);
    strokeWeight(2);
    ellipse(center.x, center.y, 2*r, 2*r);

    a.show(255);
    text("A", this.a.x+10, this.a.y-20);
    b.show(255);
    text("B", this.b.x+10, this.b.y-20);
    c.show(255);
    text("C", this.c.x+10, this.c.y-20);
    //center.show(255);
    new Point2D(center.x, center.y).show(255);
    noStroke();
  }

  void show(int red, int green, int blue) {
    noFill();
    stroke(red, green, blue);
    strokeWeight(2);
    ellipse(center.x, center.y, 2*r, 2*r);

    a.show(255);
    text("A", this.a.x+10, this.a.y-20);
    b.show(255);
    text("B", this.b.x+10, this.b.y-20);
    c.show(255);
    text("C", this.c.x+10, this.c.y-20);
    //center.show(255);
    new Point2D(center.x, center.y).show(255);
    noStroke();
  }
}

This is the Class Matrix

class Matrix {

  int m;             // number of rows
  int n;             // number of columns
  float[][] data;    // M-by-N array

  // create M-by-N matrix of 0's
  Matrix(int m, int n) {
    this.m = m;
    this.n = n;
    data = new float[m][n];
  }

  // create matrix based on 2d array
  Matrix(float[][] data) {
    m = data.length;
    n = data[0].length;
    this.data = new float[m][n];
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        this.data[i][j] = data[i][j];
  }

  // copy constructor
  private Matrix(Matrix A) { 
    copy(A.data);
  }

  float[][] copy(float[][] data) {
    float[][] copiedData = new float[data.length][data[0].length];
    for (int i = 0; i < copiedData.length; i++) {
      arrayCopy(data[i], copiedData[i]);
    }
    return copiedData;
  }

  // create and return a 1's M-by-N matrix
  Matrix ones(int m, int n) {
    Matrix a = new Matrix(m, n);
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        a.data[i][j] = 1;
    return a;
  }

  // swap rows i and j
  void swap(int i, int j) {
    float[] temp = data[i];
    data[i] = data[j];
    data[j] = temp;
  }

  // create and return the transpose of the invoking matrix
  Matrix transpose() {
    Matrix a = new Matrix(n, m);
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        a.data[j][i] = this.data[i][j];
    return a;
  }

  // return C = this + B
  Matrix plus(Matrix b) {
    Matrix a = this;
    if (b.m != a.m || b.n != a.n) throw new RuntimeException("Illegal matrix dimensions.");
    Matrix c = new Matrix(m, n);
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        c.data[i][j] = a.data[i][j] + b.data[i][j];
    return c;
  }


  // return C = this - B
  Matrix minus(Matrix b) {
    Matrix a = this;
    if (b.m != a.m || b.n != a.n) throw new RuntimeException("Illegal matrix dimensions.");
    Matrix c = new Matrix(m, n);
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        c.data[i][j] = a.data[i][j] - b.data[i][j];
    return c;
  }

  // return C = this * B
  Matrix times(Matrix b) {
    Matrix a = this;
    if (a.n != b.m) throw new RuntimeException("Illegal matrix dimensions.");
    Matrix c = new Matrix(a.m, b.n);
    for (int i = 0; i < c.m; i++)
      for (int j = 0; j < c.n; j++)
        for (int k = 0; k < a.n; k++)
          c.data[i][j] += (a.data[i][k] * b.data[k][j]);
    return c;
  }

  // does this = B exactly?
  boolean eq(Matrix b) {
    Matrix a = this;
    if (b.m != a.m || b.n != a.n) throw new RuntimeException("Illegal matrix dimensions.");
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        if (a.data[i][j] != b.data[i][j]) return false;
    return true;
  }

  // return det(this)
  float det() {
    if (this.m != this.n) {
      throw new IllegalArgumentException("Rows != Columns");
    }

    float det = 0;
    int n = this.n;

    if (n == 1) {
      det = this.data[0][0];
    } else if (n == 2) {
      det = this.data[0][0] * this.data[1][1] - this.data[1][0] * this.data[0][1];
    } else {
      for (int minorCollum = 0; minorCollum < n; minorCollum++) {
        float[][] m = new float[n - 1][n - 1];
        for (int j = 1; j < n; j++) {
          for (int i = 0; i < minorCollum; i++) {
            m[j - 1][i] = this.data[j][i];
          }
          for (int i = minorCollum + 1; i < n; i++) {
            m[j - 1][i - 1] = this.data[j][i];
          }
        }
        Matrix aa = new Matrix(m);
        det += (minorCollum % 2 == 0 ? 1 : -1) * this.data[0][minorCollum] * aa.det();
      }
    }
    return det;
  }

  // solve this * X = rhs. Return X
  Matrix solve(Matrix rhs) {
    if (m != n || rhs.m != n || rhs.n != 1)
      throw new RuntimeException("Illegal matrix dimensions.");

    // create copies of the data
    Matrix a = new Matrix(this);
    Matrix b = new Matrix(rhs);

    // Gaussian elimination with partial pivoting
    for (int i = 0; i < n; i++) {

      // find pivot row and swap
      int max = i;
      for (int j = i + 1; j < n; j++)
        if (Math.abs(a.data[j][i]) > Math.abs(a.data[max][i]))
          max = j;
      a.swap(i, max);
      b.swap(i, max);

      // singular
      if (a.data[i][i] == 0.0) throw new RuntimeException("Matrix is singular.");

      // pivot within b
      for (int j = i + 1; j < n; j++)
        b.data[j][0] -= b.data[i][0] * a.data[j][i] / a.data[i][i];

      // pivot within A
      for (int j = i + 1; j < n; j++) {
        double m = a.data[j][i] / a.data[i][i];
        for (int k = i+1; k < n; k++) {
          a.data[j][k] -= a.data[i][k] * m;
        }
        a.data[j][i] = 0.0;
      }
    }

    // back substitution
    Matrix x = new Matrix(n, 1);
    for (int j = n - 1; j >= 0; j--) {
      float t = 0.0;
      for (int k = j + 1; k < n; k++)
        t += a.data[j][k] * x.data[k][0];
      x.data[j][0] = (b.data[j][0] - t) / a.data[j][j];
    }
    return x;
  }

  // print matrix to standard output
  void show() {
    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) 
        print(nf(data[i][j], 4, 3), " ");
      println();
    }
  }
}

This is the Class Line

class Line{

  Point2D a, b;

  Line(Point2D a, Point2D b) {
    this.a = a;
    this.b = b;
  }

  Line(Point2D a, PVector v) {
    this.a = a;
    this.b = new Point2D(a.x + v.x, a.y + v.y);
  }

  void update(Point2D end) {
    b = end;
  }

  Point2D intersection(Line l) {
    // Line AB represented as a1x + b1y = c1
    float a1 = l.b.y - l.a.y;
    float b1 = l.a.x - l.b.x;
    float c1 = a1*(l.a.x) + b1*(l.a.y);

    // Line CD represented as a2x + b2y = c2
    float a2 = this.b.y - this.a.y;
    float b2 = this.a.x - this.b.x;
    float c2 = a2*(this.a.x) + b2 * (this.a.y);

    Matrix temp = new Matrix(new float[][] {{a1, b1}, {a2, b2}});
    float determinant = temp.det();

    if (determinant == 0) {
      // The lines are parallel
      //return new Point2D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
      return null;
    } else {
      float x = (b2*c1 - b1*c2)/determinant;
      float y = (a1*c2 - a2*c1)/determinant;

      return new Point2D(x, y);
    }
  }

  Point2D intersection(Segment s) {   
    if (util.orientation(a, b, s.a) != util.orientation(a, b, s.b)) {
      Line l = new Line(s.a, s.b);
      return this.intersection(l);
    } else {
      return null;
    }
  }

  float getY(float x) {
    // Line AB represented as a1x + b1y = c1
    float a1 = b.y - a.y;
    float b1 = a.x - b.x;
    float c1 = a1*(a.x) + b1*(a.y);
    return (c1 - a1 * x) / b1;
  }

  void show(int col, boolean p) {
    Point2D v = new Point2D(b.x - a.x, b.y - a.y);
    stroke(col);
    strokeWeight(2);
    if (v.x == 0) {
      line(a.x, 0, b.x, height);
    } else {
      float slope = v.y / v.x;
      float n = a.y - slope * a.x;
      line(0, n, width, slope * width + n);
    }
    noStroke();
    if (p) {
      fill(255);
      a.show(255);
      text("A", a.x + 5, a.y - 10);
      b.show(255);
      text("B", b.x + 5, b.y - 10);
      noFill();
    }
    noStroke();
  }

  void show(int red, int green, int blue, boolean p) {
    Point2D v = new Point2D(b.x - a.x, b.y - a.y);
    stroke(red, green, blue);
    strokeWeight(2);
    if (v.x == 0) {
      line(a.x, 0, b.x, height);
    } else {
      float slope = v.y / v.x;
      float n = a.y - slope * a.x;
      line(0, n, width, slope * width + n);
    }
    noStroke();
    if (p) {
      fill(255);
      a.show(255);
      text("A", a.x + 5, a.y - 10);
      b.show(255);
      text("B", b.x + 5, b.y - 10);
      noFill();
    }
    noStroke();
  }
}

This is the Class Segment (im not sure if you need but i paste it anyway)

class Segment implements Comparable<Segment> {

  Point2D a, b;
  float len;

  Segment(Point2D a, Point2D b) {
    this.a = a;
    this.b = b;
    len = a.dist1(b);
  }

  boolean inSegment(Point2D P) {
    float leftEdge = min(this.a.x, this.b.x);
    float rightEdge = max(this.a.x, this.b.x);
    float topEdge = max(this.a.y, this.b.y);
    float botEdge = min(this.a.y, this.b.y);

    boolean isInBounds = P.x <= rightEdge && P.x >= leftEdge && P.y <= topEdge && P.y >= botEdge;
    boolean isOriented = util.orientation(this.a, this.b, P) == 0;

    return isInBounds && isOriented;
  }

  Point2D intersection(Segment s) {
    //calculate the distance to intersection point
    Matrix matrix = new Matrix(new float[][] {{s.b.x - s.a.x, s.b.y - s.a.y}, {this.b.x - this.a.x, this.b.y - this.a.y}});

    float denominator = matrix.det();
    float uA = ((this.b.x-this.a.x)*(s.a.y-this.a.y) - (this.b.y-this.a.y)*(s.a.x-this.a.x)) / denominator;
    float uB = ((s.b.x-s.a.x)*(s.a.y-this.a.y) - (s.b.y-s.a.y)*(s.a.x-this.a.x)) / denominator;

    // if uA and uB are between 0-1, lines are colliding
    if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {

      // optionally, draw a circle where the lines meet
      float intersectionX = s.a.x + (uA * (s.b.x-s.a.x));
      float intersectionY = s.a.y + (uA * (s.b.y-s.a.y));

      return new Point2D(intersectionX, intersectionY);
    }
    return null;
  }

  Point2D intersection(Line l) {   
    if (util.orientation(l.a, l.b, a) != util.orientation(l.a, l.b, b)) {
      Line s = new Line(a, b);
      return s.intersection(l);
    } else {
      return null;
    }
  }

  Segment twin() {
    return new Segment(b, a);
  }

  void update(Point2D b) {
    this.b = b;
  }

  public boolean equals(Object obj) {
    if (obj == this) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Segment other = (Segment) obj;
    return (a.equals(other.a) && b.equals(other.b)) || (a.equals(other.b) && b.equals(other.a));
  }

  public int hashCode() {
    return a.hashCode() + b.hashCode();
  }

  boolean contains(Point2D p) {
    return p.equals(a) || p.equals(b);
  }

  int compareTo(Segment s) {
    if (this.len == s.len) return 0;
    else if (this.len < s.len) return -1;
    else return 1;
  }

  String toString() {
    //return "(" + a + "," + b + ")" + "Length = " + len; 
    return str(len);
  }

  void show(int col) {
    stroke(col);
    strokeWeight(2);
    line(a.x, a.y, b.x, b.y);
    noStroke();
  }

  void show(int red, int green, int blue) {
    stroke(red, green, blue);
    strokeWeight(2);
    line(a.x, a.y, b.x, b.y);
    noStroke();
  }
}

And this is the static class Util

static class util {

  private static GTC gtc = new GTC();

  static float sarea(Point2D A, Point2D B, Point2D C) {
    float [][] d = {{1, 1, 1}, {A.x, B.x, C.x}, {A.y, B.y, C.y}};
    Matrix matrix = gtc.new Matrix(d);
    return matrix.det()/2;
  }

  static int orientation(Point2D A, Point2D B, Point2D C) {
    float area = sarea(A, B, C);
    if (area < 0) {
      return -1;
    } else if (area == 0) {
      return 0;
    } else {
      return 1;
    }
  }

  static Point2D circumcenter(Point2D A, Point2D B, Point2D C) throws IllegalArgumentException {
    if (util.sarea(A, B, C) == 0) {
      throw new IllegalArgumentException("Points do not define a Circle");
      //return gtc.new Point2D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
    } else {

      Point2D AB = B.minus(A);
      Point2D AC = C.minus(A);

      Point2D ortoab = gtc.new Point2D(-AB.y, AB.x);
      Point2D ortoac = gtc.new Point2D(-AC.y, AC.x);

      Point2D midab = A.midPoint(B);
      Point2D midac = A.midPoint(C);

      Line r = gtc.new Line(midab, midab.plus(ortoab));
      Line s = gtc.new Line(midac, midac.plus(ortoac));

      return r.intersection(s);
    }
  }

  static Point2D incenter(Point2D A, Point2D B, Point2D C) {
    if (util.sarea(A, B, C) == 0) {
      //throw new RuntimeException("Points do not define a Circle");
      return gtc.new Point2D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
    } else {
      float da = B.dist1(C);
      float db = A.dist1(C);
      float dc = A.dist1(B);
      float sum = da + db + dc;

      float x = (da*A.x + db*B.x + dc*C.x)/sum;
      float y = (da*A.y + db*B.y + dc*C.y)/sum;

      return gtc.new Point2D(x, y);
    }
  }

  static Point2D[] boundingBox(Point2D[] list) {
    float xmin = xmin(list);
    float ymin = ymin(list);
    float xmax = xmax(list);
    float ymax = ymax(list);

    Point2D[] res = new Point2D[4];

    res[0] = gtc.new Point2D(xmin, ymin);
    res[1] = gtc.new Point2D(xmax, ymin);
    res[2] = gtc.new Point2D(xmax, ymax);
    res[3] = gtc.new Point2D(xmin, ymax);

    return res;
  }

  static Point2D[][] medianByDir(Point2D[] list, PVector dir) {

    int n = list.length;
    PVector d = new PVector(-dir.y, dir.x);

    Point2D[] sorted = selectionSortDir(list, d);
    Point2D[] fhalf = new Point2D[n/2];
    Point2D[] shalf = new Point2D[n/2];

    Point2D median;

    if (n % 2 == 0) {
      median = sorted[n/2 - 1].midPoint(sorted[n/2]);
    } else {
      median = sorted[n/2];
    }

    for (int i = 0; i < n/2; i++) {
      fhalf[i] = sorted[i];
      shalf[i] = sorted[n - i - 1];
    }

    return new Point2D[][] {{median}, fhalf, shalf};
  }

  static Point2D[] selectionSortDir(Point2D[] list, PVector dir) {
    int n = list.length;
    Point2D[] sorted = list.clone();

    // One by one move boundary of unsorted subarray
    for (int i = 0; i < n-1; i++) {
      // Find the minimum element in unsorted array
      int min_idx = i;
      for (int j = i+1; j < n; j++) {
        PVector normDir = dir.normalize(); 
        float d1 = sorted[j].dotProd(normDir);
        float d2 = sorted[min_idx].dotProd(normDir);
        if (d1 < d2) {
          min_idx = j;
        }
      }

      // Swap the found minimum element with the first element
      Point2D temp = sorted[min_idx];
      sorted[min_idx] = sorted[i];
      sorted[i] = temp;
    }
    return sorted;
  }

  static Point2D[] selectionSortAngle(Point2D[] list, Point2D p) {
    int n = list.length;
    Point2D[] sorted = list.clone();

    // One by one move boundary of unsorted subarray
    for (int i = 0; i < n-1; i++) {
      // Find the minimum element in unsorted array
      int min_idx = i;
      for (int j = i+1; j < n; j++) {
        float a1 = sorted[j].polar(p)[1];
        float a2 = sorted[min_idx].polar(p)[1];
        if (a1 < a2) {
          min_idx = j;
        }
      }

      // Swap the found minimum element with the first element
      Point2D temp = sorted[min_idx];
      sorted[min_idx] = sorted[i];
      sorted[i] = temp;
    }
    return sorted;
  }

  // Returns ALL the points with max x
  static Point2D[] p_xmax(Point2D[] list) {
    ArrayList<Point2D> res = new ArrayList<Point2D>();
    float xmax = xmax(list); 
    for (int i = 0; i < list.length; i++) {
      if (list[i].x == xmax)
        res.add(list[i]);
    }
    return res.toArray(new Point2D[res.size()]);
  }

  // Returns ALL the points with min x
  static Point2D[] p_xmin(Point2D[] list) {
    ArrayList<Point2D> res = new ArrayList<Point2D>();
    float xmin = xmin(list); 
    for (int i = 0; i < list.length; i++) {
      if (list[i].x == xmin)
        res.add(list[i]);
    }
    return res.toArray(new Point2D[res.size()]);
  }

  // Returns ALL the points with max y
  static Point2D[] p_ymax(Point2D[] list) {
    ArrayList<Point2D> res = new ArrayList<Point2D>();
    float ymax = ymax(list); 
    for (int i = 0; i < list.length; i++) {
      if (list[i].y == ymax)
        res.add(list[i]);
    }
    return res.toArray(new Point2D[res.size()]);
  }

  // Returns ALL the points with min y
  static Point2D[] p_ymin(Point2D[] list) {
    ArrayList<Point2D> res = new ArrayList<Point2D>();
    float ymin = ymin(list); 
    for (int i = 0; i < list.length; i++) {
      if (list[i].y == ymin)
        res.add(list[i]);
    }
    return res.toArray(new Point2D[res.size()]);
  }

  static float xmax(Point2D[] list) {
    float [] xlist = new float[list.length];
    for (int i = 0; i < xlist.length; i++) {
      xlist[i] = list[i].x;
    }
    return max(xlist);
  }

  static float xmin(Point2D[] list) {
    float [] xlist = new float[list.length];
    for (int i = 0; i < xlist.length; i++) {
      xlist[i] = list[i].x;
    }
    return min(xlist);
  }

  static float ymax(Point2D[] list) {
    float [] ylist = new float[list.length];
    for (int i = 0; i < ylist.length; i++) {
      ylist[i] = list[i].y;
    }
    return max(ylist);
  }

  static float ymin(Point2D[] list) {
    float [] ylist = new float[list.length];
    for (int i = 0; i < ylist.length; i++) {
      ylist[i] = list[i].y;
    }
    return min(ylist);
  }
}
1 Like

Need the GTC class …

The GTC class is the main Sketch. Rename it as GTC

OK I have the sketch and I can run it. Do I have to do something to generate the bug?

Yes, go to the Circle Class, and swap the commented lines on show() of the center

OK so I get the error. Let me play with it tomorrow and I will see what I can find out. :slight_smile:

Thank you very much. You can add me on discord if you prefer: Aza#4334

Problem solved.:joy:

You need to make two changes to your code

Change 1)
In the util class change line 3 from
private static GTC gtc = new GTC();
to
private static GTC gtc = null;

Change 2)
Modify the setup() method to start

void setup() {
  size(600, 500);
  util.gtc = this; // Do this immediately after call to size(...)
  background(100);

The problem was caused in the util class because the statement new GTC() was effectively creating a second sketch with its own graphics screen.

This has the added bonus in that you can call the sketch anything you like not just GTC

1 Like

Sorry I didn’t understand that.

Could you explain as if I were silly? :smiley:

And also, why is this error only for the center and not for the other points?

I assume that you have modified and run your sketch and that it works for you, am I right?

Do you understand the syntax of the code changes I have made?

Yes, the syntax yes. I dont understand why do I need an object GTC and what is that, and why to give it a value from the main, and not on the static class