def __init__(self,
              _step_max = 0.1,
              _step_min = 0.0125, 
              _max_rep_length = 24.0,
              _max_force = 0.7,
              _repulsion = 27.7,
              _rigidity = 1.1,
              _length = 5.5,
              _gravity = 0.01):
     
     LayoutGroupDepth.__init__(self)
     
     # map of forces
     self.step_max = _step_max
     self.step = self.step_max
     self.step_min = _step_min
     
     self.max_rep_length = _max_rep_length
     self.max_force = _max_force
     
     self.repulsion = _repulsion
     self.rigidity = _rigidity
     self.length = _length
     self.gravity = _gravity
     
     self.radius = 1
     self.angle = 0.0
     
     self.needModeUpdate = True
Example #2
0
 def __init__(self, _type = LT_RANDOM):
     
     LayoutGroupDepth.__init__(self)
     
     # map of forces
     self.type = _type
     
     self.needModeUpdate = True
Example #3
0
 def __init__(self,
              _distance = 4.0):
     """Constructor
     """
     LayoutGroupDepth.__init__(self)
     
     self.initDistance = self.distance = _distance
     self.delta = 0.5
     
     self.needModeUpdate = True
     
     self.root = None
     
     # node radius
     self.radius = 1.0
Example #4
0
 def _addObjectToGroup(self, _object): 
     """Appends object to layout group
     """ 
     res = LayoutGroupDepth._addObjectToGroup(self, _object)
     self.need_layout = True
     
     return res
Example #5
0
 def _removeAllObjectsFromGroup(self):
     """Removes all objects from layout group
     """
     res = LayoutGroupDepth._removeAllObjectsFromGroup(self)
     self.need_layout = True
     
     return res
    def _removeObjectFromGroup(self, _object):
        """Removes object from layout group
        """
        res = LayoutGroupDepth._removeObjectFromGroup(self, _object)
#        self.step = self.step_max
        self.need_layout = True
        
        return res
Example #7
0
 def _addObjectToGroup(self, _object):
     """Append object to layout group
     """
     #if lastAddedObject == None:            
     #param = session.search_one_shot(session.sc_constraint_new(sc_constants.CONSTR_5_f_a_a_a_f, desc_prm, 0, 0, 0, attr_), True, 5)
     res = LayoutGroupDepth._addObjectToGroup(self, _object)
     self.need_layout = True
     return res
Example #8
0
 def _removeObjectFromGroup(self, _object):
     """Removes object from layout group
     """
     res = LayoutGroupDepth._removeObjectFromGroup(self, _object)
     self.distance = self.initDistance
     self.need_layout = True
     
     return res
Example #9
0
 def __init__(self):
     LayoutGroupDepth.__init__(self)
     self.show = True
     self.root_orientation = self.SOUTH   #could be: NORTH, SOUTH, EAST, WEST
     '''        
     self.node_width = 20        #width of a node
     self.node_height = 10       #height of a node
     self.frame_thickness = 1    #fixed-sized node frame
     self.subtree_separation = 5 #gap between subtrees
     self.sibling_separation = 4 #gap between siblings
     self.level_separation = 5   #gap between levels
     self.maximum_depth = 10     #biggest tree depth
     #-------------------------------------
     self.flMeanWidth = 0    #Ave. width of 2 nodes
     '''
     #-------------------------------------
     self.needModeUpdate = True
     self.marked_nodes = []
Example #10
0
 def _apply(self):
     """Applies hierarchical layout to group
     """
     LayoutGroupDepth._apply(self)
     if len(self.nodes) > 0:
         self.tree = Tree()
         rootObject = self.nodes[0]
         print "rootObject.position: ", rootObject.position
         rootNode = TreeNode(rootObject, 0, 0)
         self.tree.setRoot(rootNode)
         self.marked_nodes = []
         self.buildTree(rootNode)
     if self.tree == None:
         return
     else:
         self._layoutTree(self.tree)
         self.needModeUpdate = False
         self.need_layout = False
Example #11
0
  def _apply(self):
      """Applies force directed layout to group
      """
      LayoutGroupDepth._apply(self)
      
      # build graph representation
      g = igraph.Graph()
      verts = []
      verts.extend(self.nodes)
      verts.extend(self.sheets)
      
      g.add_vertices(len(verts))
      obj2idx = {}
      idx = 0
      for obj in verts:
          obj2idx[obj] = idx
          idx += 1
          
      edges = []
      for pair in self.lines:
          
          if not obj2idx.has_key(pair.getBegin()):
              continue
          idx_b = obj2idx[pair.getBegin()]
          
          if not obj2idx.has_key(pair.getEnd()):
              continue
          idx_e = obj2idx[pair.getEnd()]
          
          edges.append((idx_b, idx_e))
          
      g.add_edges(edges)
      
      coords = g.layout("circle")
      
      # apply results
      idx = 0
      for v in verts:
          pos = coords[idx]
          v.setPosition(ogre.Vector3(pos[0], pos[1], 0))
          idx += 1
 
      self.need_layout = False
 def __init__(self,
              _step_max = 0.1,
              _step_min = 0.0015, 
              _max_rep_length = 10.0,
              _max_force = 0.3,
              _repulsion = 25,
              _rigidity = 6,
              _length = 6.0,
              _gravity = 0.5):
     
     LayoutGroupDepth.__init__(self)
     
     # map of forces
     self.step_max = _step_max
     self.step = self.step_max
     self.prevMaxF = 0.0
     self.minMaxF = 0.001
     self.maxf = 0.0
     self.step_min = _step_min
     self.lengthOld = 0
     
     self.max_rep_length = _max_rep_length
     self.max_force = _max_force
     
     
     self.repulsion = _repulsion
     self.rigidity = _rigidity
     self.length = _length
     self.gravity = _gravity
     self.dr = 1.5
     self.df = 0.00001
     self.kstep = 0.9
     self.alpha = 15000
     self.beta = 0.2
     self.iterations = 20
     
     self.radius = 1
     self.angle = 0.0
     
     self.needModeUpdate = True
 def __init__(self,
              _step_max = 0.00005,
              _step_min = 0.0015, 
              _max_rep_length = 30.0,
              _max_force = 0.3,
              _repulsion = 24,
              _rigidity = 16,
              _length = 5.5,
              _gravity = 0.05,
              _windowBorder = -7.0):
     
     LayoutGroupDepth.__init__(self)
     
     # map of forces
     self.step_max = _step_max
     self.step = self.step_max
     self.prevMaxF = 0.0
     self.minMaxF = 0.000015
     self.maxf = 0.0
     self.step_min = _step_min
     self.lengthOld = 0
     
     self.max_rep_length = _max_rep_length
     self.max_force = _max_force
     
     
     self.repulsion = _repulsion
     self.rigidity = _rigidity
     self.length = _length
     self.gravity = _gravity
     self.dr = 0.1
     self.kstep = 0.95
     self.df = 0.0001
     
     self.radius = 1
     self.angle = 0.0
     
     self.needModeUpdate = True
    def _addObjectToGroup(self, _object):
        """Append object to layout group
        """
        res = LayoutGroupDepth._addObjectToGroup(self, _object)
        
        if (isinstance(_object, objects.ObjectLine)):
            return True
        
#        self.step = self.step_max
        self.need_layout = True
                
        # calculate object position as an geometrical center of connected to it objects
        pos = None
        count = 0
        objs = _object.getLinkedObjects(Object.LS_IN)
        for obj in objs:
            if obj.getBegin() in self.objects:
                if pos is None:
                    pos = obj.getBegin().getPosition()
                    count += 1
                else:
                    pos += obj.getPosition()
                    count += 1
                
            
        objs = _object.getLinkedObjects(Object.LS_OUT)
        for obj in objs:
            if obj.getEnd() in self.objects:
                if pos is None:
                    pos = obj.getBegin().getPosition()
                    count += 1
                else:
                    pos += obj.getPosition()
                    count += 1
       
        if pos is not None:
            pos = pos / float(count)
        else:
            pos = ogre.Vector3(0, 0, 0)
            
        if render_engine.viewMode is render_engine.Mode_Isometric:
            pos = pos + ogre.Vector3(math.cos(len(self.objects) * (math.pi**2)), math.sin(len(self.objects)* (math.pi**2)), 0.0)
        else:
            dx = math.cos(len(self.objects) * (math.pi**2))
            dy = math.sin(len(self.objects)* (math.pi**2))
            pos = pos + ogre.Vector3(dx, dy, dx + dy)
                
        _object.setPosition(pos)
   
        return res
    def _addObjectToGroup(self, _object):
        """Append object to layout group
        """
        res = LayoutGroupDepth._addObjectToGroup(self, _object)
#        self.step = self.step_max
        self.need_layout = True
        
#        if render_engine.viewMode is render_engine.Mode_Isometric:
#            _object.setPosition(ogre.Vector3(math.cos(self.angle), math.sin(self.angle), 0.0) * self.radius)
#        else:
#            _object.setPosition(ogre.Vector3(math.cos(self.angle), math.sin(self.angle), math.sin(self.angle) + math.cos(self.angle)) * self.radius)
        #self.radius += 1.0 / 36.0
        #self.angle += 0.17
        
        # calculate object position as an geometrical center of connected to it objects
        pos = None
        count = 0
        objs = _object.getLinkedObjects(Object.LS_IN)
        for obj in objs:
            if obj.getBegin() in self.objects:
                if pos is None:
                    pos = obj.getPosition()
                    count += 1
                else:
                    pos += obj.getPosition()
                    count += 1
                
            
        objs = _object.getLinkedObjects(Object.LS_OUT)
        for obj in objs:
            if obj.getBegin() in self.objects:
                if pos is None:
                    pos = obj.getPosition()
                    count += 1
                else:
                    pos += obj.getPosition()
                    count += 1
                    
        if pos is not None:
            pos = pos / float(count)
        else:
            pos = ogre.Vector3(0, 0, 0)
            
        if render_engine.viewMode is render_engine.Mode_Isometric:
            pos = pos + ogre.Vector3(math.cos(len(self.nodes) * (math.pi**2)), math.sin(len(self.nodes)* (math.pi**2)), 0.0) * 2
        else:
            pos = pos + ogre.Vector3(2 * math.cos(len(objs)), 2 * math.sin(len(objs)), math.cos(len(objs)) + math.sin(len(objs)))
        _object.setPosition(pos)
   
        return res
 def __del__(self):
     LayoutGroupDepth.__del__(self)
Example #17
0
    def _apply(self):
        """Applies radial layout to group
        """
        LayoutGroupDepth._apply(self)
       
        n_obj = []
        n_obj.extend(self.nodes)
        n_obj.extend(self.sheets)
        ln = len(n_obj)

        if self.root is None and ln == 0:
            return
          
        # choose first node in list as the graph root
        if self.root is None:
            self.root = n_obj[0]
            
        # reset level attribute 
        for obj in n_obj:
            obj.level = -1 
        self.root.level = 0
        
        # levels count
        numLevels = self.calculateLevels()
            
        # iterate through the levels
        for lvl in range(numLevels + 1):
            
            if lvl == 0:
                # set graph root in the center
                self.root.setPosition(ogre.Vector3(0, 0, 0))   
                
            if lvl == 1: 
                # all nodes at this level
                nodes = [obj for obj in n_obj if obj.level == lvl]
                # check to resize graph
                if self.isNeedToResize(2 * math.pi, lvl, len(nodes)):
                    return
                
                self.calculate(nodes, lvl, 2 * math.pi, 0.0, 0.0)
                     
            if lvl >= 2:  
                # parents of nodes at this level
                parents = [obj for obj in n_obj if obj.level == lvl - 1 and self.hasChildsInGraph(obj)]
                if len(parents) == 0:
                    # all nodes at this level
                    nodes = [obj for obj in n_obj if obj.level == lvl]
                    # check to resize graph
                    if self.isNeedToResize(2 * math.pi, lvl, len(nodes)):
                        return
                
                    self.calculate(nodes, lvl, 2 * math.pi, 0.0, 0.0)
                
                else:
                    # loop through all childs for the every parent 
                    for parent in parents:                           
                        # childs of parent
                        childs = self.getChilds(parent)
                        # angle limits for the childs nodes
                        leftlimit = parent.leftLim
                        rightlimit = parent.rightLim
                        # check to resize graph
                        if self.isNeedToResize(leftlimit - rightlimit, lvl, len(childs)):
                            return
                        
                        self.calculate(childs, lvl, leftlimit - rightlimit, rightlimit, 0.5)
    def _apply(self):
        """Applies force directed layout to group
        """
        LayoutGroupDepth._apply(self)
        
        ln = len(self.objects)
        if ln == 0: return
        if not self.lengthOld == ln: 
            self.step = self.step_max / len(self.objects)
            self.prevMaxF = 0.0
            self.prevStep = self.step
            
        self.lengthOld = ln
                        
        n_obj = []
        n_obj.extend(self.nodes)
        n_obj.extend(self.sheets)
        n_obj.extend(self.lines)
        n = len(n_obj)
        
        #if n == 0:
        #    self.needModeUpdate = False 
        #    return
        
        forces = [ogre.Vector3(0, 0, 0)] * n
        obj_f = {}
        self.maxf = 0.0
        for idx in xrange(n):
            obj_f[n_obj[idx]] = idx
                
        o_pos = []
        # updating on mode
        if self.needModeUpdate:
            angle = 0.0
            radius = 1.0
            
            for obj in n_obj:
                pos = obj.getPosition()
                if render_engine.viewMode is render_engine.Mode_Isometric:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, 0.0))
                else:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, math.cos(angle) * radius))
                    angle += 0.25
                    radius += 0.1
                    
            self.needModeUpdate = False
        else:
            for obj in n_obj:
                o_pos.append(obj.getPosition())
              
#        _iters = min([len(self.nodes) + len(self.sheets), self.iterations])
        for it in xrange(self.iterations):
        
            # calculating repulsion forces
            for idx in xrange(n):             
                p1 = o_pos[idx]
                l = p1.length()
                
                f = 0.0
                               
                for jdx in xrange(idx + 1, n):
                    p2 = o_pos[jdx]
                    p = (p1 - p2)
                    l = p.length()
                                  
                    if l > self.max_rep_length: continue    # don't calculate repulsion if distance between objects is to
                    
                    if l < 0.005: l += 0.005
                    f = p * self.repulsion / l / l / l

                    # append forces to nodes
                    forces[idx] = forces[idx] + f# * inv_mass1
                    forces[jdx] = forces[jdx] - f# * inv_mass2
                                   
            # calculating springs
            for line in self.lines:
                
                ob = line.getBegin()
                oe = line.getEnd()
                if ob is None or oe is None:    continue
#                if not obj_f.has_key(ob) or not obj_f.has_key(oe): continue
                
                p1 = ob.getPosition()
                p2 = oe.getPosition()
                
                p = (p2 - p1)
                l = p.length()
                
                if l > 0:
                    l = l - self.length
                    f = p * self.rigidity * math.log(l) #l
                else:
                    f = ogre.Vector3(1, 1, 0)
                                
                if obj_f.has_key(ob):
                    idx = obj_f[ob]
                    forces[idx] = forces[idx] + f
                if obj_f.has_key(oe):
                    idx = obj_f[oe]
                    forces[idx] = forces[idx] - f

            # apply forces to objects
            maxf = 0.0
            for idx in xrange(n):
                f = forces[idx]
                # getting maximum force
                maxf = max([maxf, f.length()])          
            
            #_step = (maxf * self.alpha + 1.0) * self.dr / (maxf * maxf * self.alpha + self.dr)#self.dr / (maxf + 0.01)
            _step = self.dr / (maxf + 0.01)
            if (maxf - self.prevMaxF) > self.df:
                self.step = _step
            else:
                self.step = min([self.kstep * self.prevStep, _step])
            
            self.maxf = maxf * self.step
            self.prevMaxF = maxf
                
            for idx in xrange(n):
                f = forces[idx]
                offset = f * self.step
                self.maxf = max([self.maxf, offset.length()])
                pos = o_pos[idx] + offset
                forces[idx] = ogre.Vector3(0, 0, 0)
                o_pos[idx] = pos
        
            self.need_layout = not (self.dr > (maxf * self.beta))
            
            if not self.need_layout:
                break
            
            # calculate geometry center
            left = 0
            top = 0
            right = 0
            bottom = 0
            for idx in xrange(n):
                pos = o_pos[idx]
                
                if pos.x < left:
                    left = pos.x
                if pos.y < top:
                    top = pos.y
                if pos.x > right:
                    right = pos.x
                if pos.y > bottom:
                    bottom = pos.y
            
            offset = ogre.Vector3(-(right + left) / 2.0, -(top + bottom) / 2.0, 0.0)
            
            # apply positions
            for idx in xrange(n):
                n_obj[idx].setPosition(o_pos[idx] + offset)
 def _mode_changed_impl(self):
     """Sets flag to update Z axis positions 
     """
     self.needModeUpdate = True
     
     LayoutGroupDepth._mode_changed_impl(self)
    def _apply(self):
        """Applies force directed layout to group
        """
        LayoutGroupDepth._apply(self)
        
        ln = len(self.objects)
        if ln == 0: return
        if not self.lengthOld == ln: 
            self.step = self.step_max / len(self.objects)
            self.prevMaxF = 0.0
            self.prevStep = self.step
            
        self.lengthOld = ln
             
#        import math
#        items_count = len(self.nodes)
#        
#        if items_count != 0:
#            da = 2 * math.pi / items_count
#            angle = 0
#            radius = 5
#            for obj in self.nodes:
#                # set new position
#                x = radius * math.cos(angle) - obj.scale.x / 2
#                y = radius * math.sin(angle) - obj.scale.y / 2
#                z = 0
#                obj.setPosition(ogre.Vector3(x, y, z))
#                angle += da
#
        
                
        
        n_obj = []
        n_obj.extend(self.nodes)
        n_obj.extend(self.sheets)
        n = len(n_obj)
        
        #if n == 0:
        #    self.needModeUpdate = False 
        #    return
        
        forces = [ogre.Vector3(0, 0, 0)] * n
        obj_f = {}
        self.maxf = 0.0
        
#        self.step = self.step * 0.99
        
        o_pos = []
        # updating on mode
        if self.needModeUpdate:
            angle = 0.0
            radius = 1.0
            
            for obj in n_obj:
                pos = obj.getPosition()
                if render_engine.viewMode is render_engine.Mode_Isometric:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, 0.0))
                else:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, math.cos(angle) * radius))
                    angle += 0.25
                    radius += 0.1
                    
            self.needModeUpdate = False
        else:
            for obj in n_obj:
                o_pos.append(obj.getPosition())
                   
        # calculating repulsion forces
        for idx in xrange(n):
            obj_f[n_obj[idx]] = idx
            
            p1 = o_pos[idx]
            
            l = p1.length()
            
            #if l > 3:
            # mode sheet objects bottom
            f = None
#            if isinstance(n_obj[idx], objects.ObjectSheet):
#                f = ogre.Vector3(p1.x / 5.0, p1.y - self.windowBorder, 0)
#            else:
#                f = (p1) * self.gravity * (l - 3.0)
            inv_mass1 = 0.6
            if isinstance(n_obj[idx], objects.ObjectSheet):
                inv_mass1 = 1.6
                
            #f = (p1) * self.gravity * (l - 3.0)
            #forces[idx] = forces[idx] - f
            
            for jdx in xrange(idx + 1, n):
                p2 = o_pos[jdx]
                p = (p1 - p2)
                l = p.length()
#                p.normalise()
                              
                if l > self.max_rep_length: continue    # don't calculate repulsion if distance between objects is to
                
                #if l > 0.5:
                if l < 0.5: l += 0.25
                f = p * self.repulsion / l / l / l
                #else:
                #    f = ogre.Vector3(math.cos(0.17 * idx) * self.length * 7, math.sin(0.17 * (idx + 1)) * self.length * 7, 0) 
                
                inv_mass2 = 0.6
                if isinstance(n_obj[jdx], objects.ObjectSheet):
                    inv_mass2 = 1.6
                
                # append forces to nodes
#                if idx != 0:
                forces[idx] = forces[idx] + f * inv_mass1
                forces[jdx] = forces[jdx] - f * inv_mass2
                
                               
        # calculating springs
        for line in self.lines:
            
            ob = line.getBegin()
            oe = line.getEnd()
            if ob is None or oe is None:    continue
            
            p1 = ob.getPosition()
            p2 = oe.getPosition()
            
            p = (p2 - p1)
            l = p.length()
            
            if l > 0:
                l = l - self.length
                #p.normalise()
#                f = p*(self.rigidity * (l - self.length) / l)
                #cnt = self.getLinkedCount(ob) + self.getLinkedCount(oe)
                #f = p*(self.rigidity * (l - self.getLineLength(cnt)) / l)
                f = p * self.rigidity * l#math.log(l)
                
#                if (f.length() > 10):
#                    f = p * self.rigidity / l
            else:
                f = ogre.Vector3(1, 1, 0)
                
            if obj_f.has_key(ob) and not isinstance(ob, objects.ObjectLine):
                idx = obj_f[ob]
                forces[idx] = forces[idx] + f
            if obj_f.has_key(oe) and not isinstance(oe, objects.ObjectLine):
                idx = obj_f[oe]
                forces[idx] = forces[idx] - f

        
        # apply forces to objects
#        df = forces[0]
        maxf = 0.0
        for idx in xrange(n):
            f = forces[idx]
            # getting maximum force
            maxf = max([maxf, f.length()])          
        
#        if maxf >= self.max_force:
#            self.step = self.step_max
#        else:
        
        v = self.dr / (maxf + 0.01)
        if (maxf - self.prevMaxF) > self.df:
            self.step = min([self.kstep * self.step, v])
        else:
            self.step = max([v, self.step])
            
        self.prevMaxF = maxf
            
        #newStep = max([self.step * 0.98, min([self.step * 1.02, self.dr / (maxf + 0.01)])])#self.step * 0.97
    
        for idx in xrange(n):
            f = forces[idx]
            offset = f * self.step
            self.maxf = max([self.maxf, offset.length()])
            pos = o_pos[idx] + f * self.step
            if render_engine.viewMode is render_engine.Mode_Isometric:
                pos = pos * ogre.Vector3(1, 1, 0)
            n_obj[idx].setPosition(pos)  
    
        print self.maxf
#        self.prevStep = self.step
        #self.need_layout = self.step > self.step_min
        self.need_layout = self.minMaxF < self.maxf#self.step > self.step_min
    def _apply(self):
        """Applies force directed layout to group
        """
        LayoutGroupDepth._apply(self)
        
        
#        import math
#        items_count = len(self.nodes)
#        
#        if items_count != 0:
#            da = 2 * math.pi / items_count
#            angle = 0
#            radius = 5
#            for obj in self.nodes:
#                # set new position
#                x = radius * math.cos(angle) - obj.scale.x / 2
#                y = radius * math.sin(angle) - obj.scale.y / 2
#                z = 0
#                obj.setPosition(ogre.Vector3(x, y, z))
#                angle += da
#
        
                
        
        n_obj = []
        n_obj.extend(self.nodes)
        n_obj.extend(self.sheets)
        n = len(n_obj)
        
        #if n == 0:
        #    self.needModeUpdate = False 
        #    return
        
        forces = [ogre.Vector3(0, 0, 0)] * n
        obj_f = {}
        
        
#        self.step = self.step * 0.99
        
        o_pos = []
        # updating on mode
        if self.needModeUpdate:
            angle = 0.0
            radius = 1.0
            
            for obj in n_obj:
                pos = obj.getPosition()
                if render_engine.viewMode is render_engine.Mode_Isometric:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, 0.0))
                else:
                    o_pos.append(ogre.Vector3(pos.x, pos.y, math.cos(angle) * radius))
                    angle += 0.25
                    radius += 0.1
                    
            self.needModeUpdate = False
        else:
            for obj in n_obj:
                o_pos.append(obj.getPosition())
            
        
        # calculating repulsion forces
        for idx in xrange(n):
            obj_f[n_obj[idx]] = idx
            
            p1 = o_pos[idx]
            
            l = p1.length()
            
            #if l > 3:
            f = (p1) * self.gravity * (l - 3.0)
            forces[idx] = forces[idx] - f
            
            for jdx in xrange(idx + 1, n):
                
                
                p2 = o_pos[jdx]
                p = (p1 - p2)
                p.normalise()
                
                l = p1.distance(p2)
                
                if l > self.max_rep_length: continue    # don't calculate repulsion if distance between objects is to
                
                if l > 0.5:
                    f = p * self.repulsion / l / l
                else:
                    f = ogre.Vector3(math.cos(0.17 * idx) * self.length * 7, math.sin(0.17 * (idx + 1)) * self.length * 7, 0) 
                
                # append forces to nodes
#                if idx != 0:
                forces[idx] = forces[idx] + f
                forces[jdx] = forces[jdx] - f
                
        
        # calculating springs
        for line in self.lines:
            
            ob = line.getBegin()
            oe = line.getEnd()
            if ob is None or oe is None:    continue
            
            p1 = ob.getPosition()
            p2 = oe.getPosition()
            
            l = p1.distance(p2)

            if l > 0:
                p = (p2 - p1)
                p.normalise()
#                f = p*(self.rigidity * (l - self.length) / l)
                #cnt = self.getLinkedCount(ob) + self.getLinkedCount(oe)
                #f = p*(self.rigidity * (l - self.getLineLength(cnt)) / l)
                f = p * self.rigidity * math.log(l)
                
                if (f.length() > 10):
                    f = p * self.rigidity / l
            else:
                f = ogre.Vector3(0, 0, 0)
                
            if obj_f.has_key(ob):
                idx = obj_f[ob]
                forces[idx] = forces[idx] + f
            if obj_f.has_key(oe):
                idx = obj_f[oe]
                forces[idx] = forces[idx] - f

        
        # apply forces to objects
#        df = forces[0]
        maxf = 0.0
        for idx in xrange(n):
            f = forces[idx]
            # getting maximum force
            maxf = max([maxf, f.length()])
            pos = o_pos[idx] + (f) * self.step
            if render_engine.viewMode is render_engine.Mode_Isometric:
                pos = pos * ogre.Vector3(1, 1, 0)
            n_obj[idx].setPosition(pos)            
        
        if maxf >= self.max_force:
            self.step = self.step_max
        else:
            self.step = self.step * 0.97
        self.need_layout = self.step > self.step_min