/* bresen-cor.c - Edouard Thiel - 23/05/2001 Compilation : cc bresen-cor.c -o bresen-cor `~/helium/helium-cfg --cflags --libs` Exécution : bresen-cor */ #include He_node *princ, *canvas, *panel1, *panel2, *mess1, *text1, *tog1; int c_gris, c_rouge, c_vert, c_bleu, c_jaune, c_cyan, c_magenta; int gros_point = 6; enum { AFFI_DROITE_X, AFFI_DROITE_Y, AFFI_CERCLE }; int etat_affi = AFFI_DROITE_X; enum { POINT_0, POINT_1, POINT_2 }; int etat_point = POINT_0; int affi_x1, affi_y1, affi_x2, affi_y2; /*--------------------------- A F F I C H A G E ------------------------------*/ void init_couleurs () { c_gris = HeAllocRgb (150, 150, 150, he_white); c_rouge = HeAllocRgb (255, 0, 0, he_black); c_vert = HeAllocRgb (0, 255, 0, he_black); c_bleu = HeAllocRgb (0, 0, 255, he_black); c_jaune = HeAllocRgb (255, 255, 0, he_black); c_cyan = HeAllocRgb (0, 255, 255, he_black); c_magenta = HeAllocRgb (255, 0, 255, he_black); } /* * Dessin d'un gros point */ void dessin_point (Window win, int x, int y, int coul) { XSetForeground (he_display, he_gc, coul); XDrawRectangle (he_display, win, he_gc, x * gros_point, y * gros_point, gros_point, gros_point); } /*-------------------------- A L G O R I T H M E S ---------------------------*/ /* * Trace le Bresenham généralisé en x. * Appelle dessin_point. */ void trace_droite_gen_x (Window win, int x1, int y1, int x2, int y2, int coul) { int x, y, dx, dy, m, inc1, inc2, d; if (x1 == x2) return; if (x1 > x2) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } x = x1; y = y1; dx = x2-x1; dy = y2-y1; m = (dy >= 0) ? dy / dx : dy / dx - 1; inc1 = 2*dy - 2*m*dx; inc2 = 2*dy - 2*(m+1)*dx; d = 2*dy - (2*m+1)*dx; dessin_point (win, x, y, coul); while (x < x2) { x++; if (d < 0) { d += inc1; y += m; } else { d += inc2; y += m+1; } dessin_point (win, x, y, coul); } } /* * Trace le Bresenham généralisé en y. * Appelle dessin_point. */ void trace_droite_gen_y (Window win, int x1, int y1, int x2, int y2, int coul) { int x, y, dx, dy, m, inc1, inc2, d; if (y1 == y2) return; if (y1 > y2) { int t = y1; y1 = y2; y2 = t; t = x1; x1 = x2; x2 = t; } y = y1; x = x1; dy = y2-y1; dx = x2-x1; m = (dx >= 0) ? dx / dy : dx / dy - 1; inc1 = 2*dx - 2*m*dy; inc2 = 2*dx - 2*(m+1)*dy; d = 2*dx - (2*m+1)*dy; dessin_point (win, x, y, coul); while (y < y2) { y++; if (d < 0) { d += inc1; x += m; } else { d += inc2; x += m+1; } dessin_point (win, x, y, coul); } } /* * Trace 8 points symétriques autour de xC,yC. * Appelle dessin_point. */ void dessin_8points (Window win, int xC, int yC, int x, int y, int coul) { dessin_point (win, xC+x, yC+y, coul); dessin_point (win, xC-x, yC+y, coul); dessin_point (win, xC+x, yC-y, coul); dessin_point (win, xC-x, yC-y, coul); dessin_point (win, xC+y, yC+x, coul); dessin_point (win, xC-y, yC+x, coul); dessin_point (win, xC+y, yC-x, coul); dessin_point (win, xC-y, yC-x, coul); } /* * Trace un cercle discret de centre x1,y1 et de rayon R. * Appelle dessin_8points. * * Remarque : par cette méthode les 1er et derniers points sont dessinés * plusieurs fois (quand x = 0 ou y = 0 ou x = +-y). */ void trace_cercle (Window win, int x1, int y1, int R, int coul) { int x = 0, y = R, inc1 = 1, inc2 = 1-2*R, d = 1-R; dessin_8points (win, x1, y1, x, y, coul); while (x < y) { x++; if (d < 0) { d += inc1; inc1 += 2; inc2 += 2; } else { d += inc2; y -= 1; inc1 += 2; inc2 += 4; } dessin_8points (win, x1, y1, x, y, coul); } } /*--------------------------- C A L L B A C K S ------------------------------*/ void canvas_repaint (He_node *hn, Window win) { HeDrawBg (canvas, he_white); switch (etat_point) { case POINT_0 : return; case POINT_1 : dessin_point (win, affi_x1, affi_y1, c_bleu); return; case POINT_2 : dessin_point (win, affi_x1, affi_y1, c_bleu); dessin_point (win, affi_x2, affi_y2, c_bleu); break; } switch (etat_affi) { case AFFI_DROITE_X : { trace_droite_gen_x (win, affi_x1, affi_y1, affi_x2, affi_y2, c_gris); } break; case AFFI_DROITE_Y : { trace_droite_gen_y (win, affi_x1, affi_y1, affi_x2, affi_y2, c_gris); } break; case AFFI_CERCLE : { /* On prend comme rayon R = max(dx,dy) */ int dx = abs (affi_x2 - affi_x1), dy = abs (affi_y2 - affi_y1), R = (dx > dy) ? dx : dy; trace_cercle (win, affi_x1, affi_y1, R, c_gris); } break; } } void canvas_event (He_node *hn, He_event *hev) { switch (hev->type) { case ButtonPress : { char bla[100]; affi_x1 = hev->sx/gros_point; affi_y1 = hev->sy/gros_point; sprintf (bla, "(%d,%d) ..", affi_x1, affi_y1); HeSetMessageLabel (mess1, bla); etat_point = POINT_1; HePostRepaint (canvas); } break; case ButtonRelease : { char bla[100]; affi_x2 = hev->sx/gros_point; affi_y2 = hev->sy/gros_point; sprintf (bla, "(%d,%d) .. (%d,%d)", affi_x1, affi_y1, affi_x2, affi_y2); HeSetMessageLabel (mess1, bla); etat_point = POINT_2; HePostRepaint (canvas); } break; } } void princ_resize (He_node *hn, int width, int height) { /* ajuste largeurs */ HeSetWidth (panel1, width); HeSetWidth (panel2, width); HeSetWidth (canvas, width - 2); /* ajuste hauteurs */ HeSetY (panel2, height - HeGetHeight (panel2)); HeSetHeight (canvas, HeGetY(panel2) - HeGetY(canvas) - 2); } void tog1_proc (He_node *hn) { char *nom = HeGetToggleLabel (hn); if (HeGetToggleValue (hn) == FALSE) return; if (strcmp (nom, "droite en x") == 0) etat_affi = AFFI_DROITE_X; if (strcmp (nom, "droite en y") == 0) etat_affi = AFFI_DROITE_Y; else if (strcmp (nom, "cercle discret") == 0) etat_affi = AFFI_CERCLE; HePostRepaint (canvas); } void text1_proc (He_node *hn) { gros_point = atoi (HeGetTextValue(text1)); HePostRepaint (canvas); } void vide_proc (He_node *hn) { etat_point = POINT_0; HeDrawBg (canvas, he_white); HeSetMessageLabel (mess1, ""); } void quit_proc (He_node *hn) { HeQuit(0); } /*--------------------------------- M A I N ----------------------------------*/ int main (int argc, char **argv) { He_node *tmp1; HeInit (&argc, &argv); init_couleurs (); princ = HeCreateFrame (); HeSetFrameLabel (princ, "Bresenham (cor)"); HeSetFrameResizeProc (princ, princ_resize); panel1 = HeCreatePanel (princ); HeCreateMessageP (panel1, "Taille point :", TRUE); text1 = HeCreateText (panel1); HeSetTextVisibleLen (text1, 5); HeSetTextValue (text1, "6"); HeSetTextNotifyProc (text1, text1_proc); HeCreateButtonP (panel1, "Appliquer", text1_proc, NULL); HeCreateButtonP (panel1, "Vider", vide_proc, NULL); HeCreateButtonP (panel1, "Quit", quit_proc, NULL); HeSetPanelLayout (panel1, HE_LINE_FEED); HeCreateMessageP (panel1, "Afficher :", TRUE); tog1 = HeCreateToggleRadioP (panel1, "droite en x", tog1_proc, NULL); tmp1 = HeCreateToggleRadioP (panel1, "droite en y", tog1_proc, tog1); tmp1 = HeCreateToggleRadioP (panel1, "cercle discret", tog1_proc, tog1); HeFit (panel1); canvas = HeCreateCanvas (princ); HeSetCanvasRepaintProc (canvas, canvas_repaint); HeSetCanvasEventProc (canvas, canvas_event); HeSetY (canvas, HeGetHeight(panel1) + 5); HeSetWidth (canvas, 700); HeSetHeight (canvas, 500); panel2 = HeCreatePanel (princ); HeSetY (panel2, HeGetY(canvas) + HeGetHeight(canvas) + 2); mess1 = HeCreateMessageP (panel2, "Pour tracer : cliquer en un point, tirer la souris puis relacher", FALSE); HeFit (panel2); HeFit (princ); return HeMainLoop (princ); }