walkContour method

List<Offset> walkContour([
  1. double sampling = 1.0,
  2. double? tolerance
])

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