Imperfect implementation, but working sequences.
This commit is contained in:
parent
7e47b3cdf9
commit
422aa5b4c7
6 changed files with 205 additions and 65 deletions
|
@ -71,7 +71,7 @@ Column {
|
||||||
if(value.toString()=="NaN")
|
if(value.toString()=="NaN")
|
||||||
value = ""
|
value = ""
|
||||||
}
|
}
|
||||||
if(value != "" && valueInput.acceptableInput) {
|
if(value !== "" && valueInput.acceptableInput) {
|
||||||
control.model.setProperty(index, 'key', value)
|
control.model.setProperty(index, 'key', value)
|
||||||
control.changed()
|
control.changed()
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ Column {
|
||||||
if(value.toString()=="NaN")
|
if(value.toString()=="NaN")
|
||||||
value = ""
|
value = ""
|
||||||
}
|
}
|
||||||
if(value != "" && keyInput.acceptableInput) {
|
if(value !== "" && keyInput.acceptableInput) {
|
||||||
control.model.setProperty(index, 'val', value)
|
control.model.setProperty(index, 'val', value)
|
||||||
control.changed()
|
control.changed()
|
||||||
}
|
}
|
||||||
|
@ -153,6 +153,7 @@ Column {
|
||||||
var ret = []
|
var ret = []
|
||||||
for(var i = 0; i < model.count; i++)
|
for(var i = 0; i < model.count; i++)
|
||||||
ret.push(model.get(i).val)
|
ret.push(model.get(i).val)
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,13 +128,12 @@ Canvas {
|
||||||
drawVisibleText(ctx, "10"+Utils.textsup(xpow), x2px(Math.pow(10,xpow))-textSize/2, axisxpx+16+(6*(y==0)))
|
drawVisibleText(ctx, "10"+Utils.textsup(xpow), x2px(Math.pow(10,xpow))-textSize/2, axisxpx+16+(6*(y==0)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(var x = 0; x < 40*maxgradx; x += 1) {
|
for(var x = 1; x < drawMaxX; x += 1) {
|
||||||
var drawX = x*yaxisstep1
|
var drawX = x*xaxisstep1
|
||||||
var txtX = yaxisstepExpr.simplify(x)
|
var txtX = xaxisstepExpr.simplify(x)
|
||||||
var textSize = measureText(ctx, txtX, 6).height
|
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)
|
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) {
|
for(var y = 0; y < drawMaxY; y += 1) {
|
||||||
|
|
|
@ -359,6 +359,7 @@ ListView {
|
||||||
|
|
||||||
onChanged: {
|
onChanged: {
|
||||||
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = exportModel()
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = exportModel()
|
||||||
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
|
||||||
objectListList.update()
|
objectListList.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
const parser = new ExprEval.Parser()
|
const parser = new ExprEval.Parser()
|
||||||
|
|
||||||
var u = {1: 1, 2: 2, 3: 3}
|
var u = {1: 1, 2: 2, 3: 3}
|
||||||
console.log(parser.parse('u[n]+u[n+1]+u[n+2]').simplify().evaluate({"u": u, 'n': 1}))
|
|
||||||
|
|
||||||
var evalVariables = { // Variables not provided by expr-eval.js, needs to be provided manualy
|
var evalVariables = { // Variables not provided by expr-eval.js, needs to be provided manualy
|
||||||
"pi": Math.PI,
|
"pi": Math.PI,
|
||||||
|
@ -45,7 +44,7 @@ class Expression {
|
||||||
}
|
}
|
||||||
|
|
||||||
isConstant() {
|
isConstant() {
|
||||||
return this.expr.indexOf("x") == -1
|
return !this.expr.includes("x") && !this.expr.includes("n")
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(x = 1) {
|
execute(x = 1) {
|
||||||
|
@ -81,33 +80,69 @@ function executeExpression(expr){
|
||||||
class Sequence extends Expression {
|
class Sequence extends Expression {
|
||||||
constructor(name, baseValues = {}, valuePlus = 1, expr = "") {
|
constructor(name, baseValues = {}, valuePlus = 1, expr = "") {
|
||||||
// u[n+valuePlus] = expr
|
// u[n+valuePlus] = expr
|
||||||
console.log('Expression', expr)
|
|
||||||
super(expr)
|
super(expr)
|
||||||
this.name = name
|
this.name = name
|
||||||
this.baseValues = baseValues
|
this.baseValues = baseValues
|
||||||
this.valuePlus = valuePlus
|
this.calcValues = Object.assign({}, baseValues)
|
||||||
|
for(var n in this.calcValues)
|
||||||
|
if(['string', 'number'].includes(typeof this.calcValues[n]))
|
||||||
|
this.calcValues[n] = parser.parse(this.calcValues[n].toString()).simplify()
|
||||||
|
this.valuePlus = parseInt(valuePlus)
|
||||||
}
|
}
|
||||||
|
|
||||||
isConstant() {
|
isConstant() {
|
||||||
return this.expr.indexOf("n") == -1
|
return this.expr.indexOf("n") == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(n = 0) {
|
execute(n = 1) {
|
||||||
if(this.cached) return this.cachedValue
|
if(n in this.calcValues)
|
||||||
if(n in this.baseValues) return this.baseValues[n]
|
return this.calcValues[n].evaluate(evalVariables)
|
||||||
var vars = Object.assign({'n': n-this.valuePlus}, evalVariables)
|
this.cache(n)
|
||||||
vars[this.name] = this.baseValues
|
return this.calcValues[n].evaluate(evalVariables)
|
||||||
var un = this.calc.evaluate(vars)
|
}
|
||||||
this.baseValues[n] = un
|
|
||||||
return un
|
simplify(n = 1) {
|
||||||
|
if(n in this.calcValues)
|
||||||
|
return Utils.makeExpressionReadable(this.calcValues[n].toString())
|
||||||
|
this.cache(n)
|
||||||
|
return Utils.makeExpressionReadable(this.calcValues[n].toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
cache(n = 1) {
|
||||||
|
var str = this.calc.substitute('n', n-this.valuePlus).toString()
|
||||||
|
for(var newn in this.calcValues) {
|
||||||
|
var un = new RegExp(`${this.name}\\[${newn}\\]`, 'g')
|
||||||
|
if(un.test(str)) {
|
||||||
|
if (this.calcValues[newn] == undefined)
|
||||||
|
this.cache(newn)
|
||||||
|
str = str.replace(un, this.calcValues[newn])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var expr = parser.parse(str).simplify()
|
||||||
|
if(expr.evaluate(evalVariables) == 0) expr = parser.parse('0')
|
||||||
|
console.log(n, expr.toString())
|
||||||
|
expr = parser.parse(Utils.simplifyExpression(expr.toString())).simplify()
|
||||||
|
this.calcValues[n] = expr
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(forceSign=false) {
|
||||||
|
var str = Utils.makeExpressionReadable(this.calc.toString())
|
||||||
|
if(str[0] != '-' && forceSign) str = '+' + str
|
||||||
|
var subtxt = this.valuePlus == 0 ? 'ₙ' : Utils.textsub('n+' + this.valuePlus)
|
||||||
|
var ret = `${this.name}${subtxt} = ${str}${this.baseValues.length == 0 ? '' : "\n"}`
|
||||||
|
ret += Object.keys(this.baseValues).map(
|
||||||
|
n => `${this.name}${Utils.textsub(n)} = ${this.baseValues[n]}`
|
||||||
|
).join('; ')
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var test = new Sequence('u', {0: 0, 1: 1}, 2, '3*u[n]+3')
|
var test = new Sequence('u', {0: '0', 1: 'π'}, 2, '3*u[n]')
|
||||||
console.log(test)
|
console.log(test)
|
||||||
for(var i=0; i<20; i++)
|
for(var i=0; i<20; i++) {
|
||||||
|
//console.log('u' + Utils.textsub(i) + ' = ' + test.simplify(i))
|
||||||
console.log('u' + Utils.textsub(i) + ' = ' + test.execute(i))
|
console.log('u' + Utils.textsub(i) + ' = ' + test.execute(i))
|
||||||
|
}
|
||||||
// Domains
|
// Domains
|
||||||
class Domain {
|
class Domain {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
|
@ -45,10 +45,10 @@ class DrawableObject {
|
||||||
// or are instanciated by other objects.
|
// or are instanciated by other objects.
|
||||||
static createable() {return true}
|
static createable() {return true}
|
||||||
// Properties are set with key as property name and
|
// Properties are set with key as property name and
|
||||||
// value as it's type name (e.g 'Expression', 'string',
|
// value as it's type name (e.g 'Expression', 'string'...),
|
||||||
// 'Point'...), an Array for enumerations,
|
// an Enum for enumerations, an ObjectType for DrawableObjects
|
||||||
// a List instance for lists, a Dictionary instance for
|
// with a specific type, a List instance for lists, a
|
||||||
// dictionary
|
// Dictionary instance for dictionaries...
|
||||||
// Used for property modifier in the sidebar.
|
// Used for property modifier in the sidebar.
|
||||||
static properties() {return {}}
|
static properties() {return {}}
|
||||||
|
|
||||||
|
@ -206,12 +206,16 @@ class Function extends ExecutableObject {
|
||||||
'comment1': 'Ex: R+* (ℝ⁺*), N* (ℕ*), Z-* (ℤ⁻*), ]0;1[, {3;4;5}',
|
'comment1': 'Ex: R+* (ℝ⁺*), N* (ℕ*), Z-* (ℤ⁻*), ]0;1[, {3;4;5}',
|
||||||
'labelPosition': new P.Enum('above', 'below'),
|
'labelPosition': new P.Enum('above', 'below'),
|
||||||
'displayMode': new P.Enum('application', 'function'),
|
'displayMode': new P.Enum('application', 'function'),
|
||||||
'labelX': 'number'
|
'labelX': 'number',
|
||||||
|
'comment1': 'The following parameters are used in case of non-continuous ensembles\n(E.g: ℕ, ℤ, sets like {0;3}...)',
|
||||||
|
'drawPoints': 'Boolean',
|
||||||
|
'drawDashedLines': 'Boolean'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
expression = 'x', inDomain = 'RPE', outDomain = 'R',
|
expression = 'x', inDomain = 'RPE', outDomain = 'R',
|
||||||
displayMode = 'application', labelPosition = 'above', labelX = 1) {
|
displayMode = 'application', labelPosition = 'above', labelX = 1,
|
||||||
|
drawPoints = true, drawDashedLines = true) {
|
||||||
if(name == null) name = getNewName('fghjqlmnopqrstuvwabcde')
|
if(name == null) name = getNewName('fghjqlmnopqrstuvwabcde')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.type = 'Function'
|
this.type = 'Function'
|
||||||
|
@ -224,6 +228,8 @@ class Function extends ExecutableObject {
|
||||||
this.displayMode = displayMode
|
this.displayMode = displayMode
|
||||||
this.labelPosition = labelPosition
|
this.labelPosition = labelPosition
|
||||||
this.labelX = labelX
|
this.labelX = labelX
|
||||||
|
this.drawPoints = drawPoints
|
||||||
|
this.drawDashedLines = drawDashedLines
|
||||||
}
|
}
|
||||||
|
|
||||||
getReadableString() {
|
getReadableString() {
|
||||||
|
@ -237,7 +243,7 @@ class Function extends ExecutableObject {
|
||||||
export() {
|
export() {
|
||||||
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
||||||
this.expression.toEditableString(), this.inDomain.toString(), this.outDomain.toString(),
|
this.expression.toEditableString(), this.inDomain.toString(), this.outDomain.toString(),
|
||||||
this.displayMode, this.labelPosition, this.labelX]
|
this.displayMode, this.labelPosition, this.labelX, this.drawPoints, this.drawDashedLines]
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(x = 1) {
|
execute(x = 1) {
|
||||||
|
@ -257,13 +263,13 @@ class Function extends ExecutableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(canvas, ctx) {
|
draw(canvas, ctx) {
|
||||||
Function.drawFunction(canvas, ctx, this.expression, this.inDomain, this.outDomain)
|
Function.drawFunction(canvas, ctx, this.expression, this.inDomain, this.outDomain, this.drawPoints, this.drawDashedLines)
|
||||||
// Label
|
// Label
|
||||||
var text = this.getLabel()
|
var text = this.getLabel()
|
||||||
ctx.font = "14px sans-serif"
|
ctx.font = "14px sans-serif"
|
||||||
var textSize = canvas.measureText(ctx, text, 7)
|
var textSize = canvas.measureText(ctx, text, 7)
|
||||||
var posX = canvas.x2px(this.labelX)
|
var posX = canvas.x2px(this.labelX)
|
||||||
var posY = canvas.y2px(this.expression.execute(this.labelX))
|
var posY = canvas.y2px(this.execute(this.labelX))
|
||||||
switch(this.labelPosition) {
|
switch(this.labelPosition) {
|
||||||
case 'above':
|
case 'above':
|
||||||
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
|
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
|
||||||
|
@ -275,32 +281,39 @@ class Function extends ExecutableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static drawFunction(canvas, ctx, expr, inDomain, outDomain) {
|
static drawFunction(canvas, ctx, expr, inDomain, outDomain, drawPoints = true, drawDash = true) {
|
||||||
// Reusable in other objects.
|
// Reusable in other objects.
|
||||||
// Drawing small traits every 2px
|
// Drawing small traits every 2px
|
||||||
var pxprecision = 2
|
var pxprecision = 2
|
||||||
var previousX = canvas.px2x(0)
|
var previousX = canvas.px2x(0)
|
||||||
var previousY;
|
var previousY;
|
||||||
if(inDomain instanceof MathLib.SpecialDomain && inDomain.moveSupported) {
|
if(inDomain instanceof MathLib.SpecialDomain && inDomain.moveSupported) {
|
||||||
|
// Point based functions.
|
||||||
previousX = inDomain.previous(previousX)
|
previousX = inDomain.previous(previousX)
|
||||||
if(previousX === null) previousX = inDomain.next(canvas.px2x(0))
|
if(previousX === null) previousX = inDomain.next(canvas.px2x(0))
|
||||||
previousY = expr.execute(previousX)
|
previousY = expr.execute(previousX)
|
||||||
|
if(!drawPoints && !drawDash) return
|
||||||
while(previousX !== null && canvas.x2px(previousX) < canvas.canvasSize.width) {
|
while(previousX !== null && canvas.x2px(previousX) < canvas.canvasSize.width) {
|
||||||
var currentX = inDomain.next(previousX)
|
var currentX = inDomain.next(previousX)
|
||||||
var currentY = expr.execute(currentX)
|
var currentY = expr.execute(currentX)
|
||||||
if(currentX === null) break;
|
if(currentX === null) break;
|
||||||
if((inDomain.includes(currentX) || inDomain.includes(previousX)) &&
|
if((inDomain.includes(currentX) || inDomain.includes(previousX)) &&
|
||||||
(outDomain.includes(currentY) || outDomain.includes(previousY))) {
|
(outDomain.includes(currentY) || outDomain.includes(previousY))) {
|
||||||
canvas.drawDashedLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
|
if(drawDash)
|
||||||
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
|
canvas.drawDashedLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
|
||||||
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
|
if(drawPoints) {
|
||||||
|
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
|
||||||
|
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
previousX = currentX
|
previousX = currentX
|
||||||
previousY = currentY
|
previousY = currentY
|
||||||
}
|
}
|
||||||
// Drawing the last cross
|
if(drawPoints) {
|
||||||
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
|
// Drawing the last cross
|
||||||
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
|
ctx.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2)
|
||||||
|
ctx.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
previousY = expr.execute(previousX)
|
previousY = expr.execute(previousX)
|
||||||
for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) {
|
for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) {
|
||||||
|
@ -843,6 +856,7 @@ class CursorX extends DrawableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetElement() {
|
getTargetElement() {
|
||||||
|
// TODO: Use the dependency system instead.
|
||||||
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
||||||
return getObjectByName(this.targetElement, elementTypes)
|
return getObjectByName(this.targetElement, elementTypes)
|
||||||
}
|
}
|
||||||
|
@ -922,17 +936,65 @@ class Sequence extends ExecutableObject {
|
||||||
static type(){return 'Sequence'}
|
static type(){return 'Sequence'}
|
||||||
static typeMultiple(){return 'Sequences'}
|
static typeMultiple(){return 'Sequences'}
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
'defaultExpression': new P.Dictionary('string', 'int', /^.+$/, /^(\d+)$/, '{name}[n+', '] = ', true),
|
'drawPoints': 'Boolean',
|
||||||
|
'drawDashedLines': 'Boolean',
|
||||||
|
'defaultExpression': new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[n+', '] = ', true),
|
||||||
'comment1': 'Note: Use {name}[n] to refer to {name}ₙ, {name}[n+1] for {name}ₙ₊₁...',
|
'comment1': 'Note: Use {name}[n] to refer to {name}ₙ, {name}[n+1] for {name}ₙ₊₁...',
|
||||||
'markedValues': new P.Dictionary('string', 'int', /^.+$/, /^(\d+)$/, '{name}[', '] = '),
|
'baseValues': new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[', '] = '),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
defaultExp = {1: "u[n]"}, markedValues = {0: 0}) {
|
drawPoints = true, drawDashedLines = true, defaultExp = {1: "n"},
|
||||||
|
baseValues = {0: 0}) {
|
||||||
if(name == null) name = getNewName('uvwPSUVWabcde')
|
if(name == null) name = getNewName('uvwPSUVWabcde')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
|
this.drawPoints = drawPoints
|
||||||
|
this.drawDashedLines = drawDashedLines
|
||||||
this.defaultExpression = defaultExp
|
this.defaultExpression = defaultExp
|
||||||
this.markedValues = markedValues
|
this.baseValues = baseValues
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
||||||
|
this.drawPoints, this.drawDashedLines, this.defaultExpression, this.baseValues]
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
super.update()
|
||||||
|
if(
|
||||||
|
this.sequence == null || this.baseValues != this.sequence.baseValues ||
|
||||||
|
this.sequence.name != this.name ||
|
||||||
|
this.sequence.expr != Object.values(this.defaultExpression)[0] ||
|
||||||
|
this.sequence.valuePlus != Object.keys(this.defaultExpression)[0]
|
||||||
|
)
|
||||||
|
this.sequence = new MathLib.Sequence(
|
||||||
|
this.name, this.baseValues,
|
||||||
|
Object.keys(this.defaultExpression)[0],
|
||||||
|
Object.values(this.defaultExpression)[0]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getReadableString() {
|
||||||
|
return this.sequence.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(x = 1) {
|
||||||
|
if(x % 1 == 0)
|
||||||
|
return this.sequence.execute(x)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
canExecute(x = 1) {return x%1 == 0}
|
||||||
|
// Simplify returns the simplified string of the expression.
|
||||||
|
simplify(x = 1) {
|
||||||
|
if(x % 1 == 0)
|
||||||
|
return this.sequence.simplify(x)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(canvas, ctx) {
|
||||||
|
Function.drawFunction(canvas, ctx, this.sequence, canvas.logscalex ? MathLib.Domain.NE : MathLib.Domain.N, MathLib.Domain.R, this.drawPoints, this.drawDashedLines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
|
|
||||||
var powerpos = {
|
var powerpos = {
|
||||||
"-": "⁻",
|
"-": "⁻",
|
||||||
|
"+": "⁺",
|
||||||
|
"=": "⁼",
|
||||||
|
" ": " ",
|
||||||
"0": "⁰",
|
"0": "⁰",
|
||||||
"1": "¹",
|
"1": "¹",
|
||||||
"2": "²",
|
"2": "²",
|
||||||
|
@ -30,8 +33,6 @@ var powerpos = {
|
||||||
"7": "⁷",
|
"7": "⁷",
|
||||||
"8": "⁸",
|
"8": "⁸",
|
||||||
"9": "⁹",
|
"9": "⁹",
|
||||||
"+": "⁺",
|
|
||||||
"=": "⁼",
|
|
||||||
"a": "ᵃ",
|
"a": "ᵃ",
|
||||||
"b": "ᵇ",
|
"b": "ᵇ",
|
||||||
"c": "ᶜ",
|
"c": "ᶜ",
|
||||||
|
@ -56,11 +57,14 @@ var powerpos = {
|
||||||
"w": "ʷ",
|
"w": "ʷ",
|
||||||
"x": "ˣ",
|
"x": "ˣ",
|
||||||
"y": "ʸ",
|
"y": "ʸ",
|
||||||
"z": "ᶻ",
|
"z": "ᶻ"
|
||||||
}
|
}
|
||||||
|
|
||||||
var indicepos = {
|
var indicepos = {
|
||||||
"-": "₋",
|
"-": "₋",
|
||||||
|
"+": "₊",
|
||||||
|
"=": "₌",
|
||||||
|
" ": " ",
|
||||||
"0": "₀",
|
"0": "₀",
|
||||||
"1": "₁",
|
"1": "₁",
|
||||||
"2": "₂",
|
"2": "₂",
|
||||||
|
@ -71,8 +75,6 @@ var indicepos = {
|
||||||
"7": "₇",
|
"7": "₇",
|
||||||
"8": "₈",
|
"8": "₈",
|
||||||
"9": "₉",
|
"9": "₉",
|
||||||
"+": "₊",
|
|
||||||
"=": "₌",
|
|
||||||
"a": "ₐ",
|
"a": "ₐ",
|
||||||
"e": "ₑ",
|
"e": "ₑ",
|
||||||
"h": "ₕ",
|
"h": "ₕ",
|
||||||
|
@ -122,12 +124,46 @@ function textsub(text) {
|
||||||
function simplifyExpression(str) {
|
function simplifyExpression(str) {
|
||||||
var replacements = [
|
var replacements = [
|
||||||
// Operations not done by parser.
|
// Operations not done by parser.
|
||||||
|
[// Decomposition way 2
|
||||||
|
/(^.?|[+-] |\()([-.\d\w]+) ([*/]) \((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\)(.?$| [+-]|\))/g,
|
||||||
|
"$1$2 $3 $4 $6 $2 $3 $7$9"
|
||||||
|
],
|
||||||
|
[ // Decomposition way 2
|
||||||
|
/(^.?|[+-] |\()\((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\) ([*/]) ([-.\d\w]+)(.?$| [+-]|\))/g,
|
||||||
|
"$1$8 $7 $2 $4 $8 $7 $5$9"
|
||||||
|
],
|
||||||
|
[ // Factorisation of π elements.
|
||||||
|
/(([-\d\w.]+ [*/] )*)(pi|π)(( [/*] [-\d\w.]+)*) ([+-]) (([-\d\w.]+ [*/] )*)(pi|π)(( [/*] [-\d\w.]+)*)?/g,
|
||||||
|
function(match, m1, n1, pi1, m2, ope2, n2, opeM, m3, n3, pi2, m4, ope4, n4) {
|
||||||
|
// g1, g2, g3 , g4, g5, g6, g7, g8, g9, g10, g11,g12 , g13
|
||||||
|
// We don't care about mx & pix, ope2 & ope4 are either / or * for n2 & n4.
|
||||||
|
// n1 & n3 are multiplied, opeM is the main operation (- or +).
|
||||||
|
// Putting all n in form of number
|
||||||
|
//n2 = n2 == undefined ? 1 : parseFloat(n)
|
||||||
|
n1 = m1 == undefined ? 1 : eval(m1 + '1')
|
||||||
|
n2 = m2 == undefined ? 1 : eval('1' + m2)
|
||||||
|
n3 = m3 == undefined ? 1 : eval(m3 + '1')
|
||||||
|
n4 = m4 == undefined ? 1 : eval('1' + m4)
|
||||||
|
//var [n1, n2, n3, n4] = [n1, n2, n3, n4].map(n => n == undefined ? 1 : parseFloat(n))
|
||||||
|
// Falling back to * in case it does not exist (the corresponding n would be 1)
|
||||||
|
var [ope2, ope4] = [ope2, ope4].map(ope => ope == '/' ? '/' : '*')
|
||||||
|
var coeff1 = n1*n2
|
||||||
|
var coeff2 = n3*n4
|
||||||
|
var coefficient = coeff1+coeff2-(opeM == '-' ? 2*coeff2 : 0)
|
||||||
|
|
||||||
|
return `${coefficient} * π`
|
||||||
|
}
|
||||||
|
],
|
||||||
[ // Removing parenthesis when content is only added from both sides.
|
[ // Removing parenthesis when content is only added from both sides.
|
||||||
/(^.?|[+-] |\()\(([^)(]+)\)(.?$| [+-]|\))/g,
|
/(^.?|[+-] |\()\(([^)(]+)\)(.?$| [+-]|\))/g,
|
||||||
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
],
|
],
|
||||||
[ // Removing parenthesis when content is only multiplied.
|
[ // Removing parenthesis when content is only multiplied.
|
||||||
/(^.?|[*\/] |\()\(([^)(+-]+)\)(.?$| [*\/]|\))/g,
|
/(^.?|[*\/] |\()\(([^)(+-]+)\)(.?$| [*\/+-]|\))/g,
|
||||||
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
|
],
|
||||||
|
[ // Removing parenthesis when content is only multiplied.
|
||||||
|
/(^.?|[*\/-+] |\()\(([^)(+-]+)\)(.?$| [*\/]|\))/g,
|
||||||
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
],
|
],
|
||||||
[// Simplification additions/substractions.
|
[// Simplification additions/substractions.
|
||||||
|
@ -176,26 +212,33 @@ function simplifyExpression(str) {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// Simple simplifications
|
// Simple simplifications
|
||||||
[/(\s|^|\()0 \* (\([^)(]+\))/g, '$10'],
|
[/(\s|^|\()0(\.0+)? \* (\([^)(]+\))/g, '$10'],
|
||||||
[/(\s|^|\()0 \* ([^)(+-]+)/g, '$10'],
|
[/(\s|^|\()0(\.0+)? \* ([^)(+-]+)/g, '$10'],
|
||||||
[/(\([^)(]\)) \* 0(\s|$|\))/g, '0$2'],
|
[/(\([^)(]\)) \* 0(\.0+)?(\s|$|\))/g, '0$3'],
|
||||||
[/([^)(+-]) \* 0(\s|$|\))/g, '0$2'],
|
[/([^)(+-]) \* 0(\.0+)?(\s|$|\))/g, '0$3'],
|
||||||
[/(\s|^|\()1 (\*|\/) /g, '$1'],
|
[/(\s|^|\()1(\.0+)? (\*|\/) /g, '$1'],
|
||||||
[/(\s|^|\()0 (\+|\-) /g, '$1'],
|
[/(\s|^|\()0(\.0+)? (\+|\-) /g, '$1'],
|
||||||
[/ (\*|\/) 1(\s|$|\))/g, '$2'],
|
[/ (\*|\/) 1(\.0+)?(\s|$|\))/g, '$3'],
|
||||||
[/ (\+|\-) 0(\s|$|\))/g, '$2'],
|
[/ (\+|\-) 0(\.0+)?(\s|$|\))/g, '$3'],
|
||||||
[/(^| |\() /g, '$1'],
|
[/(^| |\() /g, '$1'],
|
||||||
[/ ($|\))/g, '$1'],
|
[/ ($|\))/g, '$1'],
|
||||||
]
|
]
|
||||||
|
|
||||||
// Replacements
|
// Replacements
|
||||||
replacements.forEach(function(replacement){
|
var found
|
||||||
while(replacement[0].test(str))
|
do {
|
||||||
str = str.replace(replacement[0], replacement[1])
|
found = false
|
||||||
})
|
for(var replacement of replacements)
|
||||||
|
while(replacement[0].test(str)) {
|
||||||
|
found = true
|
||||||
|
str = str.replace(replacement[0], replacement[1])
|
||||||
|
}
|
||||||
|
} while(found)
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(simplifyExpression("(4 * (4 * pi + pi)) + pi"))
|
||||||
|
|
||||||
function makeExpressionReadable(str) {
|
function makeExpressionReadable(str) {
|
||||||
var replacements = [
|
var replacements = [
|
||||||
// variables
|
// variables
|
||||||
|
@ -209,6 +252,7 @@ function makeExpressionReadable(str) {
|
||||||
[/\^([^ ]+)/g, function(match, p1) { return textsup(p1) }],
|
[/\^([^ ]+)/g, function(match, p1) { return textsup(p1) }],
|
||||||
[/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }],
|
[/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }],
|
||||||
[/_([^ ]+)/g, function(match, p1) { return textsub(p1) }],
|
[/_([^ ]+)/g, function(match, p1) { return textsub(p1) }],
|
||||||
|
[/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }],
|
||||||
[/(\d|\))×/g, '$1'],
|
[/(\d|\))×/g, '$1'],
|
||||||
//[/×(\d|\()/g, '$1'],
|
//[/×(\d|\()/g, '$1'],
|
||||||
[/\(([^)(+.\/-]+)\)/g, "$1"],
|
[/\(([^)(+.\/-]+)\)/g, "$1"],
|
||||||
|
@ -216,10 +260,9 @@ function makeExpressionReadable(str) {
|
||||||
|
|
||||||
str = simplifyExpression(str)
|
str = simplifyExpression(str)
|
||||||
// Replacements
|
// Replacements
|
||||||
replacements.forEach(function(replacement){
|
for(var replacement of replacements)
|
||||||
while(replacement[0].test(str))
|
while(replacement[0].test(str))
|
||||||
str = str.replace(replacement[0], replacement[1])
|
str = str.replace(replacement[0], replacement[1])
|
||||||
})
|
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,9 +312,8 @@ function parseName(str, removeUnallowed = true) {
|
||||||
]
|
]
|
||||||
if(!removeUnallowed) replacements.pop()
|
if(!removeUnallowed) replacements.pop()
|
||||||
// Replacements
|
// Replacements
|
||||||
replacements.forEach(function(replacement){
|
for(var replacement of replacements)
|
||||||
str = str.replace(replacement[0], replacement[1])
|
str = str.replace(replacement[0], replacement[1])
|
||||||
})
|
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue