2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

SVG.pm: log scale

git-svn-id: https://svn.fhem.de/fhem/trunk@11478 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2016-05-18 10:15:20 +00:00
parent 0c50026378
commit b7481cac4b
2 changed files with 111 additions and 45 deletions

View File

@ -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 "<td>$t&nbsp;<input type=\"checkbox\" name=\"$v\" value=\"$v\"$c></td>";
return "$t&nbsp;<input type=\"checkbox\" name=\"$v\" value=\"$v\"$c>";
}
sub
@ -365,13 +376,17 @@ SVG_PEdit($$$$)
$ret .= "</tr>";
$ret .= "<tr class=\"even\">";
$ret .= "<td>Grid aligned</td>";
$ret .= SVG_cb("gridy", "left", $conf{hasygrid});
$ret .= SVG_cb("gridy2","right",$conf{hasy2grid});
$ret .= "<td>".SVG_cb("gridy", "left", $conf{hasygrid})."</td>";
$ret .= "<td>".SVG_cb("gridy2","right",$conf{hasy2grid})."</td>";
$ret .= "</tr>";
$ret .= "<tr class=\"odd\">";
$ret .= "<td>Range as [min:max]</td>";
$ret .= "<td>".SVG_txt("yrange", "left", $conf{yrange}, 16)."</td>";
$ret .= "<td>".SVG_txt("y2range", "right", $conf{y2range}, 16)."</td>";
$ret .= "<td>".SVG_txt("yrange", "left", $conf{yrange}, 16);
$ret .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".
SVG_cb("yscale", "log", $conf{yscale})."</td>";
$ret .= "<td>".SVG_txt("y2range", "right", $conf{y2range}, 16);
$ret .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".
SVG_cb("y2scale", "log", $conf{y2scale})."</td>";
$ret .= "</tr>";
if( $conf{xrange} ) {
$ret .= "<tr class=\"odd\"><td/><td>";
@ -453,8 +468,8 @@ SVG_PEdit($$$$)
$o .= $ph;
$o .= "</td><td>";
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 "<g$display>";
@ -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 "<polyline points=\"$off3,$off2 $off4,$off2\" $cll/>";
#--grids
@ -1732,12 +1762,20 @@ SVG_render($$$$$$$$$$)
}
$off2 += $th/4;
#-- text
SVG_pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$tlabel</text>";
SVG_pO
"<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$tlabel</text>";
}
}
#-- 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 " <polyline points=\"$off3,$off2 $off4,$off2\" $cll/>";
#--grids
@ -1753,7 +1791,9 @@ SVG_render($$$$$$$$$$)
$off2 += $th/4;
#-- text
my $txt = sprintf("%g", $i);
SVG_pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$txt</text>";
SVG_pO
"<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$txt</text>";
}
}
}
SVG_pO "</g>";
@ -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 "<!-- Warning: No axis for data item $idx defined -->"
if(!defined($a));
@ -1778,6 +1822,13 @@ SVG_render($$$$$$$$$$)
SVG_pO "<!-- Warning: No data item $idx defined -->" 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);

View File

@ -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);