Beispiel #1
0
        public static Ngons MinkowskiSum(Ngon pattern, Ngons subject, NFPQUALITY quality, bool flip_pattern)
        {
            switch (quality)
            {
            case NFPQUALITY.Simple:
                return(MSumSimple(pattern, subject, flip_pattern));

            case NFPQUALITY.Convex:
                return(MSumConvex(pattern, subject, flip_pattern));

            case NFPQUALITY.ConcaveLight:
                return(MSumConcave(pattern, subject, flip_pattern, 0.25));

            case NFPQUALITY.ConcaveMedium:
                return(MSumConcave(pattern, subject, flip_pattern, 0.55));

            case NFPQUALITY.ConcaveHigh:
                return(MSumConcave(pattern, subject, flip_pattern, 0.85));

            case NFPQUALITY.ConcaveFull:
                return(MSumConcave(pattern, subject, flip_pattern, 1.0));

            case NFPQUALITY.Full:
                return(MSumFull(pattern, subject, flip_pattern));

            default:
                return(null);
            }
        }
Beispiel #2
0
 public void CMD_Nest(IEnumerable <int> handles, NFPQUALITY max_quality = NFPQUALITY.Full)
 {
     command_buffer.Enqueue(new Command()
     {
         Call = cmd_nest, param = new object[] { handles, max_quality }
     });
 }
Beispiel #3
0
        /// <summary>
        /// Parallel kernel for generating NFP of pattern on handle, return the index in the library of this NFP
        /// Decides the optimal quality for this NFP
        /// </summary>
        /// <param name="subj_handle"></param>
        /// <param name="pattern_handle"></param>
        /// <param name="lib_set_at"></param>
        /// <returns></returns>
        private int NFPKernel(int subj_handle, int pattern_handle, double max_area_bounds, int lib_set_at, NFPQUALITY max_quality = NFPQUALITY.Full)
        {
            NFPQUALITY quality = GetNFPQuality(subj_handle, pattern_handle, max_area_bounds);

            quality = (NFPQUALITY)Math.Min((int)quality, (int)max_quality);
            return(AddMinkowskiSum(subj_handle, pattern_handle, quality, true, lib_set_at));
        }
Beispiel #4
0
        public int AddMinkowskiSum(int subj_handle, int pattern_handle, NFPQUALITY quality, bool flip_pattern, int set_at = -1)
        {
            Ngons A = polygon_lib[subj_handle].GetTransformedPoly();
            Ngons B = polygon_lib[pattern_handle].GetTransformedPoly();

            Ngons   C    = GeomUtility.MinkowskiSum(B[0], A, quality, flip_pattern);
            PolyRef pref = new PolyRef()
            {
                poly = C, trans = Mat3x3.Eye()
            };

            if (set_at < 0)
            {
                polygon_lib.Add(pref);
            }
            else
            {
                polygon_lib[set_at] = pref;
            }

            return(set_at < 0 ? polygon_lib.Count - 1 : set_at);
        }
Beispiel #5
0
        /// <summary>
        /// Nest the collection of handles with minimal enclosing square from origin
        /// </summary>
        /// <param name="handles"></param>
        private void cmd_nest(params object[] param)
        {
            HashSet <int> unique      = PreprocessHandles(param[0] as IEnumerable <int>);
            NFPQUALITY    max_quality = (NFPQUALITY)param[1];

            cmd_translate_origin_to_zero(unique);

            int n = unique.Count;

            Dictionary <int, IntRect> bounds = new Dictionary <int, IntRect>();

            foreach (int handle in unique)
            {
                bounds.Add(handle, GeomUtility.GetBounds(polygon_lib[handle].GetTransformedPoly()[0]));
            }

            int[]  ordered_handles = unique.OrderByDescending(p => Math.Max(bounds[p].Height(), bounds[p].Width())).ToArray();
            double max_bound_area  = bounds[ordered_handles[0]].Area();

            int start_cnt = polygon_lib.Count;

            int[] canvas_regions = AddCanvasFitPolygon(ordered_handles);

            int base_cnt = polygon_lib.Count;

            for (int i = 0; i < n * n - n; i++)
            {
                polygon_lib.Add(new PolyRef());
            }

            int update_breaks = 10;
            int nfp_chunk_sz  = n * n / update_breaks * update_breaks == n * n ? n * n / update_breaks : n * n / update_breaks + 1;

            // the row corresponds to pattern and col to nfp for this pattern on col subj
            int[,] nfps = new int[n, n];
            for (int k = 0; k < update_breaks; k++)
            {
                int start = k * nfp_chunk_sz;
                int end   = Math.Min((k + 1) * nfp_chunk_sz, n * n);

                if (start >= end)
                {
                    break;
                }

                Parallel.For(start, end, i => nfps[i / n, i % n] = i / n == i % n ? -1 : NFPKernel(ordered_handles[i % n], ordered_handles[i / n], max_bound_area, base_cnt + i - (i % n > i / n ? 1 : 0) - i / n, max_quality));

                double progress = Math.Min(((double)(k + 1)) / (update_breaks + 1) * 50.0, 50.0);
                background_worker.ReportProgress((int)progress);

                if (background_worker.CancellationPending)
                {
                    break;
                }
            }

            int place_chunk_sz = Math.Max(n / update_breaks, 1);

            bool[] placed = new bool[n];
            for (int i = 0; i < n; i++)
            {
                if (i % 10 == 0 && background_worker.CancellationPending)
                {
                    break;
                }

                Clipper c = new Clipper();
                c.AddPath(polygon_lib[canvas_regions[i]].poly[0], PolyType.ptSubject, true);
                for (int j = 0; j < i; j++)
                {
                    if (!placed[j])
                    {
                        continue;
                    }

                    c.AddPaths(polygon_lib[nfps[i, j]].GetTransformedPoly(), PolyType.ptClip, true);
                }
                Ngons fit_region = new Ngons();
                c.Execute(ClipType.ctDifference, fit_region, PolyFillType.pftNonZero);


                IntPoint o        = polygon_lib[ordered_handles[i]].GetTransformedPoint(0, 0);
                IntRect  bds      = bounds[ordered_handles[i]];
                long     ext_x    = bds.right - o.X;
                long     ext_y    = bds.top - o.Y;
                IntPoint place    = new IntPoint(0, 0);
                long     pl_score = long.MaxValue;
                for (int k = 0; k < fit_region.Count; k++)
                {
                    for (int l = 0; l < fit_region[k].Count; l++)
                    {
                        IntPoint cand     = fit_region[k][l];
                        long     cd_score = Math.Max(cand.X + ext_x, cand.Y + ext_y);
                        if (cd_score < pl_score)
                        {
                            pl_score  = cd_score;
                            place     = cand;
                            placed[i] = true;
                        }
                    }
                }

                if (!placed[i])
                {
                    continue;
                }

                cmd_translate(ordered_handles[i], (double)(place.X - o.X), (double)(place.Y - o.Y));
                for (int k = i + 1; k < n; k++)
                {
                    cmd_translate(nfps[k, i], (double)(place.X - o.X), (double)(place.Y - o.Y));
                }

                if (i % place_chunk_sz == 0)
                {
                    double progress = Math.Min(60.0 + ((double)(i / place_chunk_sz)) / (update_breaks + 1) * 40.0, 100.0);
                    background_worker.ReportProgress((int)progress);
                }
            }

            // remove temporary added values
            polygon_lib.RemoveRange(start_cnt, polygon_lib.Count - start_cnt);
        }