walkContour method
Walk a single contour of a Path and return it as an Offset list.
The sampling is the sampling step along the contour: higher values
produce fewer samples. It only limits how finely curves are followed,
since straight stretches are skipped over and the corners between them
are located exactly.
The samples that are not needed to stay within tolerance of the sampled
contour are removed, while the corners and the points where the contour
reaches its bounds are always kept, so that the result has the size of
the contour. The tolerance defaults to half of the sampling, and
the samples themselves are taken so that the contour stays within a sixth
of it. A tolerance of zero keeps every sample.
A closed contour gives at least three vertices whatever the
sampling and the tolerance are, so that it can always be a
polygon.
Implementation
List<Offset> walkContour([double sampling = 1.0, double? tolerance]) {
assert(
sampling.isFinite && sampling > 0,
'The sampling has to be a positive number: $sampling',
);
assert(
tolerance == null || (tolerance.isFinite && tolerance >= 0),
'The tolerance can not be negative: $tolerance',
);
if (length <= 0) {
return [];
}
final validSampling = sampling.isFinite && sampling > 0 ? sampling : 1.0;
// A closed contour is sampled in at least three steps, so that it can be a
// polygon no matter how coarse the sampling is.
final step = isClosed
? min(max(validSampling, length / _maxSteps), length / 3)
: max(validSampling, length / _maxSteps);
final maxDeviation = tolerance ?? step / 2;
final sampler = _ContourSampler(this, step, maxDeviation / 6)..sample();
final points = _simplify(
sampler.points,
sampler.anchors,
closed: sampler.isClosed,
tolerance: maxDeviation,
);
if (sampler.isClosed && points.length < 3 && sampler.points.length >= 3) {
return _spread(sampler.points, 3);
}
return points;
}