def OnPaintAll(self, event):
     
     self.SetCurrent(self.context)
     if not self.init:
         self.InitGL()
         self.init = 1
         self.globFrame = SuperFixedJoint(0, identity(4), 0)
         self.globFrame.set_length(.5)
         self.globFrame.show_joint = False
         self.globFrame.theta = 0
         self.my_id = 1
 
     self.OnDraw()
     self.Redraw()
     event.Skip()
class myGLCanvas(GLCanvas):
    def __init__(self, parent, size=(700, 700)):
        super(myGLCanvas, self).__init__(parent, size=size)
        self.context = GLContext(self)
        self.Bind(wx.EVT_PAINT, self.OnPaintAll)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseDown)
        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseUp)
        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
        self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDoubleLeft)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.size = self.GetClientSize()

        #Camera General Data
        self.init = 0
        self.fov = 40
        self.aspect = 1

        #Camera Actual Configuration Data
        self.cen = [0,0,0]
        self.up = [0, 0, 1]
        self.cam = [0,-10,0]
        self.u = [0,0,10]
        self.buffer_size = 32

        #window data
        self.length = 5
        self.parent = parent

        #elements
        self.elements = []
        self.bufer = []
        self.plane = []
        self.structure = []
        self.links = []
        self.branches = []
        self.d_init = False
        self.configuration = []


    def assign_mono_scale(self):
        """Sets the coefficients used to draw objects

        This function calculates coefficients which are used
        to draw the objects (Joints, links, end-effectors)
        It computes the minimum and maximum r or d different from 0.
        Then uses those sizes to determine the reference
        numbers which are used all over the class.
        """
        minv = inf
        for jnt in self.jnt_objs[1:]:
            dist = max(abs(jnt.r), abs(jnt.d))
            if dist < minv and dist != 0:
                minv = dist
        if minv == inf:
            minv = 1.
        self.length = 0.4 * minv
        for jnt in self.jnt_objs:
            if isinstance(jnt, PrismaticJoint):
                jnt.r = 3.5 * self.length
            jnt.set_length(self.length)

    def OnEraseBackground(self, event):
        # Do nothing, to avoid flashing on MSW.
        # This is needed
        pass
    
    def OnSize(self, event):
        size = self.size = self.GetClientSize()
        if self.GetContext():
            self.SetCurrent(self.context)
            gl.glViewport(0, 0, size.width, size.height)
        event.Skip()

    ## Mouse handling
    def OnMouseDown(self, evt):
        self.CaptureMouse()
        self.lastx, self.lasty = evt.GetPosition()
        
        if not (self.parent.data.FlagGet('ADD_ANC') or self.parent.data.FlagGet('REM_ANC')):
            self.Deactivate()
        
        for key in self.parent.data.FlagList('joint'):
            if self.parent.data.FlagGet(key) == 1:
                self.parent.data.FlagIncrement(key)
                self.origin = self.lastx, self.lasty
                
            elif self.parent.data.FlagGet(key) == 2:
               self.CreateJoint(key)

        if self.parent.data.FlagGet('PICK'):
            my_buffer = self.Pick()
            if self.parent.data.FlagGet('PLANE1') or  self.parent.data.FlagGet('PLANE2') or  self.parent.data.FlagGet('PLANE3'):
                self.DefinePlane(my_buffer)
            elif self.parent.data.FlagGet('DELETE'):
                self.OnDelete(my_buffer)
            elif self.parent.data.FlagGet('ADD_ANC'):
                self.AddAncestor(my_buffer)
            elif self.parent.data.FlagGet('REM_ANC'):
                self.RemAncestor(my_buffer)
            elif self.parent.data.FlagGet('PARALLEL'):
                self.MakeConstrain(my_buffer, 'PARALLEL')
            elif self.parent.data.FlagGet('PERPENDICULAR'):
                self.MakeConstrain(my_buffer, 'PERPENDICULAR')
            elif self.parent.data.FlagGet('AT_ANGLE'):
                self.MakeConstrain(my_buffer, 'AT_ANGLE')
            elif self.parent.data.FlagGet('AT_DISTANCE'):
                self.MakeConstrain(my_buffer, 'AT_DISTANCE')
            elif self.parent.data.FlagGet('PLANE_PERPENDICULAR'):
                self.MakeConstrain(my_buffer, 'PLANE_PERPENDICULAR')
            else:
                self.Activate(my_buffer)
            
        if self.parent.data.FlagGet('REF_POINT'):
                self.DrawElements(my_type='POINT', pos = self.GetCoordinates(self.lastx, self.lasty))
                self.OnDraw()
                self.Redraw()
                self.parent.data.FlagReset('REF_POINT')
                self.parent.data.FlagIncrement('PICK')

    #   On double-click reset the flags, abandon current operation
    def OnMouseDoubleLeft(self, evt):
        self.parent.data.FlagsChange('joint')
        self.parent.data.FlagsChange('ref')
        self.parent.data.FlagsChange('plane')
        self.parent.data.FlagsChange('button')
        self.parent.data.FlagsChange('constraints')
        del self.plane[:]

    def OnMouseUp(self, _):
        if self.HasCapture():
            self.ReleaseMouse()

    def OnMouseMotion(self, evt):
        if evt.Dragging():
            x, y = evt.GetPosition()
            
            if evt.LeftIsDown():
                dx, dy = x - self.lastx, y - self.lasty
                self.lastx, self.lasty = x, y

                if evt.RightIsDown():
                    self.Pan(dx,dy)
                else:
                    self.Rotate(dx,dy)
                    
            elif evt.RightIsDown():
                self.Zoom(y)

            self.CameraTransformation()
            self.Refresh(False)

    # Exporting to the .par file
    def Export(self, name):
        NJ = len([i for i in self.elements if (isinstance(i, SuperRevoluteJoint) or isinstance(i, SuperPrismaticJoint)) and not i.virtual_joint] )
        NL = len([i for i in self.elements if isinstance(i, Point) and not i.virtual_joint] )-1
        NF = NL+2*(NJ-NL)
        
        if not self.structure:
            return
        if not self.structure[0]-self.structure[1]:
            structure = SIMPLE
        elif not NJ-NL:
            structure = TREE
        else:
            structure = CLOSED_LOOP

        robot = Robot(name, NJ=NJ, NL=NL, NF=NF, is_mobile=False,
                 structure=structure)
        
        robot.G = Matrix([var('G1'), var('G2'), var('G3')])
        if self.structure[4][0]:
            robot.Z = transpose(self.elements[self.structure[4][0]-1].T)

        frames = []
        end = []
        cut = []
        
        for branch in self.branches[self.structure[0]:self.structure[1]+1]:
            frames += [i for i in branch[1:-2] if not isinstance(self.elements[i-1], Point)]
           
            if not self.elements[branch[-2]-1].virtual_joint:
                end.append(branch[-2])
            else:
                cut.append(branch[-2])


        frames = [ i for i in frames if not i in end and not i in cut]
        frames += end + cut
        
        sigma, mu, theta, alpha, gamma, d, r, b, ant = [],[],[],[],[],[],[],[],[]

        for frame in frames:
##            
            if isinstance(self.elements[frame-1], SuperPrismaticJoint):
                sigma.append(1)
            elif isinstance(self.elements[frame-1], SuperRevoluteJoint):
                sigma.append(0)
            else:
                sigma.append(2)
                
            i = [i for i in range(len(frames)) if frames[i] == self.elements[frame-1].ant]
            
            if len(i)==0 and self.elements[frame-1].ant==self.structure[4][0]:
                ant.append(0)
            elif len(i)>0:
                ant.append(i[0]+1)
            else:
                msg = wx.MessageDialog (None, 'Export error, cannot deifne the parameters.', style=wx.OK|wx.CENTRE)
                msg.ShowModal()
                return 

            if self.elements[frame-1].active and not self.elements[frame-1].cut_joint:
                mu.append(1)
            else:
                mu.append(0)
        
            if isinstance(self.elements[frame-1], SuperRevoluteJoint) and not self.elements[frame-1].virtual_joint:
                theta.append(var('th%s' % (len(theta)+1)))
            else:
                theta.append(self.elements[frame-1].theta)
                
            if isinstance(self.elements[frame-1], SuperPrismaticJoint) and not self.elements[frame-1].virtual_joint:
                r.append(var('r%s' % (len(theta)+1)))
            else:
                r.append(self.elements[frame-1].r)
                
            alpha.append(self.elements[frame-1].alpha)
            d.append(self.elements[frame-1].d)
            gamma.append(self.elements[frame-1].gamma)
            b.append(self.elements[frame-1].b)

        robot.sigma[1:] = sigma
        robot.theta[1:] = theta
        robot.alpha[1:] = alpha
        robot.gamma[1:] = gamma
        robot.d[1:] = d
        robot.r[1:] = r
        robot.b[1:] = b
        robot.ant[1:] = ant
        robot.mu[1:] = mu
                    
        parfile.writepar(robot)
        
    # This function defines the structure of the robot, the branches, cut_joints, links and joints in the sturcture 
    def DefineStructure(self):
        #Clear elements before analysis
        to_delete = [i.my_id for i in self.elements if i.virtual_joint]
       
        for i in reversed(to_delete):
            self.Delete([i])

##        self.branches = []
##        self.struct = []
        branches = []
        links = self.links
        start = 0
        cut_joints = []
        struct = []
        start = self.FindStart(links, branches)
        branches.append([])
        used = []
        joints = []
        fixed = [start]
        my_links = []

        # Assign cut joints adn check if model is valid
        for element in self.elements:
            if isinstance(element, SuperRevoluteJoint) or isinstance(element, SuperPrismaticJoint):
                i = [i for i in self.links if i[1]==element.my_id] 
                if len(i)<2:
                    msg = wx.MessageDialog (None, 'Cannot define the structure, at least one joint missing conection.', style=wx.OK|wx.CENTRE)
                    msg.ShowModal()
                    return struct, branches
                elif element.cut_joint:
                    cut_joints.append([i[0][0],i[0][1],i[1][0]])

        NJ = len([i for i in self.elements if isinstance(i, SuperRevoluteJoint) or isinstance(i, SuperPrismaticJoint)])
        NL = len([i for i in self.elements if isinstance(i, Point)])-1

        if len(cut_joints) < NJ-NL:
            msg = wx.MessageDialog (None, 'Cannot define the structure, please define more cut joints.', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return struct, branches

        branches[-1], links, used, joints, fixed, my_links = self.GetBranch(start, links, used, joints, fixed, cut_joints, my_links)
        struct.append(len(branches)-1)

        if NJ==NL and not isinstance(self.elements[-1],Point):
            self.DrawElements(my_type='POINT')
            self.elements[-1].show_frame = False
            self.elements[-1].show_joint = False
            self.elements[-1].virtual_joint = True
        
    # Find branches
        while len(branches[-1])>1:
            key = self.FindKey(links, branches)
            branches.append([])
            branches[-1], links, used, joints, fixed, my_links= self.GetBranch(key, links, used, joints, fixed, cut_joints, my_links)

        for branch in branches:
            if len(branch)>1 and [i for i in cut_joints if i[1]==branch[-1] and i[2]==branch[-2]]:

                if isinstance(self.elements[branch[-1]-1], SuperRevoluteJoint):
                    self.DrawElements(my_type='REVOLUTE', T=self.elements[branch[-1]-1].T)
                else:
                    self.DrawElements(my_type='PRISMATIC', T=self.elements[branch[-1]-1].T)
                self.elements[-1].show_frame = False
                self.elements[-1].show_joint = False
                branch[-1] = self.elements[-1].my_id
                self.elements[-1].virtual_joint = True
                self.DrawElements(my_type='POINT', T=self.elements[branch[-1]-1].T)
                self.elements[-1].show_frame = False
                self.elements[-1].show_joint = False
                branch.append(self.elements[-1].my_id)
                self.elements[-1].virtual_joint = True

            if len(branch)>1 and [i for i in cut_joints if i[1]==branch[-1] and i[0]==branch[-2]]:
                self.DrawElements(my_type='POINT', T=self.elements[branch[-1]-1].T)
                self.elements[-1].show_frame = False
                self.elements[-1].show_joint = False
                branch.append(self.elements[-1].my_id)
                self.elements[-1].virtual_joint = True
                
    # Fill structure
        struct.append(len(branches)-2)
        struct.append(used)
        struct.append(joints)
        struct.append(fixed)
        struct.append(cut_joints)
        struct.append(my_links)
    
        return struct, branches
    
    # Find begining of the structure
    def FindStart(self, links, branches):
        i = [i[1] for i in links if not i[1]]
        if len(i):
            return i[0]
        else:
            i = [i[1] for i in links if isinstance(i[1], SuperFixedJoint)]
            if len(i):
                return i[0]
        
        return -1
    
    # Find begining of the new branch
    def FindKey(self, links, branches):
        key = -1
        for branch in branches:
            for link in links:
                if link[0] in branch[:-1] :
                    return link[0]
        return key

    # Deinfe the new branch
    def GetBranch(self, key, links, used, joints, fixed, cut_joints, my_links):
        branch = []
        check = True
        branch.append(key)
        
        
        while check:
            check = False
            if_break = False
            for link in links:
                if link[0]==key:
                    key = link[0-1]
                    branch.append(key)
                    check = True
                    if_break = True
                    remove = link
                    used.append(link)
                    if not key in joints and not isinstance(self.elements[key-1], SuperFixedJoint) and not key==0:
                        joints.append(key)
                    elif not key in fixed and (isinstance(self.elements[key-1], SuperFixedJoint) or key==0):
                        fixed.append(key)
                elif link[1]==key and (len(branch)<2 or (not ([branch[-2],branch[-1],link[0]] in cut_joints) and (not ([link[0],branch[-1],branch[-2]] in cut_joints)))):

                    branch.append(link[1-1])
                    key = link[1-1]
                    check = True
                    if_break = True
                    remove = link
                    used.append(remove)
                    if not key in link and isinstance(self.elements[key-1], Point):
                        my_links.append(key)
                if if_break:
                    links = [i for i in links if not i==remove]
                    break
                
        return  branch, links, used, joints, fixed, my_links

    # Activating the element: Joint or Link
    def Activate(self, my_buffer):
        for min_d, max_d, name in my_buffer:
    
            self.Deactivate()
            if len(name)>1:
                if name[0]:
                    self.elements[name[0]-1].color_j=[1,0,0]
                    self.parent.ActiveJoint(name[0])
                elif name[0]==0:
                    self.parent.ActiveJoint(-2)
            else:
                self.elements[name[0]-1].color_j=[1,0,0]
                self.elements[name[0]-1].color_l=[1,0,0]
                self.parent.ActiveLink(name[0])
            break
        
    # Deactivating the element: Joint or Link
    def Deactivate(self):
        if self.parent.data.FlagGet('ACTIVE_JOINT')==-2:
            self.globFrame.color_j=[0,0.6,0.5]
        elif self.parent.data.FlagGet('ACTIVE_JOINT'):
            if isinstance(self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1],SuperRevoluteJoint):
                self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1].color_j=[1,1,0]
            elif isinstance(self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1],SuperPrismaticJoint):
                self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1].color_j=[1,0.6,0]
            else:
                self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1].color_j=[0,0.6,0.5]
            
        elif self.parent.data.FlagGet('ACTIVE_LINK'):
            self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].color_j=[0,0.6,0.5]
            self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].color_l=[1,1,1]
        self.parent.Deactive()

    # Adding the link to the system
    def AddAncestor(self, my_buffer):
        for a, b, name in my_buffer:
            if not name[0] or not isinstance(self.elements[name[0]-1],Point):
                if not [self.parent.data.FlagGet('ACTIVE_LINK'),name[0]] in self.links:
                    if len([i for i in self.links if i[1]==name[0]])<2:
                        self.links.append([self.parent.data.FlagGet('ACTIVE_LINK'),name[0]])
                        if not name[0] and not [i for i in self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos if all(i==[0,0,0])]:
                            self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos.append([0,0,0])
                        elif name[0]  and not [i for i in self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos if all(i== self.elements[name[0]-1].T[3,0:3])]:
                            self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos.append(self.elements[name[0]-1].T[3,0:3])
                
                self.parent.data.FlagSet('PARAMETERS',3)
                self.parent.data.FlagReset('ADD_ANC')
                break

    # Removing link from the system
    def RemAncestor(self, my_buffer):
        for a, b, name in my_buffer:
            if not isinstance(self.elements[name[0]-1],Point) or not name[0]:
                self.links=[i for i in self.links if not i==[self.parent.data.FlagGet('ACTIVE_LINK'),name[0]]]

                if name[0]:
                    self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos = [
                        i for i in self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos if not all(i==self.elements[name[0]-1].T[3,0:3])]
                else:
                    self.elements[self.parent.data.FlagGet('ACTIVE_JOINT')-1].anc_pos = [
                        i for i in self.elements[self.parent.data.FlagGet('ACTIVE_LINK')-1].anc_pos if not all(i==[0,0,0])]

                self.parent.data.FlagSet('PARAMETERS',3)
                self.parent.data.FlagReset('REM_ANC')
                break

    # Applying the geometrical constraints
    def MakeConstrain(self, my_buffer, flag):
            for min_d, max_d, name in my_buffer:
                if  not name[0] or not isinstance(self.elements[name[0]-1],Point):
                    if self.parent.data.FlagGet(flag)==1:
                        self.plane.append(name[0])
                        self.parent.data.FlagIncrement(flag)
                    elif not all(name[0] in self.plane) and name[0]:
                        if not self.plane[0]:
                            axis = self.globFrame
                        else:
                            axis = self.elements[self.plane[-1]-1]
                        if flag=='PARALLEL':
                            self.elements[name[0]-1].T[0:3,0:3]=axis.T[0:3,0:3]
                        elif flag=='PERPENDICULAR':
                            self.elements[name[0]-1].T[0:3,0:3]=self.EulerTransformation(pi/2,[1,0,0]).dot(axis.T[0:3,0:3])
                        elif flag=='AT_ANGLE':
                            export = wx.TextEntryDialog(None, 'Give the angle(degrees)',  style=wx.SYSTEM_MENU|wx.OK|wx.CANCEL)
                            if export.ShowModal()==wx.ID_OK:
                                self.elements[name[0]-1].T[0:3,0:3]=self.EulerTransformation(radians(int(export.GetValue())),[1,0,0]).dot(axis.T[0:3,0:3])
                        elif flag=='AT_DISTANCE':
                            export = wx.TextEntryDialog(None, 'Give the distance',  style=wx.SYSTEM_MENU|wx.OK|wx.CANCEL)
                            if export.ShowModal()==wx.ID_OK:
                                val = float(export.GetValue())
                                u = subtract(self.elements[name[0]-1].T[3,0:3],axis.T[3,0:3])
                                u /= norm(u)
                                self.elements[name[0]-1].T[3,0:3]=add(axis.T[3,0:3],multiply(u,val))
                        elif flag == 'PLANE_PERPENDICULAR':
                            u = self.u/norm(self.u)
                            self.elements[name[0]-1].T[0:3,0:3]=axis.T[0:3,0:3].dot(self.EulerTransformation((pi/2),u))

                        del self.plane[:]
                        self.parent.data.FlagSet('PARAMETERS',3)
                        self.parent.data.FlagReset(flag)
                    elif not name[0]:
                        del self.plane[:]
                        self.parent.data.FlagSet('PARAMETERS',3)
                        self.parent.data.FlagReset(flag)
                    break

    # Handling deleting element from the system, check elements, links, and correcting ids of the elements                      
    def Delete(self,name):
        if name and name[0]:
            if len(name)>1:
                for l in [i[0] for i in self.links if i[1]==name[0]]:
                    self.elements[l-1].anc_pos = [i for i in self.elements[l-1].anc_pos if not all(i==self.elements[name[0]-1].T[3,0:3])]   
                self.links = [i for i in self.links if not i[1]==name[0]]
            else:
                self.links = [i for i in self.links if not i[0]==name[0]]
                
            for i in self.links:
                if i[0]>name[0]:
                    i[0] -= 1
                if i[1]>name[0]:
                    i[1] -= 1
                                         
            for element in self.elements[name[0]-1:]:
                element.my_id -= 1
            del self.elements[name[0]-1]
            self.my_id -= 1
            self.parent.data.FlagReset('DELETE')
            self.parent.data.FlagSet('PARAMETERS',3)
            return True

    # Initate the delete operation called by user                
    def OnDelete(self, my_buffer):
        for a, b, name in my_buffer:
            check = self.Delete(name)
            if check:
                break

    # Menage gathering informations about elements and intilaise creation                
    def DefinePlane(self, my_buffer):
        for key in self.parent.data.FlagList('plane'):
            if self.parent.data.FlagGet(key)==1:
                del self.plane[:]
            for min_depth, max_depth, name in my_buffer:
                if not name in self.plane:
                    if ((name[0] and (isinstance(self.elements[name[0]-1], Point) or name[1]==0)) and
                        (((key == 'PLANE3' and self.parent.data.FlagGet(key)) or (self.parent.data.FlagGet(key)==1  and  key == 'PLANE1')))):
                        self.plane.append(name)  
                        if self.parent.data.FlagGet(key) == 3:
                            self.InitPlane3()
                            break
                        else:
                            self.parent.data.FlagIncrement(key)              
                    elif (not(name[0] and (isinstance(self.elements[name[0]-1], Point) or name[1]==0)) and
                              ((self.parent.data.FlagGet(key) and key == 'PLANE2') or (self.parent.data.FlagGet(key)>1 and key == 'PLANE1'))):
                        self.plane.append(name)
                        if self.parent.data.FlagGet(key)==1 and key=='PLANE2':
                            self.parent.data.FlagIncrement(key)
                            break   
                        elif key=='PLANE1':
                            self.InitPlane1()
                            break   
                        elif key=='PLANE2':
                            self.InitPlane2()
                            break

    # Init1Plane1, InitPlane2, InitPlane3 prepare the elements to the CreatePlane
    def InitPlane1(self):
        point = self.elements[self.plane[0][0]-1].T[3,0:3]
        
        
        if self.plane[1][1]==4:
            axis = self.elements[self.plane[1][0]-1]
            vect1 = inv(self.elements[self.plane[1][0]-1].T[0:3,0:3]).dot([0,0,1])
        else:
            if not self.plane[1][0]:
                axis = self.globFrame
            else:
                axis = self.elements[self.plane[1][0]-1]
            if self.plane[1][1]==1:
                vect1 = inv(axis.T[0:3,0:3]).dot([1,0,0])
            elif self.plane[1][1]==2:
                vect1 = inv(axis.T[0:3,0:3]).dot([0,1,0])
            else:
                vect1 = inv(axis.T[0:3,0:3]).dot([0,0,1])
                
        if norm(vect1)>0.001:
            vect1 /= norm(vect1)
        else:
            msg = wx.MessageDialog (None, 'Cannot define the plane', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        
        vect2 = axis.T[3,0:3]-point
        if norm(vect2)>0.001:
            vect2 /= norm(vect2)   
        else:
            msg = wx.MessageDialog (None, 'Cannot define the plane', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        
        if norm(cross(vect1,vect2))<0.01:
            msg = wx.MessageDialog (None, 'Cannot define the frame', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        else:
            normal = cross(vect1,vect2)
            normal /= norm(normal)
            point = axis.T[3,0:3]
            self.CreatePlane(normal,point, vect1)
        self.parent.data.FlagReset('PLANE1')
        del self.plane[:]

    def InitPlane2(self):
        vect = []
        point = []
        for i in range(0,2):
            if self.plane[i][1]==4:
                vect.append(inv(self.elements[self.plane[i][0]-1].T[0:3,0:3]).dot([0,0,1]))
                point.append(self.elements[self.plane[i][0]-1].T[3,0:3])
            else:
                if not self.plane[i][0]:
                    axis = self.globFrame
                else:
                    axis = self.elements[self.plane[i][0]-1]

                if self.plane[i][1]==1:
                    vect.append(inv(axis.T[0:3,0:3]).dot([1,0,0]))
                elif self.plane[i][1]==2:
                    vect.append(inv(axis.T[0:3,0:3]).dot([0,1,0]))
                else:
                    vect.append(inv(axis.T[0:3,0:3]).dot([0,0,1]))
                point.append(axis.T[3,0:3])
            vect[i] /= norm(vect[i])
                                    
        check = point[1]-point[0]
        if norm(check) > 0.0001 and abs((vect[1][0]*vect[0][1]-vect[1][1]*vect[0][0]))>0.0001:
            t = (vect[1][0]*check[1]-vect[1][1]*check[0])/(vect[1][0]*vect[0][1]-vect[1][1]*vect[0][0])
            r = (vect[0][0]*t-check[0])/vect[1][0]
            s = check[2]-vect[0][2]*t+vect[1][2]*r
        else:
            s = 0
        if norm(cross(vect[0],vect[1]))<0.01 or abs(s) > 0.2:
            msg = wx.MessageDialog (None, 'Cannot define the frame, points lines do not cross', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
        else:
            normal = cross(vect[0],vect[1])
            normal /= norm(normal)
            self.CreatePlane(normal,point[0], vect[0])
        self.parent.data.FlagReset('PLANE2')
        del self.plane[:]

    def InitPlane3(self):
        points = []
        for i in range(0,3):
            if isinstance(self.elements[self.plane[i][0]-1], Point):
                points.append(self.elements[self.plane[i][0]-1].pos)
            else:
                points.append(self.elements[self.plane[i][0]-1].T[3,0:3])
                
        vect1 = subtract(points[0],points[1])
        vect2 = subtract(points[0],points[2])
        if norm(vect1)>0.001:
            vect1 /= norm(vect1) 
        else:
            msg = wx.MessageDialog (None, 'Cannot define the plane', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        if norm(vect2)>0.001:
            vect2 /= norm(vect2)
        else:
            msg = wx.MessageDialog (None, 'Cannot define the plane', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        if norm(cross(vect1,vect2))<0.01:
            msg = wx.MessageDialog (None, 'Cannot define the plane', style=wx.OK|wx.CENTRE)
            msg.ShowModal()
            return
        else:
            normal = cross(vect1,vect2)
            normal /= norm(normal)  
            self.CreatePlane(normal,points[0], vect1)
        self.parent.data.FlagReset('PLANE3')
        del self.plane[:]

    # Directly creating plane
    def CreatePlane(self, normal, point, line):
        self.cen = point
        
        up = cross(line,normal)
        self.up = up/norm(up)
        
        self.cen = self.cen + multiply(up,0.01)
        self.cam = add(self.cen,multiply(normal,5))
        self.plane[:] = []
        self.CameraTransformation()
        self.OnDraw()
        self.Redraw()



    ## Create joint, recalculate the parmaters from screen to the global frame
    #  Add all necessery adjustmen in the program
    def CreateJoint(self, my_type):
        coefY = norm(self.u)*tan(radians(self.fov/2))/self.size.height*2
        coefX = norm(self.u)*tan(radians(self.fov/2))/self.size.width*2*self.aspect
                
        lastX = (self.lastx-self.size.width/2)*coefX
        lastY = (-self.lasty+self.size.height/2)*coefY
        originX = (self.origin[0]-self.size.width/2)*coefX
        originY = (-self.origin[1]+self.size.height/2)*coefY
        
        angle = arctan2(lastY-originY, lastX-originX)

        G = gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX)
        R = self.EulerTransformation(angle, self.u/norm(self.u))
        T = vstack((hstack((R,vstack(([0,0,0])))),[0,0,0,1]))
        
        T = inv(G).dot(T)
        T[3,0:3]=self.GetCoordinates(self.origin[0], self.origin[1])
        if my_type=='REVOLUTE' or my_type=='PRISMATIC':
            T[0:3,0:3] = self.EulerTransformation(-pi/2,[0,1,0]).dot(T[0:3,0:3])
        self.DrawElements(T=T,my_type=my_type)
        self.OnDraw()
        self.Redraw()
        self.parent.data.FlagReset(my_type)
        self.parent.data.FlagIncrement('PICK')
    
    ## Functions conected with camera
    # Recalculating the elements form the screen to the global frame
    def GetCoordinates(self, x, y):
        coefY = norm(self.u)*tan(radians(self.fov/2))/self.size.height*2
        coefX = norm(self.u)*tan(radians(self.fov/2))/self.size.width*2*self.aspect
                
        screenX = (x-self.size.width/2)*coefX
        screenY = (-y+self.size.height/2)*coefY
        z = 0

        u = self.u/norm(self.u)
        up = self.up/norm(self.up)
        r = cross(u,up)
        r /= norm(r)
        up = cross(r,u)
        up = up/norm(up)
        dy = multiply(up,screenY)
        dx = multiply(r,screenX)
        
        trans = dy+dx+self.cen
##      print glu.gluUnProject(x,y, self.cen[2])               
        return trans
    
    # Calulate the rotation matrix from the euler parameters
    def EulerTransformation(self, angle, vector):
        e0 = cos(angle/2)
        e = multiply(sin(angle/2),vector)

        R = 2*vstack((hstack((e0*e0+e[0]*e[0]-0.5,e[0]*e[1]-e0*e[2],e[0]*e[2]+e0*e[1])),
             hstack((e[0]*e[1]+e0*e[2],e0*e0+e[1]*e[1]-0.5,e[2]*e[1]-e0*e[0])),
             hstack((e[0]*e[2]-e0*e[1],e[2]*e[1]+e0*e[0],e0*e0+e[2]*e[2]-0.5))))
        return R     

    # Change the position of the camera
    def CameraTransformation(self):
        gl.glLoadIdentity()
        glu.gluLookAt(self.cam[0],self.cam[1],self.cam[2],
            self.cen[0], self.cen[1], self.cen[2],
            self.up[0], self.up[1], self.up[2])
        self.u = subtract(self.cen,self.cam)

    ## Rotation of the camera cooperate with rotate function
    # Calulate the parameters of the camera when changes in horizontal and vertical angels are known
    def SetCamera(self, ver, hor):
        u = cross(self.up, self.u/norm(self.u))

        R1 = self.EulerTransformation(ver, u/norm(u))
        R2 = self.EulerTransformation(hor, self.up)
        u = R2.dot(R1)
        u = hstack(u.dot(vstack(self.u)))
        u = u/norm(u)

        if not norm(cross(u,self.up))<0.05:
            self.cam  = subtract(self.cen,multiply(u,norm(self.u)))
    
    def Pan(self,dx,dy):
        coefY = norm(self.u)*tan(radians(self.fov/2))/self.size.height*2
        coefX = norm(self.u)*tan(radians(self.fov/2))/self.size.width*2*self.aspect
        u = self.u/norm(self.u)
        r = cross(self.up,self.u)
        r /= norm(r)
        up = cross(self.u,r)
        up /= norm(up)
        dx = multiply(dx*coefX*0.25,r)
        dy = multiply(coefY*dy*0.5,up)
        self.cen += add(dx,dy)

    def Rotate(self,dx,dy):
        coef = norm(self.u)/self.length*sin(radians(self.fov/2.))
        d_hor = dx*coef/self.size.width
        d_ver = dy*coef/self.size.height
        self.SetCamera(d_ver,d_hor) 

    def Zoom(self,y):
        dy = y - self.lasty
        self.lasty = y
        du = 2 * float(dy) / self.size.height
        self.cam += multiply(self.u,du)

    ## Drawing Functions
    # OpenGL callback
    def OnPaintAll(self, event):
        
        self.SetCurrent(self.context)
        if not self.init:
            self.InitGL()
            self.init = 1
            self.globFrame = SuperFixedJoint(0, identity(4), 0)
            self.globFrame.set_length(.5)
            self.globFrame.show_joint = False
            self.globFrame.theta = 0
            self.my_id = 1
    
        self.OnDraw()
        self.Redraw()
        event.Skip()

    # Drawing elements, called be OnPaintAll (OpenGL) and when picking
    def OnDraw(self):
        if not self.init:
            return
        
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnableClientState(gl.GL_NORMAL_ARRAY)
        
##        globFrame.T = self.getCoordinates(self.size.width*0.1, self.size.height*0.9)
##        globFrame.set_lenght(0.25)
        
        self.globFrame.draw_glob_frame()

        if not self.parent.data.FlagGet('MODE'):
            for element in self.elements:
                element.show_frame = False
                element.draw_joint()

        elif self.branches:
            gl.glPushMatrix()
            if self.structure[4][0]:
                gl.glMultMatrixf(self.elements[self.structure[4][0]-1].T)
            self.Transform(self.branches[self.structure[0]][1:])
            gl.glPopMatrix()
        
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
        gl.glDisableClientState(gl.GL_NORMAL_ARRAY)

    # Initalize the drawing in OpenGL
    def Redraw(self):
        gl.glFlush()
        self.SwapBuffers()
        self.Refresh(False)

    # Menage recursive drawing in the parameters mode
    def Transform(self, branch):
        gl.glPushMatrix()
        for joint in branch:
            if joint==0 or not isinstance(self.elements[joint-1], Point):
                if joint:
                    self.elements[joint-1].draw()
                                
            for k in [i for i in self.branches[self.structure[0]+1:self.structure[1]+1] if i[0]==joint]:
                self.Transform(k[1:])
                
        gl.glPopMatrix()

    # Menage calculating the parameters
    def GetParameters(self, branch, start_T, start_joint):
        old = start_joint
        old_T = start_T
        init = False
        next_branch = []
        for joint in branch:
            if joint==0 or not isinstance(self.elements[joint-1], Point):
                old_T = self.Parameters(joint,old_T)
                self.elements[joint-1].ant = old
                old = joint
                if not init:
                    self.elements[joint-1].param = 6
                else:
                    self.elements[joint-1].param = 4
                if joint == self.branches[self.structure[0]][2]:
                    if not (abs(self.elements[joint-1].gamma)<0.001 and abs(self.elements[joint-1].b)<0.001):
                        self.elements[joint-1].param = 6
                
                
            for k in [i for i in self.branches[self.structure[0]+1:self.structure[1]+1] if i[0]==joint]:
                next_branch.append([k[1:],[],old])

            init = True
            
        return next_branch        

    # Adjusting the parameters into the D-H notations
    def SetParameters(self, branch):
        
        init = False
        for joint in reversed(branch):
            if (joint==0 or not isinstance(self.elements[joint-1], Point)) and (not init or not joint == self.branches[self.structure[0]][1]) :
                if not init:
                    init = True
                elif (not joint == 0) and self.elements[old-1].param == 4:
                    self.elements[joint-1].theta += self.elements[old-1].gamma
                    self.elements[joint-1].r += self.elements[old-1].b
                    self.elements[old-1].b = 0
                    self.elements[old-1].gamma = 0
                    
                else:
                    break
                old = joint

    # Puttin variables into the begining configuration
    def SetConfiguration(self):
                    
        for branch in self.branches[self.structure[0]:self.structure[1]+1]:
            for joint in branch:
                if joint and isinstance(self.elements[joint-1], SuperRevoluteJoint):
                    self.elements[joint-1].theta = 0
                elif joint and isinstance(self.elements[joint-1], SuperPrismaticJoint):
                    self.elements[joint-1].r = 0.2

    # Caluclating the transforamtion matrix for new branch
    def GetTransforms(self, branch, old_T, next_branch):
        new_T = old_T
        for joint in branch:
            if (joint==0 or not isinstance(self.elements[joint-1], Point)):
                T = self.GetT(self.elements[joint-1].gamma, self.elements[joint-1].b,
                              self.elements[joint-1].alpha, self.elements[joint-1].d,
                              self.elements[joint-1].theta, self.elements[joint-1].r)
                new_T = new_T.dot(T)
                
            for check in next_branch:
                if joint == check[2]:
                    check[1]=new_T

        return next_branch
            
    # Pure calucaltion of parameters          
    def Parameters(self,  new_id,old_T):
        if new_id:
            element = self.elements[new_id-1]
        else:
            element = self.globFrame
        
        T = dot(inv(old_T),transpose(element.T))
        
        if abs(T[0,2])<0.001 and abs(T[1,2])<0.001:
            if abs(T[2,2]-1)<0.001:
                alpha = 0
            else:
                alpha = pi
            r = 0
            b = T[2,3]
            d = sqrt((T[0,3]*T[0,3])+(T[1,3]*T[1,3]))
            gamma = arctan2(T[1,3],T[0,3])
            theta = arctan2(-cos(gamma)*T[0,1]-sin(gamma)*T[1,1],cos(gamma)*T[0,0]+sin(gamma)*T[1,0])
        else:
            gamma = arctan2(-T[0,2],T[1,2])
            alpha = arctan2(sin(gamma)*T[0,2]-cos(gamma)*T[1,2],T[2,2])
            theta = arctan2(-cos(gamma)*T[0,1]-sin(gamma)*T[1,1],cos(gamma)*T[0,0]+sin(gamma)*T[1,0])
            d = T[1,3]*sin(gamma)+T[0,3]*cos(gamma)

            if abs(sin(alpha))<0.001:
                r = 0
            elif abs(sin(gamma))<0.001:
                r = -T[1,3]/cos(gamma)/sin(alpha)
            else:
                r = (T[0,3]-d*cos(gamma))/sin(gamma)/sin(alpha)
            
            b = T[2,3]-r*cos(alpha)

        
        element.gamma = gamma
        element.alpha = alpha
        element.theta = theta
        element.d = d
        element.r = r
        element.b = b    

        new_T = self.GetT( gamma, b, alpha, d, theta, r)

        return old_T.dot(new_T)

    # Get Transformation matrix for the next frame
    def GetT(self, gamma, b, alpha, d, theta, r):
        new_T = [[cos(gamma)*cos(theta)-sin(gamma)*cos(alpha)*sin(theta),
                  -cos(gamma)*sin(theta)-sin(gamma)*cos(alpha)*cos(theta),
                  sin(gamma)*sin(alpha),
                  d*cos(gamma)+r*sin(gamma)*sin(alpha)],
                 [sin(gamma)*cos(theta)+cos(gamma)*cos(alpha)*sin(theta),
                  -sin(gamma)*sin(theta)+cos(gamma)*cos(alpha)*cos(theta),
                  -cos(gamma)*sin(alpha),
                  d*sin(gamma)-r*cos(gamma)*sin(alpha)],
                 [sin(alpha)*sin(theta),sin(alpha)*cos(theta),
                  cos(alpha),r*cos(alpha)+b],
                 [0,0,0,1]]
        return new_T

    # Keep the current configuration befor jumping into the oder mode
    def SaveConfiguration(self):
        self.configuration = []
        for element in self.elements:
            if not isinstance(element, Point):
                self.configuration.append([element.my_id, element.gamma, element.b, element.alpha, element.d, element.theta, element.r])

    # Reload the current configuration
    def LoadConfiguration(self):
        for i in self.configuration:
            self.elements[i[0]-1].gamma = i[1]
            self.elements[i[0]-1].b = i[2]
            self.elements[i[0]-1].alpha = i[3]
            self.elements[i[0]-1].d = i[4]
            self.elements[i[0]-1].theta = i[5]
            self.elements[i[0]-1].r = i[6]

    # Setting up and create the element in the program, menage global id, 
    def DrawElements(self, my_type, T=identity(4), pos=[0,0,0]):
        if my_type=='POINT':
            self.elements.append(Point(pos, self.my_id,0))
            self.elements[-1].set_length(0.3)
        else:   
            if my_type=='FIXED':
                self.elements.append(SuperFixedJoint(0, my_id=self.my_id ,T=T))
            elif my_type=='PRISMATIC':
                self.elements.append(SuperPrismaticJoint(0, my_id=self.my_id, T=T))
            elif my_type=='REVOLUTE':
                self.elements.append(SuperRevoluteJoint(0, my_id=self.my_id, T=T))
            self.elements[-1].set_length(0.5)
        self.my_id += 1
        
        if self.my_id > self.buffer_size:
            if self.buffer_size*4 <  self.max_stack:
                self.buffer_size *= 4
            elif self.my_id <= self.max_stack:
                self.buffer_size = self.max_stack
            else:
                msg = wx.MessageDialog (None, 'Maximu value of indepentend elements has been achived. New elements will not be pickble', style=wx.OK|wx.CENTRE)
                msg.ShowModal()
        self.parent.data.FlagSet('PARAMETERS',3)

                
    ##OpenGL handling
    # Picking operation
    def Pick(self):
        self.globFrame.named = False
        for element in self.elements:
            element.named = False
            
        gl.glSelectBuffer(512)
        gl.glRenderMode(gl.GL_SELECT)
        gl.glInitNames()
        gl.glPushMatrix()
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        glu.gluPickMatrix(self.lastx, self.size.height-self.lasty ,0.25, 0.25, [0, 0, self.size.width, self.size.height])
        glu.gluPerspective(self.fov, self.aspect, 0.2, 200.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)
        self.CameraTransformation()
        self.OnDraw()
        my_buffer = gl.glRenderMode(gl.GL_RENDER)
        gl.glPopMatrix()
        gl.glPushMatrix()
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        glu.gluPerspective(self.fov, self.aspect, 0.2, 200.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)
        self.CameraTransformation()
        self.OnDraw()
        self.Redraw()
        gl.glPopMatrix()
        return my_buffer

    # Initalization of the OpenGL
    def InitGL(self):
        # set viewing projection
        mat_specular = (1.0, 1.0, 1.0, 1.0)
        light_position = (.3, .3, 0.5, 0.0)
        light_position1 = (-0.3, 0.3, 0.5, 0.0)
        diffuseMaterial = (1., 1., 1., 1.0)
        ambientMaterial = (0.5, .5, .5, 1.0)

        gl.glClearColor(1.0, 1.0, 1.0, 1.0)
        gl.glShadeModel(gl.GL_SMOOTH)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glMaterialfv(gl.GL_FRONT, gl.GL_AMBIENT, ambientMaterial)
        gl.glMaterialfv(gl.GL_FRONT, gl.GL_DIFFUSE, diffuseMaterial)
        gl.glMaterialfv(gl.GL_FRONT, gl.GL_SPECULAR, mat_specular)
        gl.glMaterialf(gl.GL_FRONT, gl.GL_SHININESS, 25.0)
        gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, light_position)
        gl.glLightfv(gl.GL_LIGHT1, gl.GL_POSITION, light_position1)
        gl.glEnable(gl.GL_LIGHTING)
        gl.glEnable(gl.GL_LIGHT0)
        gl.glEnable(gl.GL_LIGHT1)

        gl.glColorMaterial(gl.GL_FRONT, gl.GL_DIFFUSE)
        gl.glEnable(gl.GL_COLOR_MATERIAL)

        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        glu.gluPerspective(self.fov, self.aspect, 0.2, 200.0)

        gl.glMatrixMode(gl.GL_MODELVIEW)
        
        self.CameraTransformation()
        self.globTrans = gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX)
        gl.glRenderMode(gl.GL_RENDER)
        self.max_stack = gl.glGetFloatv(gl.GL_MAX_NAME_STACK_DEPTH)