commit 2ce1b55bee7dd6df6b4697fac2282b54ec80469d
parent b1b5cf1381471c427482864960f1d71656334f2a
Author: Kyle Milz <kyle@getaddrinfo.net>
Date: Mon, 10 Nov 2014 21:22:03 -0700
gen_svg: add spline calculation code
Diffstat:
M | gen_svg.pl | | | 68 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/gen_svg.pl b/gen_svg.pl
@@ -8,10 +8,6 @@ use POSIX;
use shared;
-#
-# Spline code here:
-# http://www.particleincell.com/wp-content/uploads/2012/06/bezier-spline.js
-#
# my $log = get_log("gen_svg");
my $dbh = get_dbh();
@@ -80,9 +76,19 @@ while (my ($part_num, $description) = $parts_sth->fetchrow_array()) {
}
vprintf(@xs . " data points\n");
- my $points = $svg->get_path(x => \@xs, y => \@ys);
+ my $px = compute_control_points(\@xs);
+ my $py = compute_control_points(\@ys);
+ my $p;
+ for (0..(scalar @xs - 2)) {
+ $p .= sprintf("M %f %f C %f %f %f %f %f %f ",
+ $xs[$_], $ys[$_],
+ $px->{"p1"}[$_], $py->{"p1"}[$_],
+ $px->{"p2"}[$_], $py->{"p2"}[$_],
+ $xs[$_ + 1], $ys[$_ + 1]
+ );
+ }
$svg->path(
- %$points,
+ d => $p,
id => $vendor,
style => {
"fill-opacity" => 0,
@@ -162,3 +168,53 @@ while (my ($part_num, $description) = $parts_sth->fetchrow_array()) {
# close $log;
$dbh->disconnect();
+
+# shamefully ported javascript from
+# http://www.particleincell.com/wp-content/uploads/2012/06/bezier-spline.js
+sub compute_control_points
+{
+ my $K = shift;
+ my $n = @$K - 1;
+
+ my (@p1, @p2);
+ my (@a, @b, @c, @r);
+
+ # left segment
+ $a[0] = 0;
+ $b[0] = 2;
+ $c[0] = 1;
+ $r[0] = $K->[0] + 2 * $K->[1];
+
+ # internal segments
+ for (1..($n - 2)) {
+ $a[$_] = 1;
+ $b[$_] = 4;
+ $c[$_] = 1;
+ $r[$_] = 4 * $K->[$_] + 2 * $K->[$_ + 1];
+ }
+
+ # right segment
+ $a[$n - 1] = 2;
+ $b[$n - 1] = 7;
+ $c[$n - 1] = 0;
+ $r[$n - 1] = 8 * $K->[$n - 1] + $K->[$n];
+
+ # solves Ax=b with the Thomas algorithm
+ for (1..($n - 1)) {
+ my $m = $a[$_] / $b[$_ - 1];
+ $b[$_] = $b[$_] - $m * $c[$_ - 1];
+ $r[$_] = $r[$_] - $m * $r[$_ - 1];
+ }
+
+ $p1[$n - 1] = $r[$n - 1] / $b[$n - 1];
+ for (reverse(0..($n - 2))) {
+ $p1[$_] = ($r[$_] - $c[$_] * $p1[$_ + 1]) / $b[$_];
+ }
+
+ for (0..($n - 2)) {
+ $p2[$_] = 2 * $K->[$_ + 1] - $p1[$_ + 1];
+ }
+ $p2[$n - 1] = 0.5 * ($K->[$n] + $p1[$n - 1]);
+
+ return {"p1" => \@p1, "p2" => \@p2};
+}