getStrokeOutlinePoints function

List<Vec> getStrokeOutlinePoints(
  1. List<StrokePoint> strokePoints, [
  2. StrokeOptions? options
])

Implementation

List<Vec> getStrokeOutlinePoints(
  List<StrokePoint> strokePoints, [
  StrokeOptions? options,
]) {
  options ??= StrokeOptions();
  final double size = options.size;
  final TaperOptions start = options.start;
  final TaperOptions end = options.end;
  final bool isComplete = options.last;

  final bool capStart = start.cap ?? true;
  final bool capEnd = end.cap ?? true;

  if (strokePoints.isEmpty || size <= 0) {
    return [];
  }

  final StrokePoint firstStrokePoint = strokePoints[0];
  final StrokePoint lastStrokePoint = strokePoints[strokePoints.length - 1];

  final double totalLength = lastStrokePoint.runningLength;

  final double taperStart =
      start.taper == null || start.taper == false
          ? 0
          : start.taper == true
          ? max(size, totalLength)
          : (start.taper as double);

  final double taperEnd =
      end.taper == null || end.taper == false
          ? 0
          : end.taper == true
          ? max(size, totalLength)
          : (end.taper as double);

  final Map<String, List<Vec>> tracks = getStrokeOutlineTracks(
    strokePoints,
    options,
  );
  final List<Vec> leftPts = tracks['left']!;
  final List<Vec> rightPts = tracks['right']!;

  final Vec firstPoint = firstStrokePoint.point;

  final Vec lastPoint =
      strokePoints.length > 1
          ? strokePoints[strokePoints.length - 1].point
          : Vec.addXY(firstStrokePoint.point, 1, 1);

  if (strokePoints.length == 1) {
    if (!(taperStart > 0 || taperEnd > 0) || isComplete) {
      final Vec start = Vec.addVec(
        firstPoint,
        Vec.subVec(
          firstPoint,
          lastPoint,
        ).uni().per().mul(-firstStrokePoint.radius),
      );

      final List<Vec> dotPts = [];
      for (double step = 1 / 13, t = step; t <= 1; t += step) {
        dotPts.add(Vec.rotWithVec(start, firstPoint, fixedPi * 2 * t));
      }
      return dotPts;
    }
  }

  final List<Vec> startCap = [];
  if (taperStart > 0 || (taperEnd > 0 && strokePoints.length == 1)) {
  } else if (capStart) {
    for (double step = 1 / 8, t = step; t <= 1; t += step) {
      final Vec pt = Vec.rotWithVec(rightPts[0], firstPoint, fixedPi * t);
      startCap.add(pt);
    }
  } else {
    final Vec cornersVector = Vec.subVec(leftPts[0], rightPts[0]);
    final Vec offsetA = Vec.mulVec(cornersVector, 0.5);
    final Vec offsetB = Vec.mulVec(cornersVector, 0.51);

    startCap.addAll([
      Vec.subVec(firstPoint, offsetA),
      Vec.subVec(firstPoint, offsetB),
      Vec.addVec(firstPoint, offsetB),
      Vec.addVec(firstPoint, offsetA),
    ]);
  }

  final List<Vec> endCap = [];
  final Vec direction = lastStrokePoint.vector.clone().per().neg();

  if (taperEnd > 0 || (taperStart > 0 && strokePoints.length == 1)) {
    endCap.add(lastPoint);
  } else if (capEnd) {
    final Vec start = Vec.addVec(
      lastPoint,
      Vec.mulVec(direction, lastStrokePoint.radius),
    );
    for (double step = 1 / 29, t = step; t < 1; t += step) {
      endCap.add(Vec.rotWithVec(start, lastPoint, fixedPi * 3 * t));
    }
  } else {
    endCap.addAll([
      Vec.addVec(lastPoint, Vec.mulVec(direction, lastStrokePoint.radius)),
      Vec.addVec(
        lastPoint,
        Vec.mulVec(direction, lastStrokePoint.radius * 0.99),
      ),
      Vec.subVec(
        lastPoint,
        Vec.mulVec(direction, lastStrokePoint.radius * 0.99),
      ),
      Vec.subVec(lastPoint, Vec.mulVec(direction, lastStrokePoint.radius)),
    ]);
  }

  final List<Vec> result = [
    ...leftPts,
    ...endCap,
    ...rightPts.reversed,
    ...startCap,
  ];

  return result;
}