From 49598cfda3e0f23a02bfe3179e6f1daa2dabb9a5 Mon Sep 17 00:00:00 2001 From: tovjemam Date: Mon, 23 Dec 2024 16:27:06 +0100 Subject: [PATCH] remake ps --- main.c | 6 +- ps_graph.c | 162 ++++++++++++++++++++++++++++++++++++----------------- ps_graph.h | 2 +- 3 files changed, 116 insertions(+), 54 deletions(-) diff --git a/main.c b/main.c index 1b38fb5..ab72f70 100644 --- a/main.c +++ b/main.c @@ -44,7 +44,7 @@ static int parse_range(const char *str, struct graph_range *range) { return 1; } -static enum error_code export_to_file(const struct expr_node *node, const struct graph_range *range, const char *out_name) { +static enum error_code export_to_file(const struct expr_node *node, const struct graph_range *range, const char *function, const char *out_name) { FILE *file; if (!(file = fopen(out_name, "w"))) { @@ -52,7 +52,7 @@ static enum error_code export_to_file(const struct expr_node *node, const struct return ERR_INVALID_FILENAME; } - ps_export_graph(file, node, range); + ps_generate_graph(file, node, range, function); fclose(file); return ERR_NO_ERR; @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) { return parser_get_error(&parser); } - err = export_to_file(node, &range, argv[2]); + err = export_to_file(node, &range, argv[1], argv[2]); #ifdef ENABLE_GRAPHVIZ_EXPORT export_gv(node, "graph.dot"); diff --git a/ps_graph.c b/ps_graph.c index 0476e55..2ef6cb0 100644 --- a/ps_graph.c +++ b/ps_graph.c @@ -1,18 +1,77 @@ #include "ps_graph.h" #include +#define TEMP_BUF_SIZE 128 + +/* rozměry grafu */ #define GRAPH_SIZE 400 #define HALF_GRAPH_SIZE (GRAPH_SIZE / 2) + +#define GRAPH_CENTER_X 306 +#define GRAPH_CENTER_Y 500 + +/* písmo */ +#define FONT "Helvetica" +#define FONT_SIZE_HEADER 15 +#define FONT_SIZE_LABEL 12 +#define FONT_SIZE_VALUE 9 + #define GRID_STEP (GRAPH_SIZE / 10) + +/* posuny popisků */ +#define HEADER_OFFSET_Y (10) + +#define X_VAL_OFFSET_X (0) +#define X_VAL_OFFSET_Y (-13) + +#define Y_VAL_OFFSET_X (-5) +#define Y_VAL_OFFSET_Y (-3) + +#define X_LABEL_OFFSET_X (0) +#define X_LABEL_OFFSET_Y (-30) + +#define Y_LABEL_OFFSET_X (-40) +#define Y_LABEL_OFFSET_Y (-3) + +/* počet částí grafu funkce */ #define FUNCTION_SEGMENTS 1000 -void ps_export_graph(FILE *file, const struct expr_node *node, const struct graph_range *range) { - int i; - double x; - int first = 1; +/* koeficienty pro zarovnání textu */ +#define ALIGN_CENTER (-0.5) +#define ALIGN_RIGHT (-1.0) +static void generate_text_align(FILE *file, int x, int y, double alignment, const char *str) { + fprintf(file, + "newpath\n" + /* posun na cílovou pozici */ + "%d %d moveto\n" + /* vložení dvou řetězců s popiskem */ + "(%s) dup\n" + /* zjištění šířky a výšky řetežce, odstranění výšky ze zásobníku (nezajímá) */ + "stringwidth pop\n" + /* koeficient pro zarovnání */ + "%f mul\n" + /* posun o šířku doleva */ + "0 rmoveto\n" + /* zobrazení řetězce */ + "show\n" + "\n", + x, y, str, alignment + ); +} + +static void set_font(FILE *file, const char *font, int size) { + fprintf(file, + "/%s findfont\n" + "%d scalefont\n" + "setfont\n", + font, size + ); +} + +static void generate_grid(FILE *file, const struct graph_range *range) { + int i; fprintf(file, - "306 500 translate\n" "2 setlinewidth\n" "/gridline {\n" " .5 setlinewidth\n" @@ -26,62 +85,38 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap "\n" ); - /* mrizka */ for (i = -HALF_GRAPH_SIZE + GRID_STEP; i < HALF_GRAPH_SIZE; i += GRID_STEP) { fprintf(file, "%5d 0 %5d %5d gridline\n", GRAPH_SIZE, -HALF_GRAPH_SIZE, i); fprintf(file, " 0 %5d %5d %5d gridline\n", GRAPH_SIZE, i, -HALF_GRAPH_SIZE); } - /* popisky */ - fprintf(file, - "/Arial findfont\n" - "10 scalefont\n" - "setfont\n" - ); + set_font(file, FONT, FONT_SIZE_VALUE); + /* hodnoty */ for (i = -HALF_GRAPH_SIZE; i <= HALF_GRAPH_SIZE; i += GRID_STEP) { double inorm = (double)i / (double)GRAPH_SIZE + 0.5; double xval = range->xmax * inorm + range->xmin * (1.0 - inorm); double yval = range->ymax * inorm + range->ymin * (1.0 - inorm); - - fprintf(file, - "newpath\n" - "%d %d moveto\n" - "(%.2f) dup\n" - "stringwidth pop neg\n" - "0 rmoveto\n" - "-10 -3 rmoveto\n" - "show\n" - "\n", - -HALF_GRAPH_SIZE, i, yval - ); + char buf[TEMP_BUF_SIZE]; - fprintf(file, - "newpath\n" - "%d %d moveto\n" - "(%.2f) dup\n" - "stringwidth pop\n" - "2 div neg\n" - "-20 rmoveto\n" - "show\n" - "\n", - i, -HALF_GRAPH_SIZE, xval - ); + /* hodnota osy y */ + snprintf(buf, TEMP_BUF_SIZE, "%.2f", yval); + generate_text_align(file, -HALF_GRAPH_SIZE + Y_VAL_OFFSET_X, i + Y_VAL_OFFSET_Y, ALIGN_RIGHT, buf); + + /* hodnota osy x */ + snprintf(buf, TEMP_BUF_SIZE, "%.2f", xval); + generate_text_align(file, i + X_VAL_OFFSET_X, -HALF_GRAPH_SIZE + X_VAL_OFFSET_Y, ALIGN_CENTER, buf); } - fprintf(file, - "[] 0 setdash\n" - "newpath\n" - "%d %d moveto\n" - "%d 0 rlineto\n" - "0 %d rlineto\n" - "%d 0 rlineto\n" - "closepath\n" - "gsave\n" - "clip\n", - -HALF_GRAPH_SIZE, -HALF_GRAPH_SIZE, GRAPH_SIZE, GRAPH_SIZE, -GRAPH_SIZE - ); + set_font(file, FONT, FONT_SIZE_LABEL); + generate_text_align(file, -HALF_GRAPH_SIZE + Y_LABEL_OFFSET_X, Y_LABEL_OFFSET_Y, ALIGN_RIGHT, "y"); + generate_text_align(file, X_LABEL_OFFSET_X, -HALF_GRAPH_SIZE + X_LABEL_OFFSET_Y, ALIGN_CENTER, "x"); +} + +static void generate_function(FILE *file, const struct expr_node *node, const struct graph_range *range) { + int i; + int first = 1; fprintf(file, "2 setlinewidth\n" @@ -92,7 +127,7 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap for (i = 0; i < FUNCTION_SEGMENTS; ++i) { const char *cmd = "lineto"; double xpos, ypos; - double y; + double x, y; x = range->xmin + (range->xmax - range->xmin) * (double)i / (double)FUNCTION_SEGMENTS; @@ -115,6 +150,35 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap fprintf(file, "stroke\n" ); +} + +void ps_generate_graph(FILE *file, const struct expr_node *node, const struct graph_range *range, const char *function) { + char buf[TEMP_BUF_SIZE]; + + fprintf(file, "%d %d translate\n", GRAPH_CENTER_X, GRAPH_CENTER_Y); + + if (function) { + set_font(file, FONT, FONT_SIZE_HEADER); + snprintf(buf, TEMP_BUF_SIZE, "y = %s", function); + generate_text_align(file, 0, HALF_GRAPH_SIZE + HEADER_OFFSET_Y, ALIGN_CENTER, buf); + } + + generate_grid(file, range); + + fprintf(file, + "[] 0 setdash\n" + "newpath\n" + "%d %d moveto\n" + "%d 0 rlineto\n" + "0 %d rlineto\n" + "%d 0 rlineto\n" + "closepath\n" + "gsave\n" + "clip\n", + -HALF_GRAPH_SIZE, -HALF_GRAPH_SIZE, GRAPH_SIZE, GRAPH_SIZE, -GRAPH_SIZE + ); + + generate_function(file, node, range); fprintf(file, "grestore\n" @@ -122,6 +186,4 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap "0 0 0 setrgbcolor\n" "stroke\n" ); - - } \ No newline at end of file diff --git a/ps_graph.h b/ps_graph.h index 734b424..92774ae 100644 --- a/ps_graph.h +++ b/ps_graph.h @@ -9,6 +9,6 @@ struct graph_range { double ymin, ymax; }; -extern void ps_export_graph(FILE *file, const struct expr_node *node, const struct graph_range *range); +extern void ps_generate_graph(FILE *file, const struct expr_node *node, const struct graph_range *range, const char *function); #endif \ No newline at end of file