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); }
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)); }
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); }