graphcurses

Curses 2D graph generator
git clone git://git.christosmarg.xyz/graphcurses.git
Log | Files | Refs | README | LICENSE

commit 4145d64035248317f7fe7cb1af6b79b1dec429fa
parent 06df6154ed6dafa80a57bc0121a7a3afe27268b1
Author: Christos Margiolis <christos@margiolis.net>
Date:   Mon, 18 May 2020 17:23:54 +0300

changed to C

Diffstat:
MMakefile | 8++++----
Mbin/graphcurses | 0
Mobj/main.o | 0
Mobj/plane.o | 0
Asrc/main.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/main.cpp | 100-------------------------------------------------------------------------------
Asrc/plane.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/plane.cpp | 100-------------------------------------------------------------------------------
Msrc/plane.h | 53++++++++++++++++++++++++++---------------------------
9 files changed, 246 insertions(+), 231 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,13 +5,13 @@ SRC_DIR = src OBJ_DIR = obj BIN_DIR = bin -SRC = $(wildcard $(SRC_DIR)/*.cpp) -OBJ = $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) +SRC = $(wildcard $(SRC_DIR)/*.c) +OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) MOVE = mv MKDIR_P = mkdir -p -CC = g++ +CC = gcc CPPFLAGS += -Iinclude CFLAGS += -Wall LDFLAGS += -Llib @@ -26,7 +26,7 @@ $(TARGET): $(OBJ) $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(MOVE) $(TARGET) $(BIN_DIR) -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(MKDIR_P) $(OBJ_DIR) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/bin/graphcurses b/bin/graphcurses Binary files differ. diff --git a/obj/main.o b/obj/main.o Binary files differ. diff --git a/obj/plane.o b/obj/plane.o Binary files differ. diff --git a/src/main.c b/src/main.c @@ -0,0 +1,107 @@ +#include "plane.h" + +static void *f = NULL; + +static void init_curses(); +static void getfunc(Plane *p, char *buf); +static void validate_expression(Plane *p); +static float eval(float x); +static void handle_key(Plane *p, int key); + +int +main(int argc, char **argv) +{ + init_curses(); + Plane p; + plane_init(&p); + restore_zoom(&p); + validate_expression(&p); + p.yfunc = eval; + int key = 0; + + while (key != 'q') + { + attron(COLOR_PAIR(1)); + handle_key(&p, key); + erase(); + attron(A_REVERSE); + attron(A_BOLD); + mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f)); + attroff(A_REVERSE); + attroff(A_BOLD); + draw_axes(&p); + attroff(COLOR_PAIR(1)); + + draw_graph(&p); + refresh(); + key = getch(); + } + + endwin(); + /*evaluator_destroy(f); */ + + return 0; +} + +static void +init_curses() +{ + initscr(); + cbreak(); + noecho(); + curs_set(0); + keypad(stdscr, 1); + start_color(); + init_pair(1, COLOR_WHITE, COLOR_BLACK); + init_pair(2, COLOR_YELLOW, COLOR_BLACK); +} + +static void +getfunc(Plane *p, char *buf) +{ + move(0, 0); + clrtoeol(); + printw("f(x) = "); + echo(); + refresh(); + getnstr(buf, 256); + restore_zoom(p); + refresh(); + noecho(); +} + +static void +validate_expression(Plane *p) +{ + char *buf = (char *)malloc(256 + sizeof(char)); + getfunc(p, buf); + while (!(f = evaluator_create(buf))) + { + printw("Error in expression! Try again"); + getfunc(p, buf); + refresh(); + } + free(buf); +} + +static float +eval(float x) +{ + return evaluator_evaluate_x(f, x); +} + +static void +handle_key(Plane *p, int key) +{ + switch (key) + { + case 'k': case KEY_UP: shift(p, 0.0f, 1.0f); break; + case 'j': case KEY_DOWN: shift(p, 0.0f, -1.0f); break; + case 'h': case KEY_LEFT: shift(p, -1.0f, 0.0f); break; + case 'l': case KEY_RIGHT: shift(p, 1.0f, 0.0f); break; + case '+': handle_zoom(p, 1.0f/1.05f); break; + case '-': handle_zoom(p, 1.05f); break; + case 'r': restore_zoom(p); break; + case 'f': validate_expression(p); break; + } +} diff --git a/src/main.cpp b/src/main.cpp @@ -1,100 +0,0 @@ -#include "plane.h" - -static void *f = nullptr; - -static void init_curses(); -static void getfunc(char *buffer, Plane& plane); -static void validate_expression(Plane& plane); -static void handle_key(int key, Plane& plane); - -int -main(int argc, char **argv) -{ - init_curses(); - Plane plane; - plane.restore_zoom(); - validate_expression(plane); - std::function<float(float)> yfunc = - [](float x){return evaluator_evaluate_x(f, x);}; - int key = 0; - - while (key != 'q') - { - attron(COLOR_PAIR(1)); - handle_key(key, plane); - erase(); - attron(A_REVERSE); - attron(A_BOLD); - mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f)); - attroff(A_REVERSE); - attroff(A_BOLD); - plane.draw_axes(); - attroff(COLOR_PAIR(1)); - - plane.draw_graph(yfunc); - refresh(); - key = getch(); - } - - endwin(); - evaluator_destroy(f); - - return 0; -} - -static void -init_curses() -{ - initscr(); - cbreak(); - noecho(); - curs_set(0); - keypad(stdscr, true); - start_color(); - init_pair(1, COLOR_WHITE, COLOR_BLACK); - init_pair(2, COLOR_YELLOW, COLOR_BLACK); -} - -static void -getfunc(char *buffer, Plane& plane) -{ - move(0, 0); - clrtoeol(); - printw("f(x) = "); - echo(); - refresh(); - getnstr(buffer, 256); - plane.restore_zoom(); - refresh(); - noecho(); -} - -static void -validate_expression(Plane& plane) -{ - char *buffer = new char[256]; - getfunc(buffer, plane); - while (!(f = evaluator_create(buffer))) - { - printw("Error in expression! Try again"); - getfunc(buffer, plane); - refresh(); - } - delete[] buffer; -} - -static void -handle_key(int key, Plane& plane) -{ - switch (key) - { - case 'k': case KEY_UP: plane.shift(0.0f, 1.0f); break; - case 'j': case KEY_DOWN: plane.shift(0.0f, -1.0f); break; - case 'h': case KEY_LEFT: plane.shift(-1.0f, 0.0f); break; - case 'l': case KEY_RIGHT: plane.shift(1.0f, 0.0f); break; - case '+': plane.handle_zoom(1.0f/1.05f); break; - case '-': plane.handle_zoom(1.05f); break; - case 'r': plane.restore_zoom(); break; - case 'f': validate_expression(plane); break; - } -} diff --git a/src/plane.c b/src/plane.c @@ -0,0 +1,109 @@ +#include "plane.h" + +void +plane_init(Plane *p) +{ + p->xmin = XMIN_PLANE; + p->xmax = XMAX_PLANE; + p->ymin = YMIN_PLANE; + p->ymax = YMAX_PLANE; + p->xscale = XSCALE_PLANE; + p->yscale = YSCALE_PLANE; + p->xmaxs = getmaxx(stdscr); + p->ymaxs = getmaxy(stdscr); +} + +void +restore_zoom(Plane *p) +{ + p->xmin = XMIN_PLANE; + p->xmax = XMAX_PLANE; + p->ymin = YMIN_PLANE; + p->ymax = YMAX_PLANE; + p->xscale = XSCALE_PLANE; + p->yscale = YSCALE_PLANE; +} + +void +draw_axes(Plane *p) +{ + int i; + float x0 = scale(0.0f, p->xmin, p->xmax, 0.0f, p->xmaxs); + float y0 = scale(0.0f, p->ymin, p->ymax, p->ymaxs, 0.0f); + float xstep, ystep; + getstep(p, &xstep, &ystep); + for (i = 0; i < p->xmaxs; i++) + { + float plotx = p->xmin + xstep * i; + int tick = fabs(fmod(plotx, p->xscale)) < xstep; + mvaddch(y0, i, tick ? ACS_PLUS : ACS_HLINE); + } + for (i = 0; i < p->ymaxs; i++) + { + float ploty = p->ymin + ystep * i; + int tick = fabs(fmod(ploty, p->yscale)) < ystep; + mvaddch(i, x0, tick ? ACS_PLUS : ACS_VLINE); + } + mvaddch(y0, x0, ACS_PLUS); +} + +void +draw_graph(Plane *p) +{ + float x; + float xstep; + float ystep; + getstep(p, &xstep, &ystep); + attron(COLOR_PAIR(2)); + for (x = p->xmin; x <= p->xmax; x += xstep) + { + float y = p->yfunc(x); + plot(p, x, y); + } + attroff(COLOR_PAIR(2)); +} + +float +scale(float val, float omin, float omax, float nmin, float nmax) +{ + float s = (val - omin) / (omax - omin); + return s * (nmax - nmin) + nmin; +} + +void +getstep(Plane *p, float *xstep, float *ystep) +{ + if (*xstep) *xstep = (p->xmax - p->xmin) / (p->xmaxs + 1.0f); + if (*ystep) *ystep = (p->ymax - p->ymin) / (p->ymaxs + 1.0f); +} + +void +plot(Plane *p, float x, float y) +{ + float xp = scale(x, p->xmin, p->xmax, 0.0f, p->xmaxs); + float yp = scale(y, p->ymin, p->ymax, p->ymaxs, 0.0f); + mvaddch(yp, xp, '.'); +} + + +void +handle_zoom(Plane *p, float factor) +{ + float centerX = (p->xmin + p->ymax) / 2.0f; + float centerY = (p->ymin + p->ymax) / 2.0f; + p->xmin = scale(factor, 1.0f, 0.0f, p->xmin, centerX); + p->xmax = scale(factor, 1.0f, 0.0f, p->xmax, centerX); + p->ymin = scale(factor, 1.0f, 0.0f, p->ymin, centerY); + p->ymax = scale(factor, 1.0f, 0.0f, p->ymax, centerY); +} + +void +shift(Plane *p, float xshift, float yshift) +{ + xshift *= (p->xmax - p->xmin) / 16.0f; + yshift *= (p->ymax - p->ymin) / 16.0f; + p->xmin += xshift; + p->xmax += xshift; + p->ymin += yshift; + p->ymax += yshift; +} diff --git a/src/plane.cpp b/src/plane.cpp @@ -1,100 +0,0 @@ -#include "plane.h" - -Plane::Plane() - :ymin(YMIN_PLANE), ymax(YMAX_PLANE), xmin(XMIN_PLANE), xmax(XMAX_PLANE), - xscale(XSCALE_PLANE), yscale(YSCALE_PLANE), ymaxs(getmaxy(stdscr)), - xmaxs(getmaxx(stdscr)) {} - -void -Plane::restore_zoom() -{ - xmin = XMIN_PLANE; - xmax = XMAX_PLANE; - ymin = YMIN_PLANE; - ymax = YMAX_PLANE; - xscale = XSCALE_PLANE; - yscale = YSCALE_PLANE; -} - -void -Plane::draw_axes() -{ - float x0 = scale(0.0f, xmin, xmax, 0.0f, xmaxs); - float y0 = scale(0.0f, ymin, ymax, ymaxs, 0.0f); - float xstep, ystep; - getstep(xstep, ystep); - - for (int i = 0; i < xmaxs; i++) - { - float plotx = xmin + xstep * i; - int tick = fabs(fmod(plotx, xscale)) < xstep; - mvaddch(y0, i, tick ? ACS_PLUS : ACS_HLINE); - } - - for (int i = 0; i < ymaxs; i++) - { - float ploty = ymin + ystep * i; - int tick = fabs(fmod(ploty, yscale)) < ystep; - mvaddch(i, x0, tick ? ACS_PLUS : ACS_VLINE); - } -} - -void -Plane::draw_graph(const std::function<float(float)>& yfunc) -{ - float xstep; - float ystep; - getstep(xstep, ystep); - attron(COLOR_PAIR(2)); - for (float x = xmin; x <= xmax; x += xstep) - { - float y = yfunc(x); - plot(x, y); - } - attroff(COLOR_PAIR(2)); -} - -float -Plane::scale(float val, float omin, float omax, float nmin, float nmax) -{ - float s = (val - omin) / (omax - omin); - return s * (nmax - nmin) + nmin; -} - -void -Plane::getstep(float &xstep, float &ystep) -{ - if (xstep) xstep = (xmax - xmin) / (xmaxs + 1.0f); - if (ystep) ystep = (ymax - ymin) / (ymaxs + 1.0f); -} - -void -Plane::plot(float x, float y) -{ - float xp = scale(x, xmin, xmax, 0.0f, xmaxs); - float yp = scale(y, ymin, ymax, ymaxs, 0.0f); - mvaddch(yp, xp, '.'); -} - - -void -Plane::handle_zoom(float factor) -{ - float centerX = (xmin + ymax) / 2.0f; - float centerY = (ymin + ymax) / 2.0f; - xmin = scale(factor, 1.0f, 0.0f, xmin, centerX); - xmax = scale(factor, 1.0f, 0.0f, xmax, centerX); - ymin = scale(factor, 1.0f, 0.0f, ymin, centerY); - ymax = scale(factor, 1.0f, 0.0f, ymax, centerY); -} - -void -Plane::shift(float xshift, float yshift) -{ - xshift *= (xmax - xmin) / 16.0f; - yshift *= (ymax - ymin) / 16.0f; - xmin += xshift; - xmax += xshift; - ymin += yshift; - ymax += yshift; -} diff --git a/src/plane.h b/src/plane.h @@ -1,38 +1,37 @@ #ifndef PLANE_H #define PLANE_H -#include <cmath> -#include <functional> -#include <iostream> +#include <math.h> #include <matheval.h> #include <ncurses.h> +#include <stdio.h> +#include <stdlib.h> -class Plane -{ - private: - const float XMIN_PLANE = -2.0f*M_PI; - const float XMAX_PLANE = 2.0f*M_PI; - const float YMIN_PLANE = -M_PI; - const float YMAX_PLANE = M_PI; - const float XSCALE_PLANE = 1.0f; - const float YSCALE_PLANE = 1.0f; +#define XMIN_PLANE -2.0f*M_PI; +#define XMAX_PLANE 2.0f*M_PI; +#define YMIN_PLANE -M_PI; +#define YMAX_PLANE M_PI; +#define XSCALE_PLANE 1.0f; +#define YSCALE_PLANE 1.0f; - float ymin, ymax; - float xmin, xmax; - float xscale, yscale; - int ymaxs, xmaxs; +typedef struct { + float (*yfunc)(float x); + float ymin, ymax; + float xmin, xmax; + float xscale, yscale; + int ymaxs, xmaxs; +} Plane; - public: - Plane(); +extern Plane p; - void restore_zoom(); - void draw_axes(); - void draw_graph(const std::function<float(float)>& yfunc); - float scale(float val, float omin, float omax, float nmin, float nmax); - void getstep(float &xstep, float &ystep); - void plot(float x, float y); - void handle_zoom(float factor); - void shift(float xshift = 0.0f, float yshift = 0.0f); -}; +void plane_init(Plane *p); +void restore_zoom(Plane *p); +void draw_axes(Plane *p); +void draw_graph(Plane *p); +float scale(float val, float omin, float omax, float nmin, float nmax); +void getstep(Plane *p, float *xstep, float *ystep); +void plot(Plane *p, float x, float y); +void handle_zoom(Plane *p, float factor); +void shift(Plane *p, float xshift, float yshift); #endif /* PLANE_H */