getSmoothHandlePoints function
Implementation
Tuple2<List<Vector3>, List<Vector3>> getSmoothHandlePoints(
List<Vector3> points) {
var numHandles = points.length - 1;
if (numHandles < 1) {
return Tuple2([ORIGIN], [ORIGIN]);
}
var l = 2;
var u = 1;
var diag = Array.zeros(shape: Tuple2(l + u + 1, 2 * numHandles));
void setVal(double value, int col, {int start = 0, int? end, int step = 1}) {
end ??= 2 * numHandles;
for (var i in range(start: start, end: end, step: step)) {
diag.setValue(Tuple2(col, i), value);
}
}
setVal(-1, 0, start: 1, step: 2);
setVal(1, 0, start: 2, step: 2);
setVal(2, 1, start: 0, step: 2);
setVal(1, 1, start: 1, step: 2);
setVal(-2, 2, start: 1, end: 2 * numHandles - 2, step: 2);
setVal(1, 3, start: 0, end: 2 * numHandles - 3, step: 2);
diag.setValue(Tuple2(2, -2), -1);
diag.setValue(Tuple2(1, -1), 2);
var b = Array.zeros(shape: Tuple2(2 * numHandles, 3));
var pointsWithoutFirst = withoutFirst(points);
//* equivalent to b[1::2] = 2 * points[1:]
for (var ij in enumerate((range(start: 1, end: 2 * numHandles, step: 2)))) {
for (var k in range(end: 3)) {
b.setValue(Tuple2(ij.item2, k),
2 * pointsWithoutFirst[ij.item1].getComponent(k));
}
}
//* equivalent to b[0] = points[0]
for (var k in range(end: 3)) {
b.setValue(Tuple2(0, k), points.first.getComponent(k));
}
//* equivalent to b[-1] = points[-1]
for (var k in range(end: 3)) {
b.setValue(Tuple2(2 * numHandles - 1, k), points.last.getComponent(k));
}
// TODO solve banded matrix instead of using getInverse
var useClosedSolveFunction = isClosed(points);
var handlePairs = Array.zeros(shape: Tuple2(2 * numHandles, 3));
if (useClosedSolveFunction) {
var matrix = diagToMatrix(Tuple2(l, u), diag);
for (var i in IterableZip([
[0, 1, -2, -1],
[2, -1, 1, -2]
])) {
var k = -1 % matrix.shape.item1;
var j = i[0] % matrix.shape.item2;
matrix.setValue(Tuple2(k, j), i[1].toDouble());
}
matrix.values = [
[
for (var i in range(end: matrix.shape.item2))
if (i == 0 || i == matrix.shape.item2 - 1) 1 else 0
],
...withoutFirst(matrix.values)
];
b.values.first = (points[0] * 2.0).toList();
b.values.last = ORIGIN.toList();
for (var i in range(end: 3)) {
handlePairs.setColumn(i, matrix.getInverse().matMul(b).flat());
}
} else {
for (var i in range(end: 3)) {
handlePairs.setColumn(i, diag.getInverse().matMul(b).flat());
}
}
var handlePairsVectors = [
for (var line in handlePairs.getValues()) Vector3(line[0], line[1], line[2])
];
var even = handlePairsVectors.whereIndexed((i, e) => i % 2 == 0).toList();
var odd = handlePairsVectors.whereIndexed((i, e) => i % 2 == 1).toList();
return Tuple2(even, odd);
}