import numpy as np
import sys
import matplotlib.pyplot as plt
import itertools as iter
from Classes import Stroke, OffStroke
import os.path
import ntpath
from string import ascii_letters

class Picto:

    def __init__(self):
        self.Strokes = []
        self.sIndex = []
        self.offIndex = []
        self.Boundaries = [float('-inf'), float('inf'), float('-inf'), float('inf')] #Xmax, Xmin, Ymax, Ymin
        self.pictIndex = None
        self.fileName = None
        self.offStrokes = []
        self.valid = True
        self.ExerciseType = None
        self.ExerciseTypeInd = -1
        self.parent = None
        

    #def addOffStroke(self, offStroke):
    #    self.offStrokes.append(offStroke)

    #def addStroke(self, stroke):
    #    self.Strokes.append(stroke)
        
    def SetPictFileName(self, fileName):
        self.fileName = fileName

    def addSIndex(self, index):
        self.sIndex.append(index)

    def addOffIndex(self, index):
        self.OffIndex.append(index)

    def emptyMyself(self):
        self.Strokes = []
        self.sIndex = []
        self.valid = False

    def SetPictIndex(self, index):
        self.pictIndex=index

    def findBoundaries(self):
        self.Boundaries = [float('-inf'), float('inf'), float('-inf'), float('inf')]
        for strokeIndex in self.sIndex:
            self.parent.updateBound(self, strokeIndex)

    
    #def traceDataToFile(self):
    #    with open(self.fileName + self.ExerciseType + str(self.pictIndex) + ".svc", 'w') as out:
    #        for stroke in self.Strokes:
    #            for line in stroke:
    #                out.writelines(str(int(line[0])) + ' ' + str(int(line[1])) + ' ' + str(int(line[2])) + ' ' + str(int(line[3])) + ' ' 
    #                               + str(int(line[4])) + ' ' + str(int(line[5])) + ' ' + str(int(line[6])) + '\n')
    #        for stroke in self.offStrokes:
    #            for line in stroke:
    #                out.writelines(str(int(line[0])) + ' ' + str(int(line[1])) + ' ' + str(int(line[2])) + ' ' + str(int(line[3])) + ' ' 
    #                               + str(int(line[4])) + ' ' + str(int(line[5])) + ' ' + str(int(line[6])) + '\n')

            
            

class TraceData:
    def __init__(self):
        self.data = np.array
        self.traceOff = np.empty(7)
        self.traceP1 = np.empty(7)
        self.traceP2 = np.empty(7)
        self.traceP3 = np.empty(7)
        self.traceP4 = np.empty(7)
        self.strokeEdge = np.empty(3)
        #self.fig, self.ax = plt.subplots()
        #self.fig, self.ax2 = plt.subplots()
        self.Strokes = []
        self.strokeCount = 0
        self.offStrokeCount = 0
        self.Pictos = []
        self.proximityConst=500
        self.relatedStrokes = []
        self.pictoIndexes = []
        self.Singles = [] 
        self.fileName = None
        self.StrokesObj = [Stroke()]
        self.OffStrokesObj = [OffStroke()]
        self.atLeastOne = False
        self.parent = None

    def basicSolve(self):
        self.translate()
        self.divideStrokesOffStrokes()
        self.sortStrokes()
        self.distributeStrokes()   
        self.assignParet()
        self.crossCheckPictos()   
        self.assignOffTrace()
        self.sortStrokeIndexes()


    def fileToTraceData(self, fileName):
        with open(fileName, 'r') as fobj:
            arr = np.empty((7), dtype = np.int16)
            for line in fobj:
                numbers = np.array([int(num) for num in line.split()])
                if (len(numbers) == 7):
                    arr = np.vstack((arr, numbers))
        arr = np.delete(arr, 0, 0)
        self.data = arr
        self.fileName = fileName

    def getValidBorder(self, Borders, last):
        if last:
            if Borders[1] == -1:
                return Borders[0]+1
            else: return Borders[1]
        if not last:
            if Borders[0] == -1:
                return Borders[1]-1
            else: return Borders[0]



    def traceDataToFile(self, fPath):
        outData = np.empty(7)
        unAssCounter = 0
        for pict in self.Pictos:
            if pict.valid == True:
                ExerciseType = pict.ExerciseType
                if ExerciseType == None:
                    unAssCounter+=1
                    ExerciseType = "UnassignedType" + str(unAssCounter)
                if np.nanmax(pict.sIndex) - np.nanmin(pict.sIndex) == np.size(pict.sIndex, 0)-1:
                    borderOffStrokes = [self.getValidBorder((self.StrokesObj[np.nanmin(pict.sIndex)].BorderingOffStrokes), False), self.getValidBorder((self.StrokesObj[np.nanmax(pict.sIndex)].BorderingOffStrokes), True)]
                    for sInd in pict.sIndex:
                        for line in self.StrokesObj[sInd].Points:
                            outData = np.vstack((outData, line))
                    for offInd in pict.offIndex:
                        if offInd > borderOffStrokes[0] and offInd < borderOffStrokes[1]:
                            for line in self.OffStrokesObj[offInd].Points:
                                outData = np.vstack((outData, line))
                    outData = outData[outData[:,2].argsort()]
                    completeName = os.path.join(fPath, ntpath.basename(self.fileName) + ExerciseType + ".svc")
                    with open(completeName, 'w') as out:
                        outData = np.delete(outData, 0, 0)
                        for line in outData:
                            out.writelines(str(int(line[0])) + ' ' + str(int(line[1])) + ' ' + str(int(line[2])) + ' ' + str(int(line[3])) + ' ' 
                                + str(int(line[4])) + ' ' + str(int(line[5])) + ' ' + str(int(line[6])) + '\n')
                        outData = np.empty(7)

                else:
                    split = np.split(pict.sIndex, np.where(np.diff(pict.sIndex) != 1)[0]+1)
                    subPictCounter = 0
                    for subPict in split:
                        borderOffStrokes = [self.getValidBorder((self.StrokesObj[np.nanmin(subPict)].BorderingOffStrokes), False), self.getValidBorder((self.StrokesObj[np.nanmax(subPict)].BorderingOffStrokes), True)]
                        for sInd in subPict:
                            for line in self.StrokesObj[sInd].Points:
                                outData = np.vstack((outData, line))
                        for offInd in pict.offIndex:
                            if offInd > borderOffStrokes[0] and offInd < borderOffStrokes[1]:
                                for line in self.OffStrokesObj[offInd].Points:
                                    outData = np.vstack((outData, line))
                        outData = outData[outData[:,2].argsort()]
                        completeName = os.path.join(fPath, ntpath.basename(self.fileName) + ExerciseType + "_" + ascii_letters[subPictCounter] +  ".svc")
                        subPictCounter +=1
                        with open(completeName, 'w') as out:
                            outData = np.delete(outData, 0, 0)
                            for line in outData:
                                out.writelines(str(int(line[0])) + ' ' + str(int(line[1])) + ' ' + str(int(line[2])) + ' ' + str(int(line[3])) + ' ' 
                                    + str(int(line[4])) + ' ' + str(int(line[5])) + ' ' + str(int(line[6])) + '\n')
                        outData = np.empty(7)




    def generateLabFile(self, fPath):
        completeName = os.path.join(fPath, ntpath.basename(self.fileName) + ".lab")
        with open(completeName, 'w') as out:
            unAssCounter = 0
            for pict in self.Pictos:
                if pict.valid == True:
                    ExerciseType = pict.ExerciseType
                    if ExerciseType == None:
                        unAssCounter+=1
                        ExerciseType = "UnassignedType" + str(unAssCounter)
                    subPictCounter = 0
                    if np.nanmax(pict.sIndex) - np.nanmin(pict.sIndex) == np.size(pict.sIndex, 0)-1:
                        borderTimeStamp = [(np.nanmin(self.StrokesObj[np.nanmin(pict.sIndex)].Points[:,2])), (np.nanmax(self.StrokesObj[np.nanmax(pict.sIndex)].Points[:,2]))]
                        out.writelines(str(int(borderTimeStamp[0])) + ' ' + str(int(borderTimeStamp[1]))+ ' ' + ExerciseType + '\n')

                    else:
                        split = np.split(pict.sIndex, np.where(np.diff(pict.sIndex) != 1)[0]+1)
                        for subPict in split:
                            borderTimeStamp = [(np.nanmin(self.StrokesObj[np.nanmin(subPict)].Points[:,2])), (np.nanmax(self.StrokesObj[np.nanmax(subPict)].Points[:,2]))]
                            out.writelines(str(int(borderTimeStamp[0])) + ' ' + str(int(borderTimeStamp[1]))+ ' ' + ExerciseType + "_" + ascii_letters[subPictCounter] + '\n')
                            subPictCounter +=1
            
                


    #def pictosToSVC(self):
    #    for pict in self.Pictos:
    #        pict.traceDataToFile()

    def contains(self, stroke1, stroke2):
        AXmax= np.nanmax(stroke1[:,0])
        AXmin= np.nanmin(stroke1[:,0])
        AYmax= np.nanmax(stroke1[:,1])
        AYmin= np.nanmin(stroke1[:,1])
        BXmax= np.nanmax(stroke2[:,0])
        BXmin= np.nanmin(stroke2[:,0])
        BYmax= np.nanmax(stroke2[:,1])
        BYmin= np.nanmin(stroke2[:,1])
        if AXmax >=BXmax and AXmin <= BXmin and AYmax >=BYmax and AYmin <= BYmin:
            return True
        elif BXmax >=AXmax and BXmin <= AXmin and BYmax >=AYmax and BYmin <= AYmin:
            return True
        return np.array([AXmax, AXmin, AYmax, AYmin, BXmax, BXmin, BYmax, BYmin])


    def doTouch(self, stroke1, stroke2, xShared, yShared):
        for row in stroke1:
            if ((row[0] >=xShared[0] and row[0] <=xShared[1]) and (row[1] >=yShared[0] and row[1] <=yShared[1])):
                for roww in stroke2:
                    if ((roww[0] >=xShared[0] and roww[0] <=xShared[1]) and (roww[1] >=yShared[0] and roww[1] <=yShared[1])):
                        if (abs(roww[0]-row[0])<=(self.proximityConst*2)):
                            if (abs(roww[1]-row[1])<=(self.proximityConst*2)):
                                return True
        return False

    def checkIfRelated(self, stroke1, stroke2):
        containsResult = self.contains(stroke1, stroke2)
        if (isinstance(containsResult, bool)):
            if (containsResult==True):
                return True
        tooFarResult = self.tooFar(containsResult)
        if (isinstance(tooFarResult, bool)):
            if (tooFarResult==False):
                return False
        xShared = np.array([np.nanmin(tooFarResult[0]), np.nanmax(tooFarResult[0])])
        yShared = np.array([np.nanmin(tooFarResult[1]), np.nanmax(tooFarResult[1])])
        if (self.doTouch(stroke1, stroke2, xShared, yShared)==True):
            return True
        else: return False
    
    def tooFar(self, containsResult):
        rectAX = np.arange(containsResult[1]-self.proximityConst, containsResult[0]+self.proximityConst)
        rectAY = np.arange(containsResult[3]-self.proximityConst, containsResult[2]+self.proximityConst)
        rectBX = np.arange(containsResult[5]-self.proximityConst, containsResult[4]+self.proximityConst)
        rectBY = np.arange(containsResult[7]-self.proximityConst, containsResult[6]+self.proximityConst)
        xShared= np.intersect1d(rectAX, rectBX)
        yShared= np.intersect1d(rectAY, rectBY)
        if np.size(yShared, axis=0)==0 or np.size(xShared, axis=0)==0:
            return False
        else:
            result = [xShared, yShared]
            return result

    def sortStrokes(self):
        #self.checkID()
        for i in range(len(self.StrokesObj)):
            for j in range(i + 1, len(self.StrokesObj)):
                check = self.checkIfRelated(self.StrokesObj[i].Points, self.StrokesObj[j].Points)
                if check:
                    self.relatedStrokes.append(np.array([self.StrokesObj[i].ID,self.StrokesObj[j].ID]))


    def checkID(self):
        for i in range(len(self.StrokesObj)):
            if self.StrokesObj[i].ID != i:
                self.StrokesObj[i].ID = i
        for i in range(len(self.OffStrokesObj)):
            if self.OffStrokesObj[i].ID != i:
                self.OffStrokesObj[i].ID = i

    def assignOffTrace(self):
        for pict in self.Pictos:
            if pict.valid:
                temp = []
                for s in pict.sIndex:
                    if self.StrokesObj[s].BorderingOffStrokes[0] != -1:
                        temp.append(self.StrokesObj[s].BorderingOffStrokes[0])
                    if self.StrokesObj[s].BorderingOffStrokes[1] != -1:
                        temp.append(self.StrokesObj[s].BorderingOffStrokes[1])
                for a in temp:
                    if a not in pict.offIndex:
                        pict.offIndex.append(a)
                pict.offIndex.sort()
                #    self.StrokesObj[s]
                #firstOffStroke = self.StrokesObj[np.nanmin(pict.sIndex)].BorderingOffStrokes[0]
                #lastOffStroke = self.StrokesObj[np.nanmax(pict.sIndex)].BorderingOffStrokes[1]
                #if lastOffStroke == -1: lastOffStroke = self.StrokesObj[np.nanmax(pict.sIndex)].BorderingOffStrokes[0]
                #if firstOffStroke == -1: firstOffStroke = self.StrokesObj[np.nanmin(pict.sIndex)].BorderingOffStrokes[1]
                #pict.offIndex = np.arange(firstOffStroke, lastOffStroke)



    #def assignOfffTrace(self):
    #    for pict in self.Pictos:
    #        for index in pict.sIndex:
    #            for i in range(len(self.strokeEdge)):
    #               if index == self.strokeEdge[i][3]-1 and self.strokeEdge[i][4] == 1:
    #                   offStrokeTimeStamp = self.strokeEdge[i][2]
    #                   if i == 0:
    #                       prevOffstrokeTimeStamp=0
    #                   else: 
    #                       prevOffStrokeTimeStamp = self.strokeEdge[i-1][2]
    #                   offStroke = np.zeros(7)
    #                   for line in self.traceOff:
    #                       if line[2]<offStrokeTimeStamp and line[2] > prevOffStrokeTimeStamp:
    #                           offStroke = np.vstack((offStroke, line))
    #                   offStrok = np.delete(offStroke, 0, 0)
    #                   if np.size(offStrok, 0) > 6:
    #                       pict.addOffStroke(offStrok)
    #               if index == self.strokeEdge[i][3]-1 and self.strokeEdge[i][4] == 0:
    #                   offStrokeTimeStamp = self.strokeEdge[i][2]
    #                   if i == np.max(range(len(self.strokeEdge))):
    #                       nextOffstrokeTimeStamp=self.traceOff[-1][2]
    #                   else: 
    #                       nextOffStrokeTimeStamp = self.strokeEdge[i+1][2]
    #                   offStroke = np.zeros(7)
    #                   for line in self.traceOff:
    #                       if line[2]>offStrokeTimeStamp and line[2] < nextOffStrokeTimeStamp:
    #                           offStroke = np.vstack((offStroke, line))
    #                   offStrok = np.delete(offStroke, 0, 0)
    #                   if np.size(offStrok, 0)>6:
    #                       pict.addOffStroke(offStrok)


    def updateBound(self, pict, strokeIndex):
        # a= self.StrokesObj[strokeIndex].Bounds[0]
        # b=pict.Boundaries[0]
        if self.StrokesObj[strokeIndex].Bounds[0]>pict.Boundaries[0]: pict.Boundaries[0] = self.StrokesObj[strokeIndex].Bounds[0]
        if self.StrokesObj[strokeIndex].Bounds[1]<pict.Boundaries[1]: pict.Boundaries[1] = self.StrokesObj[strokeIndex].Bounds[1]
        if self.StrokesObj[strokeIndex].Bounds[2]>pict.Boundaries[2]: pict.Boundaries[2] = self.StrokesObj[strokeIndex].Bounds[2]
        if self.StrokesObj[strokeIndex].Bounds[3]<pict.Boundaries[3]: pict.Boundaries[3] = self.StrokesObj[strokeIndex].Bounds[3]

    def sortStrokeIndexes(self):
        for p in self.Pictos:
            p.sIndex.sort()
            p.offIndex.sort()

    def distributeStrokes(self):
        self.checkForSingles()
        if len(self.Singles)>0 and len(self.relatedStrokes)>0:
            for single in self.Singles:
                pict = Picto()
                pict.addSIndex(single)
                pict.SetPictIndex(len(self.Pictos))
                pict.SetPictFileName(self.fileName)
                self.updateBound(pict, single)
                self.Pictos.append(pict)
        if len(self.relatedStrokes)==0:
            for a in self.StrokesObj:
                pict = Picto()
                pict.addSIndex(a.ID)
                pict.SetPictIndex(len(self.Pictos))
                pict.SetPictFileName(self.fileName)
                self.updateBound(pict, a.ID)
                self.Pictos.append(pict)
        else:
            for pair in self.relatedStrokes:
                added=False
                if len(self.Pictos)==0:
                    pict = Picto()
                    for pear in pair:
                        pict.addSIndex(pear)
                        self.updateBound(pict, pear)
                    pict.SetPictIndex(len(self.Pictos))
                    pict.SetPictFileName(self.fileName)
                    self.Pictos.append(pict)
                    added=True
                else:
                    for p in self.Pictos:
                        for index in p.sIndex:
                            if index == pair[0] and pair[1] not in p.sIndex:
                                p.addSIndex(pair[1])
                                self.updateBound(p, pair[1])
                                added=True
                                break
                            elif index == pair[1] and pair[0] not in p.sIndex:
                                p.addSIndex(pair[0])
                                self.updateBound(p, pair[0])
                                added=True
                                break
                if added==False:
                    pict = Picto()
                    for pear in pair:
                        pict.addSIndex(pear)
                        self.updateBound(pict, pear)
                    pict.SetPictIndex(len(self.Pictos))
                    pict.SetPictFileName(self.fileName)
                    self.Pictos.append(pict)

    def assignParet(self):
        for pict in self.Pictos:
            pict.parent = self

    def crossCheckPictos(self):
        changeMade = True
        while changeMade ==True:
            changeMade=False
            for i in range(len(self.Pictos)):
                for j in range(i + 1, len(self.Pictos)):
                    for indexA in self.Pictos[i].sIndex:
                        for indexB in self.Pictos[j].sIndex:
                            if indexA==indexB:
                                changeMade=True
                                self.mergeToA(i,j)
                                #self.Pictos[i].findBoundaries() Obsolete
        for i in range(len(self.Pictos)):
            for j in range(i + 1, len(self.Pictos)):
                self.containsPicto(i, j)


    def mergeToA(self, pictA, pictB):
        if self.Pictos[pictB].valid == True and self.Pictos[pictA].valid == True:
            if self.Pictos[pictB].Boundaries[0]>self.Pictos[pictA].Boundaries[0]: self.Pictos[pictA].Boundaries[0]=self.Pictos[pictB].Boundaries[0]
            if self.Pictos[pictB].Boundaries[1]<self.Pictos[pictA].Boundaries[1]: self.Pictos[pictA].Boundaries[1]=self.Pictos[pictB].Boundaries[1]
            if self.Pictos[pictB].Boundaries[2]>self.Pictos[pictA].Boundaries[2]: self.Pictos[pictA].Boundaries[2]=self.Pictos[pictB].Boundaries[2]
            if self.Pictos[pictB].Boundaries[3]<self.Pictos[pictA].Boundaries[3]: self.Pictos[pictA].Boundaries[3]=self.Pictos[pictB].Boundaries[3]
            for sindex in self.Pictos[pictB].sIndex:
                if sindex not in self.Pictos[pictA].sIndex:
                    self.Pictos[pictA].addSIndex(sindex)
            for oindex in self.Pictos[pictB].offIndex:
                if oindex not in self.Pictos[pictA].OffIndex:
                    self.Pictos[pictA].addOffIndex(oindex)
            self.Pictos[pictB].emptyMyself()

    
    #def findPictoBoundaries(self):
    #    for pict in self.Pictos:
    #        pict.findBoundaries()


    def containsPicto(self, pictA, pictB):
        if self.Pictos[pictB].valid == True and self.Pictos[pictA].valid == True:
            if (self.Pictos[pictA].Boundaries[0]>= self.Pictos[pictB].Boundaries[0] and self.Pictos[pictA].Boundaries[1]<= self.Pictos[pictB].Boundaries[1] 
                and self.Pictos[pictA].Boundaries[2]>= self.Pictos[pictB].Boundaries[2] and self.Pictos[pictA].Boundaries[3]<= self.Pictos[pictB].Boundaries[3]):
                self.mergeToA(pictA, pictB)
            if (self.Pictos[pictB].Boundaries[0]>= self.Pictos[pictA].Boundaries[0] and self.Pictos[pictB].Boundaries[1]<= self.Pictos[pictA].Boundaries[1] 
                and self.Pictos[pictB].Boundaries[2]>= self.Pictos[pictA].Boundaries[2] and self.Pictos[pictB].Boundaries[3]<= self.Pictos[pictA].Boundaries[3]):
                self.mergeToA(pictB, pictA)
        

    
    def checkForSingles(self):
        for stroke in self.StrokesObj:
            isSingle = True
            for pair in self.relatedStrokes:
                if stroke.ID == pair[0] or stroke.ID == pair[1]:
                    isSingle = False
            if isSingle == True:
                self.Singles.append(stroke.ID)


    #priprav dat na vykresleni
    def translate(self):
        for row in self.data:
            if row[3]==0:
                self.traceOff = np.vstack((self.traceOff, row))
            elif row[6]<=250:
                self.traceP1 = np.vstack((self.traceP1, row))
            elif row[6]<=500:
                self.traceP2 = np.vstack((self.traceP2, row))
            elif row[6]<=750:
                self.traceP3 = np.vstack((self.traceP3, row))
            else:
                self.traceP4 = np.vstack((self.traceP4, row))
        self.traceOff = np.delete(self.traceOff, 0, 0)
        self.traceP1 = np.delete(self.traceP1, 0, 0)
        self.traceP2 = np.delete(self.traceP2, 0, 0)
        self.traceP3 = np.delete(self.traceP3, 0, 0)
        self.traceP4 = np.delete(self.traceP4, 0, 0)
    


    def divideStrokesOffStrokes(self):
        Bounds =[float('-inf'), float('inf'), float('-inf'), float('inf')]
        stroke = Stroke()
        offStroke = OffStroke()
        stroke.Points = np.empty(7)
        offStroke.Points = np.empty(7)
        previousRow = None
        isNew = True
        if self.data[0][3] == 1:
            onPaper = True
            writeOffStroke = False
        elif self.data[0][3]==0: 
            onPaper = False
            writeOffStroke = True
        else: return 0
        singleRow = np.empty(3)
        for row in self.data:
            singleRow[0] = row[0]
            singleRow[1] = row[1]
            singleRow[2] = row[2]

            if isNew:
                if writeOffStroke:
                    offStroke.BoundaryPoints[0] = singleRow
                elif onPaper:
                    stroke.BoundaryPoints[0]=singleRow


            if ((row[3] == 1) & (onPaper==False)):
                self.strokeEdge = np.vstack((self.strokeEdge, singleRow))

                #stroke
                stroke = Stroke()
                onPaper = True
                stroke.BoundaryPoints[0] = singleRow
                self.strokeCount+=1
                stroke.ID = len(self.StrokesObj)-1
                

                #offStroke
                writeOffStroke = False
                offStroke.BoundaryPoints[1]= previousRow
                offStroke.Points = np.delete(offStroke.Points, 0, 0)
                offStroke.BorderingStrokes = [stroke.ID-1, stroke.ID]
                offStroke.Bounds = Bounds
                self.OffStrokesObj.append(offStroke)
                
                Bounds = [float('-inf'), float('inf'), float('-inf'), float('inf')]
                isNew = False
            elif ((row[3] == 0) & (onPaper)):
                self.strokeEdge = np.vstack((self.strokeEdge, singleRow))

                #offStroke
                offStroke = OffStroke()
                writeOffStroke = True
                offStroke.BoundaryPoints[0] = singleRow
                self.offStrokeCount+=1
                offStroke.ID = len(self.OffStrokesObj)-1

                #stroke
                onPaper = False
                stroke.BoundaryPoints[1] = previousRow
                stroke.Points = np.delete(stroke.Points, 0, 0)
                stroke.BorderingOffStrokes = [offStroke.ID-1, offStroke.ID]
                stroke.Bounds = Bounds
                self.StrokesObj.append(stroke)
                
                Bounds = [float('-inf'), float('inf'), float('-inf'), float('inf')]
                isNew = False
            if onPaper:
                stroke.Points = np.vstack((stroke.Points, row))
            if writeOffStroke:
                offStroke.Points = np.vstack((offStroke.Points, row))
            if row[0]>Bounds[0]: Bounds[0]=row[0]
            if row[0]<Bounds[1]: Bounds[1]=row[0]
            if row[1]>Bounds[2]: Bounds[2]=row[1]
            if row[1]<Bounds[3]: Bounds[3]=row[1]
            previousRow = singleRow
        if onPaper:
            stroke.BoundaryPoints[1] = singleRow
            stroke.Points = np.delete(stroke.Points, 0, 0)
            stroke.BorderingOffStrokes = [offStroke.ID, -1] 
            stroke.Bounds = Bounds
            self.StrokesObj.append(stroke)
        elif writeOffStroke:
            offStroke.BoundaryPoints[1]= singleRow
            offStroke.Points = np.delete(offStroke.Points, 0, 0)
            offStroke.BorderingStrokes = [stroke.ID, -1] 
            offStroke.Bounds = Bounds
            self.OffStrokesObj.append(offStroke)
        self.OffStrokesObj = np.delete(self.OffStrokesObj, 0, 0)
        self.StrokesObj = np.delete(self.StrokesObj, 0, 0)
             

    #Oddeleni tahu
    #def findStrokeEdges(self):
    #    stroke = Stroke()
    #    stroke.Points = np.empty(7)
    #    np.nonzero
    #    onPaper = False
    #    singleRow = np.empty(5)
    #    for row in self.data:
    #        if ((row[3] == 1) & (onPaper==False)):
    #            stroke.ID = self.strokeCount
    #            self.strokeCount+=1
    #            onPaper = True
    #            singleRow[0] = row[0]
    #            singleRow[1] = row[1]
    #            singleRow[2] = row[2]
    #            singleRow[3] = self.strokeCount
    #            singleRow[4] = 1
    #            self.strokeEdge = np.vstack((self.strokeEdge, singleRow))
    #            stroke.BoundaryPoints [0] = singleRow
    #        elif ((row[3] == 0) & (onPaper==True)):
    #            onPaper = False
    #            singleRow[0] = row[0]
    #            singleRow[1] = row[1]
    #            singleRow[2] = row[2]
    #            singleRow[3] = self.strokeCount
    #            singleRow[4] = 0
    #            self.strokeEdge = np.vstack((self.strokeEdge, singleRow))
    #            stroke.BoundaryPoints[1] = singleRow
    #            stroke.Points = np.delete(stroke.Points, 0, 0)
    #            Strokes.append(stroke.Points)
    #            stroke = Stroke
    #        if onPaper == True:
    #            stroke.Points = np.vstack((stroke.Points, row))
    #    if np.ma.size(self.strokeEdge%2!=0):
    #        singleRow[0] = self.data[-1][0]
    #        singleRow[1] = self.data[-1][1]
    #        singleRow[2] = self.data[-1][2]
    #        singleRow[3] = self.strokeCount
    #        singleRow[4] = 0
    #        self.strokeEdge = np.vstack((self.strokeEdge, singleRow))
    #        stroke = np.delete(stroke, 0, 0)
    #        self.Strokes.append(stroke)
    #    self.strokeEdge = np.delete(self.strokeEdge, 0, 0)

    def renderStrokes(self):
        for s in self.StrokesObj:
            self.ax.scatter(s.Points[:,0], s.Points[:,1], marker='o', s=0.1, c=np.random.rand(3,))

    #def renderStrafedStrokes(self):
    #        for stroke in self.Strokes:
    #                    n=5
    #                    self.ax.scatter(stroke[::n,0], stroke[::n,1], marker='+', s=5, c="k")
    
    #def renderPictos(self):
    #    for pict in self.Pictos:
    #        randC=np.random.rand(3,)
    #        for stroke in pict.Strokes:
    #            self.ax.scatter(stroke[:,0], stroke[:,1], marker='o', s=0.1, c=randC)

    def renderSquare(self, leftDown = [0, 0], rightUp = [0, 0]):
        self.ax.plot([leftDown[0], rightUp[0]], [leftDown[1], leftDown[1]], color='k', linestyle='-', linewidth=2)
        self.ax.plot([leftDown[0], rightUp[0]], [rightUp[1], rightUp[1]], color='k', linestyle='-', linewidth=2)
        self.ax.plot([leftDown[0], leftDown[0]], [leftDown[1], rightUp[1]], color='k', linestyle='-', linewidth=2)
        self.ax.plot([rightUp[0], rightUp[0]], [leftDown[1], rightUp[1]], color='k', linestyle='-', linewidth=2)
           
    def renderSquareStrafed(self, leftDown = [0, 0], rightUp = [0, 0]):
        self.ax.plot([leftDown[0], rightUp[0]], [leftDown[1], leftDown[1]], color='k', linestyle='--', linewidth=1)
        self.ax.plot([leftDown[0], rightUp[0]], [rightUp[1], rightUp[1]], color='k', linestyle='--', linewidth=1)
        self.ax.plot([leftDown[0], leftDown[0]], [leftDown[1], rightUp[1]], color='k', linestyle='--', linewidth=1)
        self.ax.plot([rightUp[0], rightUp[0]], [leftDown[1], rightUp[1]], color='k', linestyle='--', linewidth=1)

    #def renderPicto(self, index):
    #    randC=np.random.rand(3,)
    #    pict = self.Pictos[index]
    #    for stroke in pict.Strokes:
    #        self.ax.scatter(stroke[:,0], stroke[:,1], marker='+', s=0.1, c=randC)

        

    #def renderTrace(self):
    #    self.ax.scatter(self.traceOff[:,0], self.traceOff[:,1], marker='o', s=0.25, c="m")
    #    self.ax.scatter(self.traceP1[:,0], self.traceP1[:,1], marker='o', s=0.25, c="b")
    #    self.ax.scatter(self.traceP2[:,0], self.traceP2[:,1], marker='o', s=0.25, c="b")
    #    self.ax.scatter(self.traceP3[:,0], self.traceP3[:,1], marker='o', s=0.25, c="b")
    #    self.ax.scatter(self.traceP4[:,0], self.traceP4[:,1], marker='o', s=0.25, c="b")

    def renderTracePressurized(self):
        if np.size(self.traceOff, 0)>6:
            self.ax.scatter(self.traceOff[:,0], self.traceOff[:,1], marker='o', s=0.25, c="m")
        if np.size(self.traceP1, 0)>6:
            self.ax.scatter(self.traceP1[:,0], self.traceP1[:,1], marker='o', s=0.25, c="b")
        if np.size(self.traceP2, 0)>6:
            self.ax.scatter(self.traceP2[:,0], self.traceP2[:,1], marker='o', s=0.25, c="g")
        if np.size(self.traceP3, 0)>6:
            self.ax.scatter(self.traceP3[:,0], self.traceP3[:,1], marker='o', s=0.25, c="y")
        if np.size(self.traceP4, 0)>6:
            self.ax.scatter(self.traceP4[:,0], self.traceP4[:,1], marker='o', s=0.25, c="r")

    def renderStrokeNumbers(self): 
        for stroke in self.StrokesObj:    
            self.ax.annotate("Tah " + str(int(stroke.ID)) + " ", (stroke.BoundaryPoints[0], stroke.BoundaryPoints[1]))




    def drawDefault(self):
            self.parent.dynamic_ax.clear()
            if np.size(self.traceOff, 0)>6:
                self.parent.dynamic_ax.scatter(self.traceOff[:,0], self.traceOff[:,1], marker='o', s=0.25, c="m")
            if np.size(self.traceP1, 0)>6:
                self.parent.dynamic_ax.scatter(self.traceP1[:,0], self.traceP1[:,1], marker='o', s=0.25, c="b")
            if np.size(self.traceP2, 0)>6:
                self.parent.dynamic_ax.scatter(self.traceP2[:,0], self.traceP2[:,1], marker='o', s=0.25, c="b")
            if np.size(self.traceP3, 0)>6:
                self.parent.dynamic_ax.scatter(self.traceP3[:,0], self.traceP3[:,1], marker='o', s=0.25, c="b")
            if np.size(self.traceP4, 0)>6:
                self.parent.dynamic_ax.scatter(self.traceP4[:,0], self.traceP4[:,1], marker='o', s=0.25, c="b")
            self.parent.dynamic_ax.figure.canvas.draw()

    def DrawPictos(self):
        self.parent.dynamic_ax.clear()
        self.parent.drawHighlights()
        try:
            
            count = 0
            for p in self.Pictos:
                if p.valid:
                    count +=1
            lino = np.linspace(0,1,num = count)
            duha = plt.cm.rainbow(lino)
            randC=iter.cycle(duha)


            for pict in self.Pictos:
                if pict.valid:
                    a = next(randC)

                    for s in pict.sIndex:

                        self.parent.dynamic_ax.scatter(self.StrokesObj[s].Points[:,0], self.StrokesObj[s].Points[:,1], marker='o', s=0.1, c=a)
            self.parent.dynamic_ax.figure.canvas.draw()
        except Exception as ex:
            print(ex)


