commit 815d7cec90b7cd59162e088bb3a6a0a6508b546f
parent 84d03a3c19b42bd2d9cf27ba67383b8c23acbecf
Author: Kyle Milz <kyle@getaddrinfo.net>
Date: Fri, 17 Apr 2015 22:10:33 -0600
gen_svg: fold into gen_html
Diffstat:
M | Makefile | | | 2 | +- |
M | gen_html | | | 300 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
D | gen_svg | | | 332 | ------------------------------------------------------------------------------- |
3 files changed, 296 insertions(+), 338 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,7 +6,7 @@ PERL_LIBDATA = $(USR)/libdata/perl5/site_perl
HTDOCS = $(VAR)/www/htdocs
DEV_BIN = /home/kyle/src/pricechart
-BINS = gen_html gen_svg pc_fcgi price_scraper product_scraper
+BINS = gen_html pc_fcgi price_scraper product_scraper
# WARNING stupid idiom used below if adding > 1 item to LIBS!!
LIBS = PriceChart.pm
HTML = tt logo pricechart.css
diff --git a/gen_html b/gen_html
@@ -8,15 +8,16 @@ use Data::Dumper;
use File::Copy;
use Getopt::Std;
use Lingua::EN::Inflect qw(PL);
-use POSIX qw(ceil);
+use POSIX;
use PriceChart;
+use SVG;
use Template;
use Time::Piece;
use URI::Escape;
my %args;
-getopts("v", \%args);
+getopts("anv", \%args);
$| = 1 if ($args{v});
@@ -88,6 +89,14 @@ for my $manufacturer (@$manufacturers) {
"manufacturers/$manufacturer/$type_link.html")
|| die "template: " . $template->error() . "\n";
}
+
+ # print Dumper($summary{$manufacturer});
+ my $vars = {
+ type => "manufacturer", name => $manufacturer_cased,
+ info => \$summary{$manufacturer}, logo => $logo_file{$manufacturer}
+ };
+ $template->process("summary.tt", $vars, "manufacturers/$manufacturer.html")
+ || die "template: " . $template->error() . "\n";
}
print "\n" if ($args{v});
@@ -95,7 +104,6 @@ my $vars = { name => "Manufacturers", list => \%summary, logo_file => \%logo_fil
$template->process("coarse_list.tt", $vars, "manufacturers.html")
|| die "template: " . $template->error() . "\n";
-exit;
#
# retailers/*
@@ -230,8 +238,6 @@ print "info: gen index.html\n" if ($args{v});
$template->process("index.tt", $vars, "index.html")
|| die "template: " . $template->error() . "\n";
-$dbh->disconnect();
-
sub get_description
{
my $manufacturer = shift;
@@ -254,3 +260,287 @@ sub get_description
return $best;
}
+
+
+
+my $svg_dir = $cfg->{http}{chroot} . $cfg->{http}{htdocs} . "/svg";
+
+# we don't output svg's when -n is given
+print "info: svg: output dir is $svg_dir\n" if ($args{v} && !$args{n});
+
+# svg dimensions
+my ($left, $center, $right, $top, $middle, $bottom) = (3, 957, 40, 15, 150, 20);
+my $width = $right + $center + $left;
+my $height = $top + $middle + $bottom;
+
+my $where_clause = $args{a} ? "" : "where svg_stale = 1";
+my $sql = "select manufacturer, part_num from products $where_clause";
+my $parts_sth = $dbh->prepare($sql);
+
+$sql = "select distinct retailer from prices where part_num = ? and manufacturer = ?";
+my $retailer_sth = $dbh->prepare($sql);
+
+$sql = "select date, price from prices where " .
+ "part_num = ? and retailer = ? order by date";
+my $point_sth = $dbh->prepare($sql);
+
+$sql = "update products set svg_stale = 0 where manufacturer = ? and part_num = ?";
+my $success_sth = $dbh->prepare($sql);
+
+$parts_sth->execute();
+print "info: svg: " if ($args{v});
+my ($raw_total, $rendered_total, $points, $series) = (0, 0, 0, 0);
+while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
+ $raw_total++;
+ spin() if ($args{v});
+ my %series;
+
+ $sql = qq{select min(date), max(date), min(price), max(price)
+ from prices where manufacturer = ? and part_num = ?};
+ my ($x_min, $x_max, $y_min, $y_max) =
+ $dbh->selectrow_array($sql, undef, $manufacturer, $part_num);
+ next unless (defined $x_min);
+
+ # each series on the chart represents a retailers prices
+ $retailer_sth->execute($part_num, $manufacturer);
+ while (my ($retailer) = $retailer_sth->fetchrow_array()) {
+ $sql = "select url, color from retailers where name = ?";
+ my ($url, $color) = $dbh->selectrow_array($sql, undef, $retailer);
+
+ # xlink:href's don't like raw ampersands
+ $url =~ s/&/&/g;
+
+ $series{$retailer}{url} = $url;
+ $series{$retailer}{color} = $color;
+
+ $point_sth->execute($part_num, $retailer);
+ $series{$retailer}{data} = $point_sth->fetchall_arrayref();
+ $points += scalar @{$series{$retailer}{data}};
+ $series++;
+ }
+
+ my $svg = make_svg(\%series, $x_min, $x_max, $y_min, $y_max, $part_num);
+
+ next if ($args{n});
+
+ # all links lower case
+ my $part_num_cased = $part_num;
+ $part_num = lc($part_num);
+
+ # giant hack, if the part number has / in it, make some directories
+ if ($part_num =~ /\//) {
+ my $needed_dirs = substr($part_num, 0, rindex($part_num, '/'));
+ make_path("$svg_dir/$needed_dirs", { verbose => $args{v} });
+ }
+ open my $svg_fh, ">", "$svg_dir/$part_num.svg" or
+ die "couldn't open $svg_dir/$part_num: $!";
+
+ # XXX: not sure how to add this programatically, hack around for now
+ my @buf = split("\n", $svg->xmlify);
+ my $css_include = "<?xml-stylesheet href=\"/pricechart.css\" type=\"text/css\"?>";
+ # must be the second line
+ splice (@buf, 1, 0, ($css_include));
+
+ print $svg_fh "$_\n" for (@buf);
+ close $svg_fh;
+
+ # we outputted something to a file, set stale to 0
+ $success_sth->execute($manufacturer, $part_num_cased);
+ $rendered_total++;
+}
+printf "\b%i rendered, %i skipped, ", $rendered_total, $raw_total - $rendered_total if ($args{v});
+printf "%i points in %i series\n", $points, $series if ($args{v});
+
+$dbh->disconnect();
+
+#
+# make a new svg with provided coordinate and label data
+#
+sub make_svg
+{
+ my $series = shift;
+ my $x_min = shift;
+ my $x_max = shift;
+ my $y_min = shift;
+ my $y_max = shift;
+ my $part_num = shift;
+
+ $y_max = ceil($y_max / 100) * 100;
+ $y_min = floor($y_min / 100) * 100;
+
+ my ($domain, $range) = ($x_max - $x_min, $y_max - $y_min);
+ $domain = 24 * 60 * 60 if ($domain <= 0);
+ $range = 20 if ($range < 20);
+
+ # clamp the total size of this thing with viewBox
+ my $svg = SVG->new(viewBox => "0 0 $width $height");
+ my $defs = $svg->defs();
+ my ($x_scale, $y_scale) = ($center / $domain, $middle / $range);
+
+ # make price labels along right side and lines across chart
+ my $num_labels = 5;
+ for (1..$num_labels) {
+ my $step = ($_ - 1) / ($num_labels - 1);
+ my $price = ceil($y_max - $range * $step);
+ my $y = $top + $middle * $step;
+
+ $svg->text(
+ id => "price_$_", x => $left + $center + 5, y => $y + 3,
+ class => "chart_price", "text-anchor" => "start"
+ )->cdata("\$$price");
+
+ $svg->line(
+ id => "horizontal_line_$_", x1 => $left, y1 => $y,
+ x2 => $width - $right, y2 => $y, class => "chart_rulers"
+ );
+ }
+
+ # make dates along the bottom
+ if ($domain == 24 * 60 * 60) {
+ $num_labels = 2;
+ }
+ for (1..$num_labels) {
+ my $step = ($_ - 1) / ($num_labels - 1);
+
+ # make the dates not hang off the ends of the chart
+ my $text_anchor = "middle";
+ $text_anchor = "start" if ($_ == 1);
+ $text_anchor = "end" if ($_ == $num_labels);
+
+ # print the dates along the x axis
+ my $x = $left + $center * $step;
+ my $time = $x_min + $domain * $step;
+ $svg->text(id => "date_$_", x => $x, y => $height - 5,
+ class => "chart_date", "text-anchor" => $text_anchor
+ )->cdata(strftime("%B %e, %Y", localtime($time)));
+
+ # print the little tick marks down from the x axis
+ my $x_axis = $top + $middle;
+ $svg->line(id => "date_marker_$_", x1 => $x, y1 => $x_axis,
+ x2 => $x, y2 => $x_axis + 5, class => "chart_rulers",
+ );
+ }
+
+ while (my ($retailer, $values) = each %$series) {
+ my $retailer_id = lc($retailer);
+ $retailer_id =~ s/ /_/;
+
+ my $url = $values->{url};
+ my $color = $values->{color};
+
+ my (@xs, @ys, @pts);
+ for (@{$values->{data}}) {
+ my ($x, $y) = @$_;
+ push @xs, sprintf "%.3f", ($x - $x_min) * $x_scale + $left;
+ push @ys, sprintf "%.3f", $height - $bottom - ($y - $y_min) * $y_scale;
+ push @pts, $xs[-1];
+ push @pts, $ys[-1];
+ }
+
+ if (@pts < 6) {
+ my $points = $svg->get_path(x => \@xs, y => \@ys, -type => "path");
+ $defs->path(%$points, id => "path_$retailer_id");
+ }
+ else {
+ # catmull rom time
+ my $d = catmullrom_to_bezier(\@pts);
+ $defs->tag("path", "d" => $d, id => "path_$retailer_id");
+ }
+
+ # the line, points, and label can be grouped under one anchor
+ my $anchor = $svg->anchor(-href => $url . $part_num,
+ target => "new_window");
+
+ # draw path first
+ $anchor->use(-href => "#path_$retailer_id",
+ class => "chart_series", style => "stroke: #$color"
+ );
+
+ # now draw individual data points
+ $defs->circle(id => "data_point_$retailer", cx => 0, cy => 0,
+ class => "chart_data", r => 2, style => "stroke: #$color;"
+ );
+ while (my $i = each @xs) {
+ $anchor->use(-href => "#data_point_$retailer",
+ x => $xs[$i], y => $ys[$i]
+ );
+ }
+
+ # show retailer name along the start of the path
+ $anchor->text(class => "chart_series_text", fill => "#$color"
+ )->tag("textPath", -href => "#path_$retailer_id"
+ )->tag("tspan", "dy" => "-5")->cdata($retailer);
+ }
+
+ # when graph is loaded make a sliding motion show the graph lines
+ # my $mask = $svg->rectangle(
+ # x => 0, y => 0, width => 1000, height => 250, rx => 0, ry => 0,
+ # id => "mask", fill => "#FFF"
+ # );
+ # $mask->animate(
+ # attributeName => "x", values => "0;1000", dur => "0.2s",
+ # fill => "freeze", -method => ""
+ # );
+
+ return $svg
+}
+
+#
+# taken from https://gist.github.com/njvack/6925609
+#
+sub catmullrom_to_bezier
+{
+ my $pts_ref = shift;
+ my @pts = @$pts_ref;
+
+ # catmull-rom to cubic bezier conversion matrix
+ # 0 1 0 0
+ # -1/6 1 1/6 0
+ # 0 1/6 1 -1/6
+ # 0 0 1 0
+
+ my $d = "M" . $pts[0] . ", " . $pts[1] . " ";
+ my $iLen = @pts;
+ for (my $i = 0; $iLen - 2 > $i; $i += 2) {
+ my @p;
+ if ($i == 0) {
+ push @p, {x => $pts[$i], y => $pts[$i + 1]};
+ push @p, {x => $pts[$i], y => $pts[$i + 1]};
+ push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
+ push @p, {x => $pts[$i + 4], y => $pts[$i + 5]};
+ }
+ elsif ($i == ($iLen - 4)) {
+ push @p, {x => $pts[$i - 2], y => $pts[$i - 1]};
+ push @p, {x => $pts[$i], y => $pts[$i + 1]};
+ push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
+ push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
+ }
+ else {
+ push @p, {x => $pts[$i - 2], y => $pts[$i - 1]};
+ push @p, {x => $pts[$i], y => $pts[$i + 1]};
+ push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
+ push @p, {x => $pts[$i + 4], y => $pts[$i + 5]};
+ }
+
+ # print Dumper(@p);
+
+ my @bp;
+ push @bp, {x => $p[1]{x}, y => $p[1]{y}};
+ push @bp, {
+ x => ((-$p[0]{x} + 6*$p[1]{x} + $p[2]{x}) / 6),
+ y => ((-$p[0]{y} + 6*$p[1]{y} + $p[2]{y}) / 6)
+ };
+ push @bp, {
+ x => (($p[1]{x} + 6*$p[2]{x} - $p[3]{x}) / 6),
+ y => (($p[1]{y} + 6*$p[2]{y} - $p[3]{y}) / 6)
+ };
+ push @bp, {x => $p[2]{x}, y => $p[2]{y}};
+
+ $d .= "C " . $bp[1]{x} . ", " . $bp[1]{y} . " " .
+ $bp[2]{x} . ", " . $bp[2]{y} . " " .
+ $bp[3]{x} . ", " . $bp[3]{y} . " ";
+ }
+
+ # print $d;
+ return $d;
+}
diff --git a/gen_svg b/gen_svg
@@ -1,332 +0,0 @@
-#!/usr/bin/env perl
-
-use strict;
-use warnings;
-
-use Config::Grammar;
-use Getopt::Std;
-use SVG;
-use POSIX;
-use PriceChart;
-
-
-my %args;
-getopts("anv", \%args);
-
-$| = 1 if ($args{v});
-
-my $cfg = get_config();
-my $dbh = get_dbh($cfg->{http}, undef, $args{v});
-
-my $svg_dir = $cfg->{http}{chroot} . $cfg->{http}{htdocs} . "/svg";
-
-# we don't output svg's when -n is given
-print "info: svg: output dir is $svg_dir\n" if ($args{v} && !$args{n});
-
-# svg dimensions
-my ($left, $center, $right, $top, $middle, $bottom) = (3, 957, 40, 15, 150, 20);
-my $width = $right + $center + $left;
-my $height = $top + $middle + $bottom;
-
-my $where_clause = $args{a} ? "" : "where svg_stale = 1";
-my $sql = "select manufacturer, part_num from products $where_clause";
-my $parts_sth = $dbh->prepare($sql);
-
-$sql = "select distinct retailer from prices where part_num = ? and manufacturer = ?";
-my $retailer_sth = $dbh->prepare($sql);
-
-$sql = "select date, price from prices where " .
- "part_num = ? and retailer = ? order by date";
-my $point_sth = $dbh->prepare($sql);
-
-$sql = "update products set svg_stale = 0 where manufacturer = ? and part_num = ?";
-my $success_sth = $dbh->prepare($sql);
-
-$parts_sth->execute();
-print "info: svg: " if ($args{v});
-my ($raw_total, $rendered_total, $points, $series) = (0, 0, 0, 0);
-while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
- $raw_total++;
- spin() if ($args{v});
- my %series;
-
- $sql = qq{select min(date), max(date), min(price), max(price)
- from prices where manufacturer = ? and part_num = ?};
- my ($x_min, $x_max, $y_min, $y_max) =
- $dbh->selectrow_array($sql, undef, $manufacturer, $part_num);
- next unless (defined $x_min);
-
- # each series on the chart represents a retailers prices
- $retailer_sth->execute($part_num, $manufacturer);
- while (my ($retailer) = $retailer_sth->fetchrow_array()) {
- $sql = "select url, color from retailers where name = ?";
- my ($url, $color) = $dbh->selectrow_array($sql, undef, $retailer);
-
- # xlink:href's don't like raw ampersands
- $url =~ s/&/&/g;
-
- $series{$retailer}{url} = $url;
- $series{$retailer}{color} = $color;
-
- $point_sth->execute($part_num, $retailer);
- $series{$retailer}{data} = $point_sth->fetchall_arrayref();
- $points += scalar @{$series{$retailer}{data}};
- $series++;
- }
-
- my $svg = make_svg(\%series, $x_min, $x_max, $y_min, $y_max, $part_num);
-
- next if ($args{n});
-
- # all links lower case
- my $part_num_cased = $part_num;
- $part_num = lc($part_num);
-
- # giant hack, if the part number has / in it, make some directories
- if ($part_num =~ /\//) {
- my $needed_dirs = substr($part_num, 0, rindex($part_num, '/'));
- make_path("$svg_dir/$needed_dirs", { verbose => $args{v} });
- }
- open my $svg_fh, ">", "$svg_dir/$part_num.svg" or
- die "couldn't open $svg_dir/$part_num: $!";
-
- # XXX: not sure how to add this programatically, hack around for now
- my @buf = split("\n", $svg->xmlify);
- my $css_include = "<?xml-stylesheet href=\"/pricechart.css\" type=\"text/css\"?>";
- # must be the second line
- splice (@buf, 1, 0, ($css_include));
-
- print $svg_fh "$_\n" for (@buf);
- close $svg_fh;
-
- # we outputted something to a file, set stale to 0
- $success_sth->execute($manufacturer, $part_num_cased);
- $rendered_total++;
-}
-printf "\b%i rendered, %i skipped, ", $rendered_total, $raw_total - $rendered_total if ($args{v});
-printf "%i points in %i series\n", $points, $series if ($args{v});
-
-$dbh->disconnect();
-
-#
-# make a new svg with provided coordinate and label data
-#
-sub make_svg
-{
- my $series = shift;
- my $x_min = shift;
- my $x_max = shift;
- my $y_min = shift;
- my $y_max = shift;
- my $part_num = shift;
-
- $y_max = ceil($y_max / 100) * 100;
- $y_min = floor($y_min / 100) * 100;
-
- my ($domain, $range) = ($x_max - $x_min, $y_max - $y_min);
- $domain = 24 * 60 * 60 if ($domain <= 0);
- $range = 20 if ($range < 20);
-
- # clamp the total size of this thing with viewBox
- my $svg = SVG->new(viewBox => "0 0 $width $height");
- my $defs = $svg->defs();
- my ($x_scale, $y_scale) = ($center / $domain, $middle / $range);
-
- # make price labels along right side and lines across chart
- my $num_labels = 5;
- for (1..$num_labels) {
- my $step = ($_ - 1) / ($num_labels - 1);
- my $price = ceil($y_max - $range * $step);
- my $y = $top + $middle * $step;
-
- $svg->text(
- id => "price_$_", x => $left + $center + 5, y => $y + 3,
- class => "chart_price", "text-anchor" => "start"
- )->cdata("\$$price");
-
- $svg->line(
- id => "horizontal_line_$_", x1 => $left, y1 => $y,
- x2 => $width - $right, y2 => $y, class => "chart_rulers"
- );
- }
-
- # make dates along the bottom
- if ($domain == 24 * 60 * 60) {
- $num_labels = 2;
- }
- for (1..$num_labels) {
- my $step = ($_ - 1) / ($num_labels - 1);
-
- # make the dates not hang off the ends of the chart
- my $text_anchor = "middle";
- $text_anchor = "start" if ($_ == 1);
- $text_anchor = "end" if ($_ == $num_labels);
-
- # print the dates along the x axis
- my $x = $left + $center * $step;
- my $time = $x_min + $domain * $step;
- $svg->text(id => "date_$_", x => $x, y => $height - 5,
- class => "chart_date", "text-anchor" => $text_anchor
- )->cdata(strftime("%B %e, %Y", localtime($time)));
-
- # print the little tick marks down from the x axis
- my $x_axis = $top + $middle;
- $svg->line(id => "date_marker_$_", x1 => $x, y1 => $x_axis,
- x2 => $x, y2 => $x_axis + 5, class => "chart_rulers",
- );
- }
-
- while (my ($retailer, $values) = each %$series) {
- my $retailer_id = lc($retailer);
- $retailer_id =~ s/ /_/;
-
- my $url = $values->{url};
- my $color = $values->{color};
-
- my (@xs, @ys, @pts);
- for (@{$values->{data}}) {
- my ($x, $y) = @$_;
- push @xs, sprintf "%.3f", ($x - $x_min) * $x_scale + $left;
- push @ys, sprintf "%.3f", $height - $bottom - ($y - $y_min) * $y_scale;
- push @pts, $xs[-1];
- push @pts, $ys[-1];
- }
-
- if (@pts < 6) {
- my $points = $svg->get_path(x => \@xs, y => \@ys, -type => "path");
- $defs->path(%$points, id => "path_$retailer_id");
- }
- else {
- # catmull rom time
- my $d = catmullrom_to_bezier(\@pts);
- $defs->tag("path", "d" => $d, id => "path_$retailer_id");
- }
-
- # the line, points, and label can be grouped under one anchor
- my $anchor = $svg->anchor(-href => $url . $part_num,
- target => "new_window");
-
- # draw path first
- $anchor->use(-href => "#path_$retailer_id",
- class => "chart_series", style => "stroke: #$color"
- );
-
- # now draw individual data points
- $defs->circle(id => "data_point_$retailer", cx => 0, cy => 0,
- class => "chart_data", r => 2, style => "stroke: #$color;"
- );
- while (my $i = each @xs) {
- $anchor->use(-href => "#data_point_$retailer",
- x => $xs[$i], y => $ys[$i]
- );
- }
-
- # show retailer name along the start of the path
- $anchor->text(class => "chart_series_text", fill => "#$color"
- )->tag("textPath", -href => "#path_$retailer_id"
- )->tag("tspan", "dy" => "-5")->cdata($retailer);
- }
-
- # when graph is loaded make a sliding motion show the graph lines
- # my $mask = $svg->rectangle(
- # x => 0, y => 0, width => 1000, height => 250, rx => 0, ry => 0,
- # id => "mask", fill => "#FFF"
- # );
- # $mask->animate(
- # attributeName => "x", values => "0;1000", dur => "0.2s",
- # fill => "freeze", -method => ""
- # );
-
- return $svg
-}
-
-sub catmullrom_to_bezier
-{
- my $pts_ref = shift;
- my @pts = @$pts_ref;
-
- # catmull-rom to cubic bezier conversion matrix
- # 0 1 0 0
- # -1/6 1 1/6 0
- # 0 1/6 1 -1/6
- # 0 0 1 0
-
- my $d = "M" . $pts[0] . ", " . $pts[1] . " ";
- my $iLen = @pts;
- for (my $i = 0; $iLen - 2 > $i; $i += 2) {
- my @p;
- if ($i == 0) {
- push @p, {x => $pts[$i], y => $pts[$i + 1]};
- push @p, {x => $pts[$i], y => $pts[$i + 1]};
- push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
- push @p, {x => $pts[$i + 4], y => $pts[$i + 5]};
- }
- elsif ($i == ($iLen - 4)) {
- push @p, {x => $pts[$i - 2], y => $pts[$i - 1]};
- push @p, {x => $pts[$i], y => $pts[$i + 1]};
- push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
- push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
- }
- else {
- push @p, {x => $pts[$i - 2], y => $pts[$i - 1]};
- push @p, {x => $pts[$i], y => $pts[$i + 1]};
- push @p, {x => $pts[$i + 2], y => $pts[$i + 3]};
- push @p, {x => $pts[$i + 4], y => $pts[$i + 5]};
- }
-
- # print Dumper(@p);
-
- my @bp;
- push @bp, {x => $p[1]{x}, y => $p[1]{y}};
- push @bp, {
- x => ((-$p[0]{x} + 6*$p[1]{x} + $p[2]{x}) / 6),
- y => ((-$p[0]{y} + 6*$p[1]{y} + $p[2]{y}) / 6)
- };
- push @bp, {
- x => (($p[1]{x} + 6*$p[2]{x} - $p[3]{x}) / 6),
- y => (($p[1]{y} + 6*$p[2]{y} - $p[3]{y}) / 6)
- };
- push @bp, {x => $p[2]{x}, y => $p[2]{y}};
-
- $d .= "C " . $bp[1]{x} . ", " . $bp[1]{y} . " " .
- $bp[2]{x} . ", " . $bp[2]{y} . " " .
- $bp[3]{x} . ", " . $bp[3]{y} . " ";
- }
-
- # print $d;
- return $d;
-}
-
-# function catmullRom2bezier( points ) {
-# // alert(points)
-# var crp = points.split(/[,\s]/);
-# var d = "";
-# for (var i = 0, iLen = crp.length; iLen - 2 > i; i+=2) {
-# var p = [];
-# if ( 0 == i ) {
-# p.push( {x: parseFloat(crp[ i ]), y: parseFloat(crp[ i + 1 ])} );
-# p.push( {x: parseFloat(crp[ i ]), y: parseFloat(crp[ i + 1 ])} );
-# p.push( {x: parseFloat(crp[ i + 2 ]), y: parseFloat(crp[ i + 3 ])} );
-# p.push( {x: parseFloat(crp[ i + 4 ]), y: parseFloat(crp[ i + 5 ])} );
-# } else if ( iLen - 4 == i ) {
-# p.push( {x: parseFloat(crp[ i - 2 ]), y: parseFloat(crp[ i - 1 ])} );
-# p.push( {x: parseFloat(crp[ i ]), y: parseFloat(crp[ i + 1 ])} );
-# p.push( {x: parseFloat(crp[ i + 2 ]), y: parseFloat(crp[ i + 3 ])} );
-# p.push( {x: parseFloat(crp[ i + 2 ]), y: parseFloat(crp[ i + 3 ])} );
-# } else {
-# p.push( {x: parseFloat(crp[ i - 2 ]), y: parseFloat(crp[ i - 1 ])} );
-# p.push( {x: parseFloat(crp[ i ]), y: parseFloat(crp[ i + 1 ])} );
-# p.push( {x: parseFloat(crp[ i + 2 ]), y: parseFloat(crp[ i + 3 ])} );
-# p.push( {x: parseFloat(crp[ i + 4 ]), y: parseFloat(crp[ i + 5 ])} );
-# }
-#
-# var bp = [];
-# bp.push( { x: p[1].x, y: p[1].y } );
-# bp.push( { x: ((-p[0].x + 6*p[1].x + p[2].x) / 6), y: ((-p[0].y + 6*p[1].y + p[2].y) / 6)} );
-# bp.push( { x: ((p[1].x + 6*p[2].x - p[3].x) / 6), y: ((p[1].y + 6*p[2].y - p[3].y) / 6) } );
-# bp.push( { x: p[2].x, y: p[2].y } );
-#
-# d += "C" + bp[1].x + "," + bp[1].y + " " + bp[2].x + "," + bp[2].y + " " + bp[3].x + "," + bp[3].y + " ";
-# }
-# return d;
-# }