package main;

import graphics.GraphicsClass;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import objects.Object;

/**
 * Main class.
 * @author Pavel_Verkhovtsov
 */
public class Main {
	private static Object[] objectArray;
	private static ArrayList<Object> objectCenters;
	private static final int DISPERSION = 800;
	private static int objectCount;
	private static int indexOfObjectWithMaxDistanse;

	/**
	 * Main method.
	 * @param args console arguments
	 */
	public static void main(final String[] args){
		System.out.print("Input count objects: ");
		objectCount = (new Scanner(System.in)).nextInt();

		objectCenters = new ArrayList<Object>();
		writeInArrayRandomObjects();
		selectRandomCenters();
		divideObjectsOnClasses();

		while(findMaximumDistanseFromClassKernel()>calculateNormDistance()){
			objectCenters.add(objectArray[indexOfObjectWithMaxDistanse]);
			divideObjectsOnClasses();
		}

		GraphicsClass.setScreenSize(DISPERSION+100);
		GraphicsClass.setObjectArray(objectArray, objectCenters);
		GraphicsClass.setAreaCount(objectCenters.size());
		GraphicsClass.visualizeClasses();

		
		while(checkOptimalityDivision()){
			divideObjectsOnClasses();
		}

		GraphicsClass.visualizeClasses();

		System.out.println("Finish");
	}

	private static double getAverageDeviation(int index){
		double sum = 0;
		for (int i = 0; i<objectCount; i++){
			if (objectArray[i].getAreaNumber()==objectArray[index].getAreaNumber()){
				sum+=Math.pow(Math.abs(objectArray[i].getX()-objectArray[index].getX()),2)+Math.pow(Math.abs(objectArray[i].getY()-objectArray[index].getY()),2);
			}
		}
		return Math.sqrt(sum/objectCount);
	}

	private static void writeInArrayRandomObjects(){
		objectArray = new Object[objectCount];
		Random rand = new Random();
		for(int i=0; i< objectCount; i++){
			objectArray[i] = new Object(rand.nextInt(DISPERSION), rand.nextInt(DISPERSION), i);
		}
	}

	private static void selectRandomCenters(){
		Random rand = new Random();
		objectCenters.add(objectArray[rand.nextInt(objectCount)]);
		objectCenters.add(objectArray[rand.nextInt(objectCount)]);
	}

	private static void divideObjectsOnClasses(){
		for (int i=0; i< objectCount; i++){
			objectArray[i].choiceArea(objectCenters);
		}
	}

	private static boolean checkOptimalityDivision(){
		boolean redefinitionClasses = false;
		for (int i=0; i<objectCount; i++){
			double kernel =  getAverageDeviation(objectCenters.get(objectArray[i].getAreaNumber()).getIndex());
			double kernelBidder = getAverageDeviation(i);
			if (kernelBidder<kernel){
				objectCenters.set(objectArray[i].getAreaNumber(),objectArray[i]);
				redefinitionClasses = true;
			}
		}
		return redefinitionClasses;
	}

	private static double calculateNormDistance(){
		double normDistance = 0;
		for(int i=0; i<objectCenters.size(); i++){
			for(int j=0; j<objectCenters.size(); j++){
				normDistance+=Math.sqrt(Math.pow(objectCenters.get(i).getX()-objectCenters.get(j).getX(),2)+Math.pow(objectCenters.get(i).getY()-objectCenters.get(j).getY(),2));
			}
		}
		return normDistance/(2*objectCenters.size()*objectCenters.size()-1);
	}

	private static double findMaximumDistanseFromClassKernel(){
		double maxDistance = 0;
 		for (int i=0; i< objectArray.length; i++){
 			double distance = Math.sqrt(Math.pow(objectArray[i].getX()-objectCenters.get(objectArray[i].getAreaNumber()).getX(),2)+Math.pow(objectArray[i].getY()-objectCenters.get(objectArray[i].getAreaNumber()).getY(),2));
 			if (distance>maxDistance){
 				maxDistance = distance;
 				indexOfObjectWithMaxDistanse = i;
 			}
 		}
 		return maxDistance;
	}

}

@@ -345,9 +345,9 @@
 N = 
-8
+6
 00;%0A
@@ -2345,16 +2345,70 @@
  false;%0A
+%09%09double kernel%5B%5D = new double%5BobjectCenters.size()%5D;%0A
 %09%09for (i
@@ -2413,35 +2413,37 @@
 (int i=0; i%3C
-objectCount
+kernel.length
 ; i++)%7B%0A%09%09%09d
@@ -2441,29 +2441,25 @@
 ++)%7B%0A%09%09%09
-double 
 kernel
+%5Bi%5D
  =  getA
@@ -2496,52 +2496,64 @@
 get(
-objectArray%5Bi%5D.getAreaNumber()).getIndex());
+i).getIndex());%0A%09%09%7D%0A%09%09for (int i=0; i%3CobjectCount; i++)%7B
 %0A%09%09%09
@@ -2624,16 +2624,48 @@
 r%3Ckernel
+%5BobjectArray%5Bi%5D.getAreaNumber()%5D
 )%7B%0A%09%09%09%09o

Change dispersion by notebook resolution Optinaze method find best kernel