Ejemplo n.º 1
0
 /// <summary>
 /// コンストラクタ、比較インターフェースと初期項目を指定して初期化する
 /// </summary>
 /// <param name="comparer">比較インターフェース</param>
 /// <param name="capacity">初期キャパシティ</param>
 /// <param name="initialValues">初期項目</param>
 public PriorityQueue(IComparer <T> comparer, int capacity, IEnumerable <T> initialValues)
 {
     _List     = capacity != 0 ? new FList <T>(capacity) : new FList <T>();
     _Comparer = comparer;
     if (initialValues != null)
     {
         _List.AddRange(initialValues);
     }
     UpdateHeap();
 }
Ejemplo n.º 2
0
        /**
         * \brief Merge a set of holes into a polygon. (templated)
         *
         * Take a polygon loop and a collection of hole loops, and patch
         * the hole loops into the polygon loop, returning a vector of
         * vertices from the polygon and holes, which describes a new
         * polygon boundary with no holes. The new polygon boundary is
         * constructed via the addition of edges * joining the polygon
         * loop to the holes.
         *
         * This may be applied to arbitrary vertex data (generally
         * carve::geom3d::Vertex pointers), but a projection function must
         * be supplied to convert vertices to coordinates in 2-space, in
         * which the work is performed.
         *
         * @tparam project_t A functor which converts vertices to a 2d
         *                   projection.
         * @tparam vert_t    The vertex type.
         * @param project The projection functor.
         * @param f_loop The polygon loop into which holes are to be
         *               incorporated.
         * @param h_loops The set of hole loops to be incorporated.
         *
         * @return A vector of vertex pointers.
         */
        public static FList <T> incorporateHolesIntoPolygon <T>(Project <T> project, FList <T> f_loop, FList <FList <T> > h_loops)
        {
            var N = f_loop.Count;

            // work out how much space to reserve for the patched in holes.
            for (int i = h_loops.Count - 1; i != -1; i--)
            {
                N += 2 + h_loops[i].Count;
            }

            // this is the vector that we will build the result in.
            var current_f_loop = new FList <T>(N);

            current_f_loop.AddRange(f_loop);

            var h_loop_min_vertex = new FList <Iterator <T> >(h_loops.Count);

            // find the major axis for the holes - this is the axis that we
            // will sort on for finding vertices on the polygon to join
            // holes up to.
            //
            // it might also be nice to also look for whether it is better
            // to sort ascending or descending.
            //
            // another trick that could be used is to modify the projection
            // by 90 degree rotations or flipping about an axis. just as
            // long as we keep the carve::geom3d::Vector pointers for the
            // real data in sync, everything should be ok. then we wouldn't
            // need to accomodate axes or sort order in the main loop.

            // find the bounding box of all the holes.
            bool    first = true;
            element min_x = element.MaxValue, min_y = element.MaxValue, max_x = element.MinValue, max_y = element.MinValue;

            for (int i = h_loops.Count - 1; i != -1; i--)
            {
                var hole = h_loops[i];
                for (int j = hole.Count - 1; j != -1; j--)
                {
                    var curr = project(hole[j]);
                    if (first)
                    {
                        min_x = max_x = curr.X;
                        min_y = max_y = curr.Y;
                        first = false;
                    }
                    else
                    {
                        if (curr.X < min_x)
                        {
                            min_x = curr.X;
                        }
                        if (curr.Y < min_y)
                        {
                            min_y = curr.Y;
                        }
                        if (max_x < curr.X)
                        {
                            max_x = curr.X;
                        }
                        if (max_y < curr.Y)
                        {
                            max_y = curr.Y;
                        }
                    }
                }
            }

            // choose the axis for which the bbox is largest.
            int axis = (max_x - min_x) > (max_y - min_y) ? 0 : 1;

            // for each hole, find the minimum vertex in the chosen axis.
            for (int i = 0, n = h_loops.Count; i < n; i++)
            {
                var hole   = h_loops[i];
                var best_i = MinElementIndex(hole, new order_h_loops <T>(project, axis));
                h_loop_min_vertex.Add(new Iterator <T>(hole, best_i));
            }

            // sort the holes by the minimum vertex.
            h_loop_min_vertex.Sort(new order_h_loops_iterator <T>(project, axis));

            // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
            for (int i = 0; i < h_loop_min_vertex.Count; ++i)
            {
                var N_f_loop = current_f_loop.Count;

                // the index of the vertex in the hole to connect.
                var h_loop_connect = h_loop_min_vertex[i].value;

                var hole_min = project(h_loop_connect);

                // we order polygon loop vertices that may be able to be connected
                // to the hole vertex by their distance to the hole vertex
                var f_loop_heap = new PriorityQueue <int>(new heap_ordering <T>(project, current_f_loop, h_loop_connect, axis), N);

                for (int j = 0; j < N_f_loop; ++j)
                {
                    // it is guaranteed that there exists a polygon vertex with
                    // coord < the min hole coord chosen, which can be joined to
                    // the min hole coord without crossing the polygon
                    // boundary. also, because we merge holes in ascending
                    // order, it is also true that this join can never cross
                    // another hole (and that doesn't need to be tested for).
                    if (project(current_f_loop[j])[axis] <= hole_min[axis])
                    {
                        f_loop_heap.Push(j);
                    }
                }

                // we are going to test each potential (according to the
                // previous test) polygon vertex as a candidate join. we order
                // by closeness to the hole vertex, so that the join we make
                // is as small as possible. to test, we need to check the
                // joining line segment does not cross any other line segment
                // in the current polygon loop (excluding those that have the
                // vertex that we are attempting to join with as an endpoint).
                var attachment_point = current_f_loop.Count;

                while (f_loop_heap.Count != 0)
                {
                    var curr = f_loop_heap.Pop();
                    // test the candidate join from current_f_loop[curr] to hole_min

                    if (!testCandidateAttachment(project, current_f_loop, curr, hole_min))
                    {
                        continue;
                    }

                    attachment_point = curr;
                    break;
                }

                if (attachment_point == current_f_loop.Count)
                {
                    throw new ApplicationException("didn't manage to link up hole!");
                }

                patchHoleIntoPolygon(current_f_loop, attachment_point, h_loop_min_vertex[i]);
            }

            return(current_f_loop);
        }