commit 8e415fb92a30876f39e1fd85c97f94aae83304a7
Author: Christos Margiolis <christos@margiolis.net>
Date: Sat, 7 Mar 2020 07:20:30 +0200
initial commit
Diffstat:
5 files changed, 237 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,36 @@
+TARGET = graphcurses
+
+SRC_DIR = src
+OBJ_DIR = obj
+BIN_DIR = bin
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
+
+MOVE = mv
+MKDIR_P = mkdir -p
+
+CC = g++
+CPPFLAGS += -Iinclude
+CFLAGS += -Wall
+LDFLAGS += -Llib
+LDLIBS += -lncurses -lm -lmatheval
+
+.PHONY: all clean
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+ $(MKDIR_P) $(BIN_DIR)
+ $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
+ $(MOVE) $(TARGET) $(BIN_DIR)
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
+ $(MKDIR_P) $(OBJ_DIR)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+run:
+ ./$(BIN_DIR)/$(TARGET) ${y}
+
+clean:
+ $(RM) $(OBJ) $(BIN_DIR)/$(TARGET)
diff --git a/README.md b/README.md
@@ -0,0 +1,17 @@
+# graphcurses
+
+**UNDER CONSTRUCTION**
+A simple ncurses graph generator.
+
+## Dependencies
+
+`ncurses`
+`matheval`
+
+## To Do
+
+* Get rid of `matheval`
+* Improve key handling
+* Add slope, curvature etc.
+* Add an options window
+* Add the option to give a function while in the program
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/src/main.cpp b/src/main.cpp
@@ -0,0 +1,184 @@
+#include <ncurses.h>
+#include <cmath>
+#include <matheval.h>
+#include <iostream>
+#include <string>
+
+#define XMIN_PLANE -2*M_PI
+#define XMAX_PLANE 2*M_PI
+#define YMIN_PLANE -M_PI
+#define YMAX_PLANE M_PI
+
+typedef struct
+{
+ double ymin, ymax;
+ double xmin, xmax;
+} Plane;
+
+typedef double (*YFunc)(double x);
+void *eval = nullptr;
+double default_func(double x) {return sin(x);}
+double evalf(double x) {return evaluator_evaluate_x(eval, x);}
+
+void init_curses()
+{
+ initscr();
+ cbreak();
+ noecho();
+ curs_set(0);
+ keypad(stdscr, true);
+ start_color();
+ init_pair(1, COLOR_GREEN, COLOR_BLACK);
+ init_pair(2, COLOR_YELLOW, COLOR_BLACK);
+}
+
+double scale(double val, double omin, double omax, double nmin, double nmax)
+{
+ double s = (val - omin) / (omax - omin);
+ return s * (nmax - nmin) + nmin;
+}
+
+void getstep(Plane &plane, double &xstep, double &ystep)
+{
+ int ymax, xmax;
+ getmaxyx(stdscr, ymax, xmax);
+ if (xstep) xstep = (plane.xmax - plane.xmin) / (xmax + 1);
+ if (ystep) ystep = (plane.ymax - plane.ymin) / (ymax + 1);
+}
+
+void draw_axes(Plane &plane)
+{
+ int ymax, xmax;
+ getmaxyx(stdscr, ymax, xmax);
+ double x0 = scale(0, plane.xmin, plane.xmax, 0, xmax);
+ double y0 = scale(0, plane.ymin, plane.ymax, ymax, 0);
+ double xstep, ystep;
+ getstep(plane, xstep, ystep);
+
+ for (int i = 0; i < xmax; i++)
+ {
+ double plotx = plane.xmin + xstep * i;
+ mvwaddch(stdscr, y0, i, ACS_HLINE);
+ }
+
+ for (int i = 0; i < ymax; i++)
+ {
+ double ploty = plane.ymin + ystep * i;
+ mvwaddch(stdscr, i, x0, ACS_VLINE);
+ }
+
+ refresh();
+}
+
+void plot(Plane &plane, double x, double y)
+{
+ int ymax, xmax;
+ getmaxyx(stdscr, ymax, xmax);
+ double xp = scale(x, plane.xmin, plane.xmax, 0, xmax);
+ double yp = scale(y, plane.ymin, plane.ymax, ymax, 0);
+ mvwaddch(stdscr, yp, xp, '.');
+}
+
+void draw_graph(Plane &plane, YFunc yfunc)
+{
+ double xstep;
+ double ystep;
+ getstep(plane, xstep, ystep);
+ attron(COLOR_PAIR(2));
+ for (double x = plane.xmin; x <= plane.xmax; x += xstep)
+ {
+ double y = yfunc(x);
+ plot(plane, x, y);
+ }
+ attroff(COLOR_PAIR(2));
+}
+
+void handle_zoom(int key, Plane &plane)
+{
+ // improve
+ if (key == '+')
+ {
+ plane.xmin += 2.0;
+ plane.xmax -= 2.0;
+ plane.ymin += 2.0;
+ plane.ymax -= 2.0;
+ }
+ else if (key == '-')
+ {
+ plane.xmin -= 2.0;
+ plane.xmax += 2.0;
+ plane.ymin -= 2.0;
+ plane.ymax += 2.0;
+ }
+ else if (key == 'r')
+ {
+ plane.xmin = XMIN_PLANE;
+ plane.xmax = XMAX_PLANE;
+ plane.ymin = YMIN_PLANE;
+ plane.ymax = YMAX_PLANE;
+ }
+
+}
+
+void handle_key(int key, Plane &plane)
+{
+ double xshift = 0, yshift = 0;
+
+ switch (key)
+ {
+ case 'k': case KEY_UP: yshift = 1; break;
+ case 'j': case KEY_DOWN: yshift = -1; break;
+ case 'h': case KEY_LEFT: xshift = -1; break;
+ case 'l': case KEY_RIGHT: xshift = 1; break;
+ case '+': case '-': case 'r': handle_zoom(key, plane); break;
+ }
+
+ xshift *= (plane.xmax - plane.xmin) / 16;
+ yshift *= (plane.ymax - plane.ymin) / 16;
+ plane.xmin += xshift;
+ plane.xmax += xshift;
+ plane.ymin += yshift;
+ plane.ymax += yshift;
+}
+
+int main(int argc, char **argv)
+{
+ Plane plane;
+ plane.xmin = XMIN_PLANE;
+ plane.xmax = XMAX_PLANE;
+ plane.ymin = YMIN_PLANE;
+ plane.ymax = YMAX_PLANE;
+
+ YFunc yfunc = default_func;
+ int key = 0;
+
+ if (argc > 1)
+ {
+ if (std::string(argv[1]) == "y=") argv[1] += 2;
+ eval = evaluator_create(argv[1]);
+ if (!eval)
+ {
+ std::cout << "Error in expression!" << std::endl;
+ return -1;
+ }
+ yfunc = evalf;
+ }
+
+ init_curses();
+ while (key != 'q')
+ {
+ handle_key(key, plane);
+ erase();
+ attron(COLOR_PAIR(1));
+ draw_axes(plane);
+ attroff(COLOR_PAIR(1));
+
+ draw_graph(plane, yfunc);
+ refresh();
+ key = getch();
+ }
+
+ endwin();
+
+ return 0;
+}