protected void repulse() {
		for (int i = 0; i < vertexArray.length; i++) {
			// Only go through rest of array and displace both
			// vertices at once. Saves 50% CPU
			for (int j = i; j < vertexArray.length; j++) {
				if (progress.isStopped())
					return;
				
				if (i != j) {
					// NOTE - this loop forms the quadratic component of the 
					// layout performance. It needs to contain as little as
					// possible, the square root method tends to dominate
					
					// delta is short hand for the difference
					// vector between the positions of the two vertices
					double deltaX = cellLocationX[i] - cellLocationX[j];
					double deltaY = cellLocationY[i] - cellLocationY[j];

					// get the distance between the ends of the edge
					double nodeDistance = Math.sqrt(deltaX*deltaX + deltaY*deltaY);

					if (nodeDistance < 0.1) {
						nodeDistance = 0.1;
						deltaX = 0.1;
						deltaY = 0.1;
					}
					
					// Ensure no divide by zero
					double fr = replusiveForce
							/ (nodeDistance * nodeDistance);
					
					// Don't allow the replusive force to be greater than the spring
					// length. Sometimes on early iteration nodes get very close
					// together and can be thrown out a great distance. Assume
					// the natural spring length is the maximum distance thrown.
					// Another iteration will be required after this one to settle
					// it down
					if (fr > springLength) {
						fr = springLength;
					} else if (fr < -springLength) {
						fr = -springLength;
					}

					double deltaNormX = deltaX / nodeDistance;
					double displacementX = deltaNormX * fr;
					double deltaNormY = deltaY / nodeDistance;
					double displacementY = deltaNormY * fr;

					if (isMoveable[i]) {
						dispX[i] += displacementX;
						dispY[i] += displacementY;
					}
					
					if (isMoveable[j]) {
						dispX[j] -= displacementX;
						dispY[j] -= displacementY;
					}
				}
			}
		}
	}