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