remake ps
This commit is contained in:
parent
5742e9af6b
commit
49598cfda3
6
main.c
6
main.c
@ -44,7 +44,7 @@ static int parse_range(const char *str, struct graph_range *range) {
|
|||||||
return 1;
|
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;
|
FILE *file;
|
||||||
|
|
||||||
if (!(file = fopen(out_name, "w"))) {
|
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;
|
return ERR_INVALID_FILENAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps_export_graph(file, node, range);
|
ps_generate_graph(file, node, range, function);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return ERR_NO_ERR;
|
return ERR_NO_ERR;
|
||||||
@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
|
|||||||
return parser_get_error(&parser);
|
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
|
#ifdef ENABLE_GRAPHVIZ_EXPORT
|
||||||
export_gv(node, "graph.dot");
|
export_gv(node, "graph.dot");
|
||||||
|
|||||||
162
ps_graph.c
162
ps_graph.c
@ -1,18 +1,77 @@
|
|||||||
#include "ps_graph.h"
|
#include "ps_graph.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#define TEMP_BUF_SIZE 128
|
||||||
|
|
||||||
|
/* rozměry grafu */
|
||||||
#define GRAPH_SIZE 400
|
#define GRAPH_SIZE 400
|
||||||
#define HALF_GRAPH_SIZE (GRAPH_SIZE / 2)
|
#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)
|
#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
|
#define FUNCTION_SEGMENTS 1000
|
||||||
|
|
||||||
void ps_export_graph(FILE *file, const struct expr_node *node, const struct graph_range *range) {
|
/* koeficienty pro zarovnání textu */
|
||||||
int i;
|
#define ALIGN_CENTER (-0.5)
|
||||||
double x;
|
#define ALIGN_RIGHT (-1.0)
|
||||||
int first = 1;
|
|
||||||
|
|
||||||
|
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,
|
fprintf(file,
|
||||||
"306 500 translate\n"
|
|
||||||
"2 setlinewidth\n"
|
"2 setlinewidth\n"
|
||||||
"/gridline {\n"
|
"/gridline {\n"
|
||||||
" .5 setlinewidth\n"
|
" .5 setlinewidth\n"
|
||||||
@ -26,62 +85,38 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap
|
|||||||
"\n"
|
"\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
/* mrizka */
|
|
||||||
for (i = -HALF_GRAPH_SIZE + GRID_STEP; i < HALF_GRAPH_SIZE; i += GRID_STEP) {
|
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, "%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);
|
fprintf(file, " 0 %5d %5d %5d gridline\n", GRAPH_SIZE, i, -HALF_GRAPH_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* popisky */
|
set_font(file, FONT, FONT_SIZE_VALUE);
|
||||||
fprintf(file,
|
|
||||||
"/Arial findfont\n"
|
|
||||||
"10 scalefont\n"
|
|
||||||
"setfont\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
/* hodnoty */
|
||||||
for (i = -HALF_GRAPH_SIZE; i <= HALF_GRAPH_SIZE; i += GRID_STEP) {
|
for (i = -HALF_GRAPH_SIZE; i <= HALF_GRAPH_SIZE; i += GRID_STEP) {
|
||||||
double inorm = (double)i / (double)GRAPH_SIZE + 0.5;
|
double inorm = (double)i / (double)GRAPH_SIZE + 0.5;
|
||||||
double xval = range->xmax * inorm + range->xmin * (1.0 - inorm);
|
double xval = range->xmax * inorm + range->xmin * (1.0 - inorm);
|
||||||
double yval = range->ymax * inorm + range->ymin * (1.0 - inorm);
|
double yval = range->ymax * inorm + range->ymin * (1.0 - inorm);
|
||||||
|
char buf[TEMP_BUF_SIZE];
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
fprintf(file,
|
/* hodnota osy y */
|
||||||
"newpath\n"
|
snprintf(buf, TEMP_BUF_SIZE, "%.2f", yval);
|
||||||
"%d %d moveto\n"
|
generate_text_align(file, -HALF_GRAPH_SIZE + Y_VAL_OFFSET_X, i + Y_VAL_OFFSET_Y, ALIGN_RIGHT, buf);
|
||||||
"(%.2f) dup\n"
|
|
||||||
"stringwidth pop\n"
|
/* hodnota osy x */
|
||||||
"2 div neg\n"
|
snprintf(buf, TEMP_BUF_SIZE, "%.2f", xval);
|
||||||
"-20 rmoveto\n"
|
generate_text_align(file, i + X_VAL_OFFSET_X, -HALF_GRAPH_SIZE + X_VAL_OFFSET_Y, ALIGN_CENTER, buf);
|
||||||
"show\n"
|
|
||||||
"\n",
|
|
||||||
i, -HALF_GRAPH_SIZE, xval
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file,
|
set_font(file, FONT, FONT_SIZE_LABEL);
|
||||||
"[] 0 setdash\n"
|
generate_text_align(file, -HALF_GRAPH_SIZE + Y_LABEL_OFFSET_X, Y_LABEL_OFFSET_Y, ALIGN_RIGHT, "y");
|
||||||
"newpath\n"
|
generate_text_align(file, X_LABEL_OFFSET_X, -HALF_GRAPH_SIZE + X_LABEL_OFFSET_Y, ALIGN_CENTER, "x");
|
||||||
"%d %d moveto\n"
|
}
|
||||||
"%d 0 rlineto\n"
|
|
||||||
"0 %d rlineto\n"
|
static void generate_function(FILE *file, const struct expr_node *node, const struct graph_range *range) {
|
||||||
"%d 0 rlineto\n"
|
int i;
|
||||||
"closepath\n"
|
int first = 1;
|
||||||
"gsave\n"
|
|
||||||
"clip\n",
|
|
||||||
-HALF_GRAPH_SIZE, -HALF_GRAPH_SIZE, GRAPH_SIZE, GRAPH_SIZE, -GRAPH_SIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"2 setlinewidth\n"
|
"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) {
|
for (i = 0; i < FUNCTION_SEGMENTS; ++i) {
|
||||||
const char *cmd = "lineto";
|
const char *cmd = "lineto";
|
||||||
double xpos, ypos;
|
double xpos, ypos;
|
||||||
double y;
|
double x, y;
|
||||||
|
|
||||||
x = range->xmin + (range->xmax - range->xmin) * (double)i / (double)FUNCTION_SEGMENTS;
|
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,
|
fprintf(file,
|
||||||
"stroke\n"
|
"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,
|
fprintf(file,
|
||||||
"grestore\n"
|
"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"
|
"0 0 0 setrgbcolor\n"
|
||||||
"stroke\n"
|
"stroke\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -9,6 +9,6 @@ struct graph_range {
|
|||||||
double ymin, ymax;
|
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
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user