funguje
This commit is contained in:
parent
c8dd221b67
commit
e13969a610
162
canvas_graph.cpp
162
canvas_graph.cpp
@ -6,24 +6,119 @@ extern "C" {
|
|||||||
|
|
||||||
using namespace emscripten;
|
using namespace emscripten;
|
||||||
|
|
||||||
|
struct Line {
|
||||||
|
double x1;
|
||||||
|
double y1;
|
||||||
|
double x2;
|
||||||
|
double y2;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void draw_lines(emscripten::val& ctx, const std::vector<Line>& lines, const char* style, double width) {
|
||||||
|
ctx.set("strokeStyle", val(style));
|
||||||
|
ctx.set("lineWidth", val(width));
|
||||||
|
ctx.call<void>("beginPath");
|
||||||
|
|
||||||
|
for (const Line& line : lines) {
|
||||||
|
ctx.call<void>("moveTo", val(std::floor(line.x1 + 0.5)), val(std::floor(line.y1 + 0.5)));
|
||||||
|
ctx.call<void>("lineTo", val(std::floor(line.x2 + 0.5)), val(std::floor(line.y2 + 0.5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.call<void>("stroke");
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_grid(emscripten::val& ctx, const struct graph_range *range, double canvas_width, double canvas_height) {
|
||||||
|
|
||||||
|
// grid
|
||||||
|
double big_range = std::max(range->xmax - range->xmin, range->ymax - range->ymin);
|
||||||
|
double log_base = 2.0;
|
||||||
|
double grid_size = std::pow(log_base, std::floor(std::log(big_range * 0.05) / std::log(log_base)));
|
||||||
|
// double grid_size = std::pow(10.0, std::floor(std::log10(big_range * 0.1)));
|
||||||
|
|
||||||
|
// if (grid_size < 0.1)
|
||||||
|
// grid_size = 0.1;
|
||||||
|
|
||||||
|
static std::vector<Line> origin_lines;
|
||||||
|
static std::vector<Line> bold_grid_lines;
|
||||||
|
static std::vector<Line> fine_grid_lines;
|
||||||
|
origin_lines.clear();
|
||||||
|
bold_grid_lines.clear();
|
||||||
|
fine_grid_lines.clear();
|
||||||
|
|
||||||
|
double x_labels_y = range->ymax / (range->ymax - range->ymin) * canvas_height + 10;
|
||||||
|
|
||||||
|
if (x_labels_y > canvas_height - 10)
|
||||||
|
x_labels_y = canvas_height - 10;
|
||||||
|
else if (x_labels_y < 10)
|
||||||
|
x_labels_y = 10;
|
||||||
|
|
||||||
|
for (int i = range->xmin / grid_size; i <= range->xmax / grid_size; ++i) {
|
||||||
|
double x = i * grid_size;
|
||||||
|
double x_canvas = (x - range->xmin) / (range->xmax - range->xmin) * canvas_width;
|
||||||
|
|
||||||
|
std::vector<Line>* lines = &fine_grid_lines;
|
||||||
|
|
||||||
|
if (i % 5 == 0) {
|
||||||
|
if (i == 0) {
|
||||||
|
lines = &origin_lines;
|
||||||
|
} else {
|
||||||
|
lines = &bold_grid_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.call<void>("fillText", val(x), val(x_canvas + 2), val(x_labels_y));
|
||||||
|
}
|
||||||
|
|
||||||
|
lines->push_back({x_canvas, 0, x_canvas, canvas_height});
|
||||||
|
}
|
||||||
|
|
||||||
|
double y_labels_x = -range->xmin / (range->xmax - range->xmin) * canvas_width;
|
||||||
|
|
||||||
|
if (y_labels_x > canvas_width - 10)
|
||||||
|
y_labels_x = canvas_width - 10;
|
||||||
|
else if (y_labels_x < 10)
|
||||||
|
y_labels_x = 10;
|
||||||
|
|
||||||
|
for (int i = range->ymin / grid_size; i <= range->ymax / grid_size; ++i) {
|
||||||
|
double y = i * grid_size;
|
||||||
|
double y_canvas = (range->ymax - y) / (range->ymax - range->ymin) * canvas_height;
|
||||||
|
|
||||||
|
std::vector<Line>* lines = &fine_grid_lines;
|
||||||
|
|
||||||
|
if (i % 5 == 0) {
|
||||||
|
if (i == 0) {
|
||||||
|
lines = &origin_lines;
|
||||||
|
} else {
|
||||||
|
lines = &bold_grid_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.call<void>("fillText", val(y), val(y_labels_x + 2), val(y_canvas - 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
lines->push_back({0, y_canvas, canvas_width, y_canvas});
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_lines(ctx, fine_grid_lines, "#dddddd", 1.0);
|
||||||
|
draw_lines(ctx, bold_grid_lines, "#444444", 1.0);
|
||||||
|
draw_lines(ctx, origin_lines, "#000000", 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
void canvas_generate_graph(const struct expr_node *node, const struct graph_range *range, const char *function) {
|
void canvas_generate_graph(const struct expr_node *node, const struct graph_range *range, const char *function) {
|
||||||
const val document = val::global("document");
|
const val document = val::global("document");
|
||||||
val temp = document.call<val>("getElementById", val("temp"));
|
// val temp = document.call<val>("getElementById", val("temp"));
|
||||||
|
|
||||||
std::string out;
|
// std::string out;
|
||||||
|
|
||||||
for (int i = -10; i <= 10; ++i) {
|
// for (int i = -10; i <= 10; ++i) {
|
||||||
double x = i * 0.1;
|
// double x = i * 0.1;
|
||||||
double y;
|
// double y;
|
||||||
eval_result res = node_eval(node, x, &y);
|
// eval_result res = node_eval(node, x, &y);
|
||||||
|
|
||||||
if (res == EVAL_OK) {
|
// if (res == EVAL_OK) {
|
||||||
out += std::to_string(y);
|
// out += std::to_string(y);
|
||||||
out += "\n";
|
// out += "\n";
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
temp.set("innerText", out);
|
// temp.set("innerText", out);
|
||||||
|
|
||||||
val canvas = document.call<val>("getElementById", val("canvas"));
|
val canvas = document.call<val>("getElementById", val("canvas"));
|
||||||
val ctx = canvas.call<val>("getContext", val("2d"));
|
val ctx = canvas.call<val>("getContext", val("2d"));
|
||||||
@ -33,35 +128,30 @@ void canvas_generate_graph(const struct expr_node *node, const struct graph_rang
|
|||||||
// clear canvas
|
// clear canvas
|
||||||
ctx.call<void>("clearRect", val(0), val(0), val(canvas_width), val(canvas_height));
|
ctx.call<void>("clearRect", val(0), val(0), val(canvas_width), val(canvas_height));
|
||||||
|
|
||||||
// grid
|
draw_grid(ctx, range, canvas_width, canvas_height);
|
||||||
double big_range = std::max(range->xmax - range->xmin, range->ymax - range->ymin);
|
|
||||||
double grid_size = std::pow((int)std::log10(big_range), 10.0);
|
|
||||||
|
|
||||||
if (grid_size < 0.1)
|
// ctx.set("strokeStyle", val("#888888"));
|
||||||
grid_size = 0.1;
|
// ctx.set("lineWidth", val(1.0));
|
||||||
|
// ctx.call<void>("beginPath");
|
||||||
|
|
||||||
ctx.set("strokeStyle", val("#888888"));
|
// double first_grid_x = (int)(range->xmin / grid_size) * grid_size;
|
||||||
ctx.set("lineWidth", val(1.0));
|
// double grid_x;
|
||||||
ctx.call<void>("beginPath");
|
// for (int i = 0; (grid_x = first_grid_x + i * grid_size) <= range->xmax; ++i) {
|
||||||
|
// double x_canvas = (grid_x - range->xmin) / (range->xmax - range->xmin) * canvas_width;
|
||||||
|
// ctx.call<void>("moveTo", val(x_canvas), val(0));
|
||||||
|
// ctx.call<void>("lineTo", val(x_canvas), val(canvas_height));
|
||||||
|
// }
|
||||||
|
|
||||||
double first_grid_x = (int)(range->xmin / grid_size) * grid_size;
|
// double first_grid_y = (int)(range->ymin / grid_size) * grid_size;
|
||||||
double grid_x;
|
// double grid_y;
|
||||||
for (int i = 0; (grid_x = first_grid_x + i * grid_size) <= range->xmax; ++i) {
|
// for (int i = 0; (grid_y = first_grid_y + i * grid_size) <= range->ymax; ++i) {
|
||||||
double x_canvas = (grid_x - range->xmin) / (range->xmax - range->xmin) * canvas_width;
|
// double y_canvas = (range->ymax - grid_y) / (range->ymax - range->ymin) * canvas_height;
|
||||||
ctx.call<void>("moveTo", val(x_canvas), val(0));
|
// ctx.call<void>("moveTo", val(0), val(y_canvas));
|
||||||
ctx.call<void>("lineTo", val(x_canvas), val(canvas_height));
|
// ctx.call<void>("lineTo", val(canvas_width), val(y_canvas));
|
||||||
}
|
// }
|
||||||
|
|
||||||
double first_grid_y = (int)(range->ymin / grid_size) * grid_size;
|
|
||||||
double grid_y;
|
|
||||||
for (int i = 0; (grid_y = first_grid_y + i * grid_size) <= range->ymax; ++i) {
|
|
||||||
double y_canvas = (range->ymax - grid_y) / (range->ymax - range->ymin) * canvas_height;
|
|
||||||
ctx.call<void>("moveTo", val(0), val(y_canvas));
|
|
||||||
ctx.call<void>("lineTo", val(canvas_width), val(y_canvas));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ctx.call<void>("stroke");
|
// ctx.call<void>("stroke");
|
||||||
|
|
||||||
// graph
|
// graph
|
||||||
ctx.set("strokeStyle", val("#000088"));
|
ctx.set("strokeStyle", val("#000088"));
|
||||||
|
|||||||
44
shell.html
44
shell.html
@ -3,9 +3,17 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Document</title>
|
<title>zbyvaj's Graphing Calculator</title>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.tt {
|
.tt {
|
||||||
font-family: "Consolas", "Courier New", monospace;
|
font-family: "Consolas", "Courier New", monospace;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@ -15,16 +23,34 @@
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#input {
|
||||||
|
width: 200px;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#floating-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
/* width: 300px; */
|
||||||
|
/* height: 100px; */
|
||||||
|
background-color: #dddddddd;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas id="canvas" width="800" height="600"></canvas>
|
<canvas id="canvas" width="800" height="600"></canvas>
|
||||||
|
|
||||||
<input type="text" id="input" oninput="fnChanged()">
|
<div id="floating-panel">
|
||||||
|
<textarea id="input" class="tt" oninput="fnChanged()"></textarea>
|
||||||
|
<!-- <input type="text" id="input" class="tt" oninput="fnChanged()"> -->
|
||||||
<pre class="tt red" id="output"></pre>
|
<pre class="tt red" id="output"></pre>
|
||||||
<pre class="tt" id="temp"></pre>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let drawGraph = null;
|
let drawGraph = null;
|
||||||
@ -95,6 +121,16 @@
|
|||||||
drawGraph(fn, xMin, xMax, yMin, yMax);
|
drawGraph(fn, xMin, xMax, yMin, yMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resize canvas size
|
||||||
|
function resizeCanvas() {
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", resizeCanvas);
|
||||||
|
resizeCanvas();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{{ SCRIPT }}}
|
{{{ SCRIPT }}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user