Example #1
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);
        }
Example #2
0
        public static Box2d GetBezierExtents(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
        {
            //equations for differentiations of the bezier polynoimial in x and y:
            double t2x = 9 * x2 - 9 * x3 + 3 * x4 - 3 * x1;
            double t1x = 6 * x1 - 12 * x2 + 6 * x3;
            double t0x = 3 * x2 - 3 * x1;

            double t2y = 9 * y2 - 9 * y3 + 3 * y4 - 3 * y1;
            double t1y = 6 * y1 - 12 * y2 + 6 * y3;
            double t0y = 3 * y2 - 3 * y1;

            double extrema1, extrema2, xp, yp;

            Box2d res = new Box2d(x1, y1, x4, y4);

            //solve x extremas
            if (MathUtil.SolveQuadratic(t2x, t1x, t0x, out extrema1, out extrema2))
            {
                if (extrema1 > 0.0 && extrema1 < 1.0)
                {
                    EvalBezier(x1, y1, x2, y2, x3, y3, x4, y4, extrema1, out xp, out yp);
                    res.Append(xp, yp);
                }

                if (extrema2 > 0.0 && extrema2 < 1.0)
                {
                    EvalBezier(x1, y1, x2, y2, x3, y3, x4, y4, extrema2, out xp, out yp);
                    res.Append(xp, yp);
                }
            }

            //solve y extremas
            if (MathUtil.SolveQuadratic(t2y, t1y, t0y, out extrema1, out extrema2))
            {
                if (extrema1 > 0.0 && extrema1 < 1.0)
                {
                    EvalBezier(x1, y1, x2, y2, x3, y3, x4, y4, extrema1, out xp, out yp);
                    res.Append(xp, yp);
                }

                if (extrema2 > 0.0 && extrema2 < 1.0)
                {
                    EvalBezier(x1, y1, x2, y2, x3, y3, x4, y4, extrema2, out xp, out yp);
                    res.Append(xp, yp);
                }
            }

            return(res);
        }
Example #3
0
        public static Box2d GetArcExtents(double x1, double y1, double x2, double y2, double bulge)
        {
            double cx, cy, rad, side;
            Box2d  res = new Box2d(x1, y1, x2, y2);

            //append quadrants if included


            if (!GetArcCenterFromBulge(x1, y1, x2, y2, bulge, out cx, out cy))
            {
                return(res); //arc is a line
            }
            rad = GetArcRadiusFromBulge(x1, y1, x2, y2, bulge);

            //include quadrant points of circle if on arc
            side = SideOfPoint(x1, y1, x2, y2, cx + rad, cy);
            if ((bulge < 0.0 && side >= 0.0) || (bulge > 0.0 && side <= 0.0))
            {
                res.Append(cx + rad, cy);
            }

            side = SideOfPoint(x1, y1, x2, y2, cx, cy + rad);
            if ((bulge < 0.0 && side >= 0.0) || (bulge > 0.0 && side <= 0.0))
            {
                res.Append(cx, cy + rad);
            }

            side = SideOfPoint(x1, y1, x2, y2, cx - rad, cy);
            if ((bulge < 0.0 && side >= 0.0) || (bulge > 0.0 && side <= 0.0))
            {
                res.Append(cx - rad, cy);
            }

            side = SideOfPoint(x1, y1, x2, y2, cx, cy - rad);
            if ((bulge < 0.0 && side >= 0.0) || (bulge > 0.0 && side <= 0.0))
            {
                res.Append(cx, cy - rad);
            }

            return(res);
        }
Example #4
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);
        }
        private void AppendPathToExtents(bool uselinewidth, bool usetransform, GFXPath pth)
        {
            Box2d ext;

            if (usetransform)
            {
                ext = pth.GetTransformedExtents(Transform);
            }
            else
            {
                ext = pth.Extents;
            }


            if (uselinewidth)
            {
                AppendWithLineWidth(pth.Extents);
            }
            else
            {
                RecordedExtents.Append(ext.XMin, ext.YMin, ext.XMax, ext.YMax);
            }
        }
Example #6
0
        public static Box2d GetEllipticExtents(double cx, double cy, double aradius, double bradius, double startangle, double sweepangle, double tilt)
        {
            Box2d extents = new Box2d();

            double vmaxx, vmaxy;

            if (MathUtil.IsZero(bradius)) //special case for zero bradius, assume maxima lies in tilt direction
            {
                vmaxy = tilt;
            }
            else
            {
                vmaxy = Math.Atan(bradius / (aradius * Math.Tan(tilt)));
            }

            if (MathUtil.IsZero(aradius)) //special case for zero bradius, assume maxima lies in tilt direction
            {
                vmaxx = tilt;
            }
            else
            {
                vmaxx = -Math.Atan((bradius * Math.Tan(tilt)) / aradius);
            }


            double startparam = EllipseAngleToParam(startangle, aradius, bradius);
            double endparam   = EllipseAngleToParam(startangle + sweepangle, aradius, bradius);
            bool   ccw        = sweepangle >= 0.0;


            if (Math.Abs(sweepangle) < MathUtil.Deg360)
            {
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, startparam));
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, endparam));
                if (MathUtil.IsAngleBetween(startparam, endparam, vmaxy, ccw))
                {
                    extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxy));
                }
                if (MathUtil.IsAngleBetween(startparam, endparam, vmaxy + MathUtil.Deg180, ccw))
                {
                    extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxy + MathUtil.Deg180));
                }
                if (MathUtil.IsAngleBetween(startparam, endparam, vmaxx, ccw))
                {
                    extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxx));
                }
                if (MathUtil.IsAngleBetween(startparam, endparam, vmaxx + MathUtil.Deg180, ccw))
                {
                    extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxx + MathUtil.Deg180));
                }
            }
            else
            {
                //not an arc, all extreme ellipse points are included => a little faster
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxy));
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxy + MathUtil.Deg180));
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxx));
                extents.Append(EvalEllipseParam(cx, cy, aradius, bradius, tilt, vmaxx + MathUtil.Deg180));
            }

            return(extents);
        }