Пример #1
0
        /// <summary>
        /// Transforms a general elliptical arc. Returns true if the transformed arc is a circular arc.
        /// </summary>
        public static bool TransformEllipseArc(ref double centerx, ref double centery, ref double aradius, ref double bradius, ref double startangle, ref double sweepangle, ref double tilt, Transform2d mat)
        {
            double endangle = startangle + sweepangle; //we do our calculations here with endangle rather than sweepangle

            mat.Apply(centerx, centery, out centerx, out centery, true);

            //get points on the untranformed ellipse and transform them to be
            //points on the central, tranformed ellipse
            double spx, spy, epx, epy;

            GeomUtil.GetPointOnCentralEllipse(aradius, bradius, tilt, startangle, out spx, out spy);
            GeomUtil.GetPointOnCentralEllipse(aradius, bradius, tilt, endangle, out epx, out epy);

            mat.Apply(spx, spy, out spx, out spy, false);
            mat.Apply(epx, epy, out epx, out epy, false);

            bool res = GeomUtil.TransformCentralEllipse(ref aradius, ref bradius, ref tilt, mat, ref sweepangle);

            startangle = Angle(0, 0, spx, spy) - tilt;
            endangle   = Angle(0, 0, epx, epy) - tilt;

            //convert endangle back to startangle
            if (sweepangle > 0.0 && endangle < startangle)
            {
                endangle += Math.PI * 2.0;
            }
            else if (sweepangle < 0.0 && endangle > startangle)
            {
                endangle -= Math.PI * 2.0;
            }
            sweepangle = endangle - startangle;

            return(res);
        }
Пример #2
0
        public virtual void DrawArcT(double x1, double y1, double x2, double y2, double bulge)
        {
            var t = Transform;

            if (t.IsUniform)
            {
                //the arc will still be an arc after transform
                //transform it an draw with standrad arc function
                t.Apply(x1, y1, out x1, out y1, true);
                t.Apply(x2, y2, out x2, out y2, true);
                DrawArc(x1, y1, x2, y2, t.Determinant < 0.0 ? -bulge : bulge); //-buylge to support mirrored arcs
                return;
            }
            else
            { //the arc might change into an elliptic arc
                double cx, cy, rad;
                if (!GeomUtil.GetArcCenterFromBulge(x1, y1, x2, y2, bulge, out cx, out cy))
                {
                    //the arc is a line
                    DrawLineT(x1, y1, x2, y2);
                    return;
                }
                rad = GeomUtil.GetArcRadiusFromBulge(x1, y1, x2, y2, bulge);
                DrawEllipticArcT(cx, cy, rad, rad, 0.0, GeomUtil.Angle(cx, cy, x1, y1), GeomUtil.GetArcSweepAngleFromBulge(bulge));
            }
        }
Пример #3
0
        public virtual void DrawRectangleT(double x1, double y1, double x2, double y2)
        {
            double xx1 = x1, yy1 = y1;
            double xx2 = x2, yy2 = y1;
            double xx3 = x2, yy3 = y2;
            double xx4 = x1, yy4 = y2;


            Transform.Apply(xx1, yy1, out xx1, out yy1, true);
            Transform.Apply(xx2, yy2, out xx2, out yy2, true);
            Transform.Apply(xx3, yy3, out xx3, out yy3, true);
            Transform.Apply(xx4, yy4, out xx4, out yy4, true);

            //check if rectangle becomes a line to avoid duplicate drawing
            if (GeomUtil.SquaredDistance(xx1, yy1, xx4, yy4) < 1.225)  //rect. is a horizontal line ( height<sqrt(1.5) )
            {
                DrawLine(xx1, yy1, xx2, yy2);
            }
            else if (GeomUtil.SquaredDistance(xx1, yy1, xx2, yy2) <= 1.225) //rect. is a verical line ( width<sqrt(1.5) )
            {
                DrawLine(xx1, yy1, xx4, yy4);
            }
            else
            {
                DrawPolyLine(true, xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4);
            }
        }
Пример #4
0
        /// <summary>
        /// Computes the extents of the path, if the path had been transformed with
        /// the given transform.
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public Box2d GetTransformedExtents(Transform2d t)
        {
            Box2d res = new Box2d();

            double penx = 0.0, peny = 0.0;
            double x, y;

            foreach (GFXPathMoveTo node in PathPoints)
            {
                if (node is GFXPathLineTo)
                {
                    t.Apply(node.X, node.Y, out x, out y, true);
                    res.Append(x, y);
                    t.Apply(penx, peny, out x, out y, true);
                    res.Append(x, y);
                }
                else if (node is GFXPathArcTo)
                {
                    res.Append(GeomUtil.GetTransformedArcExtents(penx, peny, node.X, node.Y, ((GFXPathArcTo)node).Bulge, t));
                }
                else if (node is GFXPathBezierTo)
                {
                    GFXPathBezierTo bn = (GFXPathBezierTo)node;
                    res.Append(GeomUtil.GetTransformedBezierExtents(penx, peny, bn.XC1, bn.YC1, bn.XC2, bn.YC2, bn.X, bn.Y, t));
                }


                penx = node.X;
                peny = node.Y;
            }

            return(res);
        }
Пример #5
0
        internal override void TransformFlatten(ref double penx, ref double peny, double tol, Transform2d t, FlattenCallback lcb)
        {
            double xs, ys, c1x, c1y, c2x, c2y, xe, ye;

            t.Apply(penx, peny, out xs, out ys, true);
            t.Apply(XC1, YC1, out c1x, out c1y, true);
            t.Apply(XC2, YC2, out c2x, out c2y, true);
            t.Apply(X, Y, out xe, out ye, true);
            GeomUtil.FlattenBezier(xs, ys, c1x, c1y, c2x, c2y, xe, ye, false, tol, lcb);
            penx = X;
            peny = Y;
        }
Пример #6
0
        public virtual void DrawEllipseT(double cx, double cy, double aradius, double bradius, double tilt)
        {
            bool circular = GeomUtil.TransformEllipse(ref cx, ref cy, ref aradius, ref bradius, ref tilt, Transform);

            if (circular) //draw with circle if possible=>faster
            {
                DrawCircle(cx, cy, aradius);
                return;
            }


            DrawEllipse(cx, cy, aradius, bradius, tilt);
        }
Пример #7
0
        public virtual void DrawArc(double x1, double y1, double x2, double y2, double bulge)
        {
            double cx, cy, rad;

            if (!GeomUtil.GetArcCenterFromBulge(x1, y1, x2, y2, bulge, out cx, out cy))
            {
                DrawLine(x1, y1, x2, y2);
                return;
            }

            rad = GeomUtil.GetArcRadiusFromBulge(x1, y1, x2, y2, bulge);
            DrawEllipticArc(cx, cy, rad, rad, 0.0, GeomUtil.Angle(cx, cy, x1, y1), GeomUtil.GetArcSweepAngleFromBulge(bulge));
        }
Пример #8
0
        public override void DrawEllipticArc(double cx, double cy, double aradius, double bradius, double tilt, double startangle, double sweepangle)
        {
            /*  int prevx=0,prevy=0;
             * int nextx,nexty;
             * bool first=true;
             *
             * GeomUtil.FlattenEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle, flattentol, true, (x, y,moveto) =>
             * {
             *    if (first)
             *    {
             *        prevx = GFXUtil.RealToInt(x);
             *        prevy = GFXUtil.RealToInt(y);
             *        first = false;
             *    }
             *    else
             *    {
             *        nextx = GFXUtil.RealToInt(x);
             *        nexty = GFXUtil.RealToInt(y);
             *        DrawLine(prevx,prevy,nextx,nexty);
             *        //target.Add(prevx, prevy, nextx, nexty, currentobject);
             *        prevx = nextx;
             *        prevy = nexty;
             *    }
             * });*/

            int px = 0, py = 0, nx, ny;

            int num = Clipper.ClipEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle, clipbuffer, Clip.XMin, Clip.YMin, Clip.XMax, Clip.YMax);

            for (int l = 0; l < num; l += 2)
            {
                GeomUtil.FlattenEllipticArc(cx, cy, aradius, bradius, tilt, clipbuffer[l], clipbuffer[l + 1] - clipbuffer[l], flattentol, true, (x, y, moveto) =>
                {
                    nx = GFXUtil.FloatToInt(x);
                    ny = GFXUtil.FloatToInt(y);
                    if (!moveto)
                    {
                        DrawLine(px, py, nx, ny);
                    }
                    px = nx;
                    py = ny;
                });
            }
        }
Пример #9
0
        public virtual void DrawEllipticArcT(double cx, double cy, double aradius, double bradius, double tilt, double startangle, double sweepangle)
        {
            bool circular = GeomUtil.TransformEllipseArc(ref cx, ref cy, ref aradius, ref bradius, ref startangle, ref sweepangle, ref tilt, Transform);



            if (circular)
            {
                double bulge = GeomUtil.GetArcBulgeFromSweepAngle(sweepangle);
                double x1    = cx + Math.Cos(startangle) * aradius;
                double y1    = cy + Math.Sin(startangle) * aradius;
                double x2    = cx + Math.Cos(startangle + sweepangle) * aradius;
                double y2    = cy + Math.Sin(startangle + sweepangle) * aradius;
                DrawArc(x1, y1, x2, y2, bulge);
                return;
            }

            DrawEllipticArc(cx, cy, aradius, bradius, tilt, startangle, sweepangle);
        }
Пример #10
0
        public override void DrawArc(double x1, double y1, double x2, double y2, double bulge)
        {
            int prevx = GFXUtil.FloatToInt(x1);
            int prevy = GFXUtil.FloatToInt(y1);

            int clipres = Clipper.ClipArc(x1, y1, x2, y2, bulge, clipbuffer, Clip.XMin, Clip.YMin, Clip.XMax, Clip.YMax);

            for (int idx = 0; idx < clipres; idx += 5)
            {
                int cx = GFXUtil.FloatToInt(clipbuffer[idx]), cy = GFXUtil.FloatToInt(clipbuffer[idx + 1]), nx, ny;
                GeomUtil.FlattenArc(clipbuffer[idx], clipbuffer[idx + 1], clipbuffer[idx + 2], clipbuffer[idx + 3], clipbuffer[idx + 4], false, flattentol, (x, y, moveto) =>
                {
                    nx = GFXUtil.FloatToInt(x);
                    ny = GFXUtil.FloatToInt(y);
                    target.Add(cx, cy, nx, ny, currentobject);
                    cx = nx;
                    cy = ny;
                });
            }
        }
Пример #11
0
        /// <summary>
        /// Checks if this path, after a given transformation will have a bounding box smaller than a given size. THis can be done quickly since the
        /// check can be terminated as soon as it finds a segment large enough.
        /// </summary>
        public bool IsTransformedSmallerThan(Transform2d tr, double maxwidth, double maxheight)
        {
            double penx = 0.0, peny = 0.0;
            Box2d  ext = new Box2d();

            foreach (GFXPathMoveTo mt in PathPoints)
            {
                if (mt is GFXPathBezierTo)
                {
                    var   bez  = mt as GFXPathBezierTo;
                    Box2d bext = GeomUtil.GetTransformedBezierExtents(penx, peny, bez.XC1, bez.YC1, bez.XC2, bez.YC2, bez.X, bez.Y, tr);
                    ext.Append(bext);
                }
                else if (mt is GFXPathArcTo)
                {
                    var   arc  = mt as GFXPathArcTo;
                    Box2d aext = GeomUtil.GetTransformedArcExtents(penx, peny, arc.X, arc.Y, arc.Bulge, tr);
                    ext.Append(aext);
                }
                else if (mt is GFXPathLineTo)
                {
                    double x1, y1, x2, y2;
                    tr.Apply(penx, peny, out x1, out y1, true);
                    tr.Apply(mt.X, mt.Y, out x2, out y2, true);
                    ext.Append(x1, y1, x2, y2);
                }

                // closepath and moveto needs no special handling...
                if (!ext.Empty && (ext.Width > maxwidth || ext.Height > maxheight))
                {
                    return(false);
                }

                penx = mt.X;
                peny = mt.Y;
            }


            return(true);
        }
Пример #12
0
        private void InternalDrawBezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
        {
            int n = Clipper.ClipBezier(x1, y1, x2, y2, x3, y3, x4, y4, clipbuffer, Clip.XMin, Clip.YMin, Clip.XMax, Clip.YMax);
            int penx = 0, peny = 0;

            for (int l = 0; l < n; l += 2)
            {
                GeomUtil.FlattenBezier(x1, y1, x2, y2, x3, y3, x4, y4, true, flattentol, (x, y, moveto) =>
                {
                    int nextx = GFXUtil.FloatToInt(x);
                    int nexty = GFXUtil.FloatToInt(y);

                    if (!moveto)
                    {
                        DrawLine(penx, peny, nextx, nexty);
                    }

                    penx = nextx;
                    peny = nexty;
                }, clipbuffer[l], clipbuffer[l + 1]);
            }
        }
Пример #13
0
 internal override void TransformFlatten(ref double penx, ref double peny, double tol, Transform2d t, FlattenCallback lcb)
 {
     GeomUtil.TransformFlattenArc(penx, peny, X, Y, Bulge, false, tol, t, lcb);
     penx = X;
     peny = Y;
 }
Пример #14
0
 internal override void Flatten(ref double penx, ref double peny, double tol, FlattenCallback lcb)
 {
     GeomUtil.FlattenBezier(penx, peny, XC1, YC1, XC2, YC2, X, Y, false, tol, lcb);
     penx = X;
     peny = Y;
 }
Пример #15
0
        public override void DrawEllipticArc(double cx, double cy, double aradius, double bradius, double tilt, double startangle, double sweepangle)
        {
            var ellipext = GeomUtil.GetEllipticExtents(cx, cy, aradius, bradius, startangle, sweepangle, tilt);

            AppendWithLineWidth(ellipext);
        }
Пример #16
0
        public override void DrawArc(double x1, double y1, double x2, double y2, double bulge)
        {
            Box2d rect = GeomUtil.GetArcExtents(x1, y1, x2, y2, bulge);

            AppendWithLineWidth(rect);
        }
Пример #17
0
 internal override void Flatten(ref double penx, ref double peny, double tol, FlattenCallback lcb)
 {
     GeomUtil.FlattenArc(penx, peny, X, Y, Bulge, false, tol, lcb);
     penx = X;
     peny = Y;
 }