/// <summary> /// Takes a Vrml97 parse tree (see also <seealso cref="Parser"/>) /// and augments all geometry nodes with material and /// transform attributes. /// </summary> /// <param name="root">Parse tree.</param> /// <returns>Augmented parse tree.</returns> public Vrml97Scene Perform(Vrml97Scene root) { root.ParseTree["AttributeAnnotator.Performed"] = true; // leave hint if (root.ParseTree.TypeName == "Vrml97") { string filename = root.ParseTree.Get <string>(Vrml97Sym.filename); m_path = Path.GetDirectoryName(filename); } m_material = new Stack <SymMapBase>(); m_texture = new Stack <SymMapBase>(); m_textureTransform = new Stack <SymMapBase>(); m_transform = new Stack <Trafo3d>(); m_transform.Push(Trafo3d.Identity); SymMapBaseTraversal trav = new SymMapBaseTraversal(SymMapBaseTraversal.Mode.Modifying, SymMapBaseTraversal.Visit.PreAndPost); trav.PerNameVisitors["ImageTexture"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { if (visit == SymMapBaseTraversal.Visit.Pre) { if (m_visited.ContainsKey(m)) { return(m); } List <string> urls = m.Get <List <string> >(Vrml97Sym.url); if (urls != null) { for (int i = 0; i < urls.Count; i++) { urls[i] = Path.Combine(m_path, urls[i]); } } m_visited[m] = m; } return(m); }; // geometry nodes SymMapBaseVisitor foo = (SymMapBase m, SymMapBaseTraversal.Visit visit) => { if (visit == SymMapBaseTraversal.Visit.Post) { return(m); } if (m_material.Count == 0 && m_texture.Count == 0 && m_textureTransform.Count == 0 && m_transform.Count == 0) { return(m); } var map = new SymMapBase(m); if (m_material.Count > 0) { string key = "material"; // while (m.Contains(key)) key += "X"; map[key] = m_material.Peek(); } if (m_texture.Count > 0) { string key = "texture"; // while (m.Contains(key)) key += "X"; map[key] = m_texture.Peek(); } if (m_textureTransform.Count > 0) { string key = "textureTransform"; // while (m.Contains(key)) key += "X"; var tt = m_textureTransform.Peek(); map[key] = tt.ExtractVrmlTextureTrafo(); } if (m_transform.Count > 1) // [0] contains initial identity { string key = "transform"; // while (m.Contains(key)) key += "X"; if (m.Contains(key)) { Console.WriteLine("WARNING: trying to annotate annotated node!"); } map[key] = m_transform.Peek(); } return(map); }; trav.PerNameVisitors["IndexedFaceSet"] = foo; trav.PerNameVisitors["IndexedLineSet"] = foo; // attributes trav.PerNameVisitors["Shape"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { bool hasMaterial = false; bool hasTexture = false; bool hasTextureTransform = false; SymMapBase app = null; if (m.Contains("appearance")) { app = m.Get <SymMapBase>(Vrml97Sym.appearance); hasMaterial = app.Contains(Vrml97Sym.material); hasTexture = app.Contains(Vrml97Sym.texture); hasTextureTransform = app.Contains(Vrml97Sym.textureTransform); } if (visit == SymMapBaseTraversal.Visit.Pre) { if (hasMaterial) { m_material.Push(app.Get <SymMapBase>(Vrml97Sym.material)); } if (hasTexture) { m_texture.Push(app.Get <SymMapBase>(Vrml97Sym.texture)); } if (hasTextureTransform) { m_textureTransform.Push(app.Get <SymMapBase>(Vrml97Sym.textureTransform)); } } else if (visit == SymMapBaseTraversal.Visit.Post) { if (hasMaterial) { m_material.Pop(); } if (hasTexture) { m_texture.Pop(); } if (hasTextureTransform) { m_textureTransform.Pop(); } } return(m); }; trav.PerNameVisitors["Transform"] = delegate(SymMapBase m, SymMapBaseTraversal.Visit visit) { if (visit == SymMapBaseTraversal.Visit.Pre) { var trafo = m.ExtractVrmlGeometryTrafo(); m["trafo"] = trafo; m_transform.Push(trafo * m_transform.Peek()); } else if (visit == SymMapBaseTraversal.Visit.Post) { m_transform.Pop(); } return(m); }; root.ParseTree = trav.Traverse(root.ParseTree); return(root); }
public SymMapBase Traverse(SymMapBase map) { // choose visitor SymMapBaseVisitor visitor = OnDefaultVisit; if (map.TypeName != null && m_perTypenameVisitors.ContainsKey(map.TypeName)) { visitor = m_perTypenameVisitors[map.TypeName]; } // pre visit if ((m_visit & Visit.Pre) != 0) { if (visitor != null) { if (m_mode == Mode.Modifying) { map = visitor(map, Visit.Pre); } else { SymMapBase tmp = visitor(map, Visit.Pre); if (tmp != map) { throw new ArgumentException( "The node returned by a non-modifying pre-visit is " + "different from the node that has been visited. " + "This makes no sense!" ); } } } } // traverse children if (m_mode == Mode.Modifying) { SymbolDict <object> tmp = new SymbolDict <object>(); foreach (var e in map.MapItems) { tmp[e.Key] = e.Value; } foreach (var e in tmp) { object o = e.Value; if (o is SymMapBase) { map[e.Key] = Traverse((SymMapBase)o); } else if (o is SymMapBase[]) { SymMapBase[] array = (SymMapBase[])o; for (int i = 0; i < array.Length; i++) { array[i] = Traverse(array[i]); } } else if (o is List <SymMapBase> ) { List <SymMapBase> list = (List <SymMapBase>)o; for (int i = 0; i < list.Count; i++) { list[i] = Traverse(list[i]); } } else if (o is Dict <string, SymMapBase> ) { var dict = new Dict <string, SymMapBase>(); foreach (var kvp in (Dict <string, SymMapBase>)o) { dict[kvp.Key] = Traverse(kvp.Value); } map[e.Key] = dict; } else if (o is SymbolDict <SymMapBase> ) { var dict = new SymbolDict <SymMapBase>(); foreach (var kvp in (SymbolDict <SymMapBase>)o) { dict[kvp.Key] = Traverse(kvp.Value); } map[e.Key] = dict; } else if (o is DictSet <SymMapBase> ) { var set = new DictSet <SymMapBase>(); foreach (var m in (DictSet <SymMapBase>)o) { set.Add(Traverse(m)); } map[e.Key] = set; } } } else { foreach (var e in map.MapItems) { object o = e.Value; if (o is SymMapBase) { Traverse((SymMapBase)o); } else if (o is SymMapBase[]) { foreach (var m in (SymMapBase[])o) { Traverse(m); } } else if (o is List <SymMapBase> ) { foreach (var m in (List <SymMapBase>)o) { Traverse(m); } } else if (o is Dict <string, SymMapBase> ) { foreach (var m in ((Dict <string, SymMapBase>)o).Values) { Traverse(m); } } else if (o is SymbolDict <SymMapBase> ) { foreach (var m in ((SymbolDict <SymMapBase>)o).Values) { Traverse(m); } } else if (o is DictSet <SymMapBase> ) { foreach (var m in (DictSet <SymMapBase>)o) { Traverse(m); } } } } // post visit if ((m_visit & Visit.Post) != 0) { if (visitor != null) { if (m_mode == Mode.Modifying) { map = visitor(map, Visit.Post); } else { var tmp = visitor(map, Visit.Post); if (tmp != map) { throw new ArgumentException( "The node returned by a non-modifying post-visit is " + "different from the node that has been visited. " + "This makes no sense!" ); } } } } return(map); }