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
class LayoutSimple(LayoutGroupDepth): tree = None NODE_WIDTH = 2 # Width of a node NODE_HEIGHT = 2 # Height of a node FRAME_THICKNESS = 1 # Fixed-sized node frame SUBTREE_SEPARATION = 4 # Gap between subtrees SIBLING_SEPARATION = 4 # Gap between siblings LEVEL_SEPARATION = 3 # Gap between levels MAXIMUM_DEPTH = 10 # Biggest tree # possible orientation NORTH, SOUTH, EAST, WEST = range(4) prev_node = [] xTopAdjustment = 0 # How to adjust the apex yTopAdjustment = 0 #How to adjust the apex flMeanWidth = 0 #Ave. width of 2 nodes flModsum = 0.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 = [] def __del__(self): LayoutGroupDepth.__del__(self) 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 def _removeObjectFromGroup(self, _object): """Removes object from layout group """ res = LayoutGroupDepth._removeObjectFromGroup(self, _object) self.need_layout = True return res def _removeAllObjectsFromGroup(self): """Removes all objects from layout group """ res = LayoutGroupDepth._removeAllObjectsFromGroup(self) self.need_layout = True return res def _mode_changed_impl(self): """Sets flag to update Z axis positions """ self.needModeUpdate = True LayoutGroupDepth._mode_changed_impl(self) def _checkExtentsRange(self, lxTemp, lyTemp): ''' Insert your own code here, to check when the tree drawing is going to be too big. My region is no more that 64000 units square. ''' if (abs(lxTemp) > 32000) or (abs(lyTemp) > 32000): return False else: return True #! def _treeMeanNodeSize(self, pLeftNode, pRightNode): ''' Write your own code for this procedure if your rendered nodes will have variable sizes. ---------------------------------------- Here I add the width of the contents of the right half of the pLeftNode to the left half of the right node. Since the size of the contents for all nodes is currently the same, this module computes the following trivial computation. ''' self.flMeanWidth = 0.0; # Initialize this global if self.root_orientation == self.NORTH or self.root_orientation == self.SOUTH: if pLeftNode: self.flMeanWidth = self.flMeanWidth + self.NODE_WIDTH / 2 if self.show: self.flMeanWidth = self.flMeanWidth + self.FRAME_THICKNESS if pRightNode: self.flMeanWidth = self.flMeanWidth + self.NODE_WIDTH / 2 if self.show: self.flMeanWidth = self.flMeanWidth + self.FRAME_THICKNESS else: # self.root_orientation==EAST or self.root_orientation==WEST: if pLeftNode: self.flMeanWidth = self.flMeanWidth + (self.NODE_HEIGHT / 2) if self.show: self.flMeanWidth = self.flMeanWidth + self.FRAME_THICKNESS if pRightNode: self.flMeanWidth = self.flMeanWidth + (self.NODE_HEIGHT / 2) if self.show: self.flMeanWidth = self.flMeanWidth + self.FRAME_THICKNESS def _treeApportion(self, pThisNode, nCurrentLevel): ''' Clean up the positioning of small sibling subtrees. Subtrees of a node are formed independently and placed as close together as possible. By requiring that the subtrees be rigid at the time they are put together, we avoid the undesirable effects that can accrue from positioning nodes rather than subtrees. ''' pLeftmost = pThisNode.getFirstChild() pNeighbor = pLeftmost.getLeftNeighbor() nCompareDepth = 1 nDepthToStop = self.MAXIMUM_DEPTH - nCurrentLevel #while ((pLeftmost) && (pNeighbor) && (nCompareDepth <= nDepthToStop)) { while pLeftmost and pNeighbor and nCompareDepth <= nDepthToStop: ''' Compute the location of pLeftmost and where it should be with respect to pNeighbor. ''' flRightModsum = flLeftModsum = 0.0 pAncestorLeftmost = pLeftmost pAncestorNeighbor = pNeighbor for i in range(nCompareDepth): pAncestorLeftmost = pAncestorLeftmost.getParent()#~ pAncestorNeighbor = pAncestorNeighbor.getParent()#~ flRightModsum = flRightModsum + pAncestorLeftmost.flModifier flLeftModsum = flLeftModsum + pAncestorNeighbor.flModifier ''' Determine the flDistance to be moved, and apply it to "pThisNode's" subtree. Apply appropriate portions to smaller interior subtrees ''' #Set the global mean width of these two nodes self._treeMeanNodeSize(pLeftmost, pNeighbor) flDistance = (pNeighbor.flPrelim + flLeftModsum + self.SUBTREE_SEPARATION + self.flMeanWidth) - (pLeftmost.flPrelim + flRightModsum) if flDistance > 0.0: # Count the interior sibling subtrees nLeftSiblings = 0 #for (pTempPtr = pThisNode; # pTempPtr && (pTempPtr != pAncestorNeighbor); # pTempPtr = Leftsibling(pTempPtr)) { pTempPtr = pThisNode while pTempPtr and (pTempPtr != pAncestorNeighbor): nLeftSiblings = nLeftSiblings + 1 pTempPtr = pTempPtr.leftSibling if pTempPtr: ''' Apply portions to appropriate leftsibling subtrees. ''' flPortion = flDistance / nLeftSiblings #for (pTempPtr = pThisNode; #pTempPtr != pAncestorNeighbor; #pTempPtr = LeftSibling(pTempPtr)) { pTempPtr = pThisNode while pTempPtr != pAncestorNeighbor: pTempPtr.flPrelim = pTempPtr.flPrelim + flDistance pTempPtr.flModifier = pTempPtr.flModifier + flDistance flDistance = flDistance - flPortion pTempPtr = pTempPtr.leftSibling print "wow" else: ''' Don't need to move anything--it needs to be done by an ancestor because pAncestorNeighbor and pAncestorLeftmost are not siblings of each other. ''' return #end of the while ''' Determine the leftmost descendant of pThisNode at the next lower level to compare its positioning against that of its pNeighbor. ''' nCompareDepth = nCompareDepth + 1 if pLeftmost.isLeaf(): pLeftmost = self.tree.getLeftmost(pThisNode, 0, nCompareDepth) #pLeftmost = self.tree.getLeftmost(pThisNode, nCurrentLevel, nCompareDepth) else: pLeftmost = pLeftmost.getFirstChild() if pLeftmost: pNeighbor = pLeftmost.getLeftNeighbor() else: pNeighbor = None #! def _getPrevNodeAtLevel(self, nLevelNbr): """ List Manipulation: Return pointer to previous node at this level """ #~ - kalichno sdelal - prosto for i in len(self.prev_node): i = 0 #for (pTempNode = pLevelZero; (pTempNode); pTempNode = pTempNode->pNextLevel) #level counter for pTempNode in self.prev_node: if i == nLevelNbr: #Reached desired level. Return its pointer return pTempNode i = i + 1 return None #((PNODE)0); No pointer yet for this level. def _setPrevNodeAtLevel(self, nLevelNbr, pThisNode): """ List Manipulation: Set the list element to the previous node at this level """ print "+setPrevNodeAt Level ", nLevelNbr, " node ", pThisNode._object i = 0 for pTempNode in self.prev_node: if i == nLevelNbr: #Reached desired level. Return its pointer print "setted level ", i, pThisNode._object self.prev_node[i] = pThisNode #pTempNode = pThisNode return True #elif self.prev_node[i + 1] == None:#~ #elif len(self.prev_node) < (i + 1): ''' elif len(self.prev_node) < (i + 2): print "all is ok" #pNewNode = TreeNode("node_setPrevNodeAtLevel")#~ #self.prev_node.append(pNewNode) self.prev_node.append(None) print "1appended->", pThisNode._object ''' i = i + 1 #Should only get here if self.prev_node list is empty self.prev_node.append(pThisNode) print "2appended->", pThisNode._object return True def _treeFirstWalk(self, pThisNode, nCurrentLevel): """ In a first post-order walk, every node of the tree is assigned a preliminary x-coordinate (held in field node.flPrelim). In addition, internal nodes are given modifiers, which will be used to move their children to the right (held in field node.flModifier). Returns: TRUE if no errors, otherwise returns FALSE. """ pLeftmost = None #left- & rightmost pRightmost = None #children of a node. flMidpoint = None #midpoint between left- #& rightmost children #Set up the pointer to previous node at this level pThisNode.prev = self._getPrevNodeAtLevel(nCurrentLevel) s = pThisNode.prev if s: print "-getPrevNodeAt Level ", nCurrentLevel, " node ", pThisNode.prev._object else: print "-getPrevNodeAt Level ", nCurrentLevel, " node None" #Now we're it--the previous node at this level if not self._setPrevNodeAtLevel(nCurrentLevel, pThisNode): return False #Can't allocate element #Clean up old values in a node's flModifier pThisNode.flModifier = 0.0 if pThisNode.isLeaf() or nCurrentLevel == self.MAXIMUM_DEPTH: if pThisNode.hasLeftSibling(): ''' Determine the preliminary x - coordinate based on: -preliminary x - coordinate of left sibling, -the separation between sibling nodes, and -mean width of left sibling & current node. ''' #Set the mean width of these two nodes self._treeMeanNodeSize(pThisNode.leftSibling, pThisNode) pThisNode.flPrelim = pThisNode.leftSibling.flPrelim + self.SIBLING_SEPARATION + self.flMeanWidth else: # no sibling on the left to worry about pThisNode.flPrelim = 0.0; else: #Position the leftmost of the children #if (TreeFirstWalk(pLeftmost = pRightmost = FirstChild(pThisNode), nCurrentLevel + 1)) { pLeftmost = pRightmost = pThisNode.getFirstChild()#~ if (self._treeFirstWalk(pLeftmost, nCurrentLevel + 1)): #Position each of its siblings to its right #while (HasRightSibling(pRightmost)){ while pRightmost.hasRightSibling(): pRightmost = pRightmost.rightSibling if (self._treeFirstWalk(pRightmost, nCurrentLevel + 1)): pass else: return False#malloc() failed ''' Calculate the preliminary value between the children at the far left and right ''' flMidpoint = (pLeftmost.flPrelim + pRightmost.flPrelim) / 2 #Set global mean width of these two nodes self._treeMeanNodeSize(pThisNode.leftSibling, pThisNode) if pThisNode.hasLeftSibling(): #pThisNode->flPrelim = (pThisNode->leftsibling->flPreLim) + (float)SIBLING_SEPARATION + flMeanWidth; pThisNode.flPrelim = (pThisNode.leftSibling.flPrelim) + self.SIBLING_SEPARATION + self.flMeanWidth pThisNode.flModifier = pThisNode.flPrelim - flMidpoint self._treeApportion(pThisNode, nCurrentLevel) else: pThisNode.flPrelim = flMidpoint else: return False#Couldn't get an element return True def _treeSecondWalk(self, pThisNode, nCurrentLevel): ''' During a second pre-order walk, each node is given a final x-coordinate by summing its preliminary x-coordinate and the modifiers of all the node's ancestors. The y-coordinate depends on the height of the tree. (The roles of x and y are reversed for RootOrientations of EAST or WEST.) Returns: TRUE if no errors, otherwise returns FALSE. ''' # lxTemp, lyTemp - hold calculations here #flNewModsum - local modifier value bResult = True # assume innocent #self.flModsum = 0.0 if nCurrentLevel <= self.MAXIMUM_DEPTH: flNewModsum = self.flModsum # Save the current value if self.root_orientation == self.NORTH: lxTemp = self.xTopAdjustment + (pThisNode.flPrelim + self.flModsum) lyTemp = self.yTopAdjustment + (nCurrentLevel * self.LEVEL_SEPARATION) elif self.root_orientation == self.SOUTH: lxTemp = self.xTopAdjustment + (pThisNode.flPrelim + self.flModsum); lyTemp = self.yTopAdjustment - (nCurrentLevel * self.LEVEL_SEPARATION); elif self.root_orientation == self.EAST: lxTemp = self.xTopAdjustment + (nCurrentLevel * self.LEVEL_SEPARATION); lyTemp = self.yTopAdjustment - (pThisNode.flPrelim + self.flModsum); elif self.root_orientation == self.WEST: lxTemp = self.xTopAdjustment - (nCurrentLevel * self.LEVEL_SEPARATION); lyTemp = self.yTopAdjustment - (pThisNode.flPrelim + self.flModsum); if self._checkExtentsRange(lxTemp, lyTemp): # The values are within the allowable range pThisNode.xCoordinate = lxTemp pThisNode.yCoordinate = lyTemp pThisNode._object.setPosition(ogre.Vector3(lxTemp, lyTemp, 0))#~ if pThisNode.hasChild(): # Apply the flModifier value for this # node to all its offspring. self.flModsum = flNewModsum = flNewModsum + pThisNode.flModifier bResult = self._treeSecondWalk(pThisNode.getFirstChild(), nCurrentLevel + 1) flNewModsum = flNewModsum - pThisNode.flModifier if (pThisNode.hasRightSibling()) and (bResult): self.flModsum = flNewModsum; bResult = self._treeSecondWalk(pThisNode.rightSibling, nCurrentLevel) else: bResult = False #outside of extents return bResult def buildTree(self, parentNode): #supposed that first element in self.nodes is the root of settable tree #for object in self.nodes: if parentNode: #for ls_in in object.linkedObjects['LS_IN']: for ls_in in parentNode.getObject().linkedObjects[Object.LS_IN]: child = ls_in.getBegin() if not (child in self.marked_nodes): self.marked_nodes.append(child) childNode = TreeNode(child, 0, 0) self.tree.addNode(childNode, parentNode) self.buildTree(childNode) #for ls_out in object.linkedObjects['LS_OUT']: for ls_out in parentNode.getObject().linkedObjects[Object.LS_OUT]: child = ls_out.getEnd() if not (child in self.marked_nodes): self.marked_nodes.append(child) childNode = TreeNode(child, 0, 0) self.tree.addNode(childNode, parentNode) self.buildTree(childNode) def _layoutTree(self, tree): ''' Determine the coordinates for each node in a tree. Input: Pointer to the apex node of the tree Assumption: The x & y coordinates of the apex node are already correct, since the tree underneath it will be positioned with respect to those coordinates. Returns: TRUE if no errors, otherwise returns FALSE. ''' self.tree = tree pApexNode = self.tree.getRoot() if self._treeFirstWalk(pApexNode, 0): ''' Determine how to adjust the nodes with respect to the location of the apex of the tree being positioned. ''' if self.root_orientation == self.NORTH or self.root_orientation == self.SOUTH: # Create the adjustment from x-coord self.xTopAdjustment = pApexNode.xCoordinate - pApexNode.flPrelim self.yTopAdjustment = pApexNode.yCoordinate else: # Create the adjustment from y-coord self.xTopAdjustment = pApexNode.xCoordinate self.yTopAdjustment = pApexNode.yCoordinate + pApexNode.flPrelim return self._treeSecondWalk(pApexNode, 0) else: return False # Couldn't get apex (root) element def _setTree(self, tree): self.tree = tree #_apply and other updates 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 def rotate(self, cnt): pass def getLineLength(self, cnt): """Calculates length for a line depending on output/input arcs count """ return max([self.length, cnt / 3.0]) def getLinkedCount(self, obj): return len(obj.linkedObjects[Object.LS_OUT]) + len(obj.linkedObjects[Object.LS_IN])