commit
dc030f63ad
12 changed files with 1389 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||||||
|
.idea |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
{ |
||||||
|
"display_name": "Maths", |
||||||
|
"info_text": "My try of copying GeoGebra.", |
||||||
|
"visible": false, |
||||||
|
"tags": ["Tool", "Maths"] |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
#color_picker{ |
||||||
|
width: 350px; |
||||||
|
height: 320px; |
||||||
|
margin: 20px; |
||||||
|
border: 5px solid #000; |
||||||
|
background-color: #000; |
||||||
|
-webkit-user-select: none; |
||||||
|
-moz-user-select: none; |
||||||
|
-ms-user-select: none; |
||||||
|
user-select: none; |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
#color_picker_numeric{ |
||||||
|
width: 80%; |
||||||
|
padding: 5%; |
||||||
|
margin: 5%; |
||||||
|
background-color: #888; |
||||||
|
border-radius: 10px; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
.color_picker_rgb{ |
||||||
|
float: left; |
||||||
|
width: 24%; |
||||||
|
height: 35px; |
||||||
|
font-size: 25px; |
||||||
|
color: #000; |
||||||
|
} |
||||||
|
.color_picker_rgb:nth-child(1){ |
||||||
|
margin-right: 10%; |
||||||
|
margin-left: 4%; |
||||||
|
background-color: #F00; |
||||||
|
|
||||||
|
} |
||||||
|
.color_picker_rgb:nth-child(2){ |
||||||
|
background-color: #0F0; |
||||||
|
} |
||||||
|
.color_picker_rgb:nth-child(3){ |
||||||
|
margin-left: 10%; |
||||||
|
background-color: #00F; |
||||||
|
color: #FFF; |
||||||
|
} |
||||||
|
#color_picker_hex{ |
||||||
|
width: 50%; |
||||||
|
height: 30px; |
||||||
|
font-size: 25px; |
||||||
|
margin: 10% 25% 0 25%; |
||||||
|
} |
||||||
|
#saturation{ |
||||||
|
position: relative; |
||||||
|
width: calc(100% - 33px); |
||||||
|
height: 100%; |
||||||
|
background: linear-gradient(to right, #FFF 0%, #F00 100%); |
||||||
|
float: left; |
||||||
|
margin-right: 6px; |
||||||
|
} |
||||||
|
#value { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background: linear-gradient(to top, #000 0%, rgba(255,255,255,0) 100%); |
||||||
|
} |
||||||
|
#sb_picker{ |
||||||
|
border: 2px solid; |
||||||
|
border-color: #FFF; |
||||||
|
position: absolute; |
||||||
|
width: 14px; |
||||||
|
height: 14px; |
||||||
|
border-radius: 10px; |
||||||
|
bottom: 50px; |
||||||
|
left: 50px; |
||||||
|
box-sizing: border-box; |
||||||
|
z-index: 10; |
||||||
|
} |
||||||
|
#hue { |
||||||
|
width: 27px; |
||||||
|
height: 100%; |
||||||
|
position: relative; |
||||||
|
float: left; |
||||||
|
background: linear-gradient(to bottom, #F00 0%, #F0F 17%, #00F 34%, #0FF 50%, #0F0 67%, #FF0 84%, #F00 100%); |
||||||
|
} |
||||||
|
#hue_picker { |
||||||
|
position: absolute; |
||||||
|
background: #000; |
||||||
|
border-bottom: 1px solid #000; |
||||||
|
top: 0; |
||||||
|
width: 27px; |
||||||
|
height: 2px; |
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js" type="text/javascript"></script> |
||||||
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/lib/BenjoLibrary.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/sketch.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/Editor.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/Graph.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/Variable.js" type="text/javascript"></script> |
||||||
|
<script src="scripts/ObjectStore.js" type="text/javascript"></script> |
||||||
|
<link href="styles.css" rel="stylesheet"> |
||||||
|
<link href="color_picker_styles.css" rel="stylesheet"> |
||||||
|
<title>Graph</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="canvas_holder"></div> |
||||||
|
<div id="displayer"> |
||||||
|
<center> |
||||||
|
<fieldset class="holder" id="function_holder"> |
||||||
|
<legend>Funktionen</legend> |
||||||
|
<table cellpadding="3" class="displayer" id="functions"> |
||||||
|
<!-- Javascript cells --> |
||||||
|
</table> |
||||||
|
</fieldset> |
||||||
|
<fieldset class="holder" id="variable_holder"> |
||||||
|
<legend>Variablen</legend> |
||||||
|
<table cellpadding="3" class="displayer" id="variables"> |
||||||
|
noch nicht implementiert |
||||||
|
<!-- Javascript cells --> |
||||||
|
</table> |
||||||
|
</fieldset> |
||||||
|
<fieldset class="holder" id="settings_holder"> |
||||||
|
<legend>Einstellungen</legend> |
||||||
|
<span>Scroll-Verhalten:</span> |
||||||
|
<input id="scroll_input" max="500" min="0" onchange="updateScroll()" type="range"> |
||||||
|
<span>X-Axen Verschiebung:</span> |
||||||
|
<select id="x_axis_dispo" onchange="updateDisposition(this, true)"> |
||||||
|
<option value="1">1</option> |
||||||
|
<option value="PI">PI</option> |
||||||
|
</select> |
||||||
|
<br> |
||||||
|
<br> |
||||||
|
<span>Y-Axen Verschiebung:</span> |
||||||
|
<select id="y_axis_dispo" onchange="updateDisposition(this, false)"> |
||||||
|
<option value="1">1</option> |
||||||
|
<option value="PI">PI</option> |
||||||
|
</select> |
||||||
|
</fieldset> |
||||||
|
</center> |
||||||
|
</div> |
||||||
|
<div id="input_holder"> |
||||||
|
<input id="submit" onclick="addGraph()" type="button" value="OK"/> |
||||||
|
<input id="input" type="text"/> |
||||||
|
</div> |
||||||
|
<div id="graph_editor_wrapper"> |
||||||
|
<div id="graph_editor"> |
||||||
|
<div id="color_picker"> |
||||||
|
<div id="saturation"> |
||||||
|
<div id="value"> |
||||||
|
<div id="sb_picker"></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="hue"> |
||||||
|
<div id="hue_picker"></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="color_picker_numeric"> |
||||||
|
<input class="color_picker_rgb" max="255" min="0" onchange="currentEditor.colorPicker.updateFromRGB()" oninput="currentEditor.colorPicker.updateFromRGB()" type="number"/> |
||||||
|
<input class="color_picker_rgb" max="255" min="0" onchange="currentEditor.colorPicker.updateFromRGB()" oninput="currentEditor.colorPicker.updateFromRGB()" type="number"/> |
||||||
|
<input class="color_picker_rgb" max="255" min="0" onchange="currentEditor.colorPicker.updateFromRGB()" oninput="currentEditor.colorPicker.updateFromRGB()" type="number"/> |
||||||
|
<input id="color_picker_hex" onchange="currentEditor.colorPicker.updateFromHEX(this, false)" style="background-color: #F00;" style="background-color: #F00;" type="text"/> |
||||||
|
</div> |
||||||
|
<span style="margin-left: 5%; font-size: 25px; font-family: Tahoma, Geneva, sans-serif;">Dicke: </span> |
||||||
|
<select id="graph_editor_thickness"> |
||||||
|
<option value="1">1</option> |
||||||
|
<option value="2">2</option> |
||||||
|
<option value="3">3</option> |
||||||
|
<option value="4">4</option> |
||||||
|
<option value="5">5</option> |
||||||
|
<option value="6">6</option> |
||||||
|
<option value="7">7</option> |
||||||
|
<option value="8">8</option> |
||||||
|
<option value="9">9</option> |
||||||
|
<option value="10">10</option> |
||||||
|
<option value="11">11</option> |
||||||
|
<option value="12">12</option> |
||||||
|
<option value="13">13</option> |
||||||
|
<option value="14">14</option> |
||||||
|
<option value="15">15</option> |
||||||
|
<option value="16">16</option> |
||||||
|
</select> |
||||||
|
<input id="graph_editor_input" type="text"/> |
||||||
|
<input id="graph_editor_done" onclick="currentEditor.editDone()" type="button" value="OK"/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,259 @@ |
|||||||
|
function Editor(obj, i) { |
||||||
|
var x = ($(obj).offset().left * 2 + $(obj).width()) / 2; |
||||||
|
var y = ($(obj).offset().top * 2 + $(obj).height()) / 2; |
||||||
|
|
||||||
|
$("#graph_editor").css({ |
||||||
|
"left": x, |
||||||
|
"top": y |
||||||
|
}); |
||||||
|
$("#graph_editor_thickness").val(graphs[i].getThickness()); |
||||||
|
$("#graph_editor_input").val(graphs[i].getDisplayFunction()); |
||||||
|
$("#graph_editor_wrapper").show(); |
||||||
|
editing = true; |
||||||
|
|
||||||
|
this.colorPicker = new ColorPicker(this); |
||||||
|
this.colorPicker.hex = graphs[i].getColor(); |
||||||
|
this.colorPicker.updateFromHEX(null, true); |
||||||
|
|
||||||
|
this.editDone = function(){ |
||||||
|
var newFunc = $("#graph_editor_input").val(); |
||||||
|
graphs[i].setDisplayFunction(newFunc); |
||||||
|
graphs[i].setColor(this.colorPicker.getColor()); |
||||||
|
graphs[i].setThickness(parseInt($("#graph_editor_thickness").val())); |
||||||
|
$("#function_input").val(graphs[i].getFullDescription()); |
||||||
|
$("#visible_" + i).css({ |
||||||
|
"background-color": graphs[i].getColor(), |
||||||
|
"border-color": graphs[i].getColor() |
||||||
|
}); |
||||||
|
$("#graph_editor_wrapper").hide(); |
||||||
|
editing = false; |
||||||
|
updateAll(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function ColorPicker(editor) { |
||||||
|
this.movingObject = ""; |
||||||
|
|
||||||
|
this.updateFromHSV = function(){ |
||||||
|
this.h = 1 - $("#hue_picker").position().top / $("#hue").height(); |
||||||
|
this.s = ($("#sb_picker").position().left + 8) / $("#saturation").width(); |
||||||
|
this.v = 1 - ($("#sb_picker").position().top + 8) / $("#value").height(); |
||||||
|
|
||||||
|
this.r = HSVtoRGB(this.h, this.s, this.v).r; |
||||||
|
this.g = HSVtoRGB(this.h, this.s, this.v).g; |
||||||
|
this.b = HSVtoRGB(this.h, this.s, this.v).b; |
||||||
|
|
||||||
|
this.hex = RGBtoHEX(this.r, this.g, this.b); |
||||||
|
|
||||||
|
this.updateInterface(); |
||||||
|
} |
||||||
|
|
||||||
|
this.updateFromRGB = function(){ |
||||||
|
this.r = $($(".color_picker_rgb")[0]).val(); |
||||||
|
this.g = $($(".color_picker_rgb")[1]).val(); |
||||||
|
this.b = $($(".color_picker_rgb")[2]).val(); |
||||||
|
|
||||||
|
this.h = RGBtoHSV(this.r, this.g, this.b).h; |
||||||
|
this.s = RGBtoHSV(this.r, this.g, this.b).s; |
||||||
|
this.v = RGBtoHSV(this.r, this.g, this.b).v; |
||||||
|
|
||||||
|
this.hex = RGBtoHEX(this.r, this.g, this.b); |
||||||
|
|
||||||
|
this.updateFromHEX(null, true); |
||||||
|
|
||||||
|
this.updateInterface(); |
||||||
|
} |
||||||
|
|
||||||
|
this.updateFromHEX = function(input, otf){ |
||||||
|
if (!otf){ //Not on the fly
|
||||||
|
if (isValidHEX($(input).val())) this.hex = $(input).val(); |
||||||
|
else { |
||||||
|
alert("Error!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.r = HEXtoRGB(this.hex).r; |
||||||
|
this.g = HEXtoRGB(this.hex).g; |
||||||
|
this.b = HEXtoRGB(this.hex).b; |
||||||
|
|
||||||
|
this.h = RGBtoHSV(this.r, this.g, this.b).h; |
||||||
|
this.s = RGBtoHSV(this.r, this.g, this.b).s; |
||||||
|
this.v = RGBtoHSV(this.r, this.g, this.b).v; |
||||||
|
|
||||||
|
this.updateInterface(); |
||||||
|
} |
||||||
|
|
||||||
|
this.updateInterface = function(){ |
||||||
|
var o = Math.round((this.r * 299 + (this.g * 587) + (this.b * 114)) / 1000); //https://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
|
||||||
|
this.fontColor = (o > 125) ? "#000" : "#FFF"; |
||||||
|
|
||||||
|
$($(".color_picker_rgb")[0]).val(this.r); |
||||||
|
$($(".color_picker_rgb")[1]).val(this.g); |
||||||
|
$($(".color_picker_rgb")[2]).val(this.b); |
||||||
|
|
||||||
|
$("#color_picker_hex").val(this.hex); |
||||||
|
|
||||||
|
$("#hue_picker").css("top", (1 - this.h) * $("#hue").height()); |
||||||
|
$("#sb_picker").css({ |
||||||
|
"left": this.s * $("#saturation").width() - 8, |
||||||
|
"top": (1 - this.v) * $("#value").height() - 8 |
||||||
|
}); |
||||||
|
|
||||||
|
var sRGB = HSVtoRGB(this.h, 1, 1); |
||||||
|
var saturationBackground = "linear-gradient(to right, #FFF 0%, rgb("
|
||||||
|
+ sRGB.r + ","
|
||||||
|
+ sRGB.g + ","
|
||||||
|
+ sRGB.b + ") 100%)"; |
||||||
|
|
||||||
|
$("#saturation").css("background", saturationBackground); |
||||||
|
|
||||||
|
/*$($(".color_picker_rgb")[0]).css({ |
||||||
|
"background-color": "rgb(" + this.r + ", 0, 0)" |
||||||
|
}); |
||||||
|
$($(".color_picker_rgb")[1]).css({ |
||||||
|
"background-color": "rgb(0, " + this.g + ", 0)" |
||||||
|
}); |
||||||
|
$($(".color_picker_rgb")[2]).css({ |
||||||
|
"background-color": "rgb(0, 0, " + this.b + ")" |
||||||
|
});*/ |
||||||
|
//Fancy but overloaded
|
||||||
|
|
||||||
|
$("#color_picker_hex").css({ |
||||||
|
"background-color": this.hex, |
||||||
|
"color": this.fontColor |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
this.mousePressed = function(){ |
||||||
|
var x = winMouseX - $("#saturation").offset().left; |
||||||
|
var y = winMouseY - $("#value").offset().top; |
||||||
|
if (x > 0 && x < $("#saturation").width() && y > 0 && y < $("#value").height()){ |
||||||
|
this.movingObject = "sb"; |
||||||
|
} |
||||||
|
if (x > $("#saturation").width() + 6 && x < $("#saturation").width() + 6 + $("#hue").width() && y > 0 && y < $("#hue").height()){ |
||||||
|
this.movingObject = "hue"; |
||||||
|
} |
||||||
|
this.mouseDragged(); |
||||||
|
} |
||||||
|
|
||||||
|
this.mouseDragged = function(){ |
||||||
|
if (this.movingObject == "hue"){ |
||||||
|
var objH = $("#hue"); |
||||||
|
var picker = $("#hue_picker"); |
||||||
|
var h = winMouseY - objH.offset().top; |
||||||
|
if (h > 0 && h < objH.height()){ |
||||||
|
picker.css("top", h - 1); |
||||||
|
} else if (h > objH.height()){ |
||||||
|
picker.css("top", objH.height() - 1); |
||||||
|
} else if (h < 0){ |
||||||
|
picker.css("top", -1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (this.movingObject == "sb"){ |
||||||
|
var objS = $("#saturation"); |
||||||
|
var objV = $("#value"); |
||||||
|
var picker = $("#sb_picker"); |
||||||
|
var s = winMouseX - objS.offset().left; |
||||||
|
var v = winMouseY - objV.offset().top; |
||||||
|
if (s > 0 && s < objS.width()){ |
||||||
|
picker.css("left", s - 8); |
||||||
|
} else if (s < 0){ |
||||||
|
picker.css("left", -8); |
||||||
|
} else if (s < objS.width()){ |
||||||
|
picker.css("left", objS.width() - 8); |
||||||
|
} |
||||||
|
if (v > 0 && v < objV.height()){ |
||||||
|
picker.css("top", v - 8); |
||||||
|
} else if (v < 0){ |
||||||
|
picker.css("top", -8); |
||||||
|
} else if (v > objV.height()){ |
||||||
|
picker.css("top", objV.height() - 8); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.updateFromHSV(); |
||||||
|
} |
||||||
|
|
||||||
|
this.mouseReleased = function(){ |
||||||
|
this.movingObject = ""; |
||||||
|
} |
||||||
|
|
||||||
|
this.getColor = function(){ |
||||||
|
return this.hex; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//www.stackoverflow.com -->
|
||||||
|
function RGBtoHEX(r, g, b) { |
||||||
|
var rgb = b | (g << 8) | (r << 16); |
||||||
|
return '#' + (0x1000000 + rgb).toString(16).slice(1); |
||||||
|
} |
||||||
|
|
||||||
|
function HEXtoRGB(hex) { |
||||||
|
var shorthandRegex = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i; |
||||||
|
hex = hex.replace(shorthandRegex, function(m, r, g, b) { |
||||||
|
return r + r + g + g + b + b; |
||||||
|
}); |
||||||
|
var result = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i.exec(hex); |
||||||
|
return result ? { |
||||||
|
r: parseInt(result[1], 16), |
||||||
|
g: parseInt(result[2], 16), |
||||||
|
b: parseInt(result[3], 16) |
||||||
|
} : null; |
||||||
|
} |
||||||
|
|
||||||
|
function HSVtoRGB(h, s, v) { |
||||||
|
var r, g, b, i, f, p, q, t; |
||||||
|
if (arguments.length === 1) { |
||||||
|
s = h.s, v = h.v, h = h.h; |
||||||
|
} |
||||||
|
i = Math.floor(h * 6); |
||||||
|
f = h * 6 - i; |
||||||
|
p = v * (1 - s); |
||||||
|
q = v * (1 - f * s); |
||||||
|
t = v * (1 - (1 - f) * s); |
||||||
|
switch (i % 6) { |
||||||
|
case 0: r = v, g = t, b = p; break; |
||||||
|
case 1: r = q, g = v, b = p; break; |
||||||
|
case 2: r = p, g = v, b = t; break; |
||||||
|
case 3: r = p, g = q, b = v; break; |
||||||
|
case 4: r = t, g = p, b = v; break; |
||||||
|
case 5: r = v, g = p, b = q; break; |
||||||
|
} |
||||||
|
return { |
||||||
|
r: Math.round(r * 255), |
||||||
|
g: Math.round(g * 255), |
||||||
|
b: Math.round(b * 255) |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function RGBtoHSV(r, g, b) { |
||||||
|
if (arguments.length === 1) { |
||||||
|
g = r.g, b = r.b, r = r.r; |
||||||
|
} |
||||||
|
var max = Math.max(r, g, b), min = Math.min(r, g, b), |
||||||
|
d = max - min, |
||||||
|
h, |
||||||
|
s = (max === 0 ? 0 : d / max), |
||||||
|
v = max / 255; |
||||||
|
|
||||||
|
switch (max) { |
||||||
|
case min: h = 0; break; |
||||||
|
case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break; |
||||||
|
case g: h = (b - r) + d * 2; h /= 6 * d; break; |
||||||
|
case b: h = (r - g) + d * 4; h /= 6 * d; break; |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
h: h, |
||||||
|
s: s, |
||||||
|
v: v |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function isValidHEX(hex){ |
||||||
|
return /(^#[0-9A-Fa-f]{6}$)|(^#[0-9A-Fa-f]{3}$)/i.test(hex); |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
function Graph(fullDescription) { |
||||||
|
var d = fullDescription; |
||||||
|
|
||||||
|
this.name = d.substring(0, d.indexOf("(")); |
||||||
|
|
||||||
|
this.reference = d.charAt(d.indexOf("(") + 1); |
||||||
|
|
||||||
|
this.displayFunction = d.substring(d.indexOf("=") + 1, d.length); |
||||||
|
|
||||||
|
|
||||||
|
this.color = "#000000"; |
||||||
|
this.thickness = 2; |
||||||
|
this.points = []; |
||||||
|
this.visible = true; |
||||||
|
|
||||||
|
this.getFullDescription = function(){ |
||||||
|
return (this.name + "(" + this.reference + ") = " + this.displayFunction).replace(/\s+/g, " "); |
||||||
|
} |
||||||
|
|
||||||
|
this.getDisplayFunction = function(){return this.displayFunction;} |
||||||
|
this.setDisplayFunction = function(displayFunction){ |
||||||
|
this.displayFunction = displayFunction.replace(/\s+/g, " "); |
||||||
|
this.convertToExecuteableFunction(); |
||||||
|
} |
||||||
|
|
||||||
|
this.getExecuteFunction = function(){return this.executeFunction;} |
||||||
|
|
||||||
|
this.getReference = function(){return this.reference;} |
||||||
|
|
||||||
|
this.getName = function(){return this.name;} |
||||||
|
|
||||||
|
this.getColor = function(){return this.color;} |
||||||
|
this.setColor = function(color){this.color = color;} |
||||||
|
|
||||||
|
this.getThickness = function(){return this.thickness;} |
||||||
|
this.setThickness = function(thickness){this.thickness = thickness;} |
||||||
|
|
||||||
|
this.getPoints = function(){return this.points;} |
||||||
|
this.setPoints = function(points){this.points = points;} |
||||||
|
|
||||||
|
this.convertToExecuteableFunction = function(){ |
||||||
|
var f = this.displayFunction; |
||||||
|
f = f.substr(0, f.length); |
||||||
|
f = f.replace(/,/g, "."); |
||||||
|
f = f.replace(/(\d+\.?\d*)\s*([a-z])/g, "$1*$2"); |
||||||
|
f = f.replace(/([a-z])\s*(\d+\.?\d*)/g, "$2*$1"); |
||||||
|
f = f.replace(/\-([a-z])/g, "-1*$1"); |
||||||
|
f = f.replace(new RegExp("([a-z])" + this.reference, "g"), "$1*" + this.reference); |
||||||
|
f = f.replace(new RegExp(this.reference + "([a-z])", "g"), "$1*" + this.reference); |
||||||
|
variables.forEach(function(v){f = f.replace(new RegExp(v.getName(), "g"), v.getValue());}); |
||||||
|
var powCount = f.split("^").length - 1; |
||||||
|
for (var i = 0; i < powCount; i++){f = f.replace(/(\(.*(\(.*\))*.*\)|[a-z]?(\d+\.?\d*)?)\^(\(.*(\(.*\))*.*\)|[a-z]?(\d+\.?\d*)?)/, "pow($1, $4)");} |
||||||
|
f = f.replace(/\|(.+)\|/g, "abs($1)"); |
||||||
|
f = f.replace(/e/g, "Math.E"); |
||||||
|
//console.log(f);
|
||||||
|
this.executeFunction = f; |
||||||
|
} |
||||||
|
this.convertToExecuteableFunction(); |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
|
||||||
|
|
||||||
|
function restoreSettings(){ |
||||||
|
for (var i = 0; i < Infinity; i++){ |
||||||
|
if (getItem("fullDescription" + i) == null) break; |
||||||
|
var g = new Graph(getItem("fullDescription" + i)); |
||||||
|
g.name = getItem("name" + i); |
||||||
|
g.reference = getItem("reference" + i); |
||||||
|
g.displayFunction = getItem("displayFunction" + i); |
||||||
|
g.executeFunction = getItem("executeFunction" + i); |
||||||
|
g.color = getItem("color" + i); |
||||||
|
g.thickness = int(getItem("thickness" + i)); |
||||||
|
g.visible = boolean(getItem("visible" + i)); |
||||||
|
graphs.push(g); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function safeSettings(){ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function restoreStandard(){ |
||||||
|
if (graphs.length > 0){return;} |
||||||
|
function restore(f, c, i){ |
||||||
|
var g = new Graph(f); |
||||||
|
g.setColor(c); |
||||||
|
graphs[i] = g; |
||||||
|
} |
||||||
|
restore("f(x)=x^3-2x", "#ffe602", 0); |
||||||
|
restore("g(x)=(1 - x^2)^(1/2)", "#ff0202", 1); |
||||||
|
restore("h(x)=e^(-x)", "#000000", 2); |
||||||
|
restore("i(x)= 1/(x^2)", "#31ff04", 3); |
||||||
|
restore("j(x)= |x| * x", "#0f02ff", 4); |
||||||
|
restore("k(x)=log(x)", "#ff0be2", 5); |
||||||
|
restore("l(x)= sin(2x)", "#02ffc6", 6); |
||||||
|
restore("m(x)=cos(0.5x)", "#ff8d03", 7); |
||||||
|
restore("n(x)=atan(x)", "#01cfff", 8); |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
function Variable(name, value){ |
||||||
|
this.name = name; |
||||||
|
this.value = value; |
||||||
|
this.slider = new Slider(this); |
||||||
|
|
||||||
|
this.getName = function(){return this.name;} |
||||||
|
this.setName = function(name){this.name = name;} |
||||||
|
|
||||||
|
this.getValue = function(){return this.value;} |
||||||
|
this.setValue = function(value_obj, bool){ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function Slider(variable){ |
||||||
|
this.variable = variable; |
||||||
|
} |
@ -0,0 +1,357 @@ |
|||||||
|
var TOP = 1; |
||||||
|
var RIGHT = 2 |
||||||
|
var BOTTOM = 3; |
||||||
|
var LEFT = 4; |
||||||
|
var TOP_RIGHT = 5; |
||||||
|
var BOTTOM_RIGHT = 6; |
||||||
|
var BOTTOM_LEFT = 7; |
||||||
|
var TOP_LEFT = 8; |
||||||
|
|
||||||
|
var wWidth = window.innerWidth; |
||||||
|
var wHeight = window.innerHeight; |
||||||
|
var oldWHeight; |
||||||
|
var oldWWidth; |
||||||
|
|
||||||
|
function updateVars(){ |
||||||
|
oldWWidth = wWidth; |
||||||
|
oldWHeight = wHeight; |
||||||
|
wWidth = window.innerWidth; |
||||||
|
wHeight = window.innerHeight; |
||||||
|
} |
||||||
|
|
||||||
|
function collisionDetection(obj0, obj1){ |
||||||
|
|
||||||
|
var sp = strokePadding; |
||||||
|
|
||||||
|
if (obj0.isEllipse && obj1.isRectangle){ |
||||||
|
|
||||||
|
//Ball
|
||||||
|
var b = obj0; |
||||||
|
|
||||||
|
//Rectangle
|
||||||
|
var r = obj1; |
||||||
|
|
||||||
|
for (var i = 0; i < TWO_PI; i += PI / 32){ |
||||||
|
|
||||||
|
/* Check every borderpoint of the ball beginning |
||||||
|
at the top in clock direction up to top again */ |
||||||
|
|
||||||
|
// Ball Center X
|
||||||
|
var bcx = b.x; |
||||||
|
|
||||||
|
// Ball Center Y
|
||||||
|
var bcy = b.y; |
||||||
|
|
||||||
|
// Ball Border X
|
||||||
|
var bbx = b.x + sin(i) * b.radius; |
||||||
|
|
||||||
|
// Ball Border Y inverted because Y = 0 is the TOP of the screen
|
||||||
|
var bby = b.y - cos(i) * b.radius; |
||||||
|
|
||||||
|
// Rectangle Width
|
||||||
|
var rW = r.width + 2 * sp; |
||||||
|
|
||||||
|
// Rectangle Height
|
||||||
|
var rH = r.height + 2 * sp; |
||||||
|
|
||||||
|
// Rectangle Border X
|
||||||
|
var rX = r.x - sp; |
||||||
|
|
||||||
|
// Rectangle Border Y
|
||||||
|
var rY = r.y - sp; |
||||||
|
|
||||||
|
// Objects touch
|
||||||
|
if (bbx > rX && bbx < rX + rW |
||||||
|
&& bby > rY && bby < rY + rH){ |
||||||
|
|
||||||
|
// STRAIGHT FACES //
|
||||||
|
|
||||||
|
//Top/Bottom touch
|
||||||
|
if (bcx > rX && bcx < rX + rW){
|
||||||
|
|
||||||
|
//Top touch
|
||||||
|
if (b.v.y > 0) return {isTouching: true, location: TOP}; |
||||||
|
|
||||||
|
//Bottom touch
|
||||||
|
if (b.v.y < 0) return {isTouching: true, location: BOTTOM}; |
||||||
|
} |
||||||
|
|
||||||
|
//Left/Right touch
|
||||||
|
if (bcy > rY && bcy < rY + rH){ |
||||||
|
|
||||||
|
//Left touch
|
||||||
|
if (b.v.x > 0) return {isTouching: true, location: LEFT}; |
||||||
|
|
||||||
|
//Right touch
|
||||||
|
if (b.v.x < 0) return {isTouching: true, location: RIGHT}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// CORNERS //
|
||||||
|
|
||||||
|
// BOTTOM Left/Right
|
||||||
|
if (i > 0 && i <= PI / 2) return {isTouching: true, location: BOTTOM_LEFT}; |
||||||
|
|
||||||
|
//LEFT Bottom/Top
|
||||||
|
if (i > PI / 2 && i <= PI) return {isTouching: true, location: TOP_LEFT}; |
||||||
|
|
||||||
|
//TOP Left/Right
|
||||||
|
if (i > PI && i <= PI + PI / 2) return {isTouching: true, location: TOP_RIGHT}; |
||||||
|
|
||||||
|
//RIGHT Bottom/Top
|
||||||
|
if (i > PI + PI / 2 && i <= TWO_PI) return {isTouching: true, location: BOTTOM_RIGHT}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if (obj0.isEllipse && obj1.isEllipse){ |
||||||
|
|
||||||
|
//Ball 1
|
||||||
|
var b1 = obj0; |
||||||
|
|
||||||
|
//Ball 2
|
||||||
|
var b2 = obj1; |
||||||
|
|
||||||
|
//Balls are close to each other
|
||||||
|
if (b1.x + b1.radius > b2.x - b2.radius |
||||||
|
&& b1.x - b1.radius < b2.x + b2.radius |
||||||
|
&& b1.y + b1.radius > b2.y - b2.radius |
||||||
|
&& b1.y - b1.radius < b2.y + b2.radius){ |
||||||
|
|
||||||
|
var distance = sqrt(pow(b1.x - b2.x, 2) + pow(b1.y - b2.y, 2)); |
||||||
|
|
||||||
|
if (distance < b1.radius + b2.radius) return {isTouching: true}; |
||||||
|
} |
||||||
|
} |
||||||
|
return {isTouching: false, location: 0}; |
||||||
|
} |
||||||
|
|
||||||
|
function performCollision(obj0, obj1, collision){ |
||||||
|
if (obj0.isEllipse){ |
||||||
|
|
||||||
|
var ball = obj0; |
||||||
|
|
||||||
|
//Ball collides with frameborder
|
||||||
|
if (obj1.isFrameborder){ |
||||||
|
switch (collision.location){ |
||||||
|
case BOTTOM: |
||||||
|
ball.v.y *= -1; |
||||||
|
break; |
||||||
|
case LEFT: |
||||||
|
case RIGHT: |
||||||
|
ball.v.x *= -1; |
||||||
|
break; |
||||||
|
} |
||||||
|
if (testMode && collision.location == TOP) ball.v.y *= -1; |
||||||
|
ball.move(); |
||||||
|
} |
||||||
|
|
||||||
|
//Ball collides with any brick
|
||||||
|
if (obj1.isBrick){ |
||||||
|
switch (collision.location){ |
||||||
|
case TOP: |
||||||
|
case BOTTOM: |
||||||
|
ball.v.y *= -1; |
||||||
|
ball.move(); |
||||||
|
return; |
||||||
|
case LEFT: |
||||||
|
case RIGHT: |
||||||
|
ball.v.x *= -1; |
||||||
|
ball.move(); |
||||||
|
return; |
||||||
|
case TOP_LEFT: |
||||||
|
var cornerX = obj1.x; |
||||||
|
var cornerY = obj1.y; |
||||||
|
break; |
||||||
|
case TOP_RIGHT: |
||||||
|
var cornerX = obj1.x + obj1.width; |
||||||
|
var cornerY = obj1.y; |
||||||
|
break; |
||||||
|
case BOTTOM_LEFT: |
||||||
|
var cornerX = obj1.x; |
||||||
|
var cornerY = obj1.y + obj1.height; |
||||||
|
break; |
||||||
|
case BOTTOM_RIGHT: |
||||||
|
var cornerX = obj1.x + obj1.width; |
||||||
|
var cornerY = obj1.y + obj1.height; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
var nx = ball.x - cornerX; |
||||||
|
var ny = ball.y - cornerY; |
||||||
|
var length = sqrt(nx * nx + ny * ny); |
||||||
|
nx /= length; |
||||||
|
ny /= length; |
||||||
|
|
||||||
|
var projection = ball.v.x * nx + ball.v.y * ny; |
||||||
|
ball.v.x = ball.v.x - 2 * projection * nx; |
||||||
|
ball.v.y = ball.v.y - 2 * projection * ny; |
||||||
|
|
||||||
|
ball.move(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
//Ball collides with paddleboard
|
||||||
|
if (obj1.isPaddle){ |
||||||
|
switch (collision.location){ |
||||||
|
case TOP: |
||||||
|
case TOP_LEFT: |
||||||
|
case TOP_RIGHT: |
||||||
|
ball.v.x = ball.calcVelocityX(obj1, ball.v.x); |
||||||
|
ball.v.y = -ball.calcVelocityY(); |
||||||
|
ball.move(); |
||||||
|
return; |
||||||
|
case LEFT: |
||||||
|
case RIGHT: |
||||||
|
ball.v.x *= -1; |
||||||
|
ball.move(); |
||||||
|
return; |
||||||
|
case BOTTOM_LEFT: |
||||||
|
var cornerX = obj1.x; |
||||||
|
var cornerY = obj1.y + obj1.height; |
||||||
|
break; |
||||||
|
case BOTTOM_RIGHT: |
||||||
|
var cornerX = obj1.x + obj1.width; |
||||||
|
var cornerY = obj1.y + obj1.height; |
||||||
|
break; |
||||||
|
} |
||||||
|
var nx = ball.x - cornerX; |
||||||
|
var ny = ball.y - cornerY; |
||||||
|
var length = sqrt(nx * nx + ny * ny); |
||||||
|
nx /= length; |
||||||
|
ny /= length; |
||||||
|
|
||||||
|
var projection = ball.v.x * nx + ball.v.y * ny; |
||||||
|
ball.v.x = ball.v.x - 2 * projection * nx; |
||||||
|
ball.v.y = ball.v.y - 2 * projection * ny; |
||||||
|
|
||||||
|
ball.move(); |
||||||
|
} |
||||||
|
|
||||||
|
//Ball collides with other ball
|
||||||
|
if (obj1.isEllipse){ |
||||||
|
|
||||||
|
//Ball 1
|
||||||
|
var b1 = obj0; |
||||||
|
|
||||||
|
//Ball 2
|
||||||
|
var b2 = obj1; |
||||||
|
|
||||||
|
//Set mass equal to radius of each ball
|
||||||
|
b1.mass = b1.radius; |
||||||
|
b2.mass = b2.radius; |
||||||
|
|
||||||
|
//Colliding angle of ball 1 to ball 2 using arc tan of both x and y differences
|
||||||
|
var collisionAngle = atan2((b2.y - b1.y), (b2.x - b1.x)); |
||||||
|
|
||||||
|
//Converting directions of velocity vector of balls into angles
|
||||||
|
var d1 = atan2(b1.v.y, b1.v.x); |
||||||
|
var d2 = atan2(b2.v.y, b2.v.x); |
||||||
|
|
||||||
|
//Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences
|
||||||
|
var newXspeed1 = b1.v.mag * cos(d1 - collisionAngle); |
||||||
|
var newYspeed1 = b1.v.mag * sin(d1 - collisionAngle); |
||||||
|
var newXspeed2 = b2.v.mag * cos(d2 - collisionAngle); |
||||||
|
var newYspeed2 = b2.v.mag * sin(d2 - collisionAngle); |
||||||
|
|
||||||
|
//According to the principle of linear momentum, kinetic energy stays the same after collision, so velocities are now related to masses
|
||||||
|
var finalXspeed1 = ((b1.mass - b2.mass) * newXspeed1 + b2.mass * 2 * newXspeed2) / (b1.mass + b2.mass); |
||||||
|
var finalYspeed1 = newYspeed1; |
||||||
|
var finalXspeed2 = (b1.mass * 2 * newXspeed1 + (b2.mass - b1.mass) * newXspeed2) / (b1.mass + b2.mass); |
||||||
|
var finalYspeed2 = newYspeed2; |
||||||
|
|
||||||
|
//Values of collisionAngle
|
||||||
|
var cosAngle = cos(collisionAngle); |
||||||
|
var sinAngle = sin(collisionAngle); |
||||||
|
|
||||||
|
//To also keep velocites relative to pure collisionAngle, subtract sin*x from cos*x and add sin*y to cos*y because coordSystem has y = 0 on the top
|
||||||
|
var u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1; |
||||||
|
var u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1; |
||||||
|
var u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2; |
||||||
|
var u2y = sinAngle * finalXspeed2 + cosAngle * finalYspeed2; |
||||||
|
|
||||||
|
//Set new velocities to both balls
|
||||||
|
b1.v.x = u1x; |
||||||
|
b1.v.y = u1y; |
||||||
|
b2.v.x = u2x; |
||||||
|
b2.v.y = u2y; |
||||||
|
|
||||||
|
//Update magnitude
|
||||||
|
b1.v.mag = sqrt(pow(b1.v.x, 2) + pow(b1.v.y, 2)); |
||||||
|
b2.v.mag = sqrt(pow(b2.v.x, 2) + pow(b2.v.y, 2)); |
||||||
|
|
||||||
|
|
||||||
|
//Move balls one vx/vy forward to avoid double inverting collision detection
|
||||||
|
b1.x += b1.v.x; |
||||||
|
b1.y += b1.v.y; |
||||||
|
b2.x += b2.v.x; |
||||||
|
b2.y += b2.v.y; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function toTimeString(time, hoursWanted){ |
||||||
|
|
||||||
|
var time = floor(time / 10); |
||||||
|
|
||||||
|
var hs = String(floor(time % 100)); |
||||||
|
var fs = String(floor((time / 100) % 60)); |
||||||
|
|
||||||
|
if (hoursWanted){ |
||||||
|
var min = String(floor(((time / 100) / 60) % 60)); |
||||||
|
var hr = String(floor(((time / 100) / 60) / 60)); |
||||||
|
|
||||||
|
if (hs.length < 2) hs = "0" + hs; |
||||||
|
if (fs.length < 2) fs = "0" + fs; |
||||||
|
if (min.length < 2) min = "0" + min; |
||||||
|
if (hr.length < 2) hr = "0" + hr; |
||||||
|
|
||||||
|
var timeString = hr + ":" + min + ":" + fs + ":" + hs; |
||||||
|
} else { |
||||||
|
var min = String(floor(((time / 100) / 60) % 60)); |
||||||
|
|
||||||
|
if (hs.length < 2) hs = "0" + hs; |
||||||
|
if (fs.length < 2) fs = "0" + fs; |
||||||
|
if (min.length < 2) min = "0" + min; |
||||||
|
|
||||||
|
var timeString = min + ":" + fs + ":" + hs; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return timeString; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function setCookie(name, value, years){ |
||||||
|
var expires = ""; |
||||||
|
if (years){ |
||||||
|
var date = new Date(); |
||||||
|
date.setTime(date.getTime() + (years * 365 * 24 * 60 * 60 * 1000)); |
||||||
|
expires = "; expires=" + date.toUTCString(); |
||||||
|
} |
||||||
|
document.cookie = name + "=" + value + expires + "; path=/"; |
||||||
|
} |
||||||
|
|
||||||
|
function getCookie(name){ |
||||||
|
var nameEQ = name + "="; |
||||||
|
var ca = document.cookie.split(';'); |
||||||
|
for (var i = 0; i < ca.length; i++){ |
||||||
|
var c = ca[i]; |
||||||
|
while (c.charAt(0) == ' ') c = c.substring(1, c.length); |
||||||
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
function deleteCookies(){ |
||||||
|
for (var i = 0; i < arguments.length; i++) setCookie(arguments[i], "", -1); |
||||||
|
} |
||||||
|
|
||||||
|
function deleteAllCookies(){ |
||||||
|
var cookies = document.cookie.split(";"); |
||||||
|
for (var i = 0; i < cookies.length; i++) deleteCookies(cookies[i].split("=")[0]); |
||||||
|
} |
@ -0,0 +1,319 @@ |
|||||||
|
var graphs,
|
||||||
|
variables, |
||||||
|
currentEditor, |
||||||
|
maxSquareCount,
|
||||||
|
minSquareCount,
|
||||||
|
padding,
|
||||||
|
paddingFactor, |
||||||
|
tickFactor, |
||||||
|
textHeight, |
||||||
|
paddingDivider,
|
||||||
|
scrollFactor,
|
||||||
|
squareCount, |
||||||
|
axisDispo, |
||||||
|
axisDispoPI, |
||||||
|
origin, |
||||||
|
distance, |
||||||
|
valid,
|
||||||
|
editing; |
||||||
|
|
||||||
|
|
||||||
|
function setup(){ |
||||||
|
frameRate(0); |
||||||
|
assignGlobalVariables(); |
||||||
|
restoreSettings(); |
||||||
|
//restoreStandard();
|
||||||
|
prepareVisibilites(); |
||||||
|
updateAll(); |
||||||
|
updateScroll(); |
||||||
|
} |
||||||
|
|
||||||
|
function assignGlobalVariables(){ |
||||||
|
graphs = [], |
||||||
|
variables = [], |
||||||
|
currentEditor = null, |
||||||
|
maxSquareCount = {x: 20, y: 15}, |
||||||
|
minSquareCount = {x: 15, y: 10}, |
||||||
|
squareCount = {x: 0, y: 0}, |
||||||
|
padding = {x: 50, y: 50}, |
||||||
|
paddingFactor = {x: 1, y: 1}, |
||||||
|
paddingDivider = {x: 0, y: 0}, |
||||||
|
axisDispoPI = {x: false, y: false}, |
||||||
|
axisDispo = 2, |
||||||
|
tickFactor = 1, |
||||||
|
origin = {x: 0, y: 0}, |
||||||
|
distance = {x: 0, y: 0}, |
||||||
|
textHeight = 15; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function addGraph(){ |
||||||
|
var newGraph = new Graph($("#input").val()); |
||||||
|
var same = false; |
||||||
|
if (newGraph.getName().length == 0) return; |
||||||
|
graphs.forEach(function(g){ |
||||||
|
if (g.getName() == newGraph.getName()){ |
||||||
|
newGraph.setColor(g.getColor()); |
||||||
|
newGraph.setThickness(g.getThickness()); |
||||||
|
graphs[graphs.indexOf(g)] = newGraph; |
||||||
|
same = true; |
||||||
|
} |
||||||
|
}); |
||||||
|
if (!same){ |
||||||
|
graphs.push(newGraph); |
||||||
|
$("#input").val(newGraph.getFullDescription()); |
||||||
|
} |
||||||
|
updateAll(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function updateAll(){ |
||||||
|
updateInterface(); |
||||||
|
updateDisplay(); |
||||||
|
safeSettings(); |
||||||
|
} |
||||||
|
|
||||||
|
function updateDisplay(){ |
||||||
|
prepareGridValues(); |
||||||
|
drawGrid(); |
||||||
|
drawGraphs(); |
||||||
|
} |
||||||
|
|
||||||
|
function updateInterface(){ |
||||||
|
$("#functions").html(""); |
||||||
|
graphs.forEach(function(g){ |
||||||
|
var bc = g.getColor(); |
||||||
|
var c = g.visible ? g.getColor() : "none"; |
||||||
|
$("#functions").append("<tr><td><div style=\"background-color: " + c + "; border-color: " + bc + "\" onclick=\"toggleGraph(this)\"" |
||||||
|
+ "></div></td><td><button onclick=\"editGraph(this)\">" + g.getFullDescription()
|
||||||
|
+ "</button></td><td><button onclick=\"deleteGraph(this)\">X</button></td></tr>"); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function prepareGridValues(){ |
||||||
|
squareCount.x = width / padding.x; |
||||||
|
squareCount.y = height / padding.y; |
||||||
|
while (squareCount.x > maxSquareCount.x){ |
||||||
|
squareCount.x = round(squareCount.x / axisDispo); |
||||||
|
paddingFactor.x *= axisDispo; |
||||||
|
padding.x *= axisDispo; |
||||||
|
} |
||||||
|
while (squareCount.y > maxSquareCount.y){ |
||||||
|
squareCount.y = round(squareCount.y / axisDispo); |
||||||
|
paddingFactor.y *= axisDispo; |
||||||
|
padding.y *= axisDispo; |
||||||
|
} |
||||||
|
while (squareCount.x < minSquareCount.x){ |
||||||
|
squareCount.x *= axisDispo; |
||||||
|
paddingFactor.x /= axisDispo; |
||||||
|
padding.x = round(padding.x / axisDispo); |
||||||
|
} |
||||||
|
while (squareCount.y < minSquareCount.y){ |
||||||
|
squareCount.y *= axisDispo; |
||||||
|
paddingFactor.y /= axisDispo; |
||||||
|
padding.y = round(padding.y / axisDispo); |
||||||
|
} |
||||||
|
squareCount.x = round(squareCount.x); |
||||||
|
squareCount.y = round(squareCount.y); |
||||||
|
paddingDivider.x = padding.x / paddingFactor.x; |
||||||
|
paddingDivider.y = padding.y / paddingFactor.y; |
||||||
|
} |
||||||
|
|
||||||
|
function drawGrid(){ |
||||||
|
clear(); |
||||||
|
|
||||||
|
stroke("#000"); |
||||||
|
strokeWeight(2); |
||||||
|
|
||||||
|
line(0, origin.y, width, origin.y); |
||||||
|
line(origin.x, height, origin.x, 0); |
||||||
|
|
||||||
|
strokeWeight(0.25); |
||||||
|
|
||||||
|
var centerX = (origin.x - width / 2) % padding.x + width / 2; |
||||||
|
var centerY = (origin.y - height / 2) % padding.y + height / 2; |
||||||
|
var x, y, numX, numY, textWidthX, textWidthY, i; |
||||||
|
|
||||||
|
for (i = 0; i < squareCount.x * 2; i++){ |
||||||
|
x = centerX - squareCount.x * padding.x + padding.x * i; |
||||||
|
if (axisDispoPI.x) numX = round((x - origin.x) / padding.x * paddingFactor.x / PI * 100) / 100 + "π"; |
||||||
|
if (!axisDispoPI.x) numX = round((x - origin.x) / padding.x) * paddingFactor.x; |
||||||
|
if (numX == 0 || numX == "0π") numX = ""; |
||||||
|
line(x, 0, x, height); |
||||||
|
textWidthX = textWidth(str(numX)); |
||||||
|
text(numX, x - textWidthX / 2, origin.y + textHeight / 2, textWidthX, textHeight); |
||||||
|
} |
||||||
|
for (i = 0; i < squareCount.y * 2; i++){ |
||||||
|
y = centerY - squareCount.y * padding.y + padding.y * i; |
||||||
|
if (axisDispoPI.y) numY = -round((y - origin.y) / padding.y * paddingFactor.y / PI * 100) / 100 + "π"; |
||||||
|
if (!axisDispoPI.y) numY = -round((y - origin.y) / padding.y) * paddingFactor.y; |
||||||
|
if (numY == 0 || numY == "0π") numY = ""; |
||||||
|
line(0, y, width, y); |
||||||
|
textWidthY = textWidth(str(numY)); |
||||||
|
text(numY, origin.x - textWidthY - textHeight / 2, y - textHeight / 2, textWidthY, textHeight); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function drawGraphs(){ |
||||||
|
graphs.forEach(function(g){ |
||||||
|
if (!g.visible) return; |
||||||
|
var rdyFunc = g.getExecuteFunction(); |
||||||
|
var r = g.getReference(); |
||||||
|
function f(value){ |
||||||
|
var y; |
||||||
|
var execFunc = rdyFunc.replace(new RegExp(r, "g"), value); |
||||||
|
try{y = eval(execFunc);} catch(e){y = null;} |
||||||
|
return y; |
||||||
|
} |
||||||
|
var pointsRange = [], x, y; |
||||||
|
for (var px = 0; px <= width; px += tickFactor){ |
||||||
|
x = (px - origin.x) / paddingDivider.x; |
||||||
|
y = f(x); |
||||||
|
pointsRange[px / tickFactor] = {x: x, y: y}; |
||||||
|
} |
||||||
|
g.setPoints(pointsRange); |
||||||
|
}); |
||||||
|
graphs.forEach(function(g){ |
||||||
|
if (!g.visible) return; |
||||||
|
var t = g.getThickness(), x, y; |
||||||
|
stroke(g.getColor()); |
||||||
|
strokeWeight(t); |
||||||
|
|
||||||
|
|
||||||
|
g.getPoints().forEach(function(p){ |
||||||
|
x = origin.x + p.x * paddingDivider.x; |
||||||
|
y = origin.y - p.y * paddingDivider.y; |
||||||
|
if (x != null && y != null) line(x, y, x + t / 4, y); |
||||||
|
}); |
||||||
|
|
||||||
|
//Straight lines instead of points:
|
||||||
|
|
||||||
|
/*for (var i = 0; i < g.getPoints().length; i++){ |
||||||
|
p = g.getPoints()[i]; |
||||||
|
x1 = origin.x + p.x * paddingDivider.x; |
||||||
|
y1 = origin.y - p.y * paddingDivider.y; |
||||||
|
try{ |
||||||
|
x2 = origin.x + g.getPoints()[i + 1].x * paddingDivider.x; |
||||||
|
y2 = origin.y - g.getPoints()[i + 1].y * paddingDivider.y; |
||||||
|
line(x1, y1, x2, y2); |
||||||
|
}catch(e){} |
||||||
|
}*/ |
||||||
|
|
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function editGraph(obj){ |
||||||
|
var i = $(obj).parent().parent().index(); |
||||||
|
obj.blur(); |
||||||
|
currentEditor = new Editor(obj, i); |
||||||
|
} |
||||||
|
|
||||||
|
function deleteGraph(obj){ |
||||||
|
var i = $(obj).parent().parent().index(); |
||||||
|
obj.blur(); |
||||||
|
graphs.splice(i, 1); |
||||||
|
updateAll(); |
||||||
|
} |
||||||
|
|
||||||
|
function toggleGraph(obj){ |
||||||
|
var i = $(obj).parent().parent().index(); |
||||||
|
obj.blur(); |
||||||
|
graphs[i].visible = !graphs[i].visible; |
||||||
|
updateAll(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function mouseWheel(event){ |
||||||
|
if (mouseX > 0 && mouseY < height && !editing){ |
||||||
|
var oldPaddingX = padding.x; |
||||||
|
var oldPaddingY = padding.y; |
||||||
|
var oldPaddingFactorX = paddingFactor.x; |
||||||
|
var oldPaddingFactorY = paddingFactor.y; |
||||||
|
padding.x *= (scrollFactor - (event.delta > 0 ? 3 : -3)) / scrollFactor; |
||||||
|
padding.y *= (scrollFactor - (event.delta > 0 ? 3 : -3)) / scrollFactor; |
||||||
|
padding.x = round(padding.x); |
||||||
|
padding.y = round(padding.y); |
||||||
|
|
||||||
|
prepareGridValues(); |
||||||
|
|
||||||
|
origin.x = -(mouseX - origin.x) / (oldPaddingX / oldPaddingFactorX) * (padding.x / paddingFactor.x) + mouseX; |
||||||
|
origin.y = -(mouseY - origin.y) / (oldPaddingY / oldPaddingFactorY) * (padding.y / paddingFactor.y) + mouseY; |
||||||
|
|
||||||
|
updateDisplay(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function updateScroll(){ |
||||||
|
scrollFactor = round((500 - $("#scroll_input").val() * 0.95) / 5); |
||||||
|
} |
||||||
|
|
||||||
|
function updateDisposition(obj, xAxis){ |
||||||
|
obj.blur(); |
||||||
|
var dispo = $(obj).val(); |
||||||
|
if (xAxis){ |
||||||
|
if (dispo == "PI" && !axisDispoPI.x){ |
||||||
|
paddingFactor.x *= PI; |
||||||
|
padding.x *= PI; |
||||||
|
axisDispoPI.x = true; |
||||||
|
} |
||||||
|
if (dispo == "1" && axisDispoPI.x){ |
||||||
|
paddingFactor.x /= PI; |
||||||
|
padding.x /= PI; |
||||||
|
axisDispoPI.x = false; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!xAxis){ |
||||||
|
if (dispo == "PI" && !axisDispoPI.y){ |
||||||
|
paddingFactor.y *= PI; |
||||||
|
padding.y *= PI; |
||||||
|
axisDispoPI.y = true; |
||||||
|
} |
||||||
|
if (dispo == "1" && axisDispoPI.y){ |
||||||
|
paddingFactor.y /= PI; |
||||||
|
padding.y /= PI; |
||||||
|
axisDispoPI.y = false; |
||||||
|
} |
||||||
|
} |
||||||
|
updateAll(); |
||||||
|
} |
||||||
|
|
||||||
|
function mouseDragged(){ |
||||||
|
if (editing){currentEditor.colorPicker.mouseDragged();} |
||||||
|
else if (valid){ |
||||||
|
origin.x = round(mouseX - distance.x); |
||||||
|
origin.y = round(mouseY - distance.y); |
||||||
|
updateDisplay(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function mousePressed(){ |
||||||
|
if (editing){currentEditor.colorPicker.mousePressed();} |
||||||
|
else if (mouseX > 0 && mouseY < height){ |
||||||
|
valid = true; |
||||||
|
distance.x = mouseX - origin.x; |
||||||
|
distance.y = mouseY - origin.y; |
||||||
|
$("#defaultCanvas0").css("cursor", "all-scroll"); |
||||||
|
} else {valid = false;} |
||||||
|
} |
||||||
|
|
||||||
|
function mouseReleased(){ |
||||||
|
if (editing){currentEditor.colorPicker.mouseReleased();} |
||||||
|
$("#defaultCanvas0").css("cursor", "auto"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function prepareVisibilites(){ |
||||||
|
if (!editing) $("#graph_editor_wrapper").hide(); |
||||||
|
$("#canvas_holder").css("height", windowHeight - $("#input_holder").outerHeight() + "px"); |
||||||
|
var canvas = createCanvas(windowWidth - $("#displayer").outerWidth(), windowHeight - $("#input_holder").outerHeight()); |
||||||
|
canvas.parent("canvas_holder"); |
||||||
|
$(".holder:not(#settings_holder)").css("height", windowHeight * 0.7 * 0.5 + "px"); |
||||||
|
$("#settings_holder").css("height", $("#displayer").outerHeight() - $("#function_holder").outerHeight() - $("#variable_holder").outerHeight() - 80 + "px"); |
||||||
|
origin.x = width / 2; |
||||||
|
origin.y = height / 2; |
||||||
|
textFont("Arial", textHeight); |
||||||
|
$("body").css("background-color", "#FFF"); |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
a:link, a:hover, a:active, a:visited{color: #000;} |
||||||
|
|
||||||
|
body, canvas{margin: 0; padding: 0;} |
||||||
|
|
||||||
|
*:not(#input, #graph_editor_input){ |
||||||
|
-webkit-user-select: none; |
||||||
|
-moz-user-select: none; |
||||||
|
-ms-user-select: none; |
||||||
|
user-select: none; |
||||||
|
} |
||||||
|
|
||||||
|
#functions td:nth-child(1){ |
||||||
|
width: 5%; |
||||||
|
} |
||||||
|
#functions td:nth-child(1) div{ |
||||||
|
width: 20px; |
||||||
|
height: 20px; |
||||||
|
border-width: 3px; |
||||||
|
border-style: solid; |
||||||
|
border-radius: 50%; |
||||||
|
} |
||||||
|
#functions td:nth-child(3){ |
||||||
|
width: 5%; |
||||||
|
} |
||||||
|
#functions td:nth-child(3) button{ |
||||||
|
width: 100%; |
||||||
|
background-color: #F00; |
||||||
|
border: 2px solid #F00; |
||||||
|
border-radius: 2px; |
||||||
|
} |
||||||
|
|
||||||
|
#input_holder{ |
||||||
|
position: absolute; |
||||||
|
display: block; |
||||||
|
bottom: 0; |
||||||
|
right: 0; |
||||||
|
padding: 5px 0.5% 5px 0.5%; |
||||||
|
width: 79%; |
||||||
|
height: 30px; |
||||||
|
background-color: #777; |
||||||
|
} |
||||||
|
#input{ |
||||||
|
width: 95%; |
||||||
|
height: 30px; |
||||||
|
font-size: 18px; |
||||||
|
} |
||||||
|
#submit{ |
||||||
|
width: 4%; |
||||||
|
height: 30px; |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
|
||||||
|
#displayer{ |
||||||
|
position: absolute; |
||||||
|
display: block; |
||||||
|
background-color: #999; |
||||||
|
padding: 0 1% 0 1%; |
||||||
|
width: 18%; |
||||||
|
height: 100%; |
||||||
|
border-right: 5px solid #000; |
||||||
|
} |
||||||
|
|
||||||
|
#canvas_holder{ |
||||||
|
position: absolute; |
||||||
|
left: 20%; |
||||||
|
width: 80%; |
||||||
|
} |
||||||
|
|
||||||
|
.displayer{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.holder{ |
||||||
|
border: 5px solid #000; |
||||||
|
background-color: #777; |
||||||
|
overflow-y: auto; |
||||||
|
} |
||||||
|
#variable_holder{ |
||||||
|
margin-top: 20px; |
||||||
|
margin-bottom: 20px; |
||||||
|
} |
||||||
|
#settings_holder{ |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
#settings_holder span{ |
||||||
|
margin: 10px; |
||||||
|
} |
||||||
|
legend{ |
||||||
|
font-size: 30px; |
||||||
|
} |
||||||
|
|
||||||
|
#scroll_input{ |
||||||
|
width: calc(100% - 20px); |
||||||
|
margin: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
.displayer button{ |
||||||
|
text-align: left; |
||||||
|
font-size: 20px; |
||||||
|
width: 100%; |
||||||
|
padding: 5px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
#graph_editor_wrapper{ |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background-color: rgba(0, 0, 0, 0.75); |
||||||
|
} |
||||||
|
|
||||||
|
#graph_editor{ |
||||||
|
position: absolute; |
||||||
|
width: 400px; |
||||||
|
min-height: 400px; |
||||||
|
background-color: #BBB; |
||||||
|
border-radius: 10px; |
||||||
|
border: 4px solid #000; |
||||||
|
box-shadow: 10px 10px 10px #000; |
||||||
|
} |
||||||
|
|
||||||
|
#graph_editor_thickness{ |
||||||
|
width: 20%; |
||||||
|
height: 25px; |
||||||
|
margin-left: 5%; |
||||||
|
font-size: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
#graph_editor_input{ |
||||||
|
width: 90%; |
||||||
|
height: 30px; |
||||||
|
margin: 5%; |
||||||
|
font-size: 23px; |
||||||
|
} |
||||||
|
|
||||||
|
#graph_editor_done{ |
||||||
|
width: 80px; |
||||||
|
height: 40px; |
||||||
|
font-size: 25px; |
||||||
|
margin: 20px; |
||||||
|
background-color: #99FF99; |
||||||
|
float: right; |
||||||
|
border: 3px solid #99FF99; |
||||||
|
border-radius: 5px; |
||||||
|
box-shadow: 2px 2px 5px #000; |
||||||
|
} |
After Width: | Height: | Size: 227 KiB |
Loading…
Reference in new issue