Tuesday 9 February 2010

Object orientation and images

Object orientation is a powerful concept. Using object orientation we can make our programs such that we can follow one of the golden rules of Software Development. This is, never to repeat the same code. Why reinvent the wheel when we can use part of what there already.



Java provides some useful tools to allow us to make our programs more Object Orientated. When I started programming in Java I moved from procedural programming where typically there was a start and an end. I was repeatedly given instructions from my boss to make it more OO.



I hope this program helps you make your code more OO.


Inheritance allows us to build on those existing classes and make them more advanced. Interfaces, like Java classes also support inheritance.



The following program shows both of these concepts. I have based this program on the humble triangle. There are two interfaces namely BasicTriangleInterface and SuperTriangleInterface. These interfaces specify the methods that must be described in any class that uses them. It’s a way of inforcing that the correct methods are covered in our code.



BasicTraingleInterface specifies the methods show hide and draw. The class BasicTriangle implements this interface and therefore must use these methods of the program won’t compile. Our basic triangle doesn’t do much though. We can show it and hide it but that’s really about it.



So now I want to be able to change my triangle and by selecting a point and using the mouse to reshape my triangle. I call this my SuperTriangle. SuperTriangleInterface therefore needs to specify some new methods that will need to be used to allow this. I still want my SuperTriangle to have the same characters as the BasicTriangle so instead of rewriting the code I can simply extend the SuperTriangleInterface to use the BasicTriangleInterface specifications. So Now I have the additional methods that the SuperTriangle class needs to implement. The same goes for the SuperTriangle class. By extending the BasicTriangle class I am using the methods show and hide from BasicTriangle to prevent having to rewrite the code. You will notice that I still specify the draw method in the SuperTriangle class. This is because there are specific things that the SuperTriangle does differently and so I am overriding the draw method in BasicTriangle. This is because the draw method needs some extra code to deal with the super triangle. Now I have a Super triangle that I can manipulate.


Another thing to note it that in the constructor of the SuperTriangle class I have a call to super. This simple invokes the constructor of the super class BasicTriangle. Now if you run this program you will be able to call the methods hide and show for an instance of SuperTriangle. So we are using these features of BasicTriangle without having to add these methods.

When you run this program you will see the basic triangle at the top and the super triangle at the bottom. Select a point and click and drag using your mouse and when you release the mouse the triangle will the way you specified. To aid in the selection process the mouse cursor will change when you are close enough to a point on the super triangle and I’ve used yellow lines to help you see how the super triangle will redraw.


The Program:

// Class Varibles or Global variables in this context
int circleSize = 10;
int buttonX;
BasicTriangle basicTriangle;
SuperTriangle superTriangle;

void setup() {
size(600,600);
fill(255, 204);
noStroke();
smooth();
frameRate(70);

basicTriangle = new BasicTriangle(12,12,110,150,230,160);
superTriangle = new SuperTriangle(500,500,310,350,430,460);
}

/** Mouse Dragged so call supertriangle method */
void mouseDragged() {
superTriangle.dragged();
}

/** Mouse Released so call supertriangle method */
void mouseReleased() {
superTriangle.released();
}

void draw() {
background(0);
basicTriangle.draw();
superTriangle.updatePosition();
superTriangle.draw();
}

/** The basic methods that a shape should have */
interface BasicTriangleInterface {
void hide();
void show();
void draw();
}

/** The super Triangle methods that a supertraingle should have */
interface SuperTriangleInterface extends BasicTriangleInterface {
void dragged();
void released();
void draw();
}

/** A class that encapsulates a basic triangle that can be shown and hidden */
class BasicTriangle implements BasicTriangleInterface {
boolean show = true;
int triangleX1, triangleY1, triangleX2, triangleY2, triangleX3, triangleY3;

/** A constructor that takes three coordinates */
BasicTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
this.triangleX1 = x1;
this.triangleY1 = y1;
this.triangleX2 = x2;
this.triangleY2 = y2;
this.triangleX3 = x3;
this.triangleY3 = y3;
}

/** Method to show the traingle */
void show() {
show = true;
}

/** Method to hide the triangle */
void hide() {
show = false;
}

void draw() {
stroke(255);
fill(0,0,255);

if (show) triangle(triangleX1,triangleY1, triangleX2,triangleY2, triangleX3,triangleY3);
fill(0);
stroke(255,255,0);
}
}

/** Super Triangle class that can be reshaped and extends BasicTriangle */
class SuperTriangle extends BasicTriangle implements SuperTriangleInterface{
float x1, y1, x2, y2, x3, y3;
boolean holdTriangle1, holdTriangle2, holdTriangle3, overTriangle1, overTriangle2, overTriangle3 = false;

/** Constructor to create a super triangle simple calls the constructor of BasicTriangle */
SuperTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
super(x1, y1, x2, y2, x3, y3);
}

/** Method to keep track of the mouse position */
void updatePosition() {
if(overButton(this.triangleX1, this.triangleY1, circleSize)|| this.holdTriangle1) this.overTriangle1 = true;
else this.overTriangle1 = false;
if( overButton(this.triangleX2, this.triangleY2, circleSize)|| this.holdTriangle2) this.overTriangle2 = true;
else this.overTriangle2 = false;
if( overButton(this.triangleX3, this.triangleY3, circleSize)|| this.holdTriangle3) this.overTriangle3 = true;
else this.overTriangle3 = false;
}

/** Method to determine if the mouse is over a control point */
boolean overButton(int x, int y, int diameter)
{
float disX = x - mouseX;
float disY = y - mouseY;
if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) return true;
else return false;
}

/** Method to be called when the mouse is being dragged */
void dragged(){
if (overTriangle1) holdTriangle1 = true;
if (overTriangle2) holdTriangle2 = true;
if (overTriangle3) holdTriangle3 = true;
}

/** Method to be called when the mouse has being released */
void released() {
if (holdTriangle1){
triangleX1 = mouseX;
triangleY1 = mouseY;
holdTriangle1 = false;
}
if (holdTriangle2){
triangleX2 = mouseX;
triangleY2 = mouseY;
holdTriangle2 = false;
}
if (holdTriangle3){
triangleX3 = mouseX;
triangleY3 = mouseY;
holdTriangle3 = false;
}
}


void draw() {
// Change the mouse cursor when necessary
if (overTriangle1 || overTriangle2 || overTriangle3) cursor(HAND);
else cursor(ARROW);

this.updatePosition();
stroke(255);
fill(0,0,255);

if (show)
triangle(triangleX1,triangleY1, triangleX2,triangleY2, triangleX3,triangleY3);

fill(0);
stroke(255,255,0);

if (overTriangle1 && holdTriangle1){
line(mouseX,mouseY,triangleX2,triangleY2);
line(mouseX,mouseY,triangleX3,triangleY3);
line(triangleX2,triangleY2,triangleX3,triangleY3);
}
if (overTriangle2 && holdTriangle2){
line(mouseX,mouseY,triangleX1,triangleY1);
line(mouseX,mouseY,triangleX3,triangleY3);
line(triangleX1,triangleY1,triangleX3,triangleY3);
}
if (overTriangle3 && holdTriangle3){
line(mouseX,mouseY,triangleX2,triangleY2);
line(mouseX,mouseY,triangleX1,triangleY1);
line(triangleX2,triangleY2,triangleX1,triangleY1);
}
}
}