1from pykludge3d import * 2from lsystem import * 3 4""" 5Note: I use the term 'face' a lot in this file. In this situation, 'face' is a 6synonym for 'polygon'. I use 'face' instead of 'polygon' because, when I say 7'face', I'm also referring to the L-system action/symbol involving polygons. 8 9L-system action symbols: 10 11S scale the face 12M move the face along the face's normal 13E[...] extrude the face and branch the L-system. Each item in the 14 comma-separated list between the brackets is a branch. The first 15 branch is the branch for the original face (ie the face that, 16 following the extrude, is facing in the same direction as the face 17 that was extruded). The subsequent branches are for the N other 18 faces resulting from the extrude. You do not need to specify an 19 action for all N+1 of the branches; use 'T' for branches you don't 20 care about. If there are more items in the list than faces 21 resulting from the extrude, the extra items are ignored. If there 22 are fewer items in the list than faces resulting from the extrude, 23 the extra faces will not be acted on (the same as if 'T' were 24 specified). 25 After the extrude action itself has been performed, the branches 26 will be executed in a depth-first manner, starting with the first 27 branch (the one corresponding to the original face). 28 Action symbols following the E and its braces will be executed 29 after all symbols in the E have been acted upon. 30 Note that the brackets are optional. If you do not wish to 31 manipulate the new faces resulting from an extrude, simply use E 32 by itself. 33T terminal. A no-op; no action is performed on the face. 340-9 digits are ignored 35""" 36 37def scale_face( currentFace, depth ): 38 scaleFactor = 0.75 39 scale_verts( get_verts_in_polys( [currentFace] ), scaleFactor, scaleFactor, scaleFactor ) 40 41def move_face( currentFace, depth ): 42 moveFactor = 1.0 43 normal = get_poly_normal( currentFace, None ) 44 #print normal 45 translate_verts( get_verts_in_polys( [currentFace] ), 46 normal[0] * moveFactor, normal[1] * moveFactor, 47 normal[2] * moveFactor ) 48 49def extrude_face( currentFace, depth ): 50 return polys_extrude( [currentFace], 0 ) 51 52def get_bracketed_substring( string, startIndex ): 53 if string[startIndex] != '[': 54 return '' 55 rbcount = 0 # right-bracket count 56 i = startIndex+1 57 while rbcount != 1 and i < len(string): 58 if string[i] == '[': 59 rbcount -= 1 60 if string[i] == ']': 61 rbcount += 1 62 i += 1 63 if rbcount != 1: 64 return '' 65 return string[startIndex+1 : i-1] 66# end get_bracketed_substring 67 68def interpret_branches( faces, branchString, depth ): 69 i = 0 70 faceNum = 0 71 while i < len( branchString ): 72 temp = '' 73 while i < len( branchString ) and branchString[i] != ',': 74 if branchString[i] == '[': 75 temp += branchString[i] 76 i += 1 77 # we want to skip over everything between the braces. 78 # advance i until matching bracket is found 79 rbcount = 0 # right-bracket count 80 while rbcount != 1 and i < len(branchString): 81 if branchString[i] == '[': 82 rbcount -= 1 83 if branchString[i] == ']': 84 rbcount += 1 85 temp += branchString[i] 86 i += 1 87 else: 88 temp += branchString[i] 89 i += 1 90 if i < len( branchString ) and branchString[i] == ',': 91 i += 1 92 #print '\t'*depth, 'temp is ', temp 93 #print '\t'*depth, 'i is ', i 94 interpret_action( temp, faces[faceNum], depth+1 ) 95 faceNum += 1 96# end interpret_branches 97 98def interpret_action( actionString, currentFace, depth=1 ): 99 i = 0 100 while i < len(actionString): 101 action = actionString[i] 102 if action == 'T' or action.isdigit() or action.isspace(): 103 print 'terminal/no-op' 104 elif action == 'S': 105 scale_face( currentFace, depth ) 106 elif action == 'M': 107 move_face( currentFace, depth ) 108 elif action == 'E': 109 # extrude 110 faces = extrude_face( currentFace, depth ) 111 # follow the branches 112 branchString = get_bracketed_substring( actionString, i+1 ) 113 interpret_branches( faces, branchString, depth ) 114 elif action == '[': 115 # we want to skip over everything between the braces. 116 # advance i until matching bracket is found 117 rbcount = 0 # right-bracket count 118 while rbcount != 1 and i < len(actionString): 119 if actionString[i] == '[': 120 rbcount -= 1 121 if actionString[i] == ']': 122 rbcount += 1 123 i += 1 124 else: 125 print 'Unknown action', action 126 i += 1 127# end interpret_action 128 129 130def run_lsystem( axiom = '0', rules = [('0', 'EM0')], generations = 5 ): 131 '''Runs an L-system (Lindenmeyer system), using the given initial string 132 (the axiom) and the set of rules for string-substitution. Once the 133 L-system has been run for the specified number of generations, the 134 resulting string will be interpreted (see below). 135 136 How to pass rules into the L-system: 137 The 'rules' list is a list of tuples, each tuple being a rule for string 138 substitution. Each rule tuple has two parts, a single character to look 139 for, and a string to replace the character with. Here's an example: 140 141 ('0', 'EM0') 142 143 This rule means that every time '0' is encountered, it is replaced with 144 the string 'EM0'. If our initial string is '0', and we apply this rule 145 for, say, 5 generations, we end up with the following progression: 146 147 0 -> EM0 -> EMEM0 -> EMEMEM0 -> EMEMEMEM0 -> EMEMEMEMEM0 148 149 How the result strings are interpreted: 150 A complete description of the symbols can be found in the doc string for 151 this module, but here is a brief summary: 152 S scale the face 153 M move the face along the face's normal 154 E[...] extrude the face and branch the L-system (definitely see the 155 doc string for more info) 156 T ignored 157 0-9 ignored (used to represent faces at the string-substitution 158 stage, useless once string-substitution is complete) 159 ''' 160 polys = get_selected_polys() 161 162 if len( polys ) < 1: 163 print 'At least one polygon must be selected' 164 return 165 166 system = LSystem( axiom, rules ) 167 while not system.done and system.generation < generations: 168 system.step() 169 interpret_action( system.string, polys[0] ) 170# end run_lsystem 171 172 173