예제 #1
0
        public static PathGeometry AsPathGeometry(this PathF target, float scale = 1)
        {
            var        geometry = new PathGeometry();
            PathFigure figure   = null;

            var pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    figure = new PathFigure();
                    geometry.Figures.Add(figure);
                    figure.StartPoint = target[pointIndex++].AsPoint(scale);
                }
                else if (type == PathOperation.Line)
                {
                    var lineSegment = new LineSegment {
                        Point = target[pointIndex++].AsPoint(scale)
                    };
                    figure.Segments.Add(lineSegment);
                }
                else if (type == PathOperation.Quad)
                {
                    var quadSegment = new QuadraticBezierSegment
                    {
                        Point1 = target[pointIndex++].AsPoint(scale),
                        Point2 = target[pointIndex++].AsPoint(scale)
                    };
                    figure.Segments.Add(quadSegment);
                }
                else if (type == PathOperation.Cubic)
                {
                    var cubicSegment = new BezierSegment()
                    {
                        Point1 = target[pointIndex++].AsPoint(scale),
                        Point2 = target[pointIndex++].AsPoint(scale),
                        Point3 = target[pointIndex++].AsPoint(scale),
                    };
                    figure.Segments.Add(cubicSegment);
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = target[pointIndex++];
                    var bottomRight = target[pointIndex++];
                    var startAngle  = target.GetArcAngle(arcAngleIndex++);
                    var endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var sweep    = Geometry.GetSweep(startAngle, endAngle, clockwise);
                    var absSweep = Math.Abs(sweep);

                    var rectX      = topLeft.X * scale;
                    var rectY      = topLeft.Y * scale;
                    var rectWidth  = bottomRight.X * scale - topLeft.X * scale;
                    var rectHeight = bottomRight.Y * scale - topLeft.Y * scale;

                    var startPoint = Geometry.OvalAngleToPoint(rectX, rectY, rectWidth, rectHeight, -startAngle);
                    var endPoint   = Geometry.OvalAngleToPoint(rectX, rectY, rectWidth, rectHeight, -endAngle);

                    if (figure == null)
                    {
                        figure = new PathFigure();
                        geometry.Figures.Add(figure);
                        figure.StartPoint = startPoint.AsPoint();
                    }
                    else
                    {
                        var lineSegment = new LineSegment()
                        {
                            Point = startPoint.AsPoint()
                        };
                        figure.Segments.Add(lineSegment);
                    }

                    var arcSegment = new ArcSegment()
                    {
                        Point          = new Point(endPoint.X, endPoint.Y),
                        Size           = new Size(rectWidth / 2, rectHeight / 2),
                        SweepDirection = clockwise ? SweepDirection.Clockwise : SweepDirection.Counterclockwise,
                        IsLargeArc     = absSweep >= 180,
                    };
                    figure.Segments.Add(arcSegment);
                }
                else if (type == PathOperation.Close)
                {
                    figure.IsClosed = true;
                }
            }

            return(geometry);
        }
예제 #2
0
        public static PathGeometry AsDxPath(this PathF path, float ppu, float ox, float oy, float fx, float fy, Factory factory, FillMode fillMode = FillMode.Winding)
        {
            var geometry = new PathGeometry(factory);

#if DEBUG
            try
            {
#endif

            var sink = geometry.Open();
            sink.SetFillMode(fillMode);

            var ppux = ppu * fx;
            var ppuy = ppu * fy;

            var pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;
            var figureOpen        = false;
            var segmentIndex      = -1;

            var lastOperation = PathOperation.Move;

            foreach (var type in path.SegmentTypes)
            {
                segmentIndex++;

                if (type == PathOperation.Move)
                {
                    if (lastOperation != PathOperation.Close && lastOperation != PathOperation.Move)
                    {
                        sink.EndFigure(FigureEnd.Open);
                        //vPath = vPathGeometry.Open();
                    }

                    var point = path[pointIndex++];

                    /*var vBegin = FigureBegin.Hollow;
                     * if (path.IsSubPathClosed(vSegmentIndex))
                     * {
                     *  vBegin = FigureBegin.Filled;
                     * }*/
                    var begin = FigureBegin.Filled;
                    sink.BeginFigure(ox + point.X * ppux, oy + point.Y * ppuy, begin);
                    figureOpen = true;
                }
                else if (type == PathOperation.Line)
                {
                    var point = path[pointIndex++];
                    sink.LineTo(ox + point.X * ppux, oy + point.Y * ppuy);
                }

                else if (type == PathOperation.Quad)
                {
                    var controlPoint = path[pointIndex++];
                    var endPoint     = path[pointIndex++];

                    sink.QuadTo(
                        ox + controlPoint.X * ppux,
                        oy + controlPoint.Y * ppuy,
                        ox + endPoint.X * ppux,
                        oy + endPoint.Y * ppuy);
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = path[pointIndex++];
                    var controlPoint2 = path[pointIndex++];
                    var endPoint      = path[pointIndex++];
                    sink.CubicTo(
                        ox + controlPoint1.X * ppux,
                        oy + controlPoint1.Y * ppuy,
                        ox + controlPoint2.X * ppux,
                        oy + controlPoint2.Y * ppuy,
                        ox + endPoint.X * ppux,
                        oy + endPoint.Y * ppuy);
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = path[pointIndex++];
                    var bottomRight = path[pointIndex++];
                    var startAngle  = path.GetArcAngle(arcAngleIndex++);
                    var endAngle    = path.GetArcAngle(arcAngleIndex++);
                    var clockwise   = path.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rotation    = Geometry.GetSweep(startAngle, endAngle, clockwise);
                    var absRotation = Math.Abs(rotation);

                    var rectX      = ox + topLeft.X * ppux;
                    var rectY      = oy + topLeft.Y * ppuy;
                    var rectWidth  = (ox + bottomRight.X * ppux) - rectX;
                    var rectHeight = (oy + bottomRight.Y * ppuy) - rectY;

                    var startPoint = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -startAngle);
                    var endPoint   = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -endAngle);


                    if (!figureOpen)
                    {
                        /*var vBegin = FigureBegin.Hollow;
                         * if (path.IsSubPathClosed(vSegmentIndex))
                         * {
                         *  vBegin = FigureBegin.Filled;
                         * }*/
                        var begin = FigureBegin.Filled;
                        sink.BeginFigure(startPoint.X, startPoint.Y, begin);
                        figureOpen = true;
                    }
                    else
                    {
                        sink.LineTo(startPoint.X, startPoint.Y);
                    }

                    var arcSegment = new ArcSegment
                    {
                        Point          = new Vector2(endPoint.X, endPoint.Y),
                        Size           = new Size2F(rectWidth / 2, rectHeight / 2),
                        SweepDirection = clockwise ? SweepDirection.Clockwise : SweepDirection.CounterClockwise,
                        ArcSize        = absRotation >= 180 ? ArcSize.Large : ArcSize.Small
                    };
                    sink.AddArc(arcSegment);
                }
                else if (type == PathOperation.Close)
                {
                    sink.EndFigure(FigureEnd.Closed);
                }

                lastOperation = type;
            }

            if (segmentIndex >= 0 && lastOperation != PathOperation.Close)
            {
                sink.EndFigure(FigureEnd.Open);
            }

            sink.Close();

            return(geometry);

#if DEBUG
        }

        catch (Exception exc)
        {
            geometry.Dispose();

            var definition = path.ToDefinitionString();
            Logger.Debug($"Unable to convert the path to a DXPath: {definition}", exc);
            return(null);
        }
#endif
        }
예제 #3
0
        public static GraphicsPath AsGDIPath(this PathF target, float ppu, float ox, float oy, float fx, float fy)
        {
            var path = new GraphicsPath();

#if DEBUG
            try
            {
#endif

            float ppux = ppu * fx;
            float ppuy = ppu * fy;

            int pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    path.StartFigure();
                    pointIndex++;
                }
                else if (type == PathOperation.Line)
                {
                    var startPoint = target[pointIndex - 1];
                    var endPoint   = target[pointIndex++];
                    path.AddLine(
                        ox + startPoint.X * ppux,
                        oy + startPoint.Y * ppuy,
                        ox + endPoint.X * ppux,
                        oy + endPoint.Y * ppuy);
                }
                else if (type == PathOperation.Quad)
                {
                    var startPoint       = target[pointIndex - 1];
                    var quadControlPoint = target[pointIndex++];
                    var endPoint         = target[pointIndex++];

                    var cubicControlPoint1X = startPoint.X + 2.0f * (quadControlPoint.X - startPoint.X) / 3.0f;
                    var cubicControlPoint1Y = startPoint.Y + 2.0f * (quadControlPoint.Y - startPoint.Y) / 3.0f;

                    var cubicControlPoint2X = endPoint.X + 2.0f * (quadControlPoint.X - endPoint.X) / 3.0f;
                    var cubicControlPoint2Y = endPoint.Y + 2.0f * (quadControlPoint.Y - endPoint.Y) / 3.0f;

                    path.AddBezier(
                        ox + startPoint.X * ppux,
                        oy + startPoint.Y * ppuy,
                        ox + cubicControlPoint1X * ppux,
                        oy + cubicControlPoint1Y * ppuy,
                        ox + cubicControlPoint2X * ppux,
                        oy + cubicControlPoint2Y * ppuy,
                        ox + endPoint.X * ppux,
                        oy + endPoint.Y * ppuy);
                }
                else if (type == PathOperation.Cubic)
                {
                    var startPoint         = target[pointIndex - 1];
                    var cubicControlPoint1 = target[pointIndex++];
                    var cubicControlPoint2 = target[pointIndex++];
                    var endPoint           = target[pointIndex++];

                    path.AddBezier(
                        ox + startPoint.X * ppux,
                        oy + startPoint.Y * ppuy,
                        ox + cubicControlPoint1.X * ppux,
                        oy + cubicControlPoint1.Y * ppuy,
                        ox + cubicControlPoint2.X * ppux,
                        oy + cubicControlPoint2.Y * ppuy,
                        ox + endPoint.X * ppux,
                        oy + endPoint.Y * ppuy);
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = target[pointIndex++];
                    var bottomRight = target[pointIndex++];
                    var startAngle  = target.GetArcAngle(arcAngleIndex++);
                    var endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var x      = ox + topLeft.X * ppux;
                    var y      = oy + topLeft.Y * ppuy;
                    var width  = (bottomRight.X - topLeft.X) * ppux;
                    var height = (bottomRight.Y - topLeft.Y) * ppuy;

                    float sweep = Geometry.GetSweep(startAngle, endAngle, clockwise);
                    if (!clockwise)
                    {
                        startAngle = endAngle;
                    }

                    startAngle *= -1;

                    path.AddArc(x, y, width, height, startAngle, sweep);
                }
                else if (type == PathOperation.Close)
                {
                    path.CloseFigure();
                }
            }

            return(path);

#if DEBUG
        }

        catch (Exception exc)
        {
            path.Dispose();

            var definition = target.ToDefinitionString();
            Logger.Debug(string.Format("Unable to convert the path to a GDIPath: {0}", definition), exc);
            return(null);
        }
#endif
        }
예제 #4
0
        public static CanvasGeometry AsPath(this PathF path, float ox, float oy, float fx, float fy, ICanvasResourceCreator creator, CanvasFilledRegionDetermination fillMode = CanvasFilledRegionDetermination.Winding)
        {
            var builder = new CanvasPathBuilder(creator);

#if DEBUG
            try
            {
#endif
            builder.SetFilledRegionDetermination(fillMode);

            var pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;
            var figureOpen        = false;
            var segmentIndex      = -1;

            var lastOperation = PathOperation.Move;

            foreach (var type in path.SegmentTypes)
            {
                segmentIndex++;

                if (type == PathOperation.Move)
                {
                    if (lastOperation != PathOperation.Close && lastOperation != PathOperation.Move)
                    {
                        builder.EndFigure(CanvasFigureLoop.Open);
                    }

                    var point = path[pointIndex++];
                    var begin = CanvasFigureFill.Default;
                    builder.BeginFigure(ox + point.X * fx, oy + point.Y * fy, begin);
                    figureOpen = true;
                }
                else if (type == PathOperation.Line)
                {
                    var point = path[pointIndex++];
                    builder.AddLine(ox + point.X * fx, oy + point.Y * fy);
                }

                else if (type == PathOperation.Quad)
                {
                    var controlPoint = path[pointIndex++];
                    var endPoint     = path[pointIndex++];

                    builder.AddQuadraticBezier(
                        new Vector2(ox + controlPoint.X * fx, oy + controlPoint.Y * fy),
                        new Vector2(ox + endPoint.X * fx, oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = path[pointIndex++];
                    var controlPoint2 = path[pointIndex++];
                    var endPoint      = path[pointIndex++];
                    builder.AddCubicBezier(
                        new Vector2(ox + controlPoint1.X * fx, oy + controlPoint1.Y * fy),
                        new Vector2(ox + controlPoint2.X * fx, oy + controlPoint2.Y * fy),
                        new Vector2(ox + endPoint.X * fx, oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = path[pointIndex++];
                    var bottomRight = path[pointIndex++];
                    var startAngle  = path.GetArcAngle(arcAngleIndex++);
                    var endAngle    = path.GetArcAngle(arcAngleIndex++);
                    var clockwise   = path.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rotation    = Geometry.GetSweep(startAngle, endAngle, clockwise);
                    var absRotation = Math.Abs(rotation);

                    var rectX      = ox + topLeft.X * fx;
                    var rectY      = oy + topLeft.Y * fy;
                    var rectWidth  = (ox + bottomRight.X * fx) - rectX;
                    var rectHeight = (oy + bottomRight.Y * fy) - rectY;

                    var startPoint = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -startAngle);
                    var endPoint   = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -endAngle);


                    if (!figureOpen)
                    {
                        var begin = CanvasFigureFill.Default;
                        builder.BeginFigure(startPoint.X, startPoint.Y, begin);
                        figureOpen = true;
                    }
                    else
                    {
                        builder.AddLine(startPoint.X, startPoint.Y);
                    }

                    builder.AddArc(
                        new Vector2(endPoint.X, endPoint.Y),
                        rectWidth / 2,
                        rectHeight / 2,
                        0,
                        clockwise ? CanvasSweepDirection.Clockwise : CanvasSweepDirection.CounterClockwise,
                        absRotation >= 180 ? CanvasArcSize.Large : CanvasArcSize.Small
                        );
                }
                else if (type == PathOperation.Close)
                {
                    builder.EndFigure(CanvasFigureLoop.Closed);
                }

                lastOperation = type;
            }

            if (segmentIndex >= 0 && lastOperation != PathOperation.Close)
            {
                builder.EndFigure(CanvasFigureLoop.Open);
            }

            var geometry = CanvasGeometry.CreatePath(builder);
            return(geometry);

#if DEBUG
        }

        catch (Exception exc)
        {
            builder.Dispose();

            var definition = path.ToDefinitionString();
            Logger.Debug(string.Format("Unable to convert the path to a Win2D Path: {0}", definition), exc);
            return(null);
        }
#endif
        }
예제 #5
0
        public static CGPath ToCGPath(
            this PathF target)
        {
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var operation in target.PathOperations)
            {
                if (operation == PathOperation.MoveTo)
                {
                    var point = target[pointIndex++];
                    path.MoveToPoint(point.X, point.Y);
                }
                else if (operation == PathOperation.Line)
                {
                    var endPoint = target[pointIndex++];
                    path.AddLineToPoint(endPoint.X, endPoint.Y);
                }

                else if (operation == PathOperation.Quad)
                {
                    var controlPoint = target[pointIndex++];
                    var endPoint     = target[pointIndex++];
                    path.AddQuadCurveToPoint(
                        controlPoint.X,
                        controlPoint.Y,
                        endPoint.X,
                        endPoint.Y);
                }
                else if (operation == PathOperation.Cubic)
                {
                    var controlPoint1 = target[pointIndex++];
                    var controlPoint2 = target[pointIndex++];
                    var endPoint      = target[pointIndex++];
                    path.AddCurveToPoint(
                        controlPoint1.X,
                        controlPoint1.Y,
                        controlPoint2.X,
                        controlPoint2.Y,
                        endPoint.X,
                        endPoint.Y);
                }
                else if (operation == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.IsArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = GraphicsOperations.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = GraphicsOperations.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var transform = CGAffineTransform.MakeTranslation(cx, cy);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (operation == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
예제 #6
0
        public static SKPath AsRotatedAndroidPath(this PathF target, PointF center, float ppu, float zoom, float angle)
        {
            ppu = zoom * ppu;

            var path = new SKPath();

            var pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.MoveTo(point.X * ppu, point.Y * ppu);
                }
                else if (type == PathOperation.Line)
                {
                    var endPoint = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.LineTo(endPoint.X * ppu, endPoint.Y * ppu);
                }
                else if (type == PathOperation.Quad)
                {
                    var controlPoint1 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint      = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.QuadTo(
                        controlPoint1.X * ppu,
                        controlPoint1.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var controlPoint2 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint      = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.CubicTo(
                        controlPoint1.X * ppu,
                        controlPoint1.Y * ppu,
                        controlPoint2.X * ppu,
                        controlPoint2.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = target[pointIndex++];
                    var bottomRight = target[pointIndex++];
                    var startAngle  = target.GetArcAngle(arcAngleIndex++);
                    var endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rect  = new SKRect(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
                    var sweep = Geometry.GetSweep(startAngle, endAngle, clockwise);

                    startAngle *= -1;
                    if (!clockwise)
                    {
                        sweep *= -1;
                    }

                    path.AddArc(rect, startAngle, sweep);
                }
                else if (type == PathOperation.Close)
                {
                    path.Close();
                }
            }

            return(path);
        }
예제 #7
0
        public static CanvasGeometry AsPathFromSegment(this PathF path, int segmentIndex, float zoom, ICanvasResourceCreator creator)
        {
            float scale = 1 / zoom;

            var builder = new CanvasPathBuilder(creator);

            var type = path.GetSegmentType(segmentIndex);

            if (type == PathOperation.Line)
            {
                int segmentStartingPointIndex = path.GetSegmentPointIndex(segmentIndex);
                var startPoint = path[segmentStartingPointIndex - 1];
                builder.BeginFigure(startPoint.X * scale, startPoint.Y * scale, CanvasFigureFill.Default);

                var point = path[segmentStartingPointIndex];
                builder.AddLine(point.X * scale, point.Y * scale);
            }
            else if (type == PathOperation.Quad)
            {
                int segmentStartingPointIndex = path.GetSegmentPointIndex(segmentIndex);
                var startPoint = path[segmentStartingPointIndex - 1];
                builder.BeginFigure(startPoint.X * scale, startPoint.Y * scale, CanvasFigureFill.Default);

                var controlPoint = path[segmentStartingPointIndex++];
                var endPoint     = path[segmentStartingPointIndex];
                builder.AddQuadraticBezier(
                    new Vector2(controlPoint.X * scale, controlPoint.Y * scale),
                    new Vector2(endPoint.X * scale, endPoint.Y * scale));
            }
            else if (type == PathOperation.Cubic)
            {
                int segmentStartingPointIndex = path.GetSegmentPointIndex(segmentIndex);
                var startPoint = path[segmentStartingPointIndex - 1];
                builder.BeginFigure(startPoint.X * scale, startPoint.Y * scale, CanvasFigureFill.Default);

                var controlPoint1 = path[segmentStartingPointIndex++];
                var controlPoint2 = path[segmentStartingPointIndex++];
                var endPoint      = path[segmentStartingPointIndex];
                builder.AddCubicBezier(
                    new Vector2(controlPoint1.X * scale, controlPoint1.Y * scale),
                    new Vector2(controlPoint2.X * scale, controlPoint2.Y * scale),
                    new Vector2(endPoint.X * scale, endPoint.Y * scale));
            }
            else if (type == PathOperation.Arc)
            {
                path.GetSegmentInfo(segmentIndex, out var pointIndex, out var arcAngleIndex, out var arcClockwiseIndex);

                var topLeft     = path[pointIndex++];
                var bottomRight = path[pointIndex];
                var startAngle  = path.GetArcAngle(arcAngleIndex++);
                var endAngle    = path.GetArcAngle(arcAngleIndex);
                var clockwise   = path.GetArcClockwise(arcClockwiseIndex);

                while (startAngle < 0)
                {
                    startAngle += 360;
                }

                while (endAngle < 0)
                {
                    endAngle += 360;
                }

                var rotation    = Geometry.GetSweep(startAngle, endAngle, clockwise);
                var absRotation = Math.Abs(rotation);

                var rectX      = topLeft.X * scale;
                var rectY      = topLeft.Y * scale;
                var rectWidth  = (bottomRight.X * scale) - rectX;
                var rectHeight = (bottomRight.Y * scale) - rectY;

                var startPoint = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -startAngle);
                var endPoint   = Geometry.EllipseAngleToPoint(rectX, rectY, rectWidth, rectHeight, -endAngle);

                builder.BeginFigure(startPoint.X * scale, startPoint.Y * scale, CanvasFigureFill.Default);

                builder.AddArc(
                    new Vector2(endPoint.X, endPoint.Y),
                    rectWidth / 2,
                    rectHeight / 2,
                    0,
                    clockwise ? CanvasSweepDirection.Clockwise : CanvasSweepDirection.CounterClockwise,
                    absRotation >= 180 ? CanvasArcSize.Large : CanvasArcSize.Small
                    );
            }

            builder.EndFigure(CanvasFigureLoop.Open);

            return(CanvasGeometry.CreatePath(builder));
        }
예제 #8
0
        public static SKPath AsSkiaPath(
            this PathF path,
            float ppu,
            float ox,
            float oy,
            float fx,
            float fy)
        {
            var nativePath = new SKPath();

            var ppux = ppu * fx;
            var ppuy = ppu * fy;

            var pointIndex        = 0;
            var arcAngleIndex     = 0;
            var arcClockwiseIndex = 0;

            foreach (var type in path.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = path[pointIndex++];
                    nativePath.MoveTo((ox + point.X * ppux), (oy + point.Y * ppuy));
                }
                else if (type == PathOperation.Line)
                {
                    var point = path[pointIndex++];
                    nativePath.LineTo((ox + point.X * ppux), (oy + point.Y * ppuy));
                }

                else if (type == PathOperation.Quad)
                {
                    var controlPoint = path[pointIndex++];
                    var point        = path[pointIndex++];
                    nativePath.QuadTo((ox + controlPoint.X * ppux), (oy + controlPoint.Y * ppuy), (ox + point.X * ppux), (oy + point.Y * ppuy));
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = path[pointIndex++];
                    var controlPoint2 = path[pointIndex++];
                    var point         = path[pointIndex++];
                    nativePath.CubicTo((ox + controlPoint1.X * ppux), (oy + controlPoint1.Y * ppuy), (ox + controlPoint2.X * ppux), (oy + controlPoint2.Y * ppuy), (ox + point.X * ppux),
                                       (oy + point.Y * ppuy));
                }
                else if (type == PathOperation.Arc)
                {
                    var topLeft     = path[pointIndex++];
                    var bottomRight = path[pointIndex++];
                    var startAngle  = path.GetArcAngle(arcAngleIndex++);
                    var endAngle    = path.GetArcAngle(arcAngleIndex++);
                    var clockwise   = path.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rect  = new SKRect(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
                    var sweep = Geometry.GetSweep(startAngle, endAngle, clockwise);

                    startAngle *= -1;
                    if (!clockwise)
                    {
                        sweep *= -1;
                    }

                    nativePath.AddArc(rect, startAngle, sweep);
                }
                else if (type == PathOperation.Close)
                {
                    nativePath.Close();
                }
            }

            return(nativePath);
        }
예제 #9
0
        public static SKPath AsSkiaPathFromSegment(this PathF target, int segmentIndex, float ppu, float zoom)
        {
            ppu = zoom * ppu;

            var path = new SKPath();

            var type = target.GetSegmentType(segmentIndex);

            if (type == PathOperation.Line)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveTo(startPoint.X * ppu, startPoint.Y * ppu);

                var endPoint = target[pointIndex];
                path.LineTo(endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Quad)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveTo(startPoint.X * ppu, startPoint.Y * ppu);

                var controlPoint = target[pointIndex++];
                var endPoint     = target[pointIndex];
                path.QuadTo(controlPoint.X * ppu, controlPoint.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Cubic)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveTo(startPoint.X * ppu, startPoint.Y * ppu);

                var controlPoint1 = target[pointIndex++];
                var controlPoint2 = target[pointIndex++];
                var endPoint      = target[pointIndex];
                path.CubicTo(controlPoint1.X * ppu, controlPoint1.Y * ppu, controlPoint2.X * ppu, controlPoint2.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Arc)
            {
                target.GetSegmentInfo(segmentIndex, out var pointIndex, out var arcAngleIndex, out var arcClockwiseIndex);

                var topLeft     = target[pointIndex++];
                var bottomRight = target[pointIndex];
                var startAngle  = target.GetArcAngle(arcAngleIndex++);
                var endAngle    = target.GetArcAngle(arcAngleIndex);
                var clockwise   = target.GetArcClockwise(arcClockwiseIndex);

                while (startAngle < 0)
                {
                    startAngle += 360;
                }

                while (endAngle < 0)
                {
                    endAngle += 360;
                }

                var rect  = new SKRect(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
                var sweep = Geometry.GetSweep(startAngle, endAngle, clockwise);

                startAngle *= -1;
                if (!clockwise)
                {
                    sweep *= -1;
                }

                path.AddArc(rect, startAngle, sweep);
            }

            return(path);
        }
예제 #10
0
        public static APath AsAndroidPath(this PathF path)
        {
            var nativePath = new APath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var operation in path.PathOperations)
            {
                if (operation == PathOperation.MoveTo)
                {
                    var point = path[pointIndex++];
                    nativePath.MoveTo(point.X, point.Y);
                }
                else if (operation == PathOperation.Line)
                {
                    var point = path[pointIndex++];
                    nativePath.LineTo(point.X, point.Y);
                }

                else if (operation == PathOperation.Quad)
                {
                    var controlPoint = path[pointIndex++];
                    var point        = path[pointIndex++];
                    nativePath.QuadTo(controlPoint.X, controlPoint.Y, point.X, point.Y);
                }
                else if (operation == PathOperation.Cubic)
                {
                    var controlPoint1 = path[pointIndex++];
                    var controlPoint2 = path[pointIndex++];
                    var point         = path[pointIndex++];
                    nativePath.CubicTo(controlPoint1.X, controlPoint1.Y, controlPoint2.X, controlPoint2.Y, point.X,
                                       point.Y);
                }
                else if (operation == PathOperation.Arc)
                {
                    var topLeft     = path[pointIndex++];
                    var bottomRight = path[pointIndex++];
                    var startAngle  = path.GetArcAngle(arcAngleIndex++);
                    var endAngle    = path.GetArcAngle(arcAngleIndex++);
                    var clockwise   = path.IsArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rect  = new RectF(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
                    var sweep = GraphicsOperations.GetSweep(startAngle, endAngle, clockwise);

                    startAngle *= -1;
                    if (!clockwise)
                    {
                        sweep *= -1;
                    }

                    nativePath.ArcTo(rect, startAngle, sweep);
                }
                else if (operation == PathOperation.Close)
                {
                    nativePath.Close();
                }
            }

            return(nativePath);
        }
예제 #11
0
        public static Path AsAndroidPath(
            this PathF path,
            float offsetX = 0,
            float offsetY = 0,
            float scaleX  = 1,
            float scaleY  = 1)
        {
            var nativePath = new Path();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (PathOperation vType in path.SegmentTypes)
            {
                if (vType == PathOperation.Move)
                {
                    var point = path[pointIndex++];
                    nativePath.MoveTo(offsetX + point.X * scaleX, offsetY + point.Y * scaleY);
                }
                else if (vType == PathOperation.Line)
                {
                    var point = path[pointIndex++];
                    nativePath.LineTo(offsetX + point.X * scaleX, offsetY + point.Y * scaleY);
                }

                else if (vType == PathOperation.Quad)
                {
                    var controlPoint = path[pointIndex++];
                    var point        = path[pointIndex++];
                    nativePath.QuadTo(offsetX + controlPoint.X * scaleX, offsetY + controlPoint.Y * scaleY, offsetX + point.X * scaleX, offsetY + point.Y * scaleY);
                }
                else if (vType == PathOperation.Cubic)
                {
                    var controlPoint1 = path[pointIndex++];
                    var controlPoint2 = path[pointIndex++];
                    var point         = path[pointIndex++];
                    nativePath.CubicTo(offsetX + controlPoint1.X * scaleX, offsetY + controlPoint1.Y * scaleY, offsetX + controlPoint2.X * scaleX, offsetY + controlPoint2.Y * scaleY, offsetX + point.X * scaleX,
                                       offsetY + point.Y * scaleY);
                }
                else if (vType == PathOperation.Arc)
                {
                    var topLeft     = path[pointIndex++];
                    var bottomRight = path[pointIndex++];
                    var startAngle  = path.GetArcAngle(arcAngleIndex++);
                    var endAngle    = path.GetArcAngle(arcAngleIndex++);
                    var clockwise   = path.GetArcClockwise(arcClockwiseIndex++);

                    while (startAngle < 0)
                    {
                        startAngle += 360;
                    }

                    while (endAngle < 0)
                    {
                        endAngle += 360;
                    }

                    var rect  = new RectF(offsetX + topLeft.X * scaleX, offsetY + topLeft.Y * scaleY, offsetX + bottomRight.X * scaleX, offsetY + bottomRight.Y * scaleY);
                    var sweep = Geometry.GetSweep(startAngle, endAngle, clockwise);

                    startAngle *= -1;
                    if (!clockwise)
                    {
                        sweep *= -1;
                    }

                    nativePath.ArcTo(rect, startAngle, sweep);
                }
                else if (vType == PathOperation.Close)
                {
                    nativePath.Close();
                }
            }

            return(nativePath);
        }
예제 #12
0
        public static CGPath AsCGPath(
            this PathF target,
            float ox,
            float oy,
            float fx,
            float fy)
        {
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = target[pointIndex++];
                    path.MoveToPoint((ox + point.X * fx), (oy + point.Y * fy));
                }
                else if (type == PathOperation.Line)
                {
                    var endPoint = target[pointIndex++];
                    path.AddLineToPoint((ox + endPoint.X * fx), (oy + endPoint.Y * fy));
                }

                else if (type == PathOperation.Quad)
                {
                    var controlPoint = target[pointIndex++];
                    var endPoint     = target[pointIndex++];
                    path.AddQuadCurveToPoint(
                        (ox + controlPoint.X * fx),
                        (oy + controlPoint.Y * fy),
                        (ox + endPoint.X * fx),
                        (oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = target[pointIndex++];
                    var controlPoint2 = target[pointIndex++];
                    var endPoint      = target[pointIndex++];
                    path.AddCurveToPoint(
                        (ox + controlPoint1.X * fx),
                        (oy + controlPoint1.Y * fy),
                        (ox + controlPoint2.X * fx),
                        (oy + controlPoint2.Y * fy),
                        (ox + endPoint.X * fx),
                        (oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var transform = CGAffineTransform.MakeTranslation(ox + cx, oy + cy);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r * fx, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (type == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
예제 #13
0
        public static CGPath AsRotatedCGPath(this PathF target, PointF center, float ppu, float zoom, float angle)
        {
            ppu = ppu * zoom;
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.MoveToPoint(point.X * ppu, point.Y * ppu);
                }
                else if (type == PathOperation.Line)
                {
                    var endPoint = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddLineToPoint(endPoint.X * ppu, endPoint.Y * ppu);
                }
                else if (type == PathOperation.Quad)
                {
                    var controlPoint = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint     = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddQuadCurveToPoint(
                        controlPoint.X * ppu,
                        controlPoint.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var controlPoint2 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint      = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddCurveToPoint(
                        controlPoint1.X * ppu,
                        controlPoint1.Y * ppu,
                        controlPoint2.X * ppu,
                        controlPoint2.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var rotatedCenter = Geometry.RotatePoint(center, new PointF(cx, cy), angle);

                    var transform = CGAffineTransform.MakeTranslation(rotatedCenter.X * ppu, rotatedCenter.Y * ppu);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r * ppu, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (type == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
예제 #14
0
        public static CGPath AsCGPathFromSegment(
            this PathF target,
            int segmentIndex,
            float ppu,
            float zoom)
        {
            ppu = ppu * zoom;
            var path = new CGPath();

            var type = target.GetSegmentType(segmentIndex);

            if (type == PathOperation.Line)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var endPoint = target[pointIndex];
                path.AddLineToPoint(endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Quad)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var controlPoint = target[pointIndex++];
                var endPoint     = target[pointIndex];
                path.AddQuadCurveToPoint(controlPoint.X * ppu, controlPoint.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Cubic)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var controlPoint1 = target[pointIndex++];
                var controlPoint2 = target[pointIndex++];
                var endPoint      = target[pointIndex];
                path.AddCurveToPoint(controlPoint1.X * ppu, controlPoint1.Y * ppu, controlPoint2.X * ppu, controlPoint2.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Arc)
            {
                target.GetSegmentInfo(segmentIndex, out var pointIndex, out var arcAngleIndex, out var arcClockwiseIndex);

                var topLeft     = target[pointIndex++];
                var bottomRight = target[pointIndex++];
                var startAngle  = target.GetArcAngle(arcAngleIndex++);
                var endAngle    = target.GetArcAngle(arcAngleIndex++);
                var clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                while (startAngleInRadians < 0)
                {
                    startAngleInRadians += (float)Math.PI * 2;
                }

                while (endAngleInRadians < 0)
                {
                    endAngleInRadians += (float)Math.PI * 2;
                }

                var cx     = (bottomRight.X + topLeft.X) / 2;
                var cy     = (bottomRight.Y + topLeft.Y) / 2;
                var width  = bottomRight.X - topLeft.X;
                var height = bottomRight.Y - topLeft.Y;
                var r      = width / 2;

                var transform = CGAffineTransform.MakeTranslation(cx * ppu, cy * ppu);
                transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                path.AddArc(transform, 0, 0, r * ppu, startAngleInRadians, endAngleInRadians, !clockwise);
            }

            return(path);
        }