示例#1
0
        /// <summary>
        /// nodeFilterF is used to restrict to valid nodes (eg if id space is sparse, or you only want a subset of possible nbrs)
        /// seeds list are pairs (id, seedvalue)
        /// </summary>
        public DijkstraGraphDistance(int nMaxID, bool bSparse,
                                     Func <int, bool> nodeFilterF,
                                     Func <int, int, float> nodeDistanceF,
                                     Func <int, IEnumerable <int> > neighboursF,
                                     IEnumerable <Vector2d> seeds = null // these are pairs (index, seedval)
                                     )
        {
            NodeFilterF   = nodeFilterF;
            NodeDistanceF = nodeDistanceF;
            NeighboursF   = neighboursF;


            if (bSparse)
            {
                SparseQueue    = new DynamicPriorityQueue <GraphNode>();
                SparseNodes    = new SparseObjectList <GraphNode>(nMaxID, 0);
                SparseNodePool = new MemoryPool <GraphNode>();
            }
            else
            {
                DenseQueue = new IndexPriorityQueue(nMaxID);
                DenseNodes = new GraphNodeStruct[nMaxID];
            }

            Seeds     = new List <int>();
            max_value = float.MinValue;
            if (seeds != null)
            {
                foreach (var v in seeds)
                {
                    AddSeed((int)v.x, (float)v.y);
                }
            }
        }
        protected virtual void InitializeQueue()
        {
            int NE     = mesh.EdgeCount;
            int MaxEID = mesh.MaxEdgeID;

            EdgeQuadrics = new QEdge[MaxEID];
            EdgeQueue    = new IndexPriorityQueue(MaxEID);
            float[] edgeErrors = new float[MaxEID];

            // vertex quadrics can be computed in parallel
            gParallel.BlockStartEnd(0, MaxEID - 1, (start_eid, end_eid) => {
                for (int eid = start_eid; eid <= end_eid; eid++)
                {
                    if (mesh.IsEdge(eid))
                    {
                        Index2i ev        = mesh.GetEdgeV(eid);
                        QuadricError Q    = new QuadricError(ref vertQuadrics[ev.a], ref vertQuadrics[ev.b]);
                        Vector3d opt      = OptimalPoint(eid, ref Q, ev.a, ev.b);
                        edgeErrors[eid]   = (float)Q.Evaluate(ref opt);
                        EdgeQuadrics[eid] = new QEdge(eid, ref Q, ref opt);
                    }
                }
            });

            // sorted pq insert is faster, so sort edge errors array and index map
            int[] indices = new int[MaxEID];
            for (int i = 0; i < MaxEID; ++i)
            {
                indices[i] = i;
            }
            Array.Sort(edgeErrors, indices);

            // now do inserts
            for (int i = 0; i < edgeErrors.Length; ++i)
            {
                int eid = indices[i];
                if (mesh.IsEdge(eid))
                {
                    QEdge edge = EdgeQuadrics[eid];
                    EdgeQueue.Insert(edge.eid, edgeErrors[i]);
                }
            }

            /*
             * // previous code that does unsorted insert. This is marginally slower, but
             * // might get even slower on larger meshes? have only tried up to about 350k.
             * // (still, this function is not the bottleneck...)
             * int cur_eid = start_edges();
             * bool done = false;
             * do {
             *  if (mesh.IsEdge(cur_eid)) {
             *      QEdge edge = EdgeQuadrics[cur_eid];
             *      double err = errList[cur_eid];
             *      EdgeQueue.Enqueue(cur_eid, (float)err);
             *  }
             *  cur_eid = next_edge(cur_eid, out done);
             * } while (done == false);
             */
        }