# Cluster3.py

from gpanel import *
import math
import time
import thread

datafile = "samples.dat"
colors= ["red", "orange", "green", "lightblue"]
nbClusters = 4

def euklidian(pt1, pt2):
    return math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + \
                     (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))

def loadData(fileName):
    try:
        fData = open(fileName, 'r')
    except:
        return []
    out = []
    for line in fData:
        line = line[:-1]  # remove \n
        if len(line) == 0:  # empty line
            continue
        li = [i for i in line.split(",")]
        out.append(li)
    fData.close()
    return out

def onMousePressed(x, y):
    global nbClicks, doPaint
    if isLeftMouseButton():
        nbClicks += 1
        if nbClicks <= nbClusters:
            centroid = [x, y]
            pos(centroid)
            fillCircle(2)
            centroids.append(centroid)
            if nbClicks == nbClusters:
                title("Left click to start iteration.")
        if nbClicks > nbClusters:
            drawCentroids()
            iterate()
            drawCentroids()
            title("# Iterations: " + str(nbClicks - 3) +
     ". - Left click for next. Right click for Voronoi separation.")
    if isRightMouseButton()and nbClicks >= nbClusters:
        thread.start_new_thread(drawVoronoi, ())

def drawCentroids():
    for centroid in centroids:
        pos(centroid)
        fillCircle(2)

def drawData():
    for sample in data:
        pt = [float(sample[0]), float(sample[1]), -1]
        X.append(pt)
        pos(pt)
        fillCircle(0.5)

def iterate():
    for pt in X:
        distances = []
        for k in range(nbClusters):
            distance = euklidian(pt, centroids[k])
            distances.append(distance)
        min_value = min(distances)
        min_index = distances.index(min_value)
        pt[2] = min_index

    xSums = [0] * nbClusters
    ySums = [0] * nbClusters
    nSums = [0] * nbClusters
    for pt in X: # each sample
        for k in range(nbClusters):
            if pt[2] == k:
                xSums[k] += pt[0]
                ySums[k] += pt[1]
                nSums[k] += 1
    for k in range(nbClusters):
        centroids[k][0] = xSums[k] / nSums[k]
        centroids[k][1] = ySums[k] / nSums[k]

def drawVoronoi():
    title("Performing Voronoi Separation...")
    step = 0.2
    setPaintMode()
    enableRepaint(False)
    pt = [0, 0]
    while pt[1] <= 100: # outer loop y direction
        while pt[0] <= 100: # inner loop in x direction
            pt[0] += step
            distances = [0] * nbClusters
            for k in range(nbClusters):
                distances[k] = euklidian(centroids[k], pt)
            min_value = min(distances)
            min_index = distances.index(min_value)
            setColor(colors[min_index])
            point(pt)
        setColor("blue")
        drawCentroids()
        repaint()
        pt[0] = 0
        pt[1] += step
    setColor("black")
    drawData()
    repaint()
    title("Voronoi Separation Finished")

makeGPanel(-10, 110, -10, 110, mousePressed = onMousePressed)
drawGrid(0, 100, 0, 100, "gray")
text(98, -8, "Age",)
text(-8, 105, "Income (in 1000)",)
setColor("black")
data = loadData(datafile)
X = []
centroids = []
nbClicks = 0
drawData()
setColor("green")
setXORMode("white")
title("Left click to set 3 centroids.")
keep()


