-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
The length of a circle as reported by the length property of dart:ui's PathMetric class deviates from the circle length calculated by the standard circle circumference formula c = 2 * pi * r
Steps to Reproduce
- Create a new Flutter dartpad
- Copy the code sample below and paste it into the dartpad
- Run the example.
Expected results:
I expected that the two lengths would (almost) equal each other.
Actual results:
As printed by the example code, there is a deviation between the two length calculations. From length calculations with 1000 different radii ranging from 1 to 1000, I find the mean deviation to be ~0.56 and the max deviation to be ~1.25.
I am not sure if this is a bug or not. If it is expected I am hoping that the reason can be explained and possibly added to the documentation. The documentation for path metric length currently reads:
Return the total length of the current contour.
Code sample
import 'dart:ui';
import 'dart:math';
void main() {
double maxCircleLengthDeviation = 0.0;
double maxDeviationRadius = 1.0;
double deviationSum = 0.0;
const int iterations = 1000;
for (int i = 1; i <= iterations; i++) {
final double radius = i.toDouble();
final Path circle = Path()
..addArc(Rect.fromCircle(center: const Offset(10, 10), radius: radius),
0.0, 2 * pi);
final double circlePathLength = getSingleContourPathLength(circle);
final double standardCircleLength = pi * 2 * radius;
final deviation = (circlePathLength - standardCircleLength).abs();
deviationSum += deviation;
if (deviation > maxCircleLengthDeviation) {
maxCircleLengthDeviation = deviation;
maxDeviationRadius = radius;
}
}
print('max circle length deviation: $maxCircleLengthDeviation at radius $maxDeviationRadius');
final double circleLengthMeanDeviation = deviationSum / iterations;
print('mean deviation: $circleLengthMeanDeviation');
}
double getSingleContourPathLength(Path path) {
final metrics = path.computeMetrics().toList();
if (metrics.length != 1) {
throw ArgumentError('path must have exactly one contour');
}
return metrics.fold(0.0,
(double tmpLength, PathMetric contour) => tmpLength + contour.length);
}
I have run the example on all channels available for dartpad. The output was consistent across all channels.
- Stable channel: Flutter 3.0.5 Dart SDK 2.17.6
- Beta channel: Flutter 3.1.0 Dart SDK 2.18.0-44.1.beta
- Old channel: Flutter 2.10.5 Dart SDK 2.16.2