Finished & working X Cursor, makeing objects deletable.
This commit is contained in:
parent
bb85f5b17a
commit
0dec00c87b
8 changed files with 353 additions and 72 deletions
|
@ -147,6 +147,7 @@ ApplicationWindow {
|
||||||
root.height = data["height"]
|
root.height = data["height"]
|
||||||
root.width = data["width"]
|
root.width = data["width"]
|
||||||
|
|
||||||
|
Objects.currentObjects = {}
|
||||||
Object.keys(data['objects']).forEach(function(objType){
|
Object.keys(data['objects']).forEach(function(objType){
|
||||||
Objects.currentObjects[objType] = []
|
Objects.currentObjects[objType] = []
|
||||||
data['objects'][objType].forEach(function(objData){
|
data['objects'][objType].forEach(function(objData){
|
||||||
|
|
|
@ -32,7 +32,7 @@ ListView {
|
||||||
property var listViews: {'':''} // Needs to be initialized or will be undefined -_-
|
property var listViews: {'':''} // Needs to be initialized or will be undefined -_-
|
||||||
|
|
||||||
model: Object.keys(Objects.types)
|
model: Object.keys(Objects.types)
|
||||||
implicitHeight: contentItem.childrenRect.height
|
implicitHeight: contentItem.childrenRect.height + footer.height + 10
|
||||||
|
|
||||||
delegate: ListView {
|
delegate: ListView {
|
||||||
id: objTypeList
|
id: objTypeList
|
||||||
|
@ -47,7 +47,7 @@ ListView {
|
||||||
header: Text {
|
header: Text {
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
color: sysPalette.windowText
|
color: sysPalette.windowText
|
||||||
text: objectListList.model[index] + "s:"
|
text: Objects.types[objType].typeMultiple() + ":"
|
||||||
font.pixelSize: 20
|
font.pixelSize: 20
|
||||||
visible: objTypeList.visible
|
visible: objTypeList.visible
|
||||||
height: visible ? 20 : 0
|
height: visible ? 20 : 0
|
||||||
|
@ -64,7 +64,7 @@ ListView {
|
||||||
checked: Objects.currentObjects[objType][index].visible
|
checked: Objects.currentObjects[objType][index].visible
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Objects.currentObjects[objType][index].visible = !Objects.currentObjects[objType][index].visible
|
Objects.currentObjects[objType][index].visible = this.checked
|
||||||
objectListList.changed()
|
objectListList.changed()
|
||||||
controlRow.obj = Objects.currentObjects[objType][index]
|
controlRow.obj = Objects.currentObjects[objType][index]
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ ListView {
|
||||||
Text {
|
Text {
|
||||||
id: objDescription
|
id: objDescription
|
||||||
anchors.left: visibilityCheckBox.right
|
anchors.left: visibilityCheckBox.right
|
||||||
|
anchors.right: deleteButton.left
|
||||||
height: parent.height
|
height: parent.height
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
text: obj.getReadableString()
|
text: obj.getReadableString()
|
||||||
|
@ -94,9 +95,28 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: deleteButton
|
||||||
|
width: parent.height - 10
|
||||||
|
height: width
|
||||||
|
anchors.right: colorPickRect.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.topMargin: 5
|
||||||
|
icon.source: './icons/delete.svg'
|
||||||
|
icon.name: 'delete'
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Objects.currentObjects[objType][index].delete()
|
||||||
|
Objects.currentObjects[objType].splice(index, 1)
|
||||||
|
objectListList.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: colorPickRect
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 5
|
anchors.rightMargin: 5
|
||||||
|
anchors.topMargin: 5
|
||||||
color: obj.color
|
color: obj.color
|
||||||
width: parent.height - 10
|
width: parent.height - 10
|
||||||
height: width
|
height: width
|
||||||
|
@ -227,6 +247,19 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: customPropCheckBox
|
||||||
|
visible: modelData[1] == 'Boolean'
|
||||||
|
width: parent.width
|
||||||
|
text: parent.label
|
||||||
|
checked: visible ? objEditor.obj[modelData[0]] : false
|
||||||
|
onClicked: {
|
||||||
|
objEditor.obj[modelData[0]] = this.checked
|
||||||
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex].update()
|
||||||
|
objectListList.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ComboBoxSetting {
|
ComboBoxSetting {
|
||||||
id: customPropCombo
|
id: customPropCombo
|
||||||
height: 30
|
height: 30
|
||||||
|
@ -249,6 +282,8 @@ ListView {
|
||||||
model = Objects.getObjectsName(modelData[1]).concat(['+ Create new ' + modelData[1]])
|
model = Objects.getObjectsName(modelData[1]).concat(['+ Create new ' + modelData[1]])
|
||||||
currentIndex = model.indexOf(selectedObj.name)
|
currentIndex = model.indexOf(selectedObj.name)
|
||||||
}
|
}
|
||||||
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]].requiredBy = objEditor.obj[modelData[0]].filter(function(obj) {objEditor.obj.name != obj.name})
|
||||||
|
selectedObj.requiredBy.push(Objects.currentObjects[objEditor.objType][objEditor.objIndex])
|
||||||
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = selectedObj
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = selectedObj
|
||||||
} else {
|
} else {
|
||||||
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = model[newIndex]
|
Objects.currentObjects[objEditor.objType][objEditor.objIndex][modelData[0]] = model[newIndex]
|
||||||
|
|
|
@ -156,6 +156,7 @@ Column {
|
||||||
ListElement { text: "" }
|
ListElement { text: "" }
|
||||||
ListElement { text: "y" }
|
ListElement { text: "y" }
|
||||||
ListElement { text: "G (dB)" }
|
ListElement { text: "G (dB)" }
|
||||||
|
ListElement { text: "φ (°)" }
|
||||||
ListElement { text: "φ (deg)" }
|
ListElement { text: "φ (deg)" }
|
||||||
ListElement { text: "φ (rad)" }
|
ListElement { text: "φ (rad)" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,16 +25,16 @@
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="22.4"
|
inkscape:zoom="22.4"
|
||||||
inkscape:cx="23.448337"
|
inkscape:cx="23.448337"
|
||||||
inkscape:cy="8.0833333"
|
inkscape:cy="1.0201712"
|
||||||
inkscape:document-units="px"
|
inkscape:document-units="px"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
inkscape:document-rotation="0"
|
inkscape:document-rotation="0"
|
||||||
showgrid="true"
|
showgrid="true"
|
||||||
inkscape:window-width="1920"
|
inkscape:window-width="1829"
|
||||||
inkscape:window-height="1011"
|
inkscape:window-height="916"
|
||||||
inkscape:window-x="1920"
|
inkscape:window-x="48"
|
||||||
inkscape:window-y="0"
|
inkscape:window-y="31"
|
||||||
inkscape:window-maximized="1">
|
inkscape:window-maximized="0">
|
||||||
<inkscape:grid
|
<inkscape:grid
|
||||||
type="xygrid"
|
type="xygrid"
|
||||||
id="grid2039" />
|
id="grid2039" />
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
<dc:format>image/svg+xml</dc:format>
|
<dc:format>image/svg+xml</dc:format>
|
||||||
<dc:type
|
<dc:type
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
<dc:title></dc:title>
|
<dc:title />
|
||||||
</cc:Work>
|
</cc:Work>
|
||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
@ -62,13 +62,17 @@
|
||||||
id="path1414"
|
id="path1414"
|
||||||
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
|
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0"
|
||||||
d="M 10.019082,18.146312 A 3.5,3.5 0 0 1 6.955752,22.00089 3.5,3.5 0 0 1 3.0690998,18.978357 3.5,3.5 0 0 1 6.0505,15.060064 3.5,3.5 0 0 1 10,18" />
|
d="M 10.019082,18.146312 A 3.5,3.5 0 0 1 6.955752,22.00089 3.5,3.5 0 0 1 3.0690998,18.978357 3.5,3.5 0 0 1 6.0505,15.060064 3.5,3.5 0 0 1 10,18" />
|
||||||
<g
|
<text
|
||||||
aria-label="A"
|
xml:space="preserve"
|
||||||
id="text2054"
|
style="font-style:normal;font-weight:normal;font-size:17.3373px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.00023"
|
||||||
style="font-style:normal;font-weight:normal;font-size:17.3333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none">
|
x="12.066752"
|
||||||
<path
|
y="13.922545"
|
||||||
d="m 18.990651,13.942643 h 1.73333 L 16.910655,1.9999997 H 14.830659 L 11,13.942643 h 1.663996 l 0.901332,-2.998661 h 4.523991 z M 13.963994,9.6093183 15.83599,3.3693304 17.690653,9.6093183 Z"
|
id="text14"
|
||||||
id="path3356" />
|
transform="scale(0.99446808,1.0055627)"><tspan
|
||||||
</g>
|
sodipodi:role="line"
|
||||||
|
id="tspan12"
|
||||||
|
x="12.066752"
|
||||||
|
y="13.922545"
|
||||||
|
style="font-size:17.3373px;stroke-width:1.00023">A</tspan></text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
82
qml/icons/X Cursor.svg
Normal file
82
qml/icons/X Cursor.svg
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24.0px"
|
||||||
|
height="24.0px"
|
||||||
|
viewBox="0 0 24.0 24.0"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
sodipodi:docname="X Cursor.svg.2020_12_24_14_32_23.0.svg"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
|
<defs
|
||||||
|
id="defs1469" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.4"
|
||||||
|
inkscape:cx="23.448337"
|
||||||
|
inkscape:cy="12.896609"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1829"
|
||||||
|
inkscape:window-height="916"
|
||||||
|
inkscape:window-x="19"
|
||||||
|
inkscape:window-y="31"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2039" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2058" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata1472">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Calque 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:17.3373px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.00023"
|
||||||
|
x="3.0166881"
|
||||||
|
y="13.425312"
|
||||||
|
id="text14"
|
||||||
|
transform="scale(0.99446808,1.0055627)"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan12"
|
||||||
|
x="3.0166881"
|
||||||
|
y="13.425312"
|
||||||
|
style="font-size:17.3373px;stroke-width:1.00023">X</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.774803;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect12"
|
||||||
|
width="2"
|
||||||
|
height="24"
|
||||||
|
x="17"
|
||||||
|
y="0"
|
||||||
|
ry="2.14841e-13" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
|
@ -49,7 +49,7 @@ class Expression {
|
||||||
return this.calc.evaluate(Object.assign({'x': x}, evalVariables))
|
return this.calc.evaluate(Object.assign({'x': x}, evalVariables))
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify(x = 1) {
|
simplify(x) {
|
||||||
var expr = this.calc.substitute('x', x).simplify()
|
var expr = this.calc.substitute('x', x).simplify()
|
||||||
if(expr.evaluate(evalVariables) == 0) return '0'
|
if(expr.evaluate(evalVariables) == 0) return '0'
|
||||||
return Utils.makeExpressionReadable(expr.toString())
|
return Utils.makeExpressionReadable(expr.toString())
|
||||||
|
@ -69,6 +69,10 @@ class Expression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function executeExpression(expr){
|
||||||
|
return (new Expression(expr.toString())).execute()
|
||||||
|
}
|
||||||
|
|
||||||
// Domains
|
// Domains
|
||||||
|
|
||||||
class EmptySet {
|
class EmptySet {
|
||||||
|
@ -93,6 +97,7 @@ class Domain {
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(x) {
|
includes(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()))
|
||||||
}
|
}
|
||||||
|
@ -168,10 +173,10 @@ class DomainSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(x) {
|
includes(x) {
|
||||||
var xcomputed = new Expression(x.toString()).execute()
|
if(typeof x == 'string') x = executeExpression(x)
|
||||||
var found = false
|
var found = false
|
||||||
this.values.forEach(function(value){
|
this.values.forEach(function(value){
|
||||||
if(xcomputed == value.execute()) {
|
if(x == value.execute()) {
|
||||||
found = true
|
found = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,11 @@ class DrawableObject {
|
||||||
this.requiredBy = []
|
this.requiredBy = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
// Should return what will be input as arguments when a file is loaded (serializable form)
|
||||||
|
return [this.name, this.visible, this.color.toString(), this.labelContent]
|
||||||
|
}
|
||||||
|
|
||||||
getReadableString() {
|
getReadableString() {
|
||||||
return `${this.name} = Unknown`
|
return `${this.name} = Unknown`
|
||||||
}
|
}
|
||||||
|
@ -76,11 +81,19 @@ class DrawableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export() {
|
update() {
|
||||||
return [this.name, this.visible, this.color.toString(), this.labelContent]
|
for(var i = 0; i < this.requiredBy.length; i++) {
|
||||||
|
this.requiredBy[i].update()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {}
|
delete() {
|
||||||
|
for(var i = 0; i < this.requiredBy.length; i++) {
|
||||||
|
var toRemove = this.requiredBy[i]
|
||||||
|
toRemove.delete()
|
||||||
|
currentObjects[toRemove.type] = currentObjects[toRemove.type].filter(obj => obj.name != toRemove.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
draw(canvas, ctx) {}
|
draw(canvas, ctx) {}
|
||||||
}
|
}
|
||||||
|
@ -103,12 +116,12 @@ class Point extends DrawableObject {
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
'x': 'Expression',
|
'x': 'Expression',
|
||||||
'y': 'Expression',
|
'y': 'Expression',
|
||||||
'labelPos': ['top', 'bottom', 'left', 'right'],
|
'labelPosition': ['top', 'bottom', 'left', 'right'],
|
||||||
'pointStyle': ['●', '✕', '+'],
|
'pointStyle': ['●', '✕', '+'],
|
||||||
}}
|
}}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
x = 1, y = 0, labelPos = 'top', pointStyle = '●') {
|
x = 1, y = 0, labelPosition = 'top', pointStyle = '●') {
|
||||||
if(name == null) name = getNewName('ABCDEFJKLMNOPQRSTUVW')
|
if(name == null) name = getNewName('ABCDEFJKLMNOPQRSTUVW')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.type = 'Point'
|
this.type = 'Point'
|
||||||
|
@ -116,7 +129,7 @@ class Point extends DrawableObject {
|
||||||
this.x = x
|
this.x = x
|
||||||
if(typeof y == 'number' || typeof y == 'string') y = new MathLib.Expression(y.toString())
|
if(typeof y == 'number' || typeof y == 'string') y = new MathLib.Expression(y.toString())
|
||||||
this.y = y
|
this.y = y
|
||||||
this.labelPos = labelPos
|
this.labelPosition = labelPosition
|
||||||
this.pointStyle = pointStyle
|
this.pointStyle = pointStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +138,7 @@ class Point extends DrawableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
return [this.name, this.visible, this.color.toString(), this.labelContent, this.x.toEditableString(), this.y.toEditableString(), this.labelPos, this.pointStyle]
|
return [this.name, this.visible, this.color.toString(), this.labelContent, this.x.toEditableString(), this.y.toEditableString(), this.labelPosition, this.pointStyle]
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(canvas, ctx) {
|
draw(canvas, ctx) {
|
||||||
|
@ -149,7 +162,7 @@ class Point extends DrawableObject {
|
||||||
var text = this.getLabel()
|
var text = this.getLabel()
|
||||||
ctx.font = "14px sans-serif"
|
ctx.font = "14px sans-serif"
|
||||||
var textSize = ctx.measureText(text).width
|
var textSize = ctx.measureText(text).width
|
||||||
switch(this.labelPos) {
|
switch(this.labelPosition) {
|
||||||
case 'top':
|
case 'top':
|
||||||
canvas.drawVisibleText(ctx, text, canvasX-textSize/2, canvasY-16)
|
canvas.drawVisibleText(ctx, text, canvasX-textSize/2, canvasY-16)
|
||||||
break;
|
break;
|
||||||
|
@ -165,14 +178,6 @@ 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++) {
|
|
||||||
if(currentObjects['Gain Bode'][i].ω_0.name == this.name) currentObjects['Gain Bode'][i].update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Function extends ExecutableObject {
|
class Function extends ExecutableObject {
|
||||||
|
@ -182,16 +187,17 @@ class Function extends ExecutableObject {
|
||||||
'expression': 'Expression',
|
'expression': 'Expression',
|
||||||
'inDomain': 'Domain',
|
'inDomain': 'Domain',
|
||||||
'outDomain': 'Domain',
|
'outDomain': 'Domain',
|
||||||
'labelPos': ['above', 'below'],
|
'labelPosition': ['above', 'below'],
|
||||||
'displayMode': ['application', 'function'],
|
'displayMode': ['application', 'function'],
|
||||||
'labelX': 'number'
|
'labelX': 'number'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
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', labelPos = 'above', labelX = 1) {
|
displayMode = 'application', labelPosition = 'above', labelX = 1) {
|
||||||
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'
|
||||||
if(typeof expression == 'number' || typeof expression == 'string') expression = new MathLib.Expression(expression.toString())
|
if(typeof expression == 'number' || typeof expression == 'string') expression = new MathLib.Expression(expression.toString())
|
||||||
this.expression = expression
|
this.expression = expression
|
||||||
if(typeof inDomain == 'string') inDomain = MathLib.parseDomain(inDomain)
|
if(typeof inDomain == 'string') inDomain = MathLib.parseDomain(inDomain)
|
||||||
|
@ -199,7 +205,7 @@ class Function extends ExecutableObject {
|
||||||
if(typeof outDomain == 'string') outDomain = MathLib.parseDomain(outDomain)
|
if(typeof outDomain == 'string') outDomain = MathLib.parseDomain(outDomain)
|
||||||
this.outDomain = outDomain
|
this.outDomain = outDomain
|
||||||
this.displayMode = displayMode
|
this.displayMode = displayMode
|
||||||
this.labelPos = labelPos
|
this.labelPosition = labelPosition
|
||||||
this.labelX = labelX
|
this.labelX = labelX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,12 +220,12 @@ 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.labelPos, this.labelX]
|
this.displayMode, this.labelPosition, this.labelX]
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(x = 1) {
|
execute(x = 1) {
|
||||||
if(this.inDomain.includes(x))
|
if(this.inDomain.includes(x))
|
||||||
return this.expr.execute(x)
|
return this.expression.execute(x)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +235,7 @@ class Function extends ExecutableObject {
|
||||||
|
|
||||||
simplify(x = 1) {
|
simplify(x = 1) {
|
||||||
if(this.inDomain.includes(x))
|
if(this.inDomain.includes(x))
|
||||||
return this.expr.simplify(x)
|
return this.expression.simplify(x)
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +247,7 @@ class Function extends ExecutableObject {
|
||||||
var textSize = canvas.measureText(ctx, text)
|
var textSize = canvas.measureText(ctx, text)
|
||||||
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.expression.execute(this.labelX))
|
||||||
switch(this.labelPos) {
|
switch(this.labelPosition) {
|
||||||
case 'above':
|
case 'above':
|
||||||
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
||||||
break;
|
break;
|
||||||
|
@ -279,15 +285,16 @@ class GainBode extends ExecutableObject {
|
||||||
'ω_0': 'Point',
|
'ω_0': 'Point',
|
||||||
'pass': ['high', 'low'],
|
'pass': ['high', 'low'],
|
||||||
'gain': 'Expression',
|
'gain': 'Expression',
|
||||||
'labelPos': ['above', 'below'],
|
'labelPosition': ['above', 'below'],
|
||||||
'labelX': 'number'
|
'labelX': 'number'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
ω_0 = '', pass = 'high', gain = '20', labelPos = 'above', labelX = 1) {
|
ω_0 = '', pass = 'high', gain = '20', labelPosition = 'above', labelX = 1) {
|
||||||
if(name == null) name = getNewName('G')
|
if(name == null) name = getNewName('G')
|
||||||
if(name == 'G') name = 'G₀' // G is reserved for sum of BODE magnitues (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)
|
||||||
|
this.type = 'Gain Bode'
|
||||||
if(typeof ω_0 == "string") {
|
if(typeof ω_0 == "string") {
|
||||||
// Point name or create one
|
// Point name or create one
|
||||||
ω_0 = getObjectByName(ω_0, 'Point')
|
ω_0 = getObjectByName(ω_0, 'Point')
|
||||||
|
@ -296,14 +303,15 @@ class GainBode extends ExecutableObject {
|
||||||
ω_0 = createNewRegisteredObject('Point')
|
ω_0 = createNewRegisteredObject('Point')
|
||||||
ω_0.name = getNewName('ω')
|
ω_0.name = getNewName('ω')
|
||||||
ω_0.color = this.color
|
ω_0.color = this.color
|
||||||
labelPos = 'below'
|
labelPosition = 'below'
|
||||||
}
|
}
|
||||||
|
ω_0.requiredBy.push(this)
|
||||||
}
|
}
|
||||||
this.ω_0 = ω_0
|
this.ω_0 = ω_0
|
||||||
this.pass = pass
|
this.pass = pass
|
||||||
if(typeof gain == 'number' || typeof gain == 'string') gain = new MathLib.Expression(gain.toString())
|
if(typeof gain == 'number' || typeof gain == 'string') gain = new MathLib.Expression(gain.toString())
|
||||||
this.gain = gain
|
this.gain = gain
|
||||||
this.labelPos = labelPos
|
this.labelPosition = labelPosition
|
||||||
this.labelX = labelX
|
this.labelX = labelX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +321,7 @@ class GainBode 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.ω_0.name, this.pass.toString(), this.gain.toEditableString(), this.labelPos, this.labelX]
|
this.ω_0.name, this.pass.toString(), this.gain.toEditableString(), this.labelPosition, this.labelX]
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(x=1) {
|
execute(x=1) {
|
||||||
|
@ -360,7 +368,7 @@ class GainBode extends ExecutableObject {
|
||||||
var textSize = canvas.measureText(ctx, text)
|
var textSize = canvas.measureText(ctx, text)
|
||||||
var posX = canvas.x2px(this.labelX)
|
var posX = canvas.x2px(this.labelX)
|
||||||
var posY = canvas.y2px(this.execute(this.labelX))
|
var posY = canvas.y2px(this.execute(this.labelX))
|
||||||
switch(this.labelPos) {
|
switch(this.labelPosition) {
|
||||||
case 'above':
|
case 'above':
|
||||||
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
||||||
break;
|
break;
|
||||||
|
@ -384,21 +392,21 @@ class SommeGainsBode extends DrawableObject {
|
||||||
static typeMultiple(){return 'Somme gains Bode'}
|
static typeMultiple(){return 'Somme gains Bode'}
|
||||||
static createable() {return false}
|
static createable() {return false}
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
'labelPos': ['above', 'below'],
|
'labelPosition': ['above', 'below'],
|
||||||
'labelX': 'number'
|
'labelX': 'number'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
labelPos = 'above', labelX = 1) {
|
labelPosition = 'above', labelX = 1) {
|
||||||
if(name == null) name = 'G'
|
if(name == null) name = 'G'
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.labelPos = labelPos
|
this.labelPosition = labelPosition
|
||||||
this.labelX = labelX
|
this.labelX = labelX
|
||||||
this.recalculateCache()
|
this.recalculateCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
return [this.name, this.visible, this.color.toString(), this.labelContent, this.labelPos, this.labelX]
|
return [this.name, this.visible, this.color.toString(), this.labelContent, this.labelPosition, this.labelX]
|
||||||
}
|
}
|
||||||
|
|
||||||
getReadableString() {
|
getReadableString() {
|
||||||
|
@ -493,7 +501,7 @@ class SommeGainsBode extends DrawableObject {
|
||||||
var textSize = canvas.measureText(ctx, text)
|
var textSize = canvas.measureText(ctx, text)
|
||||||
var posX = canvas.x2px(this.labelX)
|
var posX = canvas.x2px(this.labelX)
|
||||||
var posY = canvas.y2px(dbfn.execute(this.labelX))
|
var posY = canvas.y2px(dbfn.execute(this.labelX))
|
||||||
switch(this.labelPos) {
|
switch(this.labelPosition) {
|
||||||
case 'above':
|
case 'above':
|
||||||
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
||||||
break;
|
break;
|
||||||
|
@ -508,12 +516,55 @@ class SommeGainsBode extends DrawableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
class PhaseBode extends ExecutableObject {
|
class PhaseBode extends ExecutableObject {
|
||||||
|
static type(){return 'Phase Bode'}
|
||||||
|
static typeMultiple(){return 'Phases Bode'}
|
||||||
|
static properties() {return {
|
||||||
|
'ω_0': 'Point',
|
||||||
|
'phase': 'Expression',
|
||||||
|
'unit': ['°', 'deg', 'rad'],
|
||||||
|
'labelPosition': ['above', 'below'],
|
||||||
|
'labelX': 'number'
|
||||||
|
}}
|
||||||
|
|
||||||
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
|
ω_0 = '', phase = 90, unit = '°', labelPosition = 'above', labelX = 1) {
|
||||||
|
if(name == null) name = getNewName('φ')
|
||||||
|
if(name == 'φ') name = 'φ₀' // φ is reserved for sum of BODE phases (Somme phases Bode).
|
||||||
|
super(name, visible, color, labelContent)
|
||||||
|
this.type = 'Phase Bode'
|
||||||
|
if(typeof ω_0 == "string") {
|
||||||
|
// Point name or create one
|
||||||
|
ω_0 = getObjectByName(ω_0, 'Point')
|
||||||
|
if(ω_0 == null) {
|
||||||
|
// Create new point
|
||||||
|
ω_0 = createNewRegisteredObject('Point')
|
||||||
|
ω_0.name = getNewName('ω')
|
||||||
|
ω_0.color = this.color
|
||||||
|
labelPosition = 'below'
|
||||||
|
}
|
||||||
|
ω_0.requiredBy.push(this)
|
||||||
|
}
|
||||||
|
this.ω_0 = ω_0
|
||||||
|
if(typeof phase == 'number' || typeof phase == 'string') phase = new MathLib.Expression(phase.toString())
|
||||||
|
this.phase = phase
|
||||||
|
this.unit = unit
|
||||||
|
this.labelPosition = labelPosition
|
||||||
|
this.labelX = labelX
|
||||||
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
||||||
|
this.ω_0.name, this.phase.toEditableString(), this.unit, this.labelPosition, this.labelX]
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadableString() {
|
||||||
|
return `${this.name}: ${this.phase.toString(true)}${this.unit} at ω₀ = ${this.ω_0.x}\n`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CursorX extends DrawableObject {
|
class CursorX extends DrawableObject {
|
||||||
static type(){return 'CursorX'}
|
static type(){return 'X Cursor'}
|
||||||
static typeMultiple(){return 'CursorX'}
|
static typeMultiple(){return 'X Cursors'}
|
||||||
static properties() {
|
static properties() {
|
||||||
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
||||||
var elementNames = ['']
|
var elementNames = ['']
|
||||||
|
@ -522,33 +573,134 @@ class CursorX extends DrawableObject {
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
'x': 'Expression',
|
'x': 'Expression',
|
||||||
'element': elementNames,
|
'targetElement': elementNames,
|
||||||
'labelPos': ['left', 'right'],
|
'labelPosition': ['left', 'right'],
|
||||||
|
'approximate': 'Boolean',
|
||||||
|
'rounding': 'number',
|
||||||
'displayStyle': [
|
'displayStyle': [
|
||||||
'⸻⸻⸻',
|
'— — — — — — —',
|
||||||
'— — — — —',
|
'⸺⸺⸺⸺⸺⸺',
|
||||||
'• • • • •'
|
'• • • • • • • • • •'
|
||||||
]
|
],
|
||||||
|
'targetValuePosition' : ['Next to target', 'With label', 'Hidden']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
x = 1, element = null, labelPos = 'left', displayStyle = '⸻⸻⸻') {
|
x = 1, targetElement = null, labelPosition = 'left', approximate = true,
|
||||||
|
rounding = 3, displayStyle = '— — — — — — —', targetValuePosition = 'Next to target') {
|
||||||
if(name == null) name = getNewName('X')
|
if(name == null) name = getNewName('X')
|
||||||
super(name, visible, color, labelContent)
|
super(name, visible, color, labelContent)
|
||||||
this.type = 'CursorX'
|
this.type = 'X Cursor'
|
||||||
|
this.approximate = approximate
|
||||||
|
this.rounding = rounding
|
||||||
if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString())
|
if(typeof x == 'number' || typeof x == 'string') x = new MathLib.Expression(x.toString())
|
||||||
this.x = x
|
this.x = x
|
||||||
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
||||||
this.element = getObjectByName(this.element, elementTypes)
|
this.targetElement = getObjectByName(this.targetElement, elementTypes)
|
||||||
this.labelPos = labelPos
|
this.labelPosition = labelPosition
|
||||||
this.displayStyle = displayStyle
|
this.displayStyle = displayStyle
|
||||||
|
this.targetValuePosition = targetValuePosition
|
||||||
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
||||||
|
this.x.toEditableString(), this.targetElement.name, this.labelPosition,
|
||||||
|
this.approximate, this.rounding, this.displayStyle, this.targetValuePosition]
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadableString() {
|
||||||
|
if(this.targetElement == null) return `${this.name} = ${this.x.toString()}`
|
||||||
|
return `${this.name} = ${this.x.toString()}\n${this.getTargetValueLabel()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
getTargetValueLabel() {
|
||||||
|
var t = this.targetElement
|
||||||
|
var approx = ''
|
||||||
|
if(this.approximate) {
|
||||||
|
approx = t.execute(this.x.execute())
|
||||||
|
approx = approx.toPrecision(this.rounding + Math.round(approx).toString().length)
|
||||||
|
}
|
||||||
|
return `${t.name}(${this.name}) = ${t.simplify(this.x.toEditableString())}` +
|
||||||
|
(this.approximate ? ' ≃ ' + approx : '')
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabel() {
|
||||||
|
switch(this.labelContent) {
|
||||||
|
case 'name':
|
||||||
|
return this.name
|
||||||
|
break;
|
||||||
|
case 'name + value':
|
||||||
|
switch(this.targetValuePosition) {
|
||||||
|
case 'Next to target':
|
||||||
|
case 'Hidden':
|
||||||
|
return `${this.name} = ${this.x.toString()}`
|
||||||
|
break;
|
||||||
|
case 'With label':
|
||||||
|
return this.getReadableString()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'null':
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(canvas, ctx) {
|
||||||
|
var xpos = canvas.x2px(this.x.execute())
|
||||||
|
switch(this.displayStyle) {
|
||||||
|
case '— — — — — — —':
|
||||||
|
var dashPxSize = 10
|
||||||
|
for(var i = 0; i < canvas.canvasSize.height; i += dashPxSize*2)
|
||||||
|
canvas.drawLine(ctx, xpos, i, xpos, i+dashPxSize)
|
||||||
|
break;
|
||||||
|
case '⸺⸺⸺⸺⸺⸺':
|
||||||
|
canvas.drawXLine(ctx, this.x.execute())
|
||||||
|
break;
|
||||||
|
case '• • • • • • • • • •':
|
||||||
|
var pointDistancePx = 10
|
||||||
|
var pointSize = 2
|
||||||
|
ctx.beginPath();
|
||||||
|
for(var i = 0; i < canvas.canvasSize.height; i += pointDistancePx)
|
||||||
|
ctx.ellipse(xpos-pointSize/2, i-pointSize/2, pointSize, pointSize)
|
||||||
|
ctx.fill();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label
|
||||||
|
var text = this.getLabel()
|
||||||
|
ctx.font = "14px sans-serif"
|
||||||
|
var textSize = canvas.measureText(ctx, text, 7)
|
||||||
|
|
||||||
|
switch(this.labelPosition) {
|
||||||
|
case 'left':
|
||||||
|
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, textSize.height+5)
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
canvas.drawVisibleText(ctx, text, xpos+5, textSize.height+5)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.targetValuePosition == 'Next to target' && this.targetElement != null) {
|
||||||
|
var text = this.getTargetValueLabel()
|
||||||
|
var textSize = canvas.measureText(ctx, text, 7)
|
||||||
|
var ypox = canvas.y2px(this.targetElement.execute(this.x.execute()))
|
||||||
|
switch(this.labelPosition) {
|
||||||
|
case 'left':
|
||||||
|
canvas.drawVisibleText(ctx, text, xpos-textSize.width-5, ypox+textSize.height)
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
canvas.drawVisibleText(ctx, text, xpos+5, ypox.textSize.height)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
if(typeof this.element == 'string')
|
if(typeof this.targetElement == 'string') {
|
||||||
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
var elementTypes = Object.keys(currentObjects).filter(objType => types[objType].prototype instanceof ExecutableObject)
|
||||||
this.element = getObjectByName(this.element, elementTypes)
|
this.targetElement = getObjectByName(this.targetElement, elementTypes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +709,8 @@ const types = {
|
||||||
'Function': Function,
|
'Function': Function,
|
||||||
'Gain Bode': GainBode,
|
'Gain Bode': GainBode,
|
||||||
'Somme gains Bode': SommeGainsBode,
|
'Somme gains Bode': SommeGainsBode,
|
||||||
'CursorX': CursorX
|
'Phase Bode': PhaseBode,
|
||||||
|
'X Cursor': CursorX
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentObjects = {}
|
var currentObjects = {}
|
||||||
|
|
|
@ -285,7 +285,7 @@ function getRandomColor() {
|
||||||
var clrs = '0123456789ABCDEF';
|
var clrs = '0123456789ABCDEF';
|
||||||
var color = '#';
|
var color = '#';
|
||||||
for (var i = 0; i < 6; i++) {
|
for (var i = 0; i < 6; i++) {
|
||||||
color += clrs[Math.floor(Math.random() * (16-6*(i%2==0)))];
|
color += clrs[Math.floor(Math.random() * (16-5*(i%2==0)))];
|
||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue