def test_add_axe(): g = MTG() labels = g.property('label') p1 = add_plant(g) p2 = add_plant(g) vid_axe = add_axe(g, 'T0') assert g.complex(vid_axe) == p1 assert labels[g.parent(vid_axe)] == 'MS' vid_axe = add_axe(g, 'T1.3', plant_number=2) assert g.complex(vid_axe) == p2 assert labels[g.parent(vid_axe)] == 'T1' vid_metamer0 = g.component_roots_at_scale(vid_axe, 3)[0] assert labels[g.parent(vid_metamer0)] == "metamer3"
def read_lsystem_string( string, symbol_at_scale, functional_symbol={}, mtg=None ): """Read a string generated by a lsystem. :Parameters: - `string`: The lsystem string representing the axial tree. - `symbol_at_scale`: A dict containing the scale for each symbol name. :Optional parameters: - `functional_symbol`: A dict containing a function for specific symbols. The args of the function have to be coherent with those in the string. The return type of the functions have to be a dictionary of properties: dict(name, value) :Return: MTG object """ import openalea.plantgl.all as pgl s = string def transform(turtle, mesh): x = turtle.getUp() z = turtle.getHeading() bo = pgl.BaseOrientation(x, z^x) matrix = pgl.Transform4(bo.getMatrix()) matrix.translate(turtle.getPosition()) mesh = mesh.transform(matrix) return mesh # 1. Create the mtg structure. if mtg is None: mtg = MTG() # 2. add some properties to the MTG mtg.add_property('index') mtg.add_property('can_label') mtg.add_property('geometry') mtg.add_property('tissue_type') vid = mtg.root # vid of the support tree, i.e. at the finest scale current_vertex = mtg.root branching_stack = [] pending_edge = '' # edge type for the next edge to be created scale = 0 lsys_symbols = ['[', ']', '/', '+', '^', 'f'] modules = symbol_at_scale.keys() symbols = lsys_symbols + modules index = dict(zip(symbol_at_scale.keys(), [0]*len(symbol_at_scale))) is_ramif = False # 2. Create a PlantGL Turtle... turtle = pgl.Turtle() max_scale = max(symbol_at_scale.values()) for edge_type in symbols: if edge_type != 'f': s = s.replace(edge_type, '\n%s'%edge_type) else: s = s.replace('f(', '\nf(') l = s.split() try: plant_name = [s for s in symbol_at_scale.keys() if 'plant' in s.lower()][0] except: ValueError("""Incorrect plant name (should be plant)""") for node in l: # Check if node is a module tag = node[0] if tag == '[': branching_stack.append(vid) turtle.push() is_ramif = True elif tag == ']': vid = branching_stack.pop() current_vertex = vid scale = mtg.scale(vid) turtle.pop() is_ramif = False elif tag == '/': args = get_args(node[1:]) if args: angle = get_float(args[1:-1]) turtle.rollR(angle) else: turtle.rollR() elif tag == '+': args = get_args(node[1:]) if args: angle = get_float(args[1:-1]) turtle.left(angle) else: turtle.left() elif tag == '^': args = get_args(node[1:]) if args: angle = get_float(args[1:-1]) turtle.up(angle) else: turtle.up() elif tag == 'f' and node[1] == '(': args = get_args(node[1:]) if args: length = get_float(args[1:-1]) if length > 0: turtle.f(length) else: turtle.f() else: # add new modules to the mtg (i.e. add nodes) name = get_name(node) if name not in modules: print 'Unknow element %s'% name continue module_scale = symbol_at_scale[name] if is_ramif: edge_type = '+' else: edge_type = '<' log(node, module_scale, edge_type ) if module_scale == scale: if mtg.scale(vid) == scale: vid = mtg.add_child(vid, edge_type=edge_type, label=name) current_vertex = vid pending_edge = '' log('','Cas 1.1', scale, 'mtg.scale(vid)', mtg.scale(vid), 'generated vertex', vid) assert mtg.scale(vid) == module_scale else: # add the edge to the current vertex current_vertex = mtg.add_child(current_vertex, edge_type=edge_type, label=name) log('', 'Cas 1.2', scale, 'mtg.scale(vid)', mtg.scale(vid), 'generated vertex', current_vertex) assert mtg.scale(current_vertex) == module_scale is_ramif = False elif module_scale > scale: log('', 'Cas 2', scale, 'mtg.scale(vid)', mtg.scale(vid)) old_current_vertex = current_vertex while module_scale > scale: if mtg.scale(vid) == scale: assert vid == current_vertex vid = mtg.add_component(vid) current_vertex = vid log('', '', 'Cas 2.1', scale, 'generate new component', current_vertex) scale += 1 if module_scale == scale: assert mtg.scale(current_vertex) == module_scale mtg.property('label')[current_vertex] = name break else: scale += 1 current_vertex = mtg.add_component(current_vertex) else: log(node, 'add_child(%d, child=%d)'%(old_current_vertex, current_vertex)) mtg.property('label')[current_vertex] = name if mtg.scale(vid) == scale: vid = mtg.add_child(vid, child=current_vertex, edge_type=edge_type) is_ramif = False else: assert module_scale < scale while module_scale < scale: scale -= 1 current_vertex = mtg.complex(current_vertex) else: current_vertex = mtg.add_child(current_vertex, edge_type=edge_type, label=name) assert mtg.scale(current_vertex) == module_scale # MANAGE the properties, the geometry and the indices!!! index[name] += 1 if name == plant_name: for k in index.keys(): if k != name: index[k] = 0 mtg.property('index')[current_vertex] = index[name] if name in functional_symbol: features = eval(node, functional_symbol) geom = features.get('geometry') canlabel = features.get('label') ttype = features.get('tissue_type') if geom: # get the transformation from the turtle geom = transform(turtle, geom) mtg.property('geometry')[current_vertex] = geom if name == 'StemElement': # parse args to know how the turtle has to move . args = get_args(node)[1:-1] list_args= args.split(',') length = float(list_args[1]) # 2nd arg if length > 0: turtle.f(length) if canlabel: canlabel.elt_id = index[name] plant_id = mtg.complex_at_scale(current_vertex, scale=1) canlabel.plant_id = mtg.property('index')[plant_id] mtg.property('can_label')[current_vertex] = canlabel if ttype: mtg.property('tissue_type')[current_vertex] = ttype mtg = fat_mtg(mtg) return mtg