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