コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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);
        }