pricecharts

track prices of consumer electronics
Log | Files | Refs | README

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:
MMakefile | 2+-
Mgen_html | 300+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Dgen_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/&/&amp;/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/&/&amp;/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; -# }