I am writing a program in Java (Processing 4).
Processing hides some stuff in the background which makes this more complicated. The main program "GeometryView" extends the PApplet class and has the usual functions. (This is the first tab that is created when creating a project in Processing)
ArrayList<Datum> datums = new ArrayList<Datum>();
void setup(){
size(1400, 900);
surface.setResizable(true);
//fullScreen();
frameRate(120);
datums.add(new Datum(0,0));
datums.add(new Datum(1,2));
datums.add(new Datum(3,4));
}
void draw() {
background(30);
stroke(220);
if(Functions.convex(datums.get(0),datums.get(1),datums.get(2))){
println("These points are part of a convex corner of geometry");
}
}
I have a class that I use to hold X and Y values named "Datum". This is a separate tab in Processing.
class Datum {
float x;
float y;
Datum(float x, float y){
this.x = x;
this.y = y;
}
void drawDatum(int size){
//print("X = " + this.x + ", Y = " + this.y);
ellipse(this.x, -this.y, size, size);
}
Datum clone(){
return new Datum(x,y);
}
}
Under a separate tab "Functions", I have a static class I use to hold different functions. This is to simplify the main parts of the program because I can call these functions without having to instantiate the class. (This may not be the correct way to do this, but it works for now. I just have to call "Functions.funcName();" This may also be a clue as to what my issue is)
static class Functions{
//...
//other functions
//...
static float crossproduct(Datum a, Datum b) {
return a.x * b.y - a.y * b.x;
}
static boolean convex(Datum a, Datum b, Datum c) {
Datum ab = new Datum(b.x - a.x, b.y - a.y); // Error here on "new Datum(x,y)"
Datum bc = new Datum(c.x - b.x, c.y - b.y);
return crossproduct(ab, bc) > 0;
}
}
On the line with
Datum ab = new Datum(b.x - a.x, b.y - a.y);
I am getting an error that says
"No enclosing instance of type GeometryView is accessible. Must qualify the allocation with an enclosing instance of type GeometryView." (GeometryView is the name of the main class and project).
I read some other posts that mentioned making the Datum class static, but then I can't access the built-in Processing functions like ellipse() and I get this error.
"Cannot make a static reference to the non-static method ellipse(float, float, float, float) from the type PApplet"
void drawDatum(int size){
//print("X = " + this.x + ", Y = " + this.y);
ellipse(this.x, -this.y, size, size); // <---- Error is here
}
Another solution was to create another instance of the main class to access the Datum class. Maybe that would work, but seems like it could be a performance issue to instantiate the entire program again just to access a simple class.
How can I use "new Datum(x,y)" inside my Functions class without breaking other parts of my program? Will creating a reference to my main class potentially cause memory issues or is it just creating a reference?
You can call expressionOfTypeGeometryView.new Datum()
to get rid of that error, but opens a new question: How do you get that. Well, Datum instances have such a reference - non-static inner classes have a secret hidden field of its outer type (and there IS an outer type here, but processing is hiding, that too - there's a lot of voodoo magic going on here which makes this unfortunately a bit complicated).
To end up with code that isn't an utter disaster to read, though, I suggest this alternative take. Add to your Datum class:
public Datum newDatum(int x, int y) {
return new Datum(x, y);
}
This does work because Datum does have that hidden field - it can therefore make new Datum objects 'out of the box' without needing the weird expr.new Datum
syntax. It means you need an instance of Datum to make new Datum objects - but you do have an instance.
Alternatively, for even nicer API, try:
public Datum subtract(Datum other) {
return new Datum(x - other.x, y - other.y);
}
and replace Datum ab = new Datum(b.x - a.x, b.y - a.y);
in your code with Datum ab = b.subtract(a);
which strikes me as just more readable in general - the code now describes intent better.