From 065b88bfd0d393f6c743ec5069e42950a7088db6 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Fri, 25 Dec 2020 16:44:53 +0100 Subject: [PATCH] Non logarithmic scale for X! Fixing bugs, domains. --- qml/LogGraph.qml | 1 + qml/LogGraphCanvas.qml | 86 +++++++++++++++++++++++++++--------------- qml/ObjectLists.qml | 1 - qml/Settings.qml | 13 ++++++- qml/js/mathlib.js | 1 - 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/qml/LogGraph.qml b/qml/LogGraph.qml index b18b2ac..960f3d8 100644 --- a/qml/LogGraph.qml +++ b/qml/LogGraph.qml @@ -105,6 +105,7 @@ ApplicationWindow { xlabel: settings.xaxislabel ylabel: settings.yaxislabel yaxisstep: settings.yaxisstep + logscalex: settings.logscalex onPaint: { var ctx = getContext("2d"); diff --git a/qml/LogGraphCanvas.qml b/qml/LogGraphCanvas.qml index 8d5404a..0d87480 100644 --- a/qml/LogGraphCanvas.qml +++ b/qml/LogGraphCanvas.qml @@ -37,7 +37,7 @@ Canvas { property string xlabel: "" property string ylabel: "" property int maxgradx: 8 - property int maxgrady: 1000 + property bool logscalex: false property var yaxisstepExpr: (new MathLib.Expression(`x*(${yaxisstep})`)) property double yaxisstep1: yaxisstepExpr.execute(1) @@ -72,9 +72,17 @@ Canvas { // Drawing the log based graph function drawGrille(ctx) { ctx.strokeStyle = "#C0C0C0" - for(var xpow = -10; xpow <= 10; xpow++) { - for(var xmulti = 1; xmulti < 10; xmulti++) { - drawXLine(ctx, Math.pow(10, xpow)*xmulti) + if(logscalex) { + for(var xpow = -maxgradx; xpow <= maxgradx; xpow++) { + for(var xmulti = 1; xmulti < 10; xmulti++) { + drawXLine(ctx, Math.pow(10, xpow)*xmulti) + } + } + } else { + for(var x = 0; x < 40*maxgradx; x+=1) { + // TODO: Fill screen based + drawXLine(ctx, x*yaxisstep1) + drawXLine(ctx, -x*yaxisstep1) } } for(var y = 0; y < drawMaxY; y+=1) { @@ -85,35 +93,47 @@ Canvas { function drawAxises(ctx) { ctx.strokeStyle = "#000000" - drawXLine(ctx, 1) + var axisypos = logscalex ? 1 : 0 + drawXLine(ctx, axisypos) drawYLine(ctx, 0) - var axisypx = x2px(1) // X coordinate of Y axis + var axisypx = x2px(axisypos) // X coordinate of Y axis var axisxpx = y2px(0) // Y coordinate of X axis // Drawing arrows drawLine(ctx, axisypx, 0, axisypx-10, 10) drawLine(ctx, axisypx, 0, axisypx+10, 10) - drawLine(ctx, canvas.canvasSize.width, axisxpx, canvas.canvasSize.width-10, axisxpx-10) - drawLine(ctx, canvas.canvasSize.width, axisxpx, canvas.canvasSize.width-10, axisxpx+10) + drawLine(ctx, canvasSize.width, axisxpx, canvasSize.width-10, axisxpx-10) + drawLine(ctx, canvasSize.width, axisxpx, canvasSize.width-10, axisxpx+10) } function drawLabels(ctx) { - var axisypx = x2px(1) // X coordinate of Y axis + var axisypx = x2px(logscalex ? 1 : 0) // X coordinate of Y axis var axisxpx = y2px(0) // Y coordinate of X axis // Labels ctx.fillStyle = "#000000" ctx.font = "16px sans-serif" - ctx.fillText(canvas.ylabel, axisypx+5, 24) - var textSize = ctx.measureText(canvas.xlabel).width - ctx.fillText(canvas.xlabel, canvas.canvasSize.width-14-textSize, axisxpx-5) + ctx.fillText(ylabel, axisypx+5, 24) + var textSize = ctx.measureText(xlabel).width + ctx.fillText(xlabel, canvasSize.width-14-textSize, axisxpx-5) // Axis graduation labels ctx.font = "12px sans-serif" - for(var xpow = -maxgradx; xpow <= maxgradx; xpow+=1) { - var textSize = ctx.measureText("10"+Utils.textsup(xpow)).width - if(xpow != 0) - drawVisibleText(ctx, "10"+Utils.textsup(xpow), x2px(Math.pow(10,xpow))-textSize/2, axisxpx+16+(6*(y==0))) - } var txtMinus = ctx.measureText('-').width + if(logscalex) { + for(var xpow = -maxgradx; xpow <= maxgradx; xpow+=1) { + var textSize = ctx.measureText("10"+Utils.textsup(xpow)).width + if(xpow != 0) + drawVisibleText(ctx, "10"+Utils.textsup(xpow), x2px(Math.pow(10,xpow))-textSize/2, axisxpx+16+(6*(y==0))) + } + } else { + for(var x = 0; x < 40*maxgradx; x += 1) { + var drawX = x*yaxisstep1 + var txtX = yaxisstepExpr.simplify(x) + var textSize = measureText(ctx, txtX, 6).height + if(x != 0) + drawVisibleText(ctx, txtX, x2px(drawX)-4, axisxpx+6+textSize) + drawVisibleText(ctx, '-'+txtX, x2px(-drawX)-4, axisxpx+6+textSize) + } + } for(var y = 0; y < drawMaxY; y += 1) { var drawY = y*yaxisstep1 var txtY = yaxisstepExpr.simplify(y) @@ -126,26 +146,26 @@ Canvas { } function drawXLine(ctx, x) { - if(visible(x, canvas.ymax)) { - drawLine(ctx, x2px(x), 0, x2px(x), canvas.canvasSize.height) + if(visible(x, ymax)) { + drawLine(ctx, x2px(x), 0, x2px(x), canvasSize.height) } } function drawYLine(ctx, y) { - if(visible(canvas.xmin, y)) { - drawLine(ctx, 0, y2px(y), canvas.canvasSize.width, y2px(y)) + if(visible(xmin, y)) { + drawLine(ctx, 0, y2px(y), canvasSize.width, y2px(y)) } } function drawVisibleText(ctx, text, x, y, lineHeight = 14) { - if(x > 0 && x < canvas.canvasSize.width && y > 0 && y < canvas.canvasSize.height) { + if(x > 0 && x < canvasSize.width && y > 0 && y < canvasSize.height) { text.toString().split("\n").forEach(function(txt, i){ ctx.fillText(txt, x, y+(lineHeight*i)) }) } } - // Method to calculate multiline string dimensions + // Method to calculate multi-line string dimensions function measureText(ctx, text, lineHeight=14) { var theight = 0 var twidth = 0 @@ -156,26 +176,30 @@ Canvas { return {'width': twidth, 'height': theight} } - // Converts x coordinate to it's relative position on the canvas. + // Converts x coordinate to it's relative position on the function x2px(x) { - var logxmin = Math.log(canvas.xmin) - return (Math.log(x)-logxmin)*canvas.xzoom + if(logscalex) { + var logxmin = Math.log(xmin) + return (Math.log(x)-logxmin)*xzoom + } else return (x - xmin)*xzoom } - // Converts y coordinate to it's relative position on the canvas. + // Converts y coordinate to it's relative position on the // Y is NOT ln based. function y2px(y) { - return (canvas.ymax-y)*canvas.yzoom + return (ymax-y)*yzoom } // Reverse functions function px2x(px) { - return Math.exp(px/canvas.xzoom+Math.log(canvas.xmin)) + if(logscalex) { + return Math.exp(px/xzoom+Math.log(xmin)) + } else return (px/xzoom+xmin) } function px2y(px) { - return -(px/canvas.yzoom-canvas.ymax) + return -(px/yzoom-ymax) } // Checks whether a point is visible or not. function visible(x, y) { - return (x2px(x) >= 0 && x2px(x) <= canvas.canvasSize.width) && (y2px(y) >= 0 && y2px(y) <= canvas.canvasSize.height) + return (x2px(x) >= 0 && x2px(x) <= canvasSize.width) && (y2px(y) >= 0 && y2px(y) <= canvasSize.height) } // Draws a line from a (x1, y1) to (x2, y2) function drawLine(ctx, x1, y1, x2, y2) { diff --git a/qml/ObjectLists.qml b/qml/ObjectLists.qml index fa368f1..cb2402d 100644 --- a/qml/ObjectLists.qml +++ b/qml/ObjectLists.qml @@ -55,7 +55,6 @@ ListView { id: typeVisibilityCheckBox checked: Objects.currentObjects[objType] != undefined ? Objects.currentObjects[objType].every(obj => obj.visible) : true onClicked: { - console.log(Objects.currentObjects[objType].every(obj => obj.visible)) Objects.currentObjects[objType].forEach(obj => obj.visible = this.checked) objTypeList.editingRows.forEach(obj => obj.objVisible = this.checked) objectListList.changed() diff --git a/qml/Settings.qml b/qml/Settings.qml index eef4ba9..86715c8 100644 --- a/qml/Settings.qml +++ b/qml/Settings.qml @@ -37,6 +37,7 @@ Column { property string yaxisstep: "4" property string xaxislabel: "" property string yaxislabel: "" + property bool logscalex: true property string saveFilename: "" FileDialog { @@ -88,7 +89,7 @@ Column { id: minX height: 30 isDouble: true - min: 0 + min: -Infinity label: "Min X" width: settings.settingWidth defValue: settings.xmin @@ -175,6 +176,16 @@ Column { Component.onCompleted: editText = settings.yaxislabel } + CheckBox { + id: logScaleX + checked: settings.logscalex + text: 'X Log scale' + onClicked: { + settings.logscalex = checked + settings.changed() + } + } + Button { id: copyToClipboard height: 30 diff --git a/qml/js/mathlib.js b/qml/js/mathlib.js index edbe448..e54166d 100644 --- a/qml/js/mathlib.js +++ b/qml/js/mathlib.js @@ -412,7 +412,6 @@ function parseDomain(domain) { } function parseDomainSimple(domain) { - console.log('Parsing domain', domain, typeof domain) if(domain[0] == 'D') return refedDomains[parseInt(domain.substr(1))] if(domain.indexOf("U") >= 0 || domain.indexOf("∪") >= 0) return UnionDomain.import(domain) if(domain.indexOf("∩") >= 0) return IntersectionDomain.import(domain)