Пример #1
0
        public static Ngons MinkowskiSumSegment(Ngon pattern, IntPoint p1, IntPoint p2, bool flip_pattern)
        {
            Clipper clipper = new Clipper();

            Ngon p1_c = pattern.Clone(p1.X, p1.Y, flip_pattern);

            if (p1 == p2)
            {
                return new Ngons()
                       {
                           p1_c
                       }
            }
            ;

            Ngon p2_c = pattern.Clone(p2.X, p2.Y, flip_pattern);

            Ngons full = new Ngons();

            clipper.AddPath(p1_c, PolyType.ptSubject, true);
            clipper.AddPath(p2_c, PolyType.ptSubject, true);
            clipper.AddPaths(Clipper.MinkowskiSum(pattern.Clone(0, 0, flip_pattern), new Ngon()
            {
                p1, p2
            }, false), PolyType.ptSubject, true);
            clipper.Execute(ClipType.ctUnion, full, PolyFillType.pftNonZero);

            return(full);
        }
Пример #2
0
        private static Ngons MSumConcave(Ngon pattern, Ngons subject, bool flip_pattern, double rigidness = 1.0)
        {
            Ngon subj = subject[0];
            Ngon patt = pattern.Clone(0, 0, flip_pattern);

            if (rigidness < 1.0)
            {
                subj = ConvexHull(subj, rigidness);
                patt = ConvexHull(patt, rigidness);
            }

            Ngons sres = MinkowskiSumBoundary(patt, subj, false);

            return(sres.Count == 0 ? sres : new Ngons()
            {
                sres[0]
            });
        }
Пример #3
0
        private void cmd_optimal_rotation(int handle)
        {
            Ngon hull = polygon_lib[handle].GetTransformedPoly()[0];
            int  n    = hull.Count;

            double best_t    = 0;
            int    best      = 0;
            long   best_area = long.MaxValue;
            bool   flip_best = false;

            for (int i = 0; i < n; i++)
            {
                double t = GeomUtility.AlignToEdgeRotation(hull, i);

                Mat3x3 rot = Mat3x3.RotateCounterClockwise(t);

                Ngon clone = hull.Clone(rot);

                IntRect bounds = GeomUtility.GetBounds(clone);
                long    area   = bounds.Area();
                double  aspect = bounds.Aspect();

                if (area < best_area)
                {
                    best_area = area;
                    best      = i;
                    best_t    = t;
                    flip_best = aspect > 1.0;
                }
            }

            double   flip   = flip_best ? Math.PI * 0.5 : 0;
            IntPoint around = hull[best];

            cmd_translate(handle, (double)-around.X, (double)-around.Y);
            cmd_rotate(handle, best_t + flip);
            cmd_translate(handle, (double)around.X, (double)around.Y);
        }
Пример #4
0
        private static Ngons MSumConvex(Ngon pattern, Ngons subject, bool flip_pattern)
        {
            Ngon h_p = ConvexHull(pattern.Clone(0, 0, flip_pattern));
            Ngon h_s = ConvexHull(subject[0].Clone());

            int n_p = h_p.Count;
            int n_s = h_s.Count;

            int sp = 0;

            for (int k = 0; k < n_p; k++)
            {
                if (h_p[k].Y < h_p[sp].Y)
                {
                    sp = k;
                }
            }

            int ss = 0;

            for (int k = 0; k < n_s; k++)
            {
                if (h_s[k].Y < h_s[ss].Y)
                {
                    ss = k;
                }
            }

            Ngon poly = new Ngon(n_p + n_s);

            int i = 0;
            int j = 0;

            while (i < n_p || j < n_s)
            {
                int ip = (sp + i + 1) % n_p;
                int jp = (ss + j + 1) % n_s;
                int ii = (sp + i) % n_p;
                int jj = (ss + j) % n_s;

                IntPoint sum = new IntPoint(h_p[ii].X + h_s[jj].X, h_p[ii].Y + h_s[jj].Y);
                IntPoint v   = new IntPoint(h_p[ip].X - h_p[ii].X, h_p[ip].Y - h_p[ii].Y);
                IntPoint w   = new IntPoint(h_s[jp].X - h_s[jj].X, h_s[jp].Y - h_s[jj].Y);

                poly.Add(sum);

                if (i == n_p)
                {
                    j++;
                    continue;
                }

                if (j == n_s)
                {
                    i++;
                    continue;
                }

                long cross = v.Y * w.X - v.X * w.Y;

                if (cross < 0)
                {
                    i++;
                }
                else if (cross > 0)
                {
                    j++;
                }
                else
                {
                    long dot = v.X * w.X + v.Y * w.Y;
                    if (dot > 0)
                    {
                        i++;
                        j++;
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
            }

            return(Clipper.SimplifyPolygon(poly));
        }
Пример #5
0
        public static Ngon ConvexHull(Ngon subject, double rigidness = 0)
        {
            if (subject.Count == 0)
            {
                return(new Ngon());
            }

            if (rigidness >= 1)
            {
                return(subject.Clone());
            }

            subject = subject.Clone();
            if (Clipper.Area(subject) < 0)
            {
                Clipper.ReversePaths(new Ngons()
                {
                    subject
                });
            }

            Ngon last_hull = new Ngon();
            Ngon hull      = subject;

            double subj_area = Clipper.Area(hull);

            int last_vert = 0;

            for (int i = 1; i < subject.Count; i++)
            {
                if (hull[last_vert].Y > hull[i].Y)
                {
                    last_vert = i;
                }
            }

            while (last_hull.Count != hull.Count)
            {
                last_hull = hull;
                hull      = new Ngon();
                hull.Add(last_hull[last_vert]);

                int steps_since_insert = 0;
                int max_steps          = rigidness <= 0 ? int.MaxValue : (int)Math.Round(10 - (10 * rigidness));

                int n = last_hull.Count;

                int start = last_vert;
                for (int i = 1; i < n; i++)
                {
                    IntPoint a = last_hull[last_vert];
                    IntPoint b = last_hull[(start + i) % n];
                    IntPoint c = last_hull[(start + i + 1) % n];

                    IntPoint ab = new IntPoint(b.X - a.X, b.Y - a.Y);
                    IntPoint ac = new IntPoint(c.X - a.X, c.Y - a.Y);

                    if (ab.Y * ac.X < ab.X * ac.Y || steps_since_insert >= max_steps)
                    {
                        hull.Add(b);
                        last_vert          = (start + i) % n;
                        steps_since_insert = -1;
                    }
                    steps_since_insert++;
                }

                last_vert = 0;

                double hull_area = Clipper.Area(hull);

                if (subj_area / hull_area < Math.Sqrt(rigidness))
                {
                    hull = Clipper.SimplifyPolygon(hull, PolyFillType.pftNonZero)[0];
                    break;
                }
            }

            return(hull);
        }