public Node(GraphArray <T> graph)
 {
     m_Graph  = graph;
     m_Begin  = uint.MaxValue;
     m_End    = uint.MaxValue;
     m_Marker = false;
 }
 public void UnmarkNodes(GraphArray <Triangle> G)
 {
     foreach (GraphArray <Triangle> .Node t in G)
     {
         t.Marked = false;
     }
 }
        // Optimized (overloaded) functions
        public void Swap(GraphArray <T> Right)
        {
            List <Node> n = m_Nodes;
            List <Arc>  a = m_Arcs;

            m_Nodes       = Right.m_Nodes;
            m_Arcs        = Right.m_Arcs;
            Right.m_Nodes = n;
            Right.m_Arcs  = a;
        }
 void LinkNeighbours(GraphArray <Triangle> Triangles, List <TriEdge> EdgeMap, TriEdge Edge)
 {
     //Find the first edge equal to Edge
     //See if there are any other edges that are equal
     //(if so, it means that more than 2 triangles are sharing the same edge,
     //which is unlikely but not impossible)
     for (int i = BinarySearch <TriEdge>(EdgeMap, Edge, EdgeComp);
          i < EdgeMap.Count && Edge == EdgeMap[i]; i++)
     {
         Triangles.InsertArc(Edge.TriPos, EdgeMap[i].TriPos);
     }
     //Note: degenerated triangles will also point themselves as neighbour triangles
 }
        public TriStripper(uint[] TriIndices, ushort[] NodeIds, int[] ImpTable)
        {
            m_ImpTable         = ImpTable;
            m_Nodes            = NodeIds;
            m_Triangles        = new GraphArray <Triangle>((uint)TriIndices.Length / 3);
            m_StripID          = 0;
            m_FirstRun         = true;
            m_PrimitivesVector = new List <Primitive>();
            m_TriHeap          = new HeapArray(CompareType.Less);
            m_Candidates       = new List <uint>();
            m_Cache            = new CacheSimulator();
            m_BackCache        = new CacheSimulator();

            SetCacheSize();
            SetMinStripSize();
            SetBackwardSearch();
            SetPushCacheHits();

            MakeConnectivityGraph(m_Triangles, TriIndices);
        }
        void MakeConnectivityGraph(GraphArray <Triangle> Triangles, uint[] Indices)
        {
            Debug.Assert(Triangles.Count == (Indices.Length / 3));

            //Fill the triangle data
            for (int i = 0; i < Triangles.Count; i++)
            {
                Triangles[(uint)i].m_Elem = new Triangle(
                    Indices[i * 3 + 0],
                    Indices[i * 3 + 1],
                    Indices[i * 3 + 2])
                {
                    m_Index = (uint)i
                }
            }
            ;

            //Build an edge lookup table
            List <TriEdge> EdgeMap = new List <TriEdge>();

            for (uint i = 0; i < Triangles.Count; i++)
            {
                Triangle Tri = Triangles[i].m_Elem;
                EdgeMap.Add(new TriEdge(Tri.A, Tri.B, i));
                EdgeMap.Add(new TriEdge(Tri.B, Tri.C, i));
                EdgeMap.Add(new TriEdge(Tri.C, Tri.A, i));
            }
            EdgeMap.Sort(EdgeComp);

            //Link neighbour triangles together using the lookup table
            for (uint i = 0; i < Triangles.Count; i++)
            {
                Triangle Tri = Triangles[i].m_Elem;
                LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.B, Tri.A, i));
                LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.C, Tri.B, i));
                LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.A, Tri.C, i));
            }
        }
        private GraphArray <Triangle> .Arc BackLinkToNeighbour(GraphArray <Triangle> .Node Node, bool ClockWise, ref TriOrder Order)
        {
            TriangleEdge Edge = FirstEdge(Node.m_Elem, Order);

            for (uint i = Node.m_Begin; i < Node.m_End; i++)
            {
                var Link = Node.Arcs[(int)i];

                //Get the reference to the possible previous triangle
                Triangle Tri = Link.Terminal.m_Elem;

                //Check whether it's already been used
                if ((Tri.StripID != m_StripID) && !Link.Terminal.Marked)
                {
                    //Does the current candidate triangle match the required position for the strip?
                    if (Edge.B == Tri.A && Edge.A == Tri.B && TryAddNode(Tri.C))
                    {
                        Order = ClockWise ? TriOrder.CAB : TriOrder.BCA;
                        BackAddIndex(Tri.C);
                        return(Link);
                    }
                    else if (Edge.B == Tri.B && Edge.A == Tri.C && TryAddNode(Tri.A))
                    {
                        Order = ClockWise ? TriOrder.ABC : TriOrder.CAB;
                        BackAddIndex(Tri.A);
                        return(Link);
                    }
                    else if (Edge.B == Tri.C && Edge.A == Tri.A && TryAddNode(Tri.B))
                    {
                        Order = ClockWise ? TriOrder.BCA : TriOrder.ABC;
                        BackAddIndex(Tri.B);
                        return(Link);
                    }
                }
            }
            return(null);
        }
        private Strip BackExtendToStrip(uint Start, TriOrder Order, bool ClockWise)
        {
            m_CurrentNodes = new List <ushort>();
            _checkNodes    = true;

            //Begin a new strip
            Triangle tri = m_Triangles[Start].m_Elem;
            uint     b   = LastEdge(tri, Order).B;

            if (TryAddNode(b))
            {
                tri.SetStripID(++m_StripID);
                BackAddIndex(b);
            }
            else
            {
                _checkNodes = false;
                m_CurrentNodes.Clear();
                return(null);
            }

            uint Size = 1;

            GraphArray <Triangle> .Node Node = null;

            //Loop while we can further extend the strip
            for (uint i = Start; !Cache || ((Size + 2) < CacheSize); Size++)
            {
                Node = m_Triangles[i];
                var Link = BackLinkToNeighbour(Node, ClockWise, ref Order);

                //Is it the end of the strip?
                if (Link == null)
                {
                    break;
                }
                else
                {
                    i = (Node = Link.Terminal).m_Elem.m_Index;

                    Node.m_Elem.SetStripID(m_StripID);
                    ClockWise = !ClockWise;
                }
            }

            _checkNodes = false;
            m_CurrentNodes.Clear();

            //We have to start from a counterclockwise triangle.
            //Simply return an empty strip in the case where the first triangle is clockwise.
            //Even though we could discard the first triangle and start from the next counterclockwise triangle,
            //this often leads to more lonely triangles afterward.
            if (ClockWise)
            {
                return(null);
            }

            if (Cache)
            {
                m_Cache.Merge(m_BackCache, Size);
                m_BackCache.Reset();
            }

            return(new Strip(Node.m_Elem.m_Index, Order, Size));
        }