Repartition function!
This commit is contained in:
parent
6d1c3d5450
commit
3d430906fe
3 changed files with 243 additions and 3 deletions
85
qml/icons/Repartition function.svg
Normal file
85
qml/icons/Repartition function.svg
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<?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="Repartition function.svg"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
|
<defs
|
||||||
|
id="defs835" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="31.678384"
|
||||||
|
inkscape:cx="10.734927"
|
||||||
|
inkscape:cy="13.020605"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1011"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid1405" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata838">
|
||||||
|
<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></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Calque 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#000000;fill-rule:evenodd;stroke:none;stroke-width:0.377953"
|
||||||
|
id="path1412"
|
||||||
|
cx="3"
|
||||||
|
cy="12"
|
||||||
|
r="2.5" />
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-rule:evenodd;stroke:none;stroke-width:0.377953"
|
||||||
|
id="rect1414"
|
||||||
|
width="15"
|
||||||
|
height="2"
|
||||||
|
x="5"
|
||||||
|
y="11" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.755908;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path1416"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="22.049"
|
||||||
|
sodipodi:cy="12.049665"
|
||||||
|
sodipodi:rx="2.1712694"
|
||||||
|
sodipodi:ry="2.1717117"
|
||||||
|
sodipodi:start="1.5707963"
|
||||||
|
sodipodi:end="4.712389"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 22.049,14.221377 a 2.1712694,2.1717117 0 0 1 -1.880375,-1.085856 2.1712694,2.1717117 0 0 1 0,-2.171711 A 2.1712694,2.1717117 0 0 1 22.049,9.8779538"
|
||||||
|
sodipodi:open="true" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
|
@ -63,7 +63,14 @@ class Expression {
|
||||||
simplify(x) {
|
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())
|
var str = Utils.makeExpressionReadable(expr.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicate() {
|
duplicate() {
|
||||||
|
|
|
@ -234,7 +234,7 @@ class Function extends ExecutableObject {
|
||||||
|
|
||||||
getReadableString() {
|
getReadableString() {
|
||||||
if(this.displayMode == 'application') {
|
if(this.displayMode == 'application') {
|
||||||
return `${this.name}: ${this.definitionDomain} ⸺> ${this.destinationDomain}\n ${' '.repeat(this.name.length)}x ⸺> ${this.expression.toString()}`
|
return `${this.name}: ${this.definitionDomain} ⟼ ${this.destinationDomain}\n ${' '.repeat(this.name.length)}x ⟼ ${this.expression.toString()}`
|
||||||
} else {
|
} else {
|
||||||
return `${this.name}(x) = ${this.expression.toString()}\nD${Utils.textsub(this.name)} = ${this.definitionDomain}`
|
return `${this.name}(x) = ${this.expression.toString()}\nD${Utils.textsub(this.name)} = ${this.definitionDomain}`
|
||||||
}
|
}
|
||||||
|
@ -1136,6 +1136,153 @@ class Sequence extends ExecutableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RepartitionFunction extends ExecutableObject {
|
||||||
|
static type(){return 'Repartition function'}
|
||||||
|
static typeMultiple(){return 'Repartition functions'}
|
||||||
|
static properties() {return {
|
||||||
|
'beginIncluded': 'Boolean',
|
||||||
|
'drawLineEnds': 'Boolean',
|
||||||
|
'comment1': 'Note: Specify the properties for each potential result.',
|
||||||
|
'probabilities': new P.Dictionary('string', 'int', /^[\d.]+$/, /^[\d\.]+$/, 'P({name} = ', ') = '),
|
||||||
|
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
|
||||||
|
'labelX': 'number'
|
||||||
|
}}
|
||||||
|
|
||||||
|
constructor(name = null, visible = true, color = null, labelContent = 'name + value',
|
||||||
|
beginIncluded = true, drawLineEnds = true, probabilities = {0: 0}, labelPosition = 'above', labelX = 1) {
|
||||||
|
if(name == null) name = getNewName('XYZUVW')
|
||||||
|
super(name, visible, color, labelContent)
|
||||||
|
this.beginIncluded = beginIncluded
|
||||||
|
this.drawLineEnds = drawLineEnds
|
||||||
|
this.probabilities = probabilities
|
||||||
|
this.labelPosition = labelPosition
|
||||||
|
this.labelX = labelX
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
return [this.name, this.visible, this.color.toString(), this.labelContent,
|
||||||
|
this.beginIncluded, this.drawLineEnds, this.probabilities, this.labelPosition, this.labelX]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getReadableString() {
|
||||||
|
var keys = Object.keys(this.probabilities).sort();
|
||||||
|
return `F_${this.name}(x) = P(${this.name} ≤ x)\n` + keys.map(idx => `P(${this.name}=${idx})=${this.probabilities[idx]}`).join("; ")
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(x = 1) {
|
||||||
|
var ret = 0;
|
||||||
|
Object.keys(this.probabilities).sort().forEach(idx => {
|
||||||
|
if(x >= idx) ret += this.probabilities[idx]
|
||||||
|
})
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
canExecute(x = 1) {return true}
|
||||||
|
// Simplify returns the simplified string of the expression.
|
||||||
|
simplify(x = 1) {
|
||||||
|
return this.execute(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabel() {
|
||||||
|
switch(this.labelContent) {
|
||||||
|
case 'name':
|
||||||
|
return `P(${this.name} ≤ x)`
|
||||||
|
case 'name + value':
|
||||||
|
return this.getReadableString()
|
||||||
|
case 'null':
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(canvas, ctx) {
|
||||||
|
var currentY = 0;
|
||||||
|
var keys = Object.keys(this.probabilities).sort()
|
||||||
|
console.log("Keys", keys)
|
||||||
|
if(canvas.visible(keys[0],this.probabilities[keys[0]])) {
|
||||||
|
canvas.drawLine(ctx,
|
||||||
|
0,
|
||||||
|
canvas.y2px(0),
|
||||||
|
canvas.x2px(keys[0]),
|
||||||
|
canvas.y2px(0)
|
||||||
|
)
|
||||||
|
if(canvas.visible(keys[0],0)) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(canvas.x2px(keys[0])+4,canvas.y2px(0), 4, Math.PI / 2, 3 * Math.PI / 2);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(var i = 0; i < keys.length-1; i++) {
|
||||||
|
var idx = keys[i];
|
||||||
|
currentY += parseFloat(this.probabilities[idx]);
|
||||||
|
if(canvas.visible(idx,currentY) || canvas.visible(keys[i+1],currentY)) {
|
||||||
|
console.log("Drawing", idx, Math.max(0,canvas.x2px(idx)), canvas.y2px(currentY), Math.min(canvas.canvasSize.width,canvas.x2px(keys[i+1])), canvas.y2px(currentY))
|
||||||
|
canvas.drawLine(ctx,
|
||||||
|
Math.max(0,canvas.x2px(idx)),
|
||||||
|
canvas.y2px(currentY),
|
||||||
|
Math.min(canvas.canvasSize.width,canvas.x2px(keys[i+1])),
|
||||||
|
canvas.y2px(currentY)
|
||||||
|
)
|
||||||
|
if(canvas.visible(idx,currentY)) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(canvas.x2px(idx),canvas.y2px(currentY), 4, 0, 2 * Math.PI);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
if(canvas.visible(keys[i+1],currentY)) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(canvas.x2px(keys[i+1])+4,canvas.y2px(currentY), 4, Math.PI / 2, 3 * Math.PI / 2);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(canvas.visible(keys[keys.length-1],this.probabilities[keys[keys.length-1]])) {
|
||||||
|
canvas.drawLine(ctx,
|
||||||
|
Math.max(0,canvas.x2px(keys[keys.length-1])),
|
||||||
|
canvas.y2px(this.probabilities[keys[keys.length-1]]),
|
||||||
|
canvas.canvasSize.width,
|
||||||
|
canvas.y2px(this.probabilities[keys[keys.length-1]])
|
||||||
|
)
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(canvas.x2px(idx),canvas.y2px(currentY), 4, 0, 2 * Math.PI);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label
|
||||||
|
var text = this.getLabel()
|
||||||
|
ctx.font = "14px sans-serif"
|
||||||
|
var textSize = canvas.measureText(ctx, text, 7)
|
||||||
|
var posX = canvas.x2px(this.labelX)
|
||||||
|
var posY = canvas.y2px(this.execute(this.labelX))
|
||||||
|
switch(this.labelPosition) {
|
||||||
|
case 'above':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
|
||||||
|
break;
|
||||||
|
case 'below':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
|
||||||
|
break;
|
||||||
|
case 'left':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
|
||||||
|
break;
|
||||||
|
case 'above-left':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
|
||||||
|
break;
|
||||||
|
case 'above-right':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
|
||||||
|
break;
|
||||||
|
case 'below-left':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
|
||||||
|
break;
|
||||||
|
case 'below-right':
|
||||||
|
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
'Point': Point,
|
'Point': Point,
|
||||||
'Function': Function,
|
'Function': Function,
|
||||||
|
@ -1144,7 +1291,8 @@ const types = {
|
||||||
'Phase Bode': PhaseBode,
|
'Phase Bode': PhaseBode,
|
||||||
'Somme phases Bode': SommePhasesBode,
|
'Somme phases Bode': SommePhasesBode,
|
||||||
'X Cursor': CursorX,
|
'X Cursor': CursorX,
|
||||||
'Sequence': Sequence
|
'Sequence': Sequence,
|
||||||
|
'Repartition function': RepartitionFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentObjects = {}
|
var currentObjects = {}
|
||||||
|
|
Loading…
Reference in a new issue