{{ message }}

Instantly share code, notes, and snippets.

# sheerazam/ArcUtils.java

Created Oct 6, 2016
Fresco Circular Progress Drawable

*

* Note that this does not split the arc to better approximate it, for that see either: *

*
• {@link #createBezierArcDegrees(android.graphics.PointF, float, float, float, int, boolean, * android.graphics.Path)}
• *
• *
*

*

* For a technical explanation: * * http://hansmuller-flex.blogspot.de/2011/10/more-about-approximating-circular-arcs.html * * * @param path The path to add the arc to. * @param center The center of the circle. * @param start The starting point of the arc on the circle. * @param end The ending point of the arc on the circle. * @param moveToStart If {@code true}, move to the starting point of the arc * (see: {@link android.graphics.Path#moveTo(float, float)}). * * @see #createBezierArcDegrees(android.graphics.PointF, float, float, float, int, boolean, android.graphics.Path) * @see #createBezierArcRadians(android.graphics.PointF, float, double, double, int, boolean, android.graphics.Path) */ public static void addBezierArcToPath(@NotNull Path path, @NotNull PointF center, @NotNull PointF start, @NotNull PointF end, boolean moveToStart) { if (moveToStart) { path.moveTo(start.x, start.y); } if (start.equals(end)) { return; } final double ax = start.x - center.x; final double ay = start.y - center.y; final double bx = end.x - center.x; final double by = end.y - center.y; final double q1 = ax * ax + ay * ay; final double q2 = q1 + ax * bx + ay * by; final double k2 = 4d / 3d * (sqrt(2d * q1 * q2) - q2) / (ax * by - ay * bx); final float x2 = (float)(center.x + ax - k2 * ay); final float y2 = (float)(center.y + ay + k2 * ax); final float x3 = (float)(center.x + bx + k2 * by); final float y3 = (float)(center.y + by - k2 * bx); path.cubicTo(x2, y2, x3, y3, end.x, end.y); } /** * Adds a circular arc to the given path by approximating it through a cubic Bézier curve, splitting it if * necessary. The precision of the approximation can be adjusted through {@code pointsOnCircle} and * {@code overlapPoints} parameters. *

* Example: imagine an arc starting from 0° and sweeping 100° with a value of * {@code pointsOnCircle} equal to 12 (threshold -> 360° / 12 = 30°): *

*
• if {@code overlapPoints} is {@code true}, it will be split as following: *
*
• from 0° to 30° (sweep 30°)
• *
• from 30° to 60° (sweep 30°)
• *
• from 60° to 90° (sweep 30°)
• *
• from 90° to 100° (sweep 10°)
• *
*
• *
• if {@code overlapPoints} is {@code false}, it will be split into 4 equal arcs: *
*
• from 0° to 25° (sweep 25°)
• *
• from 25° to 50° (sweep 25°)
• *
• from 50° to 75° (sweep 25°)
• *
• from 75° to 100° (sweep 25°)
• *
*
• *
*

*

* For a technical explanation: * * http://hansmuller-flex.blogspot.de/2011/10/more-about-approximating-circular-arcs.html * * * @param center The center of the circle. * @param radius The radius of the circle. * @param startAngleRadians The starting angle on the circle (in radians). * @param sweepAngleRadians How long to make the total arc (in radians). * @param pointsOnCircle Defines a threshold (360° /{@code pointsOnCircle}) to split the Bézier arc to * better approximate a circular arc, depending also on the value of {@code overlapPoints}. * The suggested number to have a reasonable approximation of a circle is at least 4 (90°). * Less than 1 will be ignored (the arc will not be split). * @param overlapPoints Given the threshold defined through {@code pointsOnCircle}: *

*
• if {@code true}, split the arc on every angle which is a multiple of the * threshold (yields better results if drawing precision is required, * especially when stacking multiple arcs, but can potentially use more points)
• *
• if {@code false}, split the arc equally so that each part is shorter than * the threshold
• *

* Example: imagine an arc starting from 0° and sweeping 100° with a value of * {@code pointsOnCircle} equal to 12 (threshold -> 360° / 12 = 30°): *

*
• if {@code overlapPoints} is {@code true}, it will be split as following: *
*
• from 0° to 30° (sweep 30°)
• *
• from 30° to 60° (sweep 30°)
• *
• from 60° to 90° (sweep 30°)
• *
• from 90° to 100° (sweep 10°)
• *
*
• *
• if {@code overlapPoints} is {@code false}, it will be split into 4 equal arcs: *
*
• from 0° to 25° (sweep 25°)
• *
• from 25° to 50° (sweep 25°)
• *
• from 50° to 75° (sweep 25°)
• *
• from 75° to 100° (sweep 25°)
• *
*
• *
*

*

* For a technical explanation: * * http://hansmuller-flex.blogspot.de/2011/10/more-about-approximating-circular-arcs.html * * * @param center The center of the circle. * @param radius The radius of the circle. * @param startAngleDegrees The starting angle on the circle (in degrees). * @param sweepAngleDegrees How long to make the total arc (in degrees). * @param pointsOnCircle Defines a threshold (360° /{@code pointsOnCircle}) to split the Bézier arc to * better approximate a circular arc, depending also on the value of {@code overlapPoints}. * The suggested number to have a reasonable approximation of a circle is at least 4 (90°). * Less than 1 will ignored (the arc will not be split). * @param overlapPoints Given the threshold defined through {@code pointsOnCircle}: *

*
• if {@code true}, split the arc on every angle which is a multiple of the * threshold (yields better results if drawing precision is required, * especially when stacking multiple arcs, but can potentially use more points)
• *
• if {@code false}, split the arc equally so that each part is shorter than * the threshold
• *