Compare commits
4 commits
956de5f9e3
...
9b5356f8e7
Author | SHA1 | Date | |
---|---|---|---|
9b5356f8e7 | |||
370402f303 | |||
7f57ed13c7 | |||
325eef57e2 |
19 changed files with 134 additions and 127 deletions
|
@ -49,7 +49,7 @@ Repeater {
|
||||||
*/
|
*/
|
||||||
property var positionPicker
|
property var positionPicker
|
||||||
|
|
||||||
readonly property var textTypes: ['Domain', 'string', 'number']
|
readonly property var textTypes: ['Domain', 'string', 'number', 'int']
|
||||||
readonly property var comboBoxTypes: ['ObjectType', 'Enum']
|
readonly property var comboBoxTypes: ['ObjectType', 'Enum']
|
||||||
readonly property var listTypes: ['List', 'Dict']
|
readonly property var listTypes: ['List', 'Dict']
|
||||||
|
|
||||||
|
@ -102,13 +102,16 @@ Repeater {
|
||||||
height: 30
|
height: 30
|
||||||
label: propertyLabel
|
label: propertyLabel
|
||||||
icon: `settings/custom/${propertyIcon}.svg`
|
icon: `settings/custom/${propertyIcon}.svg`
|
||||||
|
min: propertyType == "int" ? 0 : -Infinity
|
||||||
|
isInt: propertyType == "int"
|
||||||
isDouble: propertyType == "number"
|
isDouble: propertyType == "number"
|
||||||
defValue: obj[propertyName] == null ? '' : obj[propertyName].toString()
|
defValue: obj[propertyName] == null ? '' : obj[propertyName].toString()
|
||||||
category: {
|
category: {
|
||||||
return {
|
return {
|
||||||
"Domain": "domain",
|
"Domain": "domain",
|
||||||
"string": "all",
|
"string": "all",
|
||||||
"number": "all"
|
"number": "all",
|
||||||
|
"int": "all",
|
||||||
}[propertyType]
|
}[propertyType]
|
||||||
}
|
}
|
||||||
onChanged: function(newValue) {
|
onChanged: function(newValue) {
|
||||||
|
@ -116,7 +119,8 @@ Repeater {
|
||||||
var newValueParsed = {
|
var newValueParsed = {
|
||||||
"Domain": () => MathLib.parseDomain(newValue),
|
"Domain": () => MathLib.parseDomain(newValue),
|
||||||
"string": () => newValue,
|
"string": () => newValue,
|
||||||
"number": () => parseFloat(newValue)
|
"number": () => newValue,
|
||||||
|
"int": () => newValue
|
||||||
}[propertyType]()
|
}[propertyType]()
|
||||||
|
|
||||||
// Ensuring old and new values are different to prevent useless adding to history.
|
// Ensuring old and new values are different to prevent useless adding to history.
|
||||||
|
|
|
@ -261,7 +261,7 @@ BaseDialog {
|
||||||
authors: [authors.comradekingu, authors.Ad5001]
|
authors: [authors.comradekingu, authors.Ad5001]
|
||||||
})
|
})
|
||||||
append({
|
append({
|
||||||
tranName: '🇳🇴 ' + qsTr('Spanish'),
|
tranName: '🇪🇸 ' + qsTr('Spanish'),
|
||||||
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/',
|
link: 'https://hosted.weblate.org/projects/logarithmplotter/logarithmplotter/es/',
|
||||||
authors: [authors.IngrownMink4, authors.gallegonovato]
|
authors: [authors.IngrownMink4, authors.gallegonovato]
|
||||||
})
|
})
|
||||||
|
|
|
@ -127,12 +127,15 @@ Item {
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
onEditingFinished: function() {
|
onEditingFinished: function() {
|
||||||
if(insertButton.focus || insertPopup.focus) return
|
if(insertButton.focus || insertPopup.focus) return
|
||||||
var value = text
|
let value = text
|
||||||
if(control.isInt)
|
if(control.isInt) {
|
||||||
value = isNaN(parseInt(value)) ? control.min : Math.max(control.min,parseInt(value))
|
let parsed = parseInt(value)
|
||||||
if(control.isDouble)
|
value = isNaN(parsed) ? control.min : Math.max(control.min,parsed)
|
||||||
value = isNaN(parseFloat(value)) ? control.min : Math.max(control.min,parseFloat(value))
|
} else if(control.isDouble) {
|
||||||
if(value != "" && value.toString() != defValue) {
|
let parsed = parseFloat(value)
|
||||||
|
value = isNaN(parsed) ? control.min : Math.max(control.min,parsed)
|
||||||
|
}
|
||||||
|
if(value !== "" && value.toString() != defValue) {
|
||||||
control.changed(value)
|
control.changed(value)
|
||||||
defValue = value.toString()
|
defValue = value.toString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,7 @@ class CanvasAPI extends Module {
|
||||||
} else {
|
} else {
|
||||||
for(let x = 1; x < this.axesSteps.x.maxDraw; x += 1) {
|
for(let x = 1; x < this.axesSteps.x.maxDraw; x += 1) {
|
||||||
let drawX = x*this.axesSteps.x.value
|
let drawX = x*this.axesSteps.x.value
|
||||||
let txtX = this.axesSteps.x.expression.simplify(x).replace(/^\((.+)\)$/, '$1')
|
let txtX = this.axesSteps.x.expression.simplify(x).toString().replace(/^\((.+)\)$/, '$1')
|
||||||
let textHeight = this.measureText(txtX).height
|
let textHeight = this.measureText(txtX).height
|
||||||
this.drawVisibleText(txtX, this.x2px(drawX)-4, axisxpx+this.textsize/2+textHeight)
|
this.drawVisibleText(txtX, this.x2px(drawX)-4, axisxpx+this.textsize/2+textHeight)
|
||||||
this.drawVisibleText('-'+txtX, this.x2px(-drawX)-4, axisxpx+this.textsize/2+textHeight)
|
this.drawVisibleText('-'+txtX, this.x2px(-drawX)-4, axisxpx+this.textsize/2+textHeight)
|
||||||
|
@ -301,7 +301,7 @@ class CanvasAPI extends Module {
|
||||||
if(this.showygrad) {
|
if(this.showygrad) {
|
||||||
for(let y = 0; y < this.axesSteps.y.maxDraw; y += 1) {
|
for(let y = 0; y < this.axesSteps.y.maxDraw; y += 1) {
|
||||||
let drawY = y*this.axesSteps.y.value
|
let drawY = y*this.axesSteps.y.value
|
||||||
let txtY = this.axesSteps.y.expression.simplify(y).replace(/^\((.+)\)$/, '$1')
|
let txtY = this.axesSteps.y.expression.simplify(y).toString().replace(/^\((.+)\)$/, '$1')
|
||||||
textWidth = this._ctx.measureText(txtY).width
|
textWidth = this._ctx.measureText(txtY).width
|
||||||
this.drawVisibleText(txtY, axisypx-6-textWidth, this.y2px(drawY)+4+(10*(y===0)))
|
this.drawVisibleText(txtY, axisypx-6-textWidth, this.y2px(drawY)+4+(10*(y===0)))
|
||||||
if(y !== 0)
|
if(y !== 0)
|
||||||
|
|
|
@ -199,6 +199,7 @@ export class Range extends Domain {
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(x) {
|
includes(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
return ((this.openBegin && x > this.begin.execute()) || (!this.openBegin && x >= this.begin.execute())) &&
|
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()))
|
((this.openEnd && x < this.end.execute()) || (!this.openEnd && x <= this.end.execute()))
|
||||||
|
@ -257,16 +258,19 @@ export class SpecialDomain extends Domain {
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(x) {
|
includes(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
return this.isValid(x)
|
return this.isValid(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
next(x) {
|
next(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
return this.nextValue(x)
|
return this.nextValue(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
previous(x) {
|
previous(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
return this.prevValue(x)
|
return this.prevValue(x)
|
||||||
}
|
}
|
||||||
|
@ -315,6 +319,7 @@ export class DomainSet extends SpecialDomain {
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(x) {
|
includes(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
for(let value of this.values)
|
for(let value of this.values)
|
||||||
if(x === value.execute()) return true
|
if(x === value.execute()) return true
|
||||||
|
@ -322,6 +327,7 @@ export class DomainSet extends SpecialDomain {
|
||||||
}
|
}
|
||||||
|
|
||||||
next(x) {
|
next(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
if(x < this.executedValues[0]) return this.executedValues[0]
|
if(x < this.executedValues[0]) return this.executedValues[0]
|
||||||
for(let i = 1; i < this.values.length; i++) {
|
for(let i = 1; i < this.values.length; i++) {
|
||||||
|
@ -333,6 +339,7 @@ export class DomainSet extends SpecialDomain {
|
||||||
}
|
}
|
||||||
|
|
||||||
previous(x) {
|
previous(x) {
|
||||||
|
if(x instanceof Expression) x = x.execute()
|
||||||
if(typeof x == 'string') x = executeExpression(x)
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
if(x > this.executedValues[this.executedValues.length-1])
|
if(x > this.executedValues[this.executedValues.length-1])
|
||||||
return this.executedValues[this.executedValues.length-1]
|
return this.executedValues[this.executedValues.length-1]
|
||||||
|
|
|
@ -29,8 +29,14 @@ export class Expression {
|
||||||
throw new Error('Expression parser not initialized.')
|
throw new Error('Expression parser not initialized.')
|
||||||
if(!Modules.Objects)
|
if(!Modules.Objects)
|
||||||
throw new Error('Objects API not initialized.')
|
throw new Error('Objects API not initialized.')
|
||||||
|
if(typeof expr === "string") {
|
||||||
this.expr = Utils.exponentsToExpression(expr)
|
this.expr = Utils.exponentsToExpression(expr)
|
||||||
this.calc = Modules.ExprParser.parse(this.expr).simplify()
|
this.calc = Modules.ExprParser.parse(this.expr).simplify()
|
||||||
|
} else {
|
||||||
|
// Passed an expression here directly.
|
||||||
|
this.calc = expr.simplify()
|
||||||
|
this.expr = expr.toString()
|
||||||
|
}
|
||||||
this.cached = this.isConstant()
|
this.cached = this.isConstant()
|
||||||
this.cachedValue = null
|
this.cachedValue = null
|
||||||
if(this.cached && this.allRequirementsFullfilled())
|
if(this.cached && this.allRequirementsFullfilled())
|
||||||
|
@ -72,19 +78,8 @@ export class Expression {
|
||||||
|
|
||||||
simplify(x) {
|
simplify(x) {
|
||||||
let expr = this.calc.substitute('x', x).simplify()
|
let expr = this.calc.substitute('x', x).simplify()
|
||||||
if(expr.evaluate() === 0) return '0'
|
if(expr.evaluate() === 0) expr = '0'
|
||||||
let str = Utils.makeExpressionReadable(expr.toString());
|
return new Expression(expr)
|
||||||
if(str !== undefined && str.match(/^\d*\.\d+$/)) {
|
|
||||||
if(str.split('.')[1].split('0').length > 7) {
|
|
||||||
// Likely rounding error
|
|
||||||
str = parseFloat(str.substring(0, str.length-1)).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
duplicate() {
|
|
||||||
return new Expression(this.toEditableString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toEditableString() {
|
toEditableString() {
|
||||||
|
@ -93,6 +88,12 @@ export class Expression {
|
||||||
|
|
||||||
toString(forceSign=false) {
|
toString(forceSign=false) {
|
||||||
let str = Utils.makeExpressionReadable(this.calc.toString())
|
let str = Utils.makeExpressionReadable(this.calc.toString())
|
||||||
|
if(str !== undefined && str.match(/^\d*\.\d+$/)) {
|
||||||
|
if(str.split('.')[1].split('0').length > 7) {
|
||||||
|
// Likely rounding error
|
||||||
|
str = parseFloat(str.substring(0, str.length-1)).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
if(str[0] !== '-' && forceSign) str = '+' + str
|
if(str[0] !== '-' && forceSign) str = '+' + str
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,9 @@ export class Sequence extends Expr.Expression {
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify(n = 1) {
|
simplify(n = 1) {
|
||||||
if(n in this.calcValues)
|
if(!(n in this.calcValues))
|
||||||
return Utils.makeExpressionReadable(this.calcValues[n].toString())
|
|
||||||
this.cache(n)
|
this.cache(n)
|
||||||
return Utils.makeExpressionReadable(this.calcValues[n].toString())
|
return this.calcValues[n].toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
cache(n = 1) {
|
cache(n = 1) {
|
||||||
|
|
|
@ -36,6 +36,28 @@ class ObjectsAPI extends Module {
|
||||||
this.currentObjectsByName = {}
|
this.currentObjectsByName = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new name for an object, based on the allowedLetters.
|
||||||
|
* If variables with each of the allowedLetters is created, a subscript
|
||||||
|
* number is added to the name.
|
||||||
|
* @param {string} allowedLetters
|
||||||
|
* @param {string} prefix - Prefix to the name.
|
||||||
|
* @return {string} New unused name for a new object.
|
||||||
|
*/
|
||||||
|
getNewName(allowedLetters, prefix='') {
|
||||||
|
// Allows to get a new name, based on the allowed letters,
|
||||||
|
// as well as adding a sub number when needs be.
|
||||||
|
let newid = 0
|
||||||
|
let ret
|
||||||
|
do {
|
||||||
|
let letter = allowedLetters[newid % allowedLetters.length]
|
||||||
|
let num = Math.floor((newid - (newid % allowedLetters.length)) / allowedLetters.length)
|
||||||
|
ret = prefix + letter + (num > 0 ? textsub(num-1) : '')
|
||||||
|
newid += 1
|
||||||
|
} while(ret in this.currentObjectsByName)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renames an object from its old name to the new one.
|
* Renames an object from its old name to the new one.
|
||||||
* @param {string} oldName - Current name of the object.
|
* @param {string} oldName - Current name of the object.
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { API as ObjectsCommonAPI } from "common.mjs"
|
import Objects from "../objects.mjs"
|
||||||
|
import { DrawableObject } from "common.mjs"
|
||||||
import Point from "point.mjs"
|
import Point from "point.mjs"
|
||||||
import Text from "text.mjs"
|
import Text from "text.mjs"
|
||||||
import Function from "function.mjs"
|
import Function from "function.mjs"
|
||||||
|
@ -28,15 +29,29 @@ import XCursor from "xcursor.mjs"
|
||||||
import Sequence from "sequence.mjs"
|
import Sequence from "sequence.mjs"
|
||||||
import RepartitionFunction from "repartition.mjs"
|
import RepartitionFunction from "repartition.mjs"
|
||||||
|
|
||||||
if(Object.keys(Modules.Objects.types).length === 0) {
|
/**
|
||||||
ObjectsCommonAPI.registerObject(Point)
|
* Registers the object obj in the object list.
|
||||||
ObjectsCommonAPI.registerObject(Text)
|
* @param {DrawableObject} obj - Object to be registered.
|
||||||
ObjectsCommonAPI.registerObject(Function)
|
*/
|
||||||
ObjectsCommonAPI.registerObject(GainBode)
|
function registerObject(obj) {
|
||||||
ObjectsCommonAPI.registerObject(PhaseBode)
|
// Registers an object to be used in LogarithmPlotter.
|
||||||
ObjectsCommonAPI.registerObject(SommeGainsBode)
|
if(obj.prototype instanceof DrawableObject) {
|
||||||
ObjectsCommonAPI.registerObject(SommePhasesBode)
|
if(!Objects.types[obj.type()])
|
||||||
ObjectsCommonAPI.registerObject(XCursor)
|
Objects.types[obj.type()] = obj
|
||||||
ObjectsCommonAPI.registerObject(Sequence)
|
} else {
|
||||||
ObjectsCommonAPI.registerObject(RepartitionFunction)
|
console.error("Could not register object " + (obj?.type() ?? obj.constructor.name) + ", as it isn't a DrawableObject.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Object.keys(Modules.Objects.types).length === 0) {
|
||||||
|
registerObject(Point)
|
||||||
|
registerObject(Text)
|
||||||
|
registerObject(Function)
|
||||||
|
registerObject(GainBode)
|
||||||
|
registerObject(PhaseBode)
|
||||||
|
registerObject(SommeGainsBode)
|
||||||
|
registerObject(SommePhasesBode)
|
||||||
|
registerObject(XCursor)
|
||||||
|
registerObject(Sequence)
|
||||||
|
registerObject(RepartitionFunction)
|
||||||
}
|
}
|
|
@ -24,59 +24,6 @@ import {ensureTypeSafety, serializesByPropertyType} from "../parameters.mjs"
|
||||||
|
|
||||||
// This file contains the default data to be imported from all other objects
|
// This file contains the default data to be imported from all other objects
|
||||||
|
|
||||||
class ObjectsCommonAPI extends Module {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super('ObjectsCommon', [
|
|
||||||
Modules.Objects,
|
|
||||||
Modules.ExprParser,
|
|
||||||
Modules.Latex
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new name for an object, based on the allowedLetters.
|
|
||||||
* If variables with each of the allowedLetters is created, a subscript
|
|
||||||
* number is added to the name.
|
|
||||||
* @param {string} allowedLetters
|
|
||||||
* @param {string} prefix - Prefix to the name.
|
|
||||||
* @return {string} New unused name for a new object.
|
|
||||||
*/
|
|
||||||
getNewName(allowedLetters, prefix='') {
|
|
||||||
// Allows to get a new name, based on the allowed letters,
|
|
||||||
// as well as adding a sub number when needs be.
|
|
||||||
let newid = 0
|
|
||||||
let ret
|
|
||||||
do {
|
|
||||||
let letter = allowedLetters[newid % allowedLetters.length]
|
|
||||||
let num = Math.floor((newid - (newid % allowedLetters.length)) / allowedLetters.length)
|
|
||||||
ret = prefix + letter + (num > 0 ? textsub(num-1) : '')
|
|
||||||
newid += 1
|
|
||||||
} while(ret in Objects.currentObjectsByName)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the object obj in the object list.
|
|
||||||
* @param {DrawableObject} obj - Object to be registered.
|
|
||||||
*/
|
|
||||||
registerObject(obj) {
|
|
||||||
// Registers an object to be used in LogarithmPlotter.
|
|
||||||
// This function is called from autoload.mjs
|
|
||||||
if(obj.prototype instanceof DrawableObject) {
|
|
||||||
if(!Objects.types[obj.type()])
|
|
||||||
Objects.types[obj.type()] = obj
|
|
||||||
} else {
|
|
||||||
console.error("Could not register object " + (obj.type()) + ", as it isn't a DrawableObject.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {ObjectsCommonAPI} */
|
|
||||||
Modules.ObjectsCommon = Modules.ObjectsCommon || new ObjectsCommonAPI()
|
|
||||||
|
|
||||||
export const API = Modules.ObjectsCommon
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to extend for every type of object that
|
* Class to extend for every type of object that
|
||||||
* can be drawn on the canvas.
|
* can be drawn on the canvas.
|
||||||
|
@ -433,7 +380,7 @@ export class ExecutableObject extends DrawableObject {
|
||||||
* Returns the simplified expression string for a given x.
|
* Returns the simplified expression string for a given x.
|
||||||
*
|
*
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
* @returns {string}
|
* @returns {string|Expression}
|
||||||
*/
|
*/
|
||||||
simplify(x = 1) {return '0'}
|
simplify(x = 1) {return '0'}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { textsub } from "../utils.mjs"
|
import { textsub } from "../utils.mjs"
|
||||||
import { API as Common, ExecutableObject } from "common.mjs"
|
import Objects from "../objects.mjs"
|
||||||
|
import { ExecutableObject } from "common.mjs"
|
||||||
import { parseDomain, Expression, SpecialDomain } from "../mathlib.mjs"
|
import { parseDomain, Expression, SpecialDomain } from "../mathlib.mjs"
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
|
@ -50,7 +51,7 @@ export default class Function extends ExecutableObject {
|
||||||
expression = 'x', definitionDomain = 'RPE', destinationDomain = 'R',
|
expression = 'x', definitionDomain = 'RPE', destinationDomain = 'R',
|
||||||
displayMode = 'application', labelPosition = 'above', labelX = 1,
|
displayMode = 'application', labelPosition = 'above', labelX = 1,
|
||||||
drawPoints = true, drawDashedLines = true) {
|
drawPoints = true, drawDashedLines = true) {
|
||||||
if(name == null) name = Common.getNewName('fghjqlmnopqrstuvwabcde')
|
if(name == null) name = Objects.getNewName('fghjqlmnopqrstuvwabcde')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
if(typeof expression == 'number' || typeof expression == 'string') expression = new Expression(expression.toString())
|
if(typeof expression == 'number' || typeof expression == 'string') expression = new Expression(expression.toString())
|
||||||
this.expression = expression
|
this.expression = expression
|
||||||
|
|
|
@ -21,7 +21,7 @@ import * as P from "../parameters.mjs"
|
||||||
import Objects from "../objects.mjs"
|
import Objects from "../objects.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
|
|
||||||
import { API as Common, ExecutableObject } from "common.mjs"
|
import { ExecutableObject } from "common.mjs"
|
||||||
import Function from "function.mjs"
|
import Function from "function.mjs"
|
||||||
|
|
||||||
import { API as HistoryAPI } from "../history/common.mjs"
|
import { API as HistoryAPI } from "../history/common.mjs"
|
||||||
|
@ -43,7 +43,7 @@ export default class GainBode extends ExecutableObject {
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
om_0 = '', pass = 'high', gain = '20', labelPosition = 'above', labelX = 1, omGraduation = false) {
|
om_0 = '', pass = 'high', gain = '20', labelPosition = 'above', labelX = 1, omGraduation = false) {
|
||||||
if(name == null) name = Common.getNewName('G')
|
if(name == null) name = Objects.getNewName('G')
|
||||||
if(name === 'G') name = 'G₀' // G is reserved for sum of BODE magnitudes (Somme gains Bode).
|
if(name === 'G') name = 'G₀' // G is reserved for sum of BODE magnitudes (Somme gains Bode).
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
if(typeof om_0 == "string") {
|
if(typeof om_0 == "string") {
|
||||||
|
@ -51,7 +51,7 @@ export default class GainBode extends ExecutableObject {
|
||||||
om_0 = Objects.currentObjectsByName[om_0]
|
om_0 = Objects.currentObjectsByName[om_0]
|
||||||
if(om_0 == null) {
|
if(om_0 == null) {
|
||||||
// Create new point
|
// Create new point
|
||||||
om_0 = Objects.createNewRegisteredObject('Point', [Common.getNewName('ω'), true, this.color, 'name'])
|
om_0 = Objects.createNewRegisteredObject('Point', [Objects.getNewName('ω'), true, this.color, 'name'])
|
||||||
HistoryAPI.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export()))
|
HistoryAPI.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export()))
|
||||||
om_0.update()
|
om_0.update()
|
||||||
labelPosition = 'below'
|
labelPosition = 'below'
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
import { executeExpression, Expression } from "../mathlib.mjs"
|
import { executeExpression, Expression } from "../mathlib.mjs"
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
import Objects from "../objects.mjs"
|
import Objects from "../objects.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
|
||||||
|
|
||||||
import { API as Common, ExecutableObject } from "common.mjs"
|
|
||||||
import { API as HistoryAPI } from "../history/common.mjs"
|
import { API as HistoryAPI } from "../history/common.mjs"
|
||||||
import { CreateNewObject } from "../historylib.mjs"
|
import { CreateNewObject } from "../historylib.mjs"
|
||||||
|
import Latex from "../math/latex.mjs"
|
||||||
|
|
||||||
|
import { ExecutableObject } from "common.mjs"
|
||||||
|
|
||||||
|
|
||||||
export default class PhaseBode extends ExecutableObject {
|
export default class PhaseBode extends ExecutableObject {
|
||||||
|
@ -40,7 +40,7 @@ export default class PhaseBode extends ExecutableObject {
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
om_0 = '', phase = 90, unit = '°', labelPosition = 'above', labelX = 1) {
|
om_0 = '', phase = 90, unit = '°', labelPosition = 'above', labelX = 1) {
|
||||||
if(name == null) name = Common.getNewName('φ')
|
if(name == null) name = Objects.getNewName('φ')
|
||||||
if(name === 'φ') name = 'φ₀' // φ is reserved for sum of BODE phases (Somme phases Bode).
|
if(name === 'φ') name = 'φ₀' // φ is reserved for sum of BODE phases (Somme phases Bode).
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
if(typeof phase == 'number' || typeof phase == 'string') phase = new Expression(phase.toString())
|
if(typeof phase == 'number' || typeof phase == 'string') phase = new Expression(phase.toString())
|
||||||
|
@ -50,7 +50,7 @@ export default class PhaseBode extends ExecutableObject {
|
||||||
om_0 = Objects.currentObjectsByName[om_0]
|
om_0 = Objects.currentObjectsByName[om_0]
|
||||||
if(om_0 == null) {
|
if(om_0 == null) {
|
||||||
// Create new point
|
// Create new point
|
||||||
om_0 = Objects.createNewRegisteredObject('Point', [Common.getNewName('ω'), this.color, 'name'])
|
om_0 = Objects.createNewRegisteredObject('Point', [Objects.getNewName('ω'), this.color, 'name'])
|
||||||
om_0.labelPosition = this.phase.execute() >= 0 ? 'above' : 'below'
|
om_0.labelPosition = this.phase.execute() >= 0 ? 'above' : 'below'
|
||||||
HistoryAPI.history.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export()))
|
HistoryAPI.history.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export()))
|
||||||
labelPosition = 'below'
|
labelPosition = 'below'
|
||||||
|
@ -88,7 +88,7 @@ export default class PhaseBode extends ExecutableObject {
|
||||||
return this.om_0.y.toString()
|
return this.om_0.y.toString()
|
||||||
} else {
|
} else {
|
||||||
let newExp = this.om_0.y.toEditableString() + ' + ' + this.phase.toEditableString()
|
let newExp = this.om_0.y.toEditableString() + ' + ' + this.phase.toEditableString()
|
||||||
return (new Expression(newExp)).toString()
|
return new Expression(newExp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,10 @@
|
||||||
|
|
||||||
import { Expression } from "../mathlib.mjs"
|
import { Expression } from "../mathlib.mjs"
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
|
import Objects from "../objects.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
import { API as Common, DrawableObject } from "common.mjs"
|
|
||||||
|
import { DrawableObject } from "common.mjs"
|
||||||
|
|
||||||
|
|
||||||
export default class Point extends DrawableObject {
|
export default class Point extends DrawableObject {
|
||||||
|
@ -36,7 +38,7 @@ export default class Point extends DrawableObject {
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
x = 1, y = 0, labelPosition = 'above', pointStyle = '●') {
|
x = 1, y = 0, labelPosition = 'above', pointStyle = '●') {
|
||||||
if(name == null) name = Common.getNewName('ABCDEFJKLMNOPQRSTUVW')
|
if(name == null) name = Objects.getNewName('ABCDEFJKLMNOPQRSTUVW')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString())
|
if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString())
|
||||||
this.x = x
|
this.x = x
|
||||||
|
|
|
@ -16,10 +16,12 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { API as Common, ExecutableObject } from "common.mjs"
|
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
|
import Objects from "../objects.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
|
|
||||||
|
import { ExecutableObject } from "common.mjs"
|
||||||
|
|
||||||
|
|
||||||
export default class RepartitionFunction extends ExecutableObject {
|
export default class RepartitionFunction extends ExecutableObject {
|
||||||
static type(){return 'Repartition'}
|
static type(){return 'Repartition'}
|
||||||
|
@ -46,7 +48,7 @@ export default class RepartitionFunction extends ExecutableObject {
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
probabilities = {'0': '0'}, labelPosition = 'above', labelX = 1) {
|
probabilities = {'0': '0'}, labelPosition = 'above', labelX = 1) {
|
||||||
if(name == null) name = Common.getNewName('XYZUVW', "F_")
|
if(name == null) name = Objects.getNewName('XYZUVW', "F_")
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.probabilities = probabilities
|
this.probabilities = probabilities
|
||||||
this.labelPosition = labelPosition
|
this.labelPosition = labelPosition
|
||||||
|
@ -79,7 +81,7 @@ export default class RepartitionFunction extends ExecutableObject {
|
||||||
|
|
||||||
// Simplify returns the simplified string of the expression.
|
// Simplify returns the simplified string of the expression.
|
||||||
simplify(x = 1) {
|
simplify(x = 1) {
|
||||||
return this.execute(x)
|
return this.execute(x).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
getLabel() {
|
getLabel() {
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
import { Sequence as MathSequence, Domain } from "../mathlib.mjs"
|
import { Sequence as MathSequence, Domain } from "../mathlib.mjs"
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
|
import Objects from "../objects.mjs"
|
||||||
|
|
||||||
import { API as Common, ExecutableObject } from "common.mjs"
|
import { ExecutableObject } from "common.mjs"
|
||||||
import Function from "function.mjs"
|
import Function from "function.mjs"
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ export default class Sequence extends ExecutableObject {
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
drawPoints = true, drawDashedLines = true, defaultExp = {1: "n"},
|
drawPoints = true, drawDashedLines = true, defaultExp = {1: "n"},
|
||||||
baseValues = {0: 0}, labelPosition = 'above', labelX = 1) {
|
baseValues = {0: 0}, labelPosition = 'above', labelX = 1) {
|
||||||
if(name == null) name = Common.getNewName('uvwPSUVWabcde')
|
if(name == null) name = Objects.getNewName('uvwPSUVWabcde')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.drawPoints = drawPoints
|
this.drawPoints = drawPoints
|
||||||
this.drawDashedLines = drawDashedLines
|
this.drawDashedLines = drawDashedLines
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
|
|
||||||
import { Expression } from "../mathlib.mjs"
|
import { Expression } from "../mathlib.mjs"
|
||||||
import * as P from "../parameters.mjs"
|
import * as P from "../parameters.mjs"
|
||||||
|
import Objects from "../objects.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
|
|
||||||
import { API as Common, DrawableObject } from "common.mjs"
|
import { DrawableObject } from "common.mjs"
|
||||||
|
|
||||||
|
|
||||||
export default class Text extends DrawableObject {
|
export default class Text extends DrawableObject {
|
||||||
|
@ -41,7 +42,7 @@ export default class Text extends DrawableObject {
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'null',
|
constructor(name = null, visible = true, color = null, labelContent = 'null',
|
||||||
x = 1, y = 0, labelPosition = 'center', text = 'New text', disableLatex = false) {
|
x = 1, y = 0, labelPosition = 'center', text = 'New text', disableLatex = false) {
|
||||||
if(name == null) name = Common.getNewName('t')
|
if(name == null) name = Objects.getNewName('t')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString())
|
if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString())
|
||||||
this.x = x
|
this.x = x
|
||||||
|
|
|
@ -21,7 +21,7 @@ import * as P from "../parameters.mjs"
|
||||||
import Latex from "../math/latex.mjs"
|
import Latex from "../math/latex.mjs"
|
||||||
import Objects from "../objects.mjs"
|
import Objects from "../objects.mjs"
|
||||||
|
|
||||||
import { API as Common, DrawableObject } from "common.mjs"
|
import { DrawableObject } from "common.mjs"
|
||||||
|
|
||||||
|
|
||||||
export default class XCursor extends DrawableObject {
|
export default class XCursor extends DrawableObject {
|
||||||
|
@ -33,7 +33,7 @@ export default class XCursor extends DrawableObject {
|
||||||
[QT_TRANSLATE_NOOP('prop','targetElement')]: new P.ObjectType('ExecutableObject', true),
|
[QT_TRANSLATE_NOOP('prop','targetElement')]: new P.ObjectType('ExecutableObject', true),
|
||||||
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
||||||
[QT_TRANSLATE_NOOP('prop','approximate')]: 'boolean',
|
[QT_TRANSLATE_NOOP('prop','approximate')]: 'boolean',
|
||||||
[QT_TRANSLATE_NOOP('prop','rounding')]: 'number',
|
[QT_TRANSLATE_NOOP('prop','rounding')]: 'int',
|
||||||
[QT_TRANSLATE_NOOP('prop','displayStyle')]: new P.Enum(
|
[QT_TRANSLATE_NOOP('prop','displayStyle')]: new P.Enum(
|
||||||
'— — — — — — —',
|
'— — — — — — —',
|
||||||
'⸺⸺⸺⸺⸺⸺',
|
'⸺⸺⸺⸺⸺⸺',
|
||||||
|
@ -45,7 +45,7 @@ export default class XCursor extends DrawableObject {
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
x = 1, targetElement = null, labelPosition = 'left', approximate = true,
|
x = 1, targetElement = null, labelPosition = 'left', approximate = true,
|
||||||
rounding = 3, displayStyle = '— — — — — — —', targetValuePosition = 'Next to target') {
|
rounding = 3, displayStyle = '— — — — — — —', targetValuePosition = 'Next to target') {
|
||||||
if(name == null) name = Common.getNewName('X')
|
if(name == null) name = Objects.getNewName('X')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.approximate = approximate
|
this.approximate = approximate
|
||||||
this.rounding = rounding
|
this.rounding = rounding
|
||||||
|
@ -77,8 +77,10 @@ export default class XCursor extends DrawableObject {
|
||||||
var t = this.targetElement
|
var t = this.targetElement
|
||||||
var approx = ''
|
var approx = ''
|
||||||
if(this.approximate) {
|
if(this.approximate) {
|
||||||
approx = t.execute(this.x.execute())
|
approx = (t.execute(this.x.execute()))
|
||||||
approx = approx.toPrecision(this.rounding + Math.round(approx).toString().length)
|
let intLength = Math.round(approx).toString().length
|
||||||
|
let rounding = Math.min(this.rounding, approx.toString().length - intLength - 1)
|
||||||
|
approx = approx.toPrecision(rounding + intLength)
|
||||||
}
|
}
|
||||||
return `${t.name}(${this.name}) = ${t.simplify(this.x.toEditableString())}` +
|
return `${t.name}(${this.name}) = ${t.simplify(this.x.toEditableString())}` +
|
||||||
(this.approximate ? ' ≈ ' + approx : '')
|
(this.approximate ? ' ≈ ' + approx : '')
|
||||||
|
@ -88,11 +90,13 @@ export default class XCursor extends DrawableObject {
|
||||||
let t = this.targetElement
|
let t = this.targetElement
|
||||||
let approx = ''
|
let approx = ''
|
||||||
if(this.approximate) {
|
if(this.approximate) {
|
||||||
approx = t.execute(this.x.execute())
|
approx = (t.execute(this.x.execute()))
|
||||||
approx = approx.toPrecision(this.rounding + Math.round(approx).toString().length)
|
let intLength = Math.round(approx).toString().length
|
||||||
|
let rounding = Math.min(this.rounding, approx.toString().length - intLength - 1)
|
||||||
|
approx = approx.toPrecision(rounding + intLength)
|
||||||
}
|
}
|
||||||
let simpl = t.simplify(this.x.toEditableString())
|
let simpl = t.simplify(this.x.toEditableString())
|
||||||
return `${Latex.variable(t.name)}(${Latex.variable(this.name)}) = ${simpl.tokens ? Latex.expression(simpl.tokens) : simpl}` +
|
return `${Latex.variable(t.name)}(${Latex.variable(this.name)}) = ${simpl.latexMarkup ? simpl.latexMarkup : Latex.variable(simpl)}` +
|
||||||
(this.approximate ? ' \\simeq ' + approx : '')
|
(this.approximate ? ' \\simeq ' + approx : '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,8 +272,6 @@ export function makeExpressionReadable(str) {
|
||||||
[/_([\d\w+-]+)/g, function(match, p1) { return textsub(p1) }],
|
[/_([\d\w+-]+)/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'],
|
|
||||||
[/([^a-z])\(([^)(+.\/-]+)\)/g, "$1×$2"],
|
|
||||||
[/integral\((.+),\s?(.+),\s?["'](.+)["'],\s?["'](.+)["']\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
|
[/integral\((.+),\s?(.+),\s?["'](.+)["'],\s?["'](.+)["']\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
|
||||||
if(a.length < b.length) {
|
if(a.length < b.length) {
|
||||||
return `∫${textsub(a)}${textsup(b)} ${body} d${by}`
|
return `∫${textsub(a)}${textsup(b)} ${body} d${by}`
|
||||||
|
|
Loading…
Reference in a new issue