From 487daa426a38558a22eb17cf5f3ed29b64fa3c32 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Wed, 23 Dec 2020 00:23:38 +0100 Subject: [PATCH] Started CursorX & Executableobjects, --- qml/LogGraphCanvas.qml | 6 +- qml/ObjectLists.qml | 2 - qml/js/mathlib.js | 14 ++-- qml/js/objects.js | 177 +++++++++++++++++++++++++++++++++-------- qml/js/utils.js | 9 +++ 5 files changed, 167 insertions(+), 41 deletions(-) diff --git a/qml/LogGraphCanvas.qml b/qml/LogGraphCanvas.qml index bcfce5a..850daf1 100644 --- a/qml/LogGraphCanvas.qml +++ b/qml/LogGraphCanvas.qml @@ -35,6 +35,8 @@ Canvas { property double yaxisstep: 3 property string xlabel: "" property string ylabel: "" + property int maxgradx: 8 + property int maxgrady: 1000 onPaint: { //console.log('Redrawing') @@ -99,12 +101,12 @@ Canvas { // Axis graduation labels ctx.font = "14px sans-serif" - for(var xpow = -10; xpow <= 10; xpow+=1) { + 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+12+(6*(y==0))) } - for(var y = -Math.round(100/yaxisstep)*yaxisstep; y < canvas.ymax; y+=yaxisstep) { + for(var y = -Math.round(maxgrady/yaxisstep)*yaxisstep; y < canvas.ymax; y+=yaxisstep) { var textSize = ctx.measureText(y).width drawVisibleText(ctx, y, axisypx-3-textSize, y2px(y)+6+(6*(y==0))) } diff --git a/qml/ObjectLists.qml b/qml/ObjectLists.qml index d0cb167..e7f2308 100644 --- a/qml/ObjectLists.qml +++ b/qml/ObjectLists.qml @@ -84,7 +84,6 @@ ListView { MouseArea { anchors.fill: parent onClicked: { - console.log('Showing', objType, index, Objects.currentObjects[objType]) objEditor.obj = Objects.currentObjects[objType][index] objEditor.objType = objType objEditor.objIndex = index @@ -278,7 +277,6 @@ ListView { text: modelData width: createRow.width visible: Objects.types[modelData].createable() - Component.onCompleted: console.log(modelData, visible, Objects)//, Objects.type[modelData]) height: visible ? implicitHeight : 0 icon.source: './icons/'+modelData+'.svg' // Default to dark version diff --git a/qml/js/mathlib.js b/qml/js/mathlib.js index e392ecf..74bbf4d 100644 --- a/qml/js/mathlib.js +++ b/qml/js/mathlib.js @@ -33,7 +33,7 @@ class Expression { return this.expr.indexOf("x") == -1 } - evaluate(x = 0) { + execute(x = 1) { return this.calc.evaluate({ "x": x, "pi": Math.PI, @@ -45,6 +45,10 @@ class Expression { }) } + simplify(x = 1) { + return Utils.makeExpressionReadable(this.calc.substitute('x', x).simplify().toString()) + } + toEditableString() { return this.calc.toString() } @@ -83,8 +87,8 @@ class Domain { } includes(x) { - return ((this.openBegin && x > this.begin.evaluate()) || (!this.openBegin && x >= this.begin.evaluate())) && - ((this.openEnd && x < this.end.evaluate()) || (!this.openEnd && x <= this.end.evaluate())) + return ((this.openBegin && x > this.begin.execute()) || (!this.openBegin && x >= this.begin.execute())) && + ((this.openEnd && x < this.end.execute()) || (!this.openEnd && x <= this.end.execute())) } toString() { @@ -158,10 +162,10 @@ class DomainSet { } includes(x) { - var xcomputed = new Expression(x.toString()).evaluate() + var xcomputed = new Expression(x.toString()).execute() var found = false this.values.forEach(function(value){ - if(xcomputed == value.evaluate()) { + if(xcomputed == value.execute()) { found = true return } diff --git a/qml/js/objects.js b/qml/js/objects.js index a56b911..10bba62 100644 --- a/qml/js/objects.js +++ b/qml/js/objects.js @@ -32,13 +32,22 @@ function getNewName(allowedLetters, category) { } class DrawableObject { + // Class to extend for every type of object that + // can be drawn on the canvas. static type(){return 'Unknown'} + // Label used for the list on the ObjectsList sidebar. static typeMultiple(){return 'Unknown'} + // Whether this object can be created by the user + // or are instanciated by other objects. static createable() {return true} + // Properties are set with key as property name and + // value as it's type name (e.g 'Expression', 'string', + // 'Point'...) or an array with possibilities for enums. + // Used for property modifier in the sidebar. static properties() {return {}} constructor(name, visible = true, color = null, labelContent = 'name + value') { - if(color == null) color = this.getRandomColor() + if(color == null) color = Utils.getRandomColor() this.type = 'Unknown' this.name = name this.visible = visible @@ -47,15 +56,6 @@ class DrawableObject { this.requiredBy = [] } - getRandomColor() { - var x = '0123456789ABCDEF'; // Removing for less flashy colors. - var color = '#'; - for (var i = 0; i < 6; i++) { - color += x[Math.floor(Math.random() * (16-6*(i%2==0)))]; - } - return color; - } - getReadableString() { return `${this.name} = Unknown` } @@ -81,6 +81,18 @@ class DrawableObject { draw(canvas, ctx) {} } +class ExecutableObject extends DrawableObject { + // Class to be extended for every class upon which we + // calculate an y for a x with the execute function. + // If a value cannot be found during execute, it should + // return null. However, theses values should + // return false when passed to canExecute. + execute(x = 1) {return 0} + canExecute(x = 1) {return true} + // Simplify returns the simplified string of the expression. + simplify(x = 1) {return '0'} +} + class Point extends DrawableObject { static type(){return 'Point'} static typeMultiple(){return 'Points'} @@ -113,7 +125,7 @@ class Point extends DrawableObject { } draw(canvas, ctx) { - var [canvasX, canvasY] = [canvas.x2px(this.x.evaluate()), canvas.y2px(this.y.evaluate())] + var [canvasX, canvasY] = [canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute())] var pointSize = 8 switch(this.pointStyle) { case 'dot': @@ -153,14 +165,13 @@ class Point extends DrawableObject { update() { if(currentObjects['Somme gains Bode'] != undefined && currentObjects['Gain Bode'] != undefined) { for(var i = 0; i < currentObjects['Gain Bode'].length; i++) { - console.log(currentObjects['Gain Bode'][i].ω_0.name) if(currentObjects['Gain Bode'][i].ω_0.name == this.name) currentObjects['Gain Bode'][i].update() } } } } -class Function extends DrawableObject { +class Function extends ExecutableObject { static type(){return 'Function'} static typeMultiple(){return 'Functions'} static properties() {return { @@ -201,6 +212,22 @@ class Function extends DrawableObject { this.displayMode, this.labelPos, this.labelX] } + execute(x = 1) { + if(this.inDomain.includes(x)) + return this.expr.execute(x) + return null + } + + canExecute(x = 1) { + return this.inDomain.includes(x) + } + + simplify(x = 1) { + if(this.inDomain.includes(x)) + return this.expr.simplify(x) + return '' + } + draw(canvas, ctx) { Function.drawFunction(canvas, ctx, this.expression, this.inDomain, this.outDomain) // Label @@ -208,7 +235,7 @@ class Function extends DrawableObject { ctx.font = "14px sans-serif" var textSize = canvas.measureText(ctx, text) var posX = canvas.x2px(this.labelX) - var posY = canvas.y2px(this.expression.evaluate(this.labelX)) + var posY = canvas.y2px(this.expression.execute(this.labelX)) switch(this.labelPos) { case 'above': canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height) @@ -225,10 +252,10 @@ class Function extends DrawableObject { // Drawing small traits every 2px var pxprecision = 2 var previousX = canvas.px2x(0) - var previousY = expr.evaluate(previousX) + var previousY = expr.execute(previousX) for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) { var currentX = canvas.px2x(px) - var currentY = expr.evaluate(currentX) + var currentY = expr.execute(currentX) if((inDomain.includes(currentX) || inDomain.includes(previousX)) && (outDomain.includes(currentY) || outDomain.includes(previousY)) && Math.abs(previousY-currentY)<100) { // 100 per 2px is a lot (probably inf to inf issue) @@ -240,7 +267,7 @@ class Function extends DrawableObject { } } -class GainBode extends DrawableObject { +class GainBode extends ExecutableObject { static type(){return 'Gain Bode'} static typeMultiple(){return 'Gains Bode'} static properties() {return { @@ -263,9 +290,10 @@ class GainBode extends DrawableObject { // Create new point ω_0 = createNewRegisteredObject('Point') ω_0.name = getNewName('ω', 'Gain Bode') + ω_0.color = this.color + labelPos = 'below' } } - console.log(this, ω_0) this.ω_0 = ω_0 this.pass = pass if(typeof gain == 'number' || typeof gain == 'string') gain = new MathLib.Expression(gain.toString()) @@ -284,18 +312,31 @@ class GainBode extends DrawableObject { this.ω_0.name, this.pass.toString(), this.gain.toEditableString(), this.labelPos, this.labelX] } - evaluate(x=1) { + execute(x=1) { if((this.pass == 'high' && x < this.ω_0.x) || (this.pass == 'low' && x > this.ω_0.x)) { - var dbfn = new MathLib.Expression(`${this.gain.evaluate()}*(ln(x)-ln(${this.ω_0.x}))/ln(10)+${this.ω_0.y}`) - return dbfn.evaluate(x) + var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.ω_0.x}))/ln(10)+${this.ω_0.y}`) + return dbfn.execute(x) } else { - return this.ω_0.y.evaluate() + return this.ω_0.y.execute() } } + simplify(x = 1) { + if((this.pass == 'high' && x < this.ω_0.x) || (this.pass == 'low' && x > this.ω_0.x)) { + var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.ω_0.x}))/ln(10)+${this.ω_0.y}`) + return dbfn.simplify(x) + } else { + return this.ω_0.y.toString() + } + } + + canExecute(x = 1) { + return true + } + draw(canvas, ctx) { var base = [canvas.x2px(this.ω_0.x), canvas.y2px(this.ω_0.y)] - var dbfn = new MathLib.Expression(`${this.gain.evaluate()}*(ln(x)-ln(${this.ω_0.x}))/ln(10)+${this.ω_0.y}`) + var dbfn = new MathLib.Expression(`${this.gain.execute()}*(ln(x)-ln(${this.ω_0.x}))/ln(10)+${this.ω_0.y}`) var inDrawDom = new MathLib.EmptySet() if(this.pass == 'high') { @@ -314,7 +355,7 @@ class GainBode extends DrawableObject { ctx.font = "14px sans-serif" var textSize = canvas.measureText(ctx, text) var posX = canvas.x2px(this.labelX) - var posY = canvas.y2px(this.evaluate(this.labelX)) + var posY = canvas.y2px(this.execute(this.labelX)) switch(this.labelPos) { case 'above': canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height) @@ -360,6 +401,30 @@ class SommeGainsBode extends DrawableObject { return `${this.name} = ${getObjectsName('Gain Bode').join(' + ')}` } + execute(x = 0) { + for(var i=0; i types[objType].prototype instanceof ExecutableObject) + var elementNames = [] + elementTypes.forEach(function(elemType){ + elementNames = elementNames.concat(currentObjects[elemType].map(obj => obj.name)) + }) + console.log(currentObjects[elementTypes[0]].map(obj => obj.name), elementNames, elementNames[0], elementTypes, Array.isArray(elementNames)) + return { + 'x': 'Expression', + 'element': elementNames, + 'labelPos': ['left', 'right'], + } + } + + constructor(name = null, visible = true, color = null, labelContent = 'name + value', + x = 1, element = null, labelPos = 'left') { + if(name == null) name = getNewName('ABCDEFJKLMNOPQRSTUVW', 'Point') + super(name, visible, color, labelContent) + this.type = 'CursorX' + if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString()) + this.getElement() + this.labelPost = labelPos + } + + update() { + if(typeof this.element == 'string') this.getElement() + console.log(this.element) + } + + getElement(){ + var element = this.element + var elem = null + Object.keys(currentObjects).forEach(function(objType){ + var ele = getObjectByName(objType, element) + if(ele != null) elem = ele + }) + this.element = elem + } +} + const types = { 'Point': Point, 'Function': Function, 'Gain Bode': GainBode, - 'Somme gains Bode': SommeGainsBode + 'Somme gains Bode': SommeGainsBode, + 'CursorX': CursorX } var currentObjects = {} diff --git a/qml/js/utils.js b/qml/js/utils.js index c434722..6f682fc 100644 --- a/qml/js/utils.js +++ b/qml/js/utils.js @@ -202,3 +202,12 @@ function camelCase2readable(label) { var parsed = parseName(label, false) return parsed.charAt(0).toLatinUppercase() + parsed.slice(1).replace(/([A-Z])/g," $1") } + +function getRandomColor() { + var clrs = '0123456789ABCDEF'; + var color = '#'; + for (var i = 0; i < 6; i++) { + color += clrs[Math.floor(Math.random() * (16-6*(i%2==0)))]; + } + return color; +}