//----------------------------------------------------------------------------- // Velmi jednoduchy prohlizec souboru typu PLT upraveny pro pouziti se soubory // urcenymi pro plotter HP 7475 // // Autor: Pavel Tisnovsky // //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #include <windows.h> #endif #include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <ctype.h> #define WINDOW_TITLE "simple HPGL viewer" // titulek okna #define WINDOW_WIDTH 800 // pocatecni velikost okna #define WINDOW_HEIGHT 600 // typ prikazu typedef enum { PEN_UP, // zvednuti kresliciho pera PEN_DOWN, // spusteni kresliciho pera MOVE_TO, // presun kresliciho pera SELECT_PEN // vyber kresliciho pera ~ vyber barvy } Command; // jeden zaznam ziskany ze souboru HPGL typedef struct Item { Command cmd; // prikaz - (PEN_UP, PEN_DOWN, MOVE_TO, SELECT_PEN) double x; // souradnice double y; int pen; // barva pera struct Item *next; // vazba v linearnim seznamu } Item; double scale=1.0; double xpos=0.0; double ypos=0.0; int redraw=1; Item *p_first; // ukazatele v linearnim seznamu Item *p_last; // informace o okne struct { int width; int height; } window={WINDOW_WIDTH, WINDOW_HEIGHT}; // informace o mysi struct { int status; int xtran0, xtran1, xtran2; int ytran0, ytran1, ytran2; int ztran0, ztran1, ztran2; } mouse={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //----------------------------------------------------------------------------- // Inicializace linearniho seznamu //----------------------------------------------------------------------------- void initItem(void) { p_first=NULL; p_last=NULL; } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addItem(Command cmd, double x, double y, int pen) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=cmd; item->x=x; item->y=y; item->pen=pen; item->next=NULL; // prvek bude umisten na konci seznamu // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek /* Item *p=p_first; while (p->next !=NULL) p=p->next; p->next=item; */ } } //----------------------------------------------------------------------------- // Prescteni HPGL souboru urceneho pro HP7475 //----------------------------------------------------------------------------- int readItems(char *fileName) { FILE *fin=fopen(fileName, "rt"); int c; char s[100]; if (!fin) return 0; // smycka, ve ktere se zanalyzuje cely soubor HPGL do { int i; // nacteni jednoho prikazu (oddelovacem je vetsinou strednik) for (i=0; (c=fgetc(fin))!=';' && c!=EOF; i++) { // tato podminka je nutna pro ovladace, // ktere generuji kod ve stylu 'PUPA10,10' // misto 'PU;PA10,10 if (i==2 && isalpha(c)) { ungetc(c, fin); break; } // prevod znaku na velka pismena (pro jistotu) s[i]=(c>='a' && c<='z') ? c-'a'+'A':c; } s[i]=0; // ukonceni retezce if (!strcmp(s, "PU")) { addItem(PEN_UP, 0, 0, 0); } if (!strcmp(s, "PD")) { addItem(PEN_DOWN, 0, 0, 0); } if (!strncmp(s, "SP", 2)) { // prikaz SP int pen=strtol(s+2, NULL, 10); // = nacteme barvu pera addItem(SELECT_PEN, 0, 0, pen); } if (!strncmp(s, "PA", 2)) { // prikaz PA double x, y; // = musime nacist obe souradnice for (i=0; s[i]!='-' && s[i]!='+' && !isdigit(s[i]); i++) ; x=strtod(s+i, NULL); i++; for (; s[i]!='-' && s[i]!='+' && s[i]!=','; i++) ; i++; y=strtod(s+i, NULL); addItem(MOVE_TO, x, y, 0); } } while (c!=EOF); // cteni az do konce souboru fclose(fin); return 1; } //----------------------------------------------------------------------------- // Prekresleni vektorove kresby //----------------------------------------------------------------------------- void redrawDrawing(double scale, // meritko obrazce double xpos, // posun obrazce double ypos) { Item *item=p_first; double x1=0, y1=0, x2=0, y2=0; // souradnice pro vypocet usecek float r=1.0, g=1.0, b=1.0; // barva kresliciho pera float scale2=mouse.ztran0/100.0+1.0; // zmena meritka zadana mysi Command pen=PEN_DOWN; // posun a zmena meritka kresby glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(xpos, ypos, 0); // posun zadany klavesnici glTranslatef(mouse.xtran0, -mouse.ytran0, 0); // posun zadany mysi // posunuti pocatku (pro zmenu meritka vuci stredu okna // je nutna mala programova uprava) glTranslatef(window.width/2, window.height/2, 0); glScalef(scale, scale, scale); // zmena meritka zadana klavesnici glScalef(scale2, scale2, scale2); // zmena meritka zadana mysi glScalef(0.1, 0.1, 0.1); glTranslatef(-window.width/2, -window.height/2, 0); // projit celym seznamem a aplikovat v nem ulozene prikazy while (item!=NULL) { Command cmd=item->cmd; // nacist prikaz double x=item->x; // nacist souradnice double y=item->y; int pencolor=item->pen; // nacist barvu pera item=item->next; // prechod na dalsi polozku switch (cmd) { case PEN_UP: // zvednuti kresliciho pera pen=PEN_UP; break; case PEN_DOWN: // polozeni kresliciho pera pen=PEN_DOWN; break; case MOVE_TO: // zmena pozice kresliciho pera if (pen==PEN_UP) { // PEN_UP - presun bez kresleni x1=x; y1=y; } else { // PEN_DOWN - kreslime x2=x; y2=y; glColor3f(r, g, b); // nastavit barvu glBegin(GL_LINES); // a vykreslit usecku glVertex2d(x1, y1); glVertex2d(x2, y2); glEnd(); x1=x; // zapamatovat si pozici y1=y; // pro dalsi MOVE_TO } break; case SELECT_PEN: // zmena barvy pera { static float palette[][3]={ // static=alokace 1x za behu {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0, 1.0}, {1.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {0.5, 0.5, 0.5}, }; if (pencolor>=0 && pencolor<=7) { // HP7475 ma osm per r=palette[pencolor][0]; g=palette[pencolor][1]; b=palette[pencolor][2]; } else { // kazdy jiny index=bila barva r=1.0; g=1.0; b=1.0; } } break; default: // ostatni prikazy ignorujeme break; } } } //----------------------------------------------------------------------------- // Funkce volana pro inicializaci vykreslovani //----------------------------------------------------------------------------- void onInit(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // mod ulozeni pixelu glPointSize(1.0f); glLineWidth(1.0f); glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); } //----------------------------------------------------------------------------- // Nastaveni souradneho systemu v zavislosti na velikosti okna //----------------------------------------------------------------------------- void onResize(int w, int h) // argumenty w a h reprezentuji novou velikost okna { glViewport(0, 0, w, h); // viditelna oblast pres cele okno glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) glOrtho(0, w, 0, h, -1, 1); // mapovani abstraktnich souradnic do souradnic okna window.width=w; window.height=h; } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri kazdem prekresleni okna //----------------------------------------------------------------------------- void onDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // vymazani vsech bitovych rovin barvoveho bufferu glDrawBuffer(GL_BACK); // pixmapa se bude kreslit do zadniho barvoveho bufferu redrawDrawing(scale, xpos, ypos); glFlush(); // provedeni a vykresleni vsech zmen glutSwapBuffers(); } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni ASCII klavesy //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #pragma option -w-par #endif void onKeyboard(unsigned char key, int x, int y) { key=(key>='A' && key<='Z') ? key-'A'+'a': key; if (key>='0' && key<='9') { glutPostRedisplay(); } // nastaveni barvove palety switch (key) { case 27: // pokud byla stlacena klavesa ESC, konec programu case 'q': exit(0); break; // totez co klavesa ESC default: break; } } #ifdef __BORLANDC__ #pragma option -w+par #endif //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni non-ASCII klavesy //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #pragma option -w-par #endif void onSpecial(int key, int x, int y) { // posun kresby a zmena meritka switch (key) { case GLUT_KEY_LEFT: xpos-=25; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_RIGHT: xpos+=25; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_UP: ypos+=25; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_DOWN: ypos-=25; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_PAGE_UP: scale*=1.1; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_PAGE_DOWN: scale/=1.1; redraw=1; glutPostRedisplay(); break; default: break; } } #ifdef __BORLANDC__ #pragma option -w+par #endif //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni ci pusteni tlacitka mysi //----------------------------------------------------------------------------- void onMouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: // posun kresby if (state==GLUT_DOWN) { mouse.status=1; mouse.xtran1=x; mouse.ytran1=y; } else { mouse.status=0; mouse.xtran2=mouse.xtran0; mouse.ytran2=mouse.ytran0; } break; case GLUT_RIGHT_BUTTON: // zmena meritka kresby if (state==GLUT_DOWN) { mouse.status=2; mouse.ztran1=y; } else { mouse.status=0; mouse.ztran2=mouse.ztran0; } break; default: break; } } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri posunu kurzoru mysi //----------------------------------------------------------------------------- void onMouseMotion(int x, int y) { switch (mouse.status) { case 1: // posun kresby mouse.xtran0=mouse.xtran2+x-mouse.xtran1; mouse.ytran0=mouse.ytran2+y-mouse.ytran1; glutPostRedisplay(); break; case 2: // zmena meritka kresby mouse.ztran0=mouse.ztran2+y-mouse.ztran1; glutPostRedisplay(); break; default: break; } } //----------------------------------------------------------------------------- // Hlavni funkce konzolove aplikace //----------------------------------------------------------------------------- int main(int argc, char **argv) { glutInit(&argc, argv); // inicializace knihovny GLUT glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow(WINDOW_TITLE); // vytvoreni okna pro kresleni glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);// zmena velikosti okna glutPositionWindow(100, 100); // pozice leveho horniho rohu okna glutDisplayFunc(onDisplay); // registrace funkce volane pri prekreslovani okna glutReshapeFunc(onResize); // registrace funkce volane pri zmene velikosti okna glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stlaceni klavesy glutSpecialFunc(onSpecial); // registrace funkce volane pri stlaceni specialni klavesy glutMouseFunc(onMouse); // funkce volana pri stlaceni tlacitka mysi glutMotionFunc(onMouseMotion); // funkce volana pri posunu mysi onInit(); // inicializace vykreslovani if (!readItems(argv[1])) return 0; // nacteni celeho souboru s kresbou glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce return 0; // navratova hodnota vracena operacnimu systemu } //----------------------------------------------------------------------------- // finito //-----------------------------------------------------------------------------