From 69980765a1d5585195bd57afe961990ce14074e2 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Thu, 22 Jan 2015 06:39:03 +0000 Subject: [PATCH] 98_SVG.pm: spline patches from eki (Forum #32430) git-svn-id: https://svn.fhem.de/fhem/trunk@7657 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_SVG.pm | 85 ++++++++++++++++++++++++++++-- fhem/docs/commandref_frame.html | 4 +- fhem/docs/commandref_frame_DE.html | 4 +- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/fhem/FHEM/98_SVG.pm b/fhem/FHEM/98_SVG.pm index 6530faa2f..959df703d 100755 --- a/fhem/FHEM/98_SVG.pm +++ b/fhem/FHEM/98_SVG.pm @@ -43,6 +43,8 @@ sub SVG_openFile($$$); sub SVG_doShowLog($$$$;$$); sub SVG_getData($$$$$); sub SVG_sel($$$;$$); +sub SVG_getControlPoints($$$$$$$$$$$); +sub SVG_calcControlPoints($$$); my %SVG_devs; # hash of from/to entries per device @@ -399,7 +401,7 @@ SVG_PEdit($$$$) ($v && $v eq "x1y1") ? "left" : "right"); $o .= SVG_sel("type_${idx}", "lines,points,steps,fsteps,histeps,bars,". - "cubic,cubicSmooth,quadratic,quadraticSmooth", + "cubic,quadratic", $conf{lType}[$idx]); my $ls = $conf{lStyle}[$idx]; if($ls) { @@ -1794,9 +1796,14 @@ SVG_render($$$$$$$$$;$$) } else { # lines and everything else my ($ymin, $ymax) = (99999999, -99999999); - my %lt =(cubic=>"C",cubicSmooth=>"S",quadratic=>"Q",quadraticSmooth=>"T"); + my %lt =(cubic=>"C",quadratic=>"Q"); my ($x1, $y1); my $lt = ($lt{$lType} ? $lt{$lType} : "L"); # defaults to line + + my(@xcp1, @xcp2, @ycp1, @ycp2); + + SVG_getControlPoints(\@xcp1, \@xcp2, \@ycp1, \@ycp2, $dxp, $dyp, $x, $y, $h, $min, $hmul) if ($lt ne "L"); + foreach my $i (0..int(@{$dxp})-1) { if( !defined($dxp->[$i]) ) { # specials @@ -1880,7 +1887,9 @@ SVG_render($$$$$$$$$;$$) $ret .= sprintf(" %d,%d", $lx, $ly); ($ymin, $ymax) = (99999999, -99999999); } - $ret .= sprintf(" %d,%d", $x1, $y1); + $ret .= sprintf(" %d,%d", $x1, $y1) if ($lt eq "L"); + $ret .= sprintf(" %d,%d,%d,%d,%d,%d", $xcp1[$i-1], $ycp1[$i-1], $xcp2[$i-1], $ycp2[$i-1], $x1, $y1) if ($lt eq "C"); + $ret .= sprintf(" %d,%d,%d,%d", $xcp2[$i-1], $ycp2[$i-1], $x1, $y1) if ($lt eq "Q"); $lx = $x1; $ly = $y1; } #-- insert last point for filled line @@ -1918,6 +1927,76 @@ SVG_render($$$$$$$$$;$$) return $SVG_RET; } +###################### +# Derives control points for interpolation of bezier curves for SVG "path" +sub +SVG_getControlPoints($$$$$$$$$$$) +{ + my ($xcp1, $xcp2, $ycp1, $ycp2, $dxp, $dyp, $x, $y, $h, $min, $hmul) = @_; + my (@xa, @ya); + + foreach my $i (0..int(@{$dxp})-1) { + + if( defined($dxp->[$i]) ) { # non specials + ($xa[$i], $ya[$i]) = (int($x+$dxp->[$i]), + int($y+$h-($dyp->[$i]-$min)*$hmul)); + } else { + ($xa[$i], $ya[$i]) = ($xa[$i-1], $ya[$i-1]) if ($xa[$i-1] && $ya[$i-1]); + } + } + + SVG_calcControlPoints($xcp1, $xcp2, \@xa); + SVG_calcControlPoints($ycp1, $ycp2, \@ya); + + return(1); +} + +###################### +# Calculate control points for interpolation of bezier curves for SVG "path" +sub +SVG_calcControlPoints($$$) +{ + my ($p1, $p2, $input) = @_; + + my (@a, @b, @c, @r); + my $n = @{$input}-1; + + $a[0] = 0; + $b[0] = 2; + $c[0] = 1; + $r[0] = $input->[0] + $input->[1]*2; + + for (my $i=1; $i<$n-1; $i++) { + $a[$i] = 1; + $b[$i] = 4; + $c[$i] = 1; + $r[$i] = $input->[$i]*4 + $input->[$i+1]*2; + } + + $a[$n-1] = 2; + $b[$n-1] = 7; + $c[$n-1] = 0; + $r[$n-1] = $input->[$n-1]*8 + $input->[$n]; + + for (my $i=1; $i<$n; $i++) { + my $m = $a[$i]/$b[$i-1]; + $b[$i] = $b[$i] - $m*$c[$i-1]; + $r[$i] = $r[$i] - $m*$r[$i-1]; + } + + $p1->[$n-1] = SVG_doround($r[$n-1]/$b[$n-1], 0.5, 1); + for (my $i=$n-2; $i>=0; --$i) { + $p1->[$i] = SVG_doround(($r[$i] - $c[$i]*$p1->[$i+1]) / $b[$i], 0.5, 1); + } + + for (my $i=0; $i<$n-1; $i++) { + $p2->[$i] = SVG_doround($input->[$i+1]*2-$p1->[$i+1], 0.5, 1); + } + $p2->[$n-1] = SVG_doround(($input->[$n]+$p1->[$n-1])*0.5, 0.5, 1); + + return (1); +} + sub SVG_fmtTime($$) { diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html index 6dc7d5fc5..1da373a9e 100644 --- a/fhem/docs/commandref_frame.html +++ b/fhem/docs/commandref_frame.html @@ -1580,8 +1580,8 @@ The .gnuplot file consists of 3 parts: Specify the line type. Following types are recognized: points, steps, fsteps, histeps and lines. Everything unknown will be mapped to the type lines. - SVG special: cubic, cubicSmooth, quadratic, quadraticSmooth, are mapped - to the SVG path types C,S,Q and T respectively. + SVG special: cubic and quadratic, are mapped to the SVG path types C, + and Q respectively.
  • ls <linestyle>
    The linestyle defaults to l0 for the first line, l1 for the second, and diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html index 3baeef625..437b86c61 100644 --- a/fhem/docs/commandref_frame_DE.html +++ b/fhem/docs/commandref_frame_DE.html @@ -1700,8 +1700,8 @@ Die folgenden lokalen Attribute werden von mehreren Geräte verwendet: spezifiziert die Art der Linie. Folgende Linienarten können verwendet werden: points, steps, fsteps, histeps and lines. Nicht bekannte Linienarten werden als Typ "lines" dargestellt. - SVG Spezial: cubic, cubicSmooth, quadratic, quadraticSmooth werden zu - den SVG path Typen C,S,Q und T gewandelt. + SVG Spezial: cubic und quadratic werden zu den SVG path Typen C und Q + gewandelt.
  • ls <linestyle>