Пример #1
0
        void tracetoList(List <List <Curve> > ListOfPathes)
        {
            if (ListOfPathes == null)
            {
                return;
            }
            for (int i = 0; i < pathlist.Count; i++)
            {
                Path         P         = pathlist[i];
                List <Curve> CurveList = new List <Curve>();
                ListOfPathes.Add(CurveList);
                dPoint L = P.curve.c[(P.curve.n - 1) * 3 + 2];
                for (int j = 0; j < P.curve.n; j++)
                {
                    dPoint A = P.curve.c[j * 3 + 1];
                    dPoint B = P.curve.c[j * 3 + 2];

                    if (P.curve.tag[j] == POTRACE_CORNER)
                    {
                        CurveList.Add(new Curve(CurveKind.Line, L, L, A, A));
                        CurveList.Add(new Curve(CurveKind.Line, A, A, B, B));
                    }
                    else
                    {
                        dPoint CP = P.curve.c[j * 3];
                        CurveList.Add(new Curve(CurveKind.Bezier, L, CP, A, B));
                    }
                    L = B;
                }
            }
        }
Пример #2
0
        /* range over the straight line segment [a,b] when lambda ranges over [0,1] */
        static dPoint interval(double lambda, dPoint a, dPoint b)
        {
            dPoint res = new dPoint();

            res.X = a.X + lambda * (b.X - a.X);
            res.Y = a.Y + lambda * (b.Y - a.Y);
            return(res);
        }
Пример #3
0
 /// <summary>
 /// Creates a curve
 /// </summary>
 /// <param name="Kind"></param>
 /// <param name="A">Startpoint</param>
 /// <param name="ControlPointA">Controlpoint</param>
 /// <param name="ControlPointB">Controlpoint</param>
 /// <param name="B">Endpoint</param>
 public Curve(CurveKind Kind, dPoint A, dPoint ControlPointA, dPoint ControlPointB, dPoint B)
 {
     this.Kind          = Kind;
     this.A             = A;
     this.B             = B;
     this.ControlPointA = ControlPointA;
     this.ControlPointB = ControlPointB;
 }
Пример #4
0
        /* return a direction that is 90 degrees counterclockwise from p2-p0,
         *                but then restricted to one of the major wind directions (n, nw, w, etc) */
        static dPoint dorth_infty(dPoint p0, dPoint p2)
        {
            dPoint r = new dPoint();

            r.Y = sign(p2.X - p0.X);
            r.X = -sign(p2.Y - p0.Y);

            return(r);
        }
Пример #5
0
        /* calculate (p1-p0)*(p3-p2) */
        static double iprod1(dPoint p0, dPoint p1, dPoint p2, dPoint p3)
        {
            double x1, y1, x2, y2;

            x1 = p1.X - p0.X;
            y1 = p1.Y - p0.Y;
            x2 = p3.X - p2.X;
            y2 = p3.Y - p2.Y;

            return(x1 * x2 + y1 * y2);
        }
Пример #6
0
        /* calculate (p1-p0)x(p3-p2) */
        static double cprod(dPoint p0, dPoint p1, dPoint p2, dPoint p3)
        {
            double x1, y1, x2, y2;

            x1 = p1.X - p0.X;
            y1 = p1.Y - p0.Y;
            x2 = p3.X - p2.X;
            y2 = p3.Y - p2.Y;

            return(x1 * y2 - x2 * y1);
        }
Пример #7
0
        /* return (p1-p0)x(p2-p0), the area of the parallelogram */
        static double dpara(dPoint p0, dPoint p1, dPoint p2)
        {
            double x1, y1, x2, y2;

            x1 = p1.X - p0.X;
            y1 = p1.Y - p0.Y;
            x2 = p2.X - p0.X;
            y2 = p2.Y - p0.Y;

            return(x1 * y2 - x2 * y1);
        }
Пример #8
0
        /* calculate point of a bezier curve */
        static dPoint bezier(double t, dPoint p0, dPoint p1, dPoint p2, dPoint p3)
        {
            double s = 1 - t; dPoint res = new dPoint();

            /* Note: a good optimizing compiler (such as gcc-3) reduces the
             *                 following to 16 multiplications, using common subexpression
             *                 elimination. */
            res.X = s * s * s * p0.X + 3 * (s * s * t) * p1.X + 3 * (t * t * s) * p2.X + t * t * t * p3.X;
            res.Y = s * s * s * p0.Y + 3 * (s * s * t) * p1.Y + 3 * (t * t * s) * p2.Y + t * t * t * p3.Y;

            return(res);
        }
Пример #9
0
        internal static List <List <Curve> > BuildFilling(List <List <Curve> > plist, double spacing, double w, double h, LaserGRBL.RasterConverter.ImageProcessor.Direction dir)
        {
            if (dir == LaserGRBL.RasterConverter.ImageProcessor.Direction.NewInsetFilling)
            {
                return(BuildInsetFilling(plist, spacing));
            }

            List <List <Curve> > flist = new List <List <Curve> >();

            Clipper c = new Clipper();

            AddGridSubject(c, spacing, w, h, dir);
            AddGridClip(plist, c);

            long     t1        = Tools.HiResTimer.TotalMilliseconds;
            PolyTree solution  = new PolyTree();
            bool     succeeded = c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            long t2 = Tools.HiResTimer.TotalMilliseconds;

            System.Diagnostics.Debug.WriteLine($"ClipperExecute: {t2 - t1}ms");

            //GraphicsPath result = new GraphicsPath();

            List <List <IntPoint> > ll = Clipper.OpenPathsFromPolyTree(solution);

            foreach (List <IntPoint> pg in ll)
            {
                PointF[] pts = PolygonToPointFArray(pg, resolution);
                if (pts.Count() > 2)
                {
                    ;                    // result.AddPolygon(pts);
                }
                else
                {
                    dPoint a = new dPoint(pts[0].X, pts[0].Y);
                    dPoint b = new dPoint(pts[1].X, pts[1].Y);
                    flist.Add(new List <Curve>()
                    {
                        new Curve(CurveKind.Line, a, a, b, b)
                    });
                }
                //result.AddLine(pts[0], pts[1]);
            }

            flist.Reverse();
            return(flist);
        }
Пример #10
0
        /* Apply quadratic form Q to vector w = (w.x,w.y) */
        static double quadform(Quad Q, dPoint w)
        {
            double sum = 0;

            double[] v = new double[3];
            v[0] = w.X;
            v[1] = w.Y;
            v[2] = 1;
            sum  = 0.0;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    sum += v[i] * Q.at(i, j) * v[j];
                }
            }
            return(sum);
        }
Пример #11
0
        /* calculate the point t in [0..1] on the (convex) bezier curve
         *               (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
         *               solution in [0..1]. */
        static double tangent(dPoint p0, dPoint p1, dPoint p2, dPoint p3, dPoint q0, dPoint q1)
        {
            double A, B, C;               /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */

            double a, b, c;               /* a t^2 + b t + c = 0 */
            double d, s, r1, r2;

            A = cprod(p0, p1, q0, q1);
            B = cprod(p1, p2, q0, q1);
            C = cprod(p2, p3, q0, q1);

            a = A - 2 * B + C;
            b = -2 * A + 2 * B;
            c = A;

            d = b * b - 4 * a * c;

            if (a == 0 || d < 0)
            {
                return(-1.0);
            }

            s = Math.Sqrt(d);

            r1 = (-b + s) / (2 * a);
            r2 = (-b - s) / (2 * a);

            if (r1 >= 0 && r1 <= 1)
            {
                return(r1);
            }
            else if (r2 >= 0 && r2 <= 1)
            {
                return(r2);
            }
            else
            {
                return(-1.0);
            }
        }
Пример #12
0
        private static List <List <Curve> > ToPotraceList(List <List <IntPoint> > ll, bool close)
        {
            List <List <Curve> > flist = new List <List <Curve> >();

            foreach (List <IntPoint> pg in ll)
            {
                if (pg.Count == 2)
                {
                    dPoint a = new dPoint(pg[0].X / resolution, pg[0].Y / resolution);
                    dPoint b = new dPoint(pg[1].X / resolution, pg[1].Y / resolution);
                    flist.Add(new List <Curve>()
                    {
                        new Curve(CurveKind.Line, a, a, b, b)
                    });
                }
                else
                {
                    List <Curve> potcurve = new List <Curve>();
                    for (int i = 0; i < pg.Count - 1; i++)
                    {
                        dPoint a = new dPoint(pg[i].X / resolution, pg[i].Y / resolution);
                        dPoint b = new dPoint(pg[i + 1].X / resolution, pg[i + 1].Y / resolution);
                        potcurve.Add(new Curve(CurveKind.Line, a, a, b, b));
                    }
                    if (close)
                    {
                        dPoint a = new dPoint(pg[pg.Count - 1].X / resolution, pg[pg.Count - 1].Y / resolution);
                        dPoint b = new dPoint(pg[0].X / resolution, pg[0].Y / resolution);
                        potcurve.Add(new Curve(CurveKind.Line, a, a, b, b));
                    }

                    flist.Add(potcurve);
                }
            }

            //flist.Reverse();
            return(flist);
        }
Пример #13
0
        /* ddenom/dpara have the property that the square of radius 1 centered
         *        at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
        static double ddenom(dPoint p0, dPoint p2)
        {
            dPoint r = dorth_infty(p0, p2);

            return(r.Y * (p2.X - p0.X) - r.X * (p2.Y - p0.Y));
        }
Пример #14
0
 public static Rg.Point3d ToRhPoint(this Pt.dPoint input, double height)
 {
     return(new Rg.Point3d(input.x, height - input.y, 0));
 }
Пример #15
0
        /* Stage 3: vertex adjustment (Sec. 2.3.1). */

        /* Adjust vertices of optimal polygon: calculate the intersection of
         * the two "optimal" line segments, then move it into the unit square
         * if it lies outside. Return 1 with errno set on error; 0 on
         * success. */

        /* calculate "optimal" point-slope representation for each line segment */

        static void adjustVertices(Path path)
        {
            int m = path.m;

            int[]        po = path.po;
            int          n  = path.len;
            List <Point> pt = path.pt;
            double       x0 = path.x0;
            double       y0 = path.y0;

            dPoint[] ctr = new dPoint[m];
            dPoint[] dir = new dPoint[m];
            Quad[]   q = new Quad[m];
            int      i, j, k, l;

            double[] v = new double[3];

            dPoint s = new dPoint();
            double d;

            path.curve = new privcurve(m);

            /* calculate "optimal" point-slope representation for each line
             *              segment */
            for (i = 0; i < m; i++)
            {
                j      = po[mod(i + 1, m)];
                j      = mod(j - po[i], n) + po[i];
                ctr[i] = new dPoint();
                dir[i] = new dPoint();
                pointslope(path, po[i], j, ctr[i], dir[i]);
            }

            /* represent each line segment as a singular quadratic form; the
             *                       distance of a point (x,y) from the line segment will be
             *                       (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
            for (i = 0; i < m; i++)
            {
                q[i] = new Quad();
                d    = dir[i].X * dir[i].X + dir[i].Y * dir[i].Y;
                if (d == 0.0)
                {
                    for (j = 0; j < 3; j++)
                    {
                        for (k = 0; k < 3; k++)
                        {
                            q[i].data[j * 3 + k] = 0;
                        }
                    }
                }
                else
                {
                    v[0] = dir[i].Y;
                    v[1] = -dir[i].X;
                    v[2] = -v[1] * ctr[i].Y - v[0] * ctr[i].X;
                    for (l = 0; l < 3; l++)
                    {
                        for (k = 0; k < 3; k++)
                        {
                            q[i].data[l * 3 + k] = v[l] * v[k] / d;
                        }
                    }
                }
            }

            double dx, dy, det;
            int    z;
            double xmin, ymin;            /* coordinates of minimum */
            double min, cand;             /* minimum and candidate for minimum of quad. form */

            /* now calculate the "intersections" of consecutive segments.
             * Instead of using the actual intersection, we find the point
             * within a given unit square which minimizes the square distance to
             * the two lines. */
            for (i = 0; i < m; i++)
            {
                Quad   Q = new Quad();
                dPoint w = new dPoint();
                /* let s be the vertex, in coordinates relative to x0/y0 */
                s.X = pt[po[i]].X - x0;
                s.Y = pt[po[i]].Y - y0;
                /* intersect segments i-1 and i */
                j = mod(i - 1, m);
                /* add quadratic forms */
                for (l = 0; l < 3; l++)
                {
                    for (k = 0; k < 3; k++)
                    {
                        Q.data[l * 3 + k] = q[j].at(l, k) + q[i].at(l, k);
                    }
                }

                while (true)
                {
                    /* minimize the quadratic form Q on the unit square */
                    /* find intersection */
                    det = Q.at(0, 0) * Q.at(1, 1) - Q.at(0, 1) * Q.at(1, 0);
                    if (det != 0.0)
                    {
                        w.X = (-Q.at(0, 2) * Q.at(1, 1) + Q.at(1, 2) * Q.at(0, 1)) / det;
                        w.Y = (Q.at(0, 2) * Q.at(1, 0) - Q.at(1, 2) * Q.at(0, 0)) / det;
                        break;
                    }

                    /* matrix is singular - lines are parallel. Add another,
                     *                        orthogonal axis, through the center of the unit square */
                    if (Q.at(0, 0) > Q.at(1, 1))
                    {
                        v[0] = -Q.at(0, 1);
                        v[1] = Q.at(0, 0);
                    }
                    else if (Q.at(1, 1) != 0.0)
                    {
                        v[0] = -Q.at(1, 1);
                        v[1] = Q.at(1, 0);
                    }
                    else
                    {
                        v[0] = 1;
                        v[1] = 0;
                    }
                    d    = v[0] * v[0] + v[1] * v[1];
                    v[2] = -v[1] * s.Y - v[0] * s.X;
                    for (l = 0; l < 3; l++)
                    {
                        for (k = 0; k < 3; k++)
                        {
                            Q.data[l * 3 + k] += v[l] * v[k] / d;
                        }
                    }
                }
                dx = Math.Abs(w.X - s.X);
                dy = Math.Abs(w.Y - s.Y);
                if (dx <= 0.5 && dy <= 0.5)
                {
                    path.curve.vertex[i] = new dPoint(w.X + x0, w.Y + y0);
                    continue;
                }

                /* the minimum was not in the unit square; now minimize quadratic
                 * on boundary of square */
                min  = quadform(Q, s);
                xmin = s.X;
                ymin = s.Y;

                if (Q.at(0, 0) != 0.0)
                {
                    for (z = 0; z < 2; z++)
                    {
                        /* value of the y-coordinate */
                        w.Y  = s.Y - 0.5 + z;
                        w.X  = -(Q.at(0, 1) * w.Y + Q.at(0, 2)) / Q.at(0, 0);
                        dx   = Math.Abs(w.X - s.X);
                        cand = quadform(Q, w);
                        if (dx <= 0.5 && cand < min)
                        {
                            min  = cand;
                            xmin = w.X;
                            ymin = w.Y;
                        }
                    }
                }

                if (Q.at(1, 1) != 0.0)
                {
                    for (z = 0; z < 2; z++)
                    {
                        /* value of the x-coordinate */
                        w.X  = s.X - 0.5 + z;
                        w.Y  = -(Q.at(1, 0) * w.X + Q.at(1, 2)) / Q.at(1, 1);
                        dy   = Math.Abs(w.Y - s.Y);
                        cand = quadform(Q, w);
                        if (dy <= 0.5 && cand < min)
                        {
                            min  = cand;
                            xmin = w.X;
                            ymin = w.Y;
                        }
                    }
                }
                /* check four corners */
                for (l = 0; l < 2; l++)
                {
                    for (k = 0; k < 2; k++)
                    {
                        w.X  = s.X - 0.5 + l;
                        w.Y  = s.Y - 0.5 + k;
                        cand = quadform(Q, w);
                        if (cand < min)
                        {
                            min  = cand;
                            xmin = w.X;
                            ymin = w.Y;
                        }
                    }
                }

                path.curve.vertex[i] = new dPoint(xmin + x0, ymin + y0);
            }
        }
Пример #16
0
 /* calculate p1 x p2 */
 static double xprod(dPoint p1, dPoint p2)
 {
     return(p1.X * p2.Y - p1.Y * p2.X);
 }
Пример #17
0
 /* calculate distance between two points */
 static double ddist(dPoint p, dPoint q)
 {
     return(Math.Sqrt((p.X - q.X) * (p.X - q.X) + (p.Y - q.Y) * (p.Y - q.Y)));
 }
Пример #18
0
        /* determine the center and slope of the line i..j. Assume i<j. Needs
         *         "sum" components of p to be set. */
        static void pointslope(Path path, int i, int j, dPoint ctr, dPoint dir)
        {
            int        n = path.len;
            List <Sum> sums = path.sums;
            double     x, y, x2, xy, y2;
            double     a, b, c, lambda2, l;
            int        k = 0;
            /* assume i<j */
            int r = 0;             /* rotations from i to j */

            while (j >= n)
            {
                j -= n;
                r += 1;
            }
            while (i >= n)
            {
                i -= n;
                r -= 1;
            }
            while (j < 0)
            {
                j += n;
                r -= 1;
            }
            while (i < 0)
            {
                i += n;
                r += 1;
            }

            x  = sums[j + 1].x - sums[i].x + r * sums[n].x;
            y  = sums[j + 1].y - sums[i].y + r * sums[n].y;
            x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2;
            xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy;
            y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2;
            k  = j + 1 - i + r * n;

            ctr.X = x / k;
            ctr.Y = y / k;

            a = (x2 - x * x / k) / k;
            b = (xy - x * y / k) / k;
            c = (y2 - y * y / k) / k;

            lambda2 = (a + c + Math.Sqrt((a - c) * (a - c) + 4 * b * b)) / 2;              /* larger e.value */

            a -= lambda2;
            c -= lambda2;

            if (Math.Abs(a) >= Math.Abs(c))
            {
                l = Math.Sqrt(a * a + b * b);
                if (l != 0)
                {
                    dir.X = -b / l;
                    dir.Y = a / l;
                }
            }
            else
            {
                l = Math.Sqrt(c * c + b * b);
                if (l != 0)
                {
                    dir.X = -c / l;
                    dir.Y = b / l;
                }
            }
            if (l == 0)
            {
                dir.X = dir.Y = 0;                  /* sometimes this can happen when k=4:
                                                     * the two eigenvalues coincide */
            }
        }
Пример #19
0
        private static List <List <Curve> > BuildInsetFilling(List <List <Curve> > plist, double spacing)
        {
            int  loop  = 1;
            bool empty = false;
            List <List <Curve> > flist = new List <List <Curve> >();

            ClipperOffset c = new ClipperOffset();

            foreach (List <Curve> LC in plist)
            {
                GraphicsPath Current = new GraphicsPath();
                for (int j = 0; j < LC.Count; j++)
                {
                    Curve C = LC[j];
                    if (C.Kind == CurveKind.Line)
                    {
                        Current.AddLine(new PointF((float)C.A.X, (float)C.A.Y), new PointF((float)C.B.X, (float)C.B.Y));
                    }
                    else
                    {
                        PointF A = new PointF((float)C.A.X, (float)C.A.Y);
                        Current.AddBezier(new PointF((float)C.A.X, (float)C.A.Y), new PointF((float)C.ControlPointA.X, (float)C.ControlPointA.Y), new PointF((float)C.ControlPointB.X, (float)C.ControlPointB.Y), new PointF((float)C.B.X, (float)C.B.Y));
                    }
                }

                AddClip(c, Current);
            }

            while (!empty)
            {
                long t1 = Tools.HiResTimer.TotalMilliseconds;
                List <List <IntPoint> > solution = new List <List <IntPoint> >();
                c.Execute(ref solution, -spacing * loop * resolution);

                loop++;

                long t2 = Tools.HiResTimer.TotalMilliseconds;
                System.Diagnostics.Debug.WriteLine($"ClipperExecute: {t2 - t1}ms");

                //GraphicsPath result = new GraphicsPath();
                if (solution.Count == 0)
                {
                    empty = true;
                }

                foreach (List <IntPoint> pg in solution)
                {
                    PointF[] pts = PolygonToPointFArray(pg, resolution);
                    if (pts.Count() > 2)
                    {
                        List <Curve> curve = new List <Curve>();
                        for (int i = 0; i < pts.Length - 1; i++)
                        {
                            dPoint a = new dPoint(pts[i].X, pts[i].Y);
                            dPoint b = new dPoint(pts[i + 1].X, pts[i + 1].Y);
                            curve.Add(new Curve(CurveKind.Line, a, a, b, b));
                        }

                        //chiudi la figura
                        dPoint a1 = new dPoint(pts[pts.Length - 1].X, pts[pts.Length - 1].Y);
                        dPoint b1 = new dPoint(pts[0].X, pts[0].Y);
                        curve.Add(new Curve(CurveKind.Line, a1, a1, b1, b1));
                        flist.Add(curve);
                    }
                    else
                    {
                        dPoint a = new dPoint(pts[0].X, pts[0].Y);
                        dPoint b = new dPoint(pts[1].X, pts[1].Y);
                        flist.Add(new List <Curve>()
                        {
                            new Curve(CurveKind.Line, a, a, b, b)
                        });
                    }
                    //result.AddLine(pts[0], pts[1]);
                }
            }

            return(flist);
        }
Пример #20
0
 public static Sw.Point ToPoint(this Pt.dPoint input)
 {
     return(new Sw.Point(input.x, input.y));
 }