Ejemplo n.º 1
0
        public static SvgPathSegmentList NormalizeAndTruncate(this SvgPathSegmentList path, out DoubleMatrix transform, double halfSize = 2048)
        {
            // Calculate the bounding box of the path
            var points = path.Curves().SelectMany(c => c.EnclosingPolygon).ToArray();

            // Don't normalize an empty path
            if (points.Length == 0)
            {
                transform = DoubleMatrix.Identity;
                return(path);
            }

            var minx = double.PositiveInfinity;
            var maxx = double.NegativeInfinity;
            var miny = double.PositiveInfinity;
            var maxy = double.NegativeInfinity;

            // Find the bounding box
            foreach (var pt in points)
            {
                minx = Math.Min(minx, pt.X);
                maxx = Math.Max(maxx, pt.X);
                miny = Math.Min(miny, pt.Y);
                maxy = Math.Max(maxy, pt.Y);
            }

            // Calculate the points
            var center = new Double2(minx + maxx, miny + maxy) / 2;

            // And the half-sizes
            var hx = (maxx - minx) / 2;
            var hy = (maxy - miny) / 2;

            // Chose the maximum value of it
            var d  = halfSize / Math.Max(hx, hy);
            var dm = Double2.Zero;

            // And transform the path
            var newPath = new SvgPathSegmentList();

            foreach (var segment in path)
            {
                if (segment is SvgMoveToSegment move)
                {
                    newPath.Add(new SvgMoveToSegment(Transform(move.Start)));
                }
                else if (segment is SvgLineSegment line)
                {
                    newPath.Add(new SvgLineSegment(Transform(line.Start), Transform(line.End)));
                }
                else if (segment is SvgQuadraticCurveSegment quad)
                {
                    newPath.Add(new SvgQuadraticCurveSegment(Transform(quad.Start), Transform(quad.ControlPoint), Transform(quad.End)));
                }
                else if (segment is SvgCubicCurveSegment cubic)
                {
                    newPath.Add(new SvgCubicCurveSegment(Transform(cubic.Start), Transform(cubic.FirstControlPoint),
                                                         Transform(cubic.SecondControlPoint), Transform(cubic.End)));
                }
                else if (segment is SvgArcSegment arc)
                {
                    newPath.Add(new SvgArcSegment(Transform(arc.Start), (float)(arc.RadiusX * d).Truncate(),
                                                  (float)(arc.RadiusY * d).Truncate(), arc.Angle, arc.Size, arc.Sweep, Transform(arc.End)));
                }
                else if (segment is SvgClosePathSegment)
                {
                    newPath.Add(new SvgClosePathSegment());
                }
            }

            // Mount the inverse matrix
            transform = new DoubleMatrix(1 / d, 0, 0, 1 / d, center.X, center.Y);
            return(newPath);

            System.Drawing.PointF Transform(System.Drawing.PointF point)
            {
                var pt = (point.ToDouble2() * d - center * d).Truncate() + dm;

                return(new System.Drawing.PointF((float)pt.X, (float)pt.Y));
            }
        }
Ejemplo n.º 2
0
 // The bounding box matrix should map [-2048,2048] to [0,1] on both directions
 public static DoubleRectangle BoundingBox(this SvgPathSegmentList path)
 => path.Curves().Select(c => c.BoundingBox).Aggregate(DoubleRectangle.Union);