From b7481cac4be374f5ec3e07df3755beaeec73d734 Mon Sep 17 00:00:00 2001
From: rudolfkoenig <>
Date: Wed, 18 May 2016 10:15:20 +0000
Subject: [PATCH] SVG.pm: log scale
git-svn-id: https://svn.fhem.de/fhem/trunk@11478 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/98_SVG.pm | 125 ++++++++++++++++++++++++++++++-------------
fhem/www/pgm2/svg.js | 31 +++++++----
2 files changed, 111 insertions(+), 45 deletions(-)
diff --git a/fhem/FHEM/98_SVG.pm b/fhem/FHEM/98_SVG.pm
index a8601fe8e..d676b9574 100755
--- a/fhem/FHEM/98_SVG.pm
+++ b/fhem/FHEM/98_SVG.pm
@@ -187,6 +187,17 @@ SVG_isEmbed($)
# $FW_userAgent !~ m/(iPhone|iPad|iPod).*OS (8|9)/));
}
+sub
+SVG_log10($)
+{
+ my ($n) = @_;
+
+ return 0.0000000001 if( $n <= 0 );
+
+ return log($n)/log(10);
+}
+
+
##################
sub
SVG_FwFn($$$$)
@@ -292,7 +303,7 @@ SVG_cb($$$)
{
my ($v,$t,$c) = @_;
$c = ($c ? " checked" : "");
- return "
";
$ret .= "Range as [min:max] | ";
- $ret .= "".SVG_txt("yrange", "left", $conf{yrange}, 16)." | ";
- $ret .= "".SVG_txt("y2range", "right", $conf{y2range}, 16)." | ";
+ $ret .= "".SVG_txt("yrange", "left", $conf{yrange}, 16);
+ $ret .= " ".
+ SVG_cb("yscale", "log", $conf{yscale})." | ";
+ $ret .= "".SVG_txt("y2range", "right", $conf{y2range}, 16);
+ $ret .= " ".
+ SVG_cb("y2scale", "log", $conf{y2scale})." | ";
$ret .= "
";
if( $conf{xrange} ) {
$ret .= " | ";
@@ -453,8 +468,8 @@ SVG_PEdit($$$$)
$o .= $ph;
$o .= " | ";
my $v = $conf{lAxis}[$idx];
- $o .= SVG_sel("axes_${idx}", "left,right",
- ($v && $v eq "x1y1") ? "left" : "right");
+ my $sel = ($v && $v eq "x1y1") ? "left" : "right";
+ $o .= SVG_sel("axes_${idx}", "left,right,left log,right log", $sel );
$o .= SVG_sel("type_${idx}",
"lines,points,steps,fsteps,histeps,bars,ibars,".
"cubic,quadratic,quadraticSmooth",
@@ -651,6 +666,8 @@ SVG_WriteGplot($)
push @rows, "set xrange $FW_webArgs{xrange}" if($FW_webArgs{xrange});
push @rows, "set yrange $FW_webArgs{yrange}" if($FW_webArgs{yrange});
push @rows, "set y2range $FW_webArgs{y2range}" if($FW_webArgs{y2range});
+ push @rows, "set yscale log" if($FW_webArgs{yscale});
+ push @rows, "set y2scale log" if($FW_webArgs{y2scale});
push @rows, "";
my @plot;
@@ -1671,33 +1688,38 @@ SVG_render($$$$$$$$$$)
my $dh = $hmax{$a} - $hmin{$a};
my $hmul = $dh>0 ? $h/$dh : $h;
+ my $idx = 1;
+ $idx = $1 if( $a =~ m/x\d+y(\d+)/ );
+
+ my $scale = "y".($idx)."scale";
+ $scale = "yscale" if( $idx == 1 );
+ my $log = "";
+ $log = $conf{$scale} if( $conf{$scale} );
+
# offsets
my ($align,$display,$cll);
- if( $a =~ m/x1y(\d)/ ) {
- my $idx = $1;
- if( $idx <= $use_left_axis ) {
- $off1 = $x - ($idx-1)*$axis_width-4-$th*0.3;
- $off3 = $x - ($idx-1)*$axis_width-4;
- $off4 = $off3+5;
- $align = " text-anchor=\"end\"";
- $display = "";
- $cll = "";
- } elsif( $idx <= $use_left_axis+$use_right_axis ) {
- $off1 = $x+4+$w+($idx-1-$use_left_axis)*$axis_width+$th*0.3;
- $off3 = $x+4+$w+($idx-1-$use_left_axis)*$axis_width-5;
- $off4 = $off3+5;
- $align = "";
- $display = "";
- $cll = "";
- } else {
- $off1 = $x-$th*0.3+30;
- $off3 = $x+30;
- $off4 = $off3+5;
- $align = " text-anchor=\"end\"";
- $display = " display=\"none\" id=\"hline_$idx\"";
- $cll = " class=\"SVGplot l$idx\"";
- }
- };
+ if( $idx <= $use_left_axis ) {
+ $off1 = $x - ($idx-1)*$axis_width-4-$th*0.3;
+ $off3 = $x - ($idx-1)*$axis_width-4;
+ $off4 = $off3+5;
+ $align = " text-anchor=\"end\"";
+ $display = "";
+ $cll = "";
+ } elsif( $idx <= $use_left_axis+$use_right_axis ) {
+ $off1 = $x+4+$w+($idx-1-$use_left_axis)*$axis_width+$th*0.3;
+ $off3 = $x+4+$w+($idx-1-$use_left_axis)*$axis_width-5;
+ $off4 = $off3+5;
+ $align = "";
+ $display = "";
+ $cll = "";
+ } else {
+ $off1 = $x-$th*0.3+30;
+ $off3 = $x+30;
+ $off4 = $off3+5;
+ $align = " text-anchor=\"end\"";
+ $display = " display=\"none\" id=\"hline_$idx\"";
+ $cll = " class=\"SVGplot l$idx\"";
+ }
#-- grouping
SVG_pO "";
@@ -1712,13 +1734,21 @@ SVG_render($$$$$$$$$$)
#-- tics as in the config-file
if($tic && $tic !~ m/mirror/) {
$tic =~ s/^\((.*)\)$/$1/; # Strip ()
+ for(my $decimal = 0;
+ $decimal < ($log eq 'log'?SVG_log10($hmax{$a}):1);
+ $decimal++ ) {
+ my $f = SVG_log10($hmax{$a}) / $hmax{$a};
foreach my $onetic (split(",", $tic)) {
$onetic =~ s/^ *(.*) *$/$1/;
my ($tlabel, $tvalue) = split(" ", $onetic);
$tlabel =~ s/^"(.*)"$/$1/;
$tvalue = 0 if( !$tvalue );
+ $tvalue /= 10 ** $decimal;
+ $tlabel = $tvalue if( !$tlabel );
$off2 = int($y+($hmax{$a}-$tvalue)*$hmul);
+ $off2 = int($y+($hmax{$a}-SVG_log10($tvalue)/$f)*$hmul)
+ if( $log eq 'log' );
#-- tics
SVG_pO "";
#--grids
@@ -1732,12 +1762,20 @@ SVG_render($$$$$$$$$$)
}
$off2 += $th/4;
#-- text
- SVG_pO "$tlabel";
+ SVG_pO
+ "$tlabel";
+ }
}
#-- tics automatically
} elsif( $hstep{$a}>0 ) {
+ for(my $decimal = 0;
+ $decimal < ($log eq 'log'?SVG_log10($hmax{$a}):1);
+ $decimal++ ) {
+ my $f = SVG_log10($hmax{$a}) / $hmax{$a};
for(my $i = $hmin{$a}; $i <= $hmax{$a}; $i += $hstep{$a}) {
+ my $i = $i / 10 ** $decimal;
$off2 = int($y+($hmax{$a}-$i)*$hmul);
+ $off2 = int($y+($hmax{$a}-SVG_log10($i)/$f)*$hmul) if( $log eq 'log' );
#-- tics
SVG_pO " ";
#--grids
@@ -1753,7 +1791,9 @@ SVG_render($$$$$$$$$$)
$off2 += $th/4;
#-- text
my $txt = sprintf("%g", $i);
- SVG_pO "$txt";
+ SVG_pO
+ "$txt";
+ }
}
}
SVG_pO "";
@@ -1764,6 +1804,10 @@ SVG_render($$$$$$$$$$)
# Second loop over the data: draw the measured points
for(my $idx=$#hdx; $idx >= 0; $idx--) {
my $a = $conf{lAxis}[$idx];
+ my $scale = "y".($idx+1)."scale";
+ $scale = "yscale" if( $idx == 0 );
+ my $log = "";
+ $log = $conf{$scale} if( $conf{$scale} );
SVG_pO ""
if(!defined($a));
@@ -1778,6 +1822,13 @@ SVG_render($$$$$$$$$$)
SVG_pO "" if(!defined($dxp));
next if(!defined($dxp));
+ if( $log eq 'log' ) {
+ my $f = SVG_log10($hmax{$a}) / $hmax{$a};
+ foreach my $i (1..int(@{$dxp})-1) {
+ $dyp->[$i] = SVG_log10($dyp->[$i]) / $f;
+ }
+ }
+
my $yh = $y+$h;
#-- Title attributes
my $tl = $conf{lTitle}[$idx] ? $conf{lTitle}[$idx] : "";
@@ -1785,8 +1836,11 @@ SVG_render($$$$$$$$$$)
my $dec = length(sprintf("%d",$hmul*3))-1;
$dec = 0 if($dec < 0);
my $attributes = "id=\"line_$idx\" decimals=\"$dec\" ".
- "x_off=\"$fromsec\" x_min=\"$x\" x_mul=\"$tmul\" ".
+ "x_min=\"$x\" ".
+ ($conf{xrange}?"x_off=\"$xmin\" ":"x_off=\"$fromsec\" ").
+ ($conf{xrange}?"x_mul=\"$xmul\" ":"t_mul=\"$tmul\" ").
"y_h=\"$yh\" y_min=\"$min\" y_mul=\"$hmul\" title=\"$tl\" ".
+ ($log eq 'log'?"log_scale=\"".SVG_log10($hmax{$a})/$hmax{$a}."\" ":"").
"onclick=\"parent.svg_click(evt)\" $conf{lWidth}[$idx]";
my $lStyle = $conf{lStyle}[$idx];
my $isFill = ($conf{lStyle}[$idx] =~ m/fill/);
@@ -1965,7 +2019,6 @@ SVG_render($$$$$$$$$$)
next if($x1 == $lx && $y1 == $ly);
-
# calc ymin/ymax for points with the same x coordinates
if($x1 == $lx && $i < $maxIdx) {
$ymin = $y1 if($y1 < $ymin);
diff --git a/fhem/www/pgm2/svg.js b/fhem/www/pgm2/svg.js
index 5cbe871d7..682fa2721 100644
--- a/fhem/www/pgm2/svg.js
+++ b/fhem/www/pgm2/svg.js
@@ -42,7 +42,8 @@ svg_load(key, nextFn)
function
svg_prepareHash(el)
{
- var obj = { y_mul:0,y_h:0,y_min:0, decimals:0, x_mul:0,x_off:0,x_min:0 };
+ var obj = { y_mul:0,y_h:0,y_min:0, decimals:0,
+ t_mul:0,x_off:0,x_min:0, x_mul:0, log_scale:undefined };
for(var name in obj)
obj[name] = parseFloat($(el).attr(name));
return obj;
@@ -55,7 +56,7 @@ svg_click(evt)
var o = svg_prepareHash(t);
var y_org = (((o.y_h-evt.clientY)/o.y_mul)+o.y_min).toFixed(o.decimals);
- var d = new Date((((evt.clientX-o.x_min)/o.x_mul)+o.x_off) * 1000);
+ var d = new Date((((evt.clientX-o.x_min)/o.t_mul)+o.x_off) * 1000);
var ts = (d.getHours() < 10 ? '0' : '') + d.getHours() + ":"+
(d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
@@ -254,15 +255,27 @@ sv_menu(evt, embed)
var xR = (xRaw-pp.x)/(pn.x-pp.x); // Compute interim values
var yRaw = pp.y+xR*(pn.y-pp.y);
- var y = (((par.y_h-yRaw)/par.y_mul)+par.y_min).toFixed(par.decimals);
+ var y = (((par.y_h-yRaw)/par.y_mul)+par.y_min);
+
+ if( par.log_scale ) {
+ y *= par.log_scale;
+ y = Math.pow(10,y);
+ }
+
+ y = y.toFixed(par.decimals);
+
+ if( par.x_mul ) {
+ ts = (((xRaw-par.x_min)/par.x_mul)+par.x_off).toFixed(par.decimals);
- var d = new Date((((xRaw-par.x_min)/par.x_mul)+par.x_off) * 1000), ts;
- if(par.x_mul < 0.0001) { // Year
- ts = (d.getMonth()+1)+"."+pad0(d.getDate());
- } else if(par.x_mul < 0.001) { // Month
- ts = d.getDate()+". "+pad0(d.getHours())+":"+pad0(d.getMinutes());
} else {
- ts = pad0(d.getHours())+":"+pad0(d.getMinutes());
+ var d = new Date((((xRaw-par.x_min)/par.t_mul)+par.x_off) * 1000), ts;
+ if(par.t_mul < 0.0001) { // Year
+ ts = (d.getMonth()+1)+"."+pad0(d.getDate());
+ } else if(par.t_mul < 0.001) { // Month
+ ts = d.getDate()+". "+pad0(d.getHours())+":"+pad0(d.getMinutes());
+ } else {
+ ts = pad0(d.getHours())+":"+pad0(d.getMinutes());
+ }
}
$(par.circle).attr("cx", xRaw).attr("cy", yRaw);
|