Advertisement

this edited version of your code does not show the buttons in the panel. The problem was your incorrect implementation of JPanels. You should never override paint(..) but paintComponent(..) instead. your implementation would have been ok for AWT but not Swing. get rid of all of your update and paint functions. put your 'update' code in paintComponent() save the call to repaint(). The DefaultPoints Panel is unnecessary. here is a revision of GrahamScan:

package runjava;

* Author Paul wood

* This class is a JPanel used to display all of the steps

* involved in the Grahams Scan algorithm. It addds an animation

* feature to the JPanel using threads

import javax.swing.JOptionPane;

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

public class GrahamScan extends JPanel implements Runnable {

//Edited by BlairTheMagician

static int[][]coords = new int[][]{ {20, 90}, {100, 140}, {25, 200}, {150, 140},

{120, 220}, {115, 200}, {150, 55}, {125, 120},

{200, 140}, {250, 210},{220, 265}, {240, 240} };

// Create an array of type Point

static Point[] defaultPoints = new Point[coords.length];

static

// add the points of the coords 2d array into the point array

for(int i = 0; i < defaultPoints.length; i++)

defaultPoints[i] = new Point(coords[0],coords[i][1]);

}// end edit by the Magician

// initialise constants used for button presses

public final static int COMPLETE = 1;

public final static int ANCHOR = 2;

public final static int ANGLE = 3;

public final static int CONVEX = 4;

public final static int ANIMATION = 5;

public final static int STOPANIM = 6;

public final static int STEP = 7;

public final static int BUILD = 8;

private int complete;

private int anchor;

private int angle;

private int build;

private int convex;

private int step;

private int nextStep;

Point test1;

Point test2;

// these are used to get the sets of points

DefaultPanel defaultPanel;

OwnPointsDemo ownPointsPanel;

Point[] points;

// this is still not workink

//Point[] points = ownPointPanel.points;

int draw = 2;

int count = 2;

int val = 0;

int[][] lineDraw;

boolean completeHull = false;

int start = 0;

// default delay

int delay = 1000;

// animation stuff

int frameNumber = 0;

volatile Thread animatorThread = null;

boolean threadSuspended = false;

// create an array to hold the final convex hull points

Point[] convexHull;

ArrayStack S;

public GrahamScan(DefaultPanel defaultPanel, OwnPointsDemo ownPointsPanel )

// add demo panel

// JPanel grahamScanPanel = new JPanel();

this.defaultPanel = defaultPanel;

this.ownPointsPanel = ownPointsPanel;

points = defaultPanel.points;

convexHull = new Point[points.length];

S = new ArrayStack(points.length);

//Point[] points = ownPointPanel.points;

lineDraw = new int[points.length][points.length];

public void startAnimation()

//Create and start the animating thread.

if (animatorThread == null) {

animatorThread = new Thread(this);

animatorThread.start();

public void stopAnimation() {

//Stop the animating thread.

if (animatorThread != null) {

animatorThread = null;

public void run()

final Thread currentThread = Thread.currentThread();

reset();

step = STEP;

while( animatorThread == currentThread) {

try{

currentThread.sleep(delay);

synchronized(this) {

while (threadSuspended && animatorThread == currentThread)

wait();

}catch( InterruptedException ex ){}

frameNumber++;

nextStep++;

repaint();

public void paint( Graphics g )

update(g);

public void paintComponent( Graphics g )

Graphics2D g2 = (Graphics2D)g;

//super.paint( g2 );

g2.setColor(Color.white);

g2.fillRect(0,0,this.getWidth(),this.getHeight());

g2.setColor(Color.black);

// edit by BTM begin

// draw default points

for(int i = 0; i < defaultPoints.length; i++)

g2.fillOval( defaultPoints[i].x, defaultPoints[i].y, 4, 4 );

// end edit by BTM

// initialise a polygon for visual testing of the algorithm

Polygon polygon1 = new Polygon();

g2.drawString("frame = " + frameNumber, ( 200 ),( 300 ) );

if( anchor == ANCHOR )

// now start the algoithm by finding the anchor point

findAnchorPoint();

g2.setColor(Color.blue);

g2.drawString("<-- Anchor point", ( points[0].x + 5 ),( points[0].y +5 ) );

if( angle == ANGLE )

// next sort the array into angular order

angleSort( points );

for(int i = 1; i < points.length; i++)

g2.drawLine(points[0].x, points[0].y, points[i].x, points[i].y );

if( step == STEP )

g2.drawString("step = " + nextStep, ( 100 ),( 300 ) );

if( nextStep == 1 )

anchor(ANCHOR);

// this is needed to stop the image being repainted until

// step is pressed again

nextStep++;

else if( nextStep == 3 )

angle( ANGLE );

// this is needed to stop the image being repainted until

// step is pressed again

nextStep++;

else if( nextStep == 5 )

buildConvex( BUILD );

// this is needed to stop the image being repainted until

// step is pressed again

nextStep++;

if( build == BUILD )

convexHull( points );

if (completeHull == true)

// add the points in the point array to the polygon

for ( int i = 0; i < convexHull.length && convexHull[ i ] != null; i++ )

polygon1.addPoint( convexHull[ i ].x, convexHull[ i ].y );

// draw the polygon

g2.drawPolygon( polygon1 );

else

// g2.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);

test1 = S.top();

test2 = S.secTop();

if( val < 1 )

lineDraw[0][0] = points[0].x;

lineDraw[0][1] = points[0].y;

// lineDraw[1][0] = points[1].x;

// lineDraw[1][1] = points[1].y;

lineDraw[1][0] = test2.x;

lineDraw[1][1] = test2.y;

lineDraw[2][0] = test1.x;

lineDraw[2][1] = test1.y;

val++;

if(test1.x == lineDraw[draw][0] && test1.y == lineDraw[draw][1] )

//just draw what we've already got

for( int i = 1; i < lineDraw.length && lineDraw[i][0] > 0; i++ )

g2.setColor( Color.blue );

g2.drawLine(lineDraw[i-1][0], lineDraw[i-1][1], lineDraw[i][0], lineDraw[i][1] );

else

//add to lineDraw then draw lines

lineDraw[draw][0] = test1.x;

lineDraw[draw][1] = test1.y;

lineDraw[draw][0] = test2.x;

lineDraw[draw][1] = test2.y;

for( int i = 1; i < lineDraw.length && lineDraw[i][0] > 0; i++ )

g2.setColor( Color.blue );

g2.drawLine(lineDraw[i-1][0], lineDraw[i-1][1], lineDraw[i][0], lineDraw[i][1] );

g2.setColor( Color.red );

g2.drawLine(test1.x, test1.y, test2.x, test2.y);

if( convex == CONVEX )

// finally find which points are on the convex hull

testMeth( points );

// add the points in the point array to the polygon

for ( int i = 0; i < convexHull.length && convexHull[ i ] != null; i++ )

polygon1.addPoint( convexHull[ i ].x, convexHull[ i ].y );

// draw the polygon

g2.setColor(Color.blue);

g2.drawPolygon( polygon1 );

// these next methods all relate to button presses in he main AlgoApp class

public void anim ( int animation )

convex = 0;

angle = 0;

anchor = 0;

if( animation == ANIMATION )

threadSuspended = false;

startAnimation();

else if( animation == STOPANIM )

threadSuspended = true;

stopAnimation();

public void anchor ( int anchorPoint )

convex = 0;

angle = 0;

anchor = anchorPoint;

repaint();

public void angle ( int angleSort )

convex = 0;

angle = angleSort;

repaint();

public void step ( int stepByStep )

convex = 0;

step = stepByStep;

nextStep++;

repaint();

public void buildConvex( int buildHull )

angle = 0;

build = buildHull;

repaint();

public void convex ( int convexHull )

angle = 0;

convex = convexHull;

repaint();

public void sliderValue( int slider )

delay = slider;

public void reset()

complete = 0;

anchor = 0;

angle = 0;

build = 0;

convex = 0;

step = 0;

nextStep = 0;

frameNumber = 0;

start = 0;

draw = 2;

count = 2;

val = 0;

completeHull = false;

// used to delete lineDraw array so it redraws from the start

for( int i = 0; i < lineDraw.length; i++)

lineDraw[i][0] = 0;

lineDraw[i][1] = 0;

repaint();

*This is where Graham's Scan algorithm is

// first we find the anchor point

public void findAnchorPoint()

int min = points[0].y;

int max = points[0].x;

int anchorPoint = 0;

int anchorIndex = 0;

for (int i = 0; i < points.length && points[i] != null; i++)

if (points[i].y > min)

min = points[i].y;

max = points[i].x;

anchorPoint = i;

else if (points[i].y == min)

if (points[i].x > max)

min = points[i].y;

max = points[i].x;

anchorPoint = i;

// puts the anchor point at the beginning of the array

swapPoint( points, anchorPoint, anchorIndex );

public void swapPoint( Point pointArray[], int first, int second )

Point hold;

hold = pointArray[ first ];

pointArray[ first ] = pointArray[ second ];

pointArray[ second ] = hold;

public void swapDouble( double doubleArray[], int first, int second )

double temp;

temp = doubleArray[ first ];

doubleArray[ first ] = doubleArray[ second ];

doubleArray[ second ] = temp;

public double[] arraySort(double sortArray[])

for( int pass = 0; pass < sortArray.length; pass++)

for(int i = 2; i < sortArray.length; i++)

if(sortArray[i] > sortArray[i-1] )

swapPoint(points, i, i-1);

swapDouble(sortArray, i, i-1);

return sortArray;

// next we calculate the angles

public void angleSort( Point arr2[] )

double angleArray[] = new double[arr2.length];

double orderArray[] = new double[arr2.length];

int indexOfAngle = 0;

// works out angle of every point with x0 and y0 as the anchor point

for (int i = 0; i < arr2.length; i++) {

double pointAngle = Math.atan2((arr2[i].y - arr2[0].y), (arr2[ i ].x - arr2[0].x));

// if its on the line with the anchor point at 180 degrees, this equals PI.

// to make this come last in the array change PI to minus PI

if ( pointAngle == Math.PI)

pointAngle = -Math.PI;

angleArray[i] = pointAngle;

// call sortArray to sort the array angularly

orderArray = arraySort(angleArray);

// finally we claculate the final convex hull

public void convexHull(Point stackArr[] )

float leftCheck;

if ( start == 0 )

S.push(stackArr[0]);

S.push(stackArr[1]);

start += 1;

if ( draw < stackArr.length )

Point pt1 = S.top();

Point pt2 = S.secTop();

leftCheck = isLeft(pt1,pt2,stackArr[draw]);

if ( leftCheck > 0)

S.push(stackArr[draw]);

count++;

draw++;

else

S.pop();

count--;

if ( draw == stackArr.length )

completeHull = true;

// stack called temp is used to get elements output in the correct order

ArrayStack temp = new ArrayStack(stackArr.length);

for ( int counter = 0; counter < count; counter++ )

Point tempPoint = S.pop();

temp.push(tempPoint);

// put the coordinate onto final convex hull array

for (int j = 0; j < count; j++)

convexHull[j] = temp.pop();

draw++;

// this testMeth is used to allow the Get Convex Hull button to work

public void testMeth(Point stackArr[] )

int count = 2;

int i = 2 ;

float leftCheck;

ArrayStack S = new ArrayStack(stackArr.length);

S.push(stackArr[0]);

S.push(stackArr[1]);

while ( i < stackArr.length)

Point pt1 = S.top();

Point pt2 = S.secTop();

leftCheck = isLeft(pt1,pt2,stackArr[i]);

if ( leftCheck > 0)

S.push(stackArr[i]);

count++;

i++;

else

S.pop();

count--;

// stack called temp is used to get elements output in the correct order

ArrayStack temp = new ArrayStack(stackArr.length);

String testOutput = "\nConvex Hull = \n ";

for ( int counter = 0; counter < count; counter++ )

Point tempPoint = S.pop();

temp.push(tempPoint);

// put the coordinate onto final convex hull array

for (int j = 0; j < count; j++)

convexHull[j] = temp.pop();

//==============================================================================

// Copyright 2001, softSurfer (www.softsurfer.com)

// This code may be freely used and modified for any purpose

// providing that this copyright notice is included with it.

// SoftSurfer makes no warranty for this code, and cannot be held

// liable for any real or imagined damage resulting from its use.

// Users of this code must verify correctness for their application.

// This is a C++ implementation which I, Paul Wood have modified slighty

// for use in Java (07/03/2005).

// isLeft(): tests if a point is Left|On|Right of an infinite line.

// Input: three points P0, P1, and P2

// Return: >0 for P2 left of the line through P0 and P1

// =0 for P2 on the line

// <0 for P2 right of the line

public float isLeft( Point P0, Point P1, Point P2 )

return (P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y);

//==============================================================================