예제 #1
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);
        }
예제 #2
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));
        }
예제 #3
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);
        }