1 /* 2 Code for drawing color interpolated triangles using X-windows. 3 */ 4 #include <../src/sys/classes/draw/impls/x/ximpl.h> 5 6 PETSC_INTERN PetscErrorCode PetscDrawInterpolatedTriangle_X(PetscDraw_X *, int, int, int, int, int, int, int, int, int); 7 8 #define SHIFT_VAL 6 9 10 PetscErrorCode PetscDrawInterpolatedTriangle_X(PetscDraw_X *win, int x1, int y_1, int t1, int x2, int y2, int t2, int x3, int y3, int t3) 11 { 12 PetscReal rfrac, lfrac; 13 PetscReal R_y2_y_1, R_y3_y_1, R_y3_y2; 14 int lc, rc = 0, lx, rx = 0, xx, y, c; 15 int rc_lc, rx_lx, t2_t1, x2_x1, t3_t1, x3_x1, t3_t2, x3_x2; 16 17 PetscFunctionBegin; 18 /* 19 Is triangle even visible in window? 20 */ 21 if (x1 < 0 && x2 < 0 && x3 < 0) PetscFunctionReturn(PETSC_SUCCESS); 22 if (y_1 < 0 && y2 < 0 && y3 < 0) PetscFunctionReturn(PETSC_SUCCESS); 23 if (x1 > win->w && x2 > win->w && x3 > win->w) PetscFunctionReturn(PETSC_SUCCESS); 24 if (y_1 > win->h && y2 > win->h && y3 > win->h) PetscFunctionReturn(PETSC_SUCCESS); 25 26 t1 = t1 << SHIFT_VAL; 27 t2 = t2 << SHIFT_VAL; 28 t3 = t3 << SHIFT_VAL; 29 30 /* Sort the vertices */ 31 #define SWAP(a, b) \ 32 do { \ 33 int _a; \ 34 _a = a; \ 35 a = b; \ 36 b = _a; \ 37 } while (0) 38 if (y_1 > y2) { 39 SWAP(y_1, y2); 40 SWAP(t1, t2); 41 SWAP(x1, x2); 42 } 43 if (y_1 > y3) { 44 SWAP(y_1, y3); 45 SWAP(t1, t3); 46 SWAP(x1, x3); 47 } 48 if (y2 > y3) { 49 SWAP(y2, y3); 50 SWAP(t2, t3); 51 SWAP(x2, x3); 52 } 53 /* This code is decidedly non-optimal; it is intended to be a start at 54 an implementation */ 55 56 if (y2 != y_1) R_y2_y_1 = 1.0 / ((double)(y2 - y_1)); 57 else R_y2_y_1 = 0.0; 58 if (y3 != y_1) R_y3_y_1 = 1.0 / ((double)(y3 - y_1)); 59 else R_y3_y_1 = 0.0; 60 t2_t1 = t2 - t1; 61 x2_x1 = x2 - x1; 62 t3_t1 = t3 - t1; 63 x3_x1 = x3 - x1; 64 for (y = y_1; y <= y2; y++) { 65 /* PetscDraw a line with the correct color from t1-t2 to t1-t3 */ 66 /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */ 67 lfrac = ((double)(y - y_1)) * R_y2_y_1; 68 lc = (int)(lfrac * (t2_t1) + t1); 69 lx = (int)(lfrac * (x2_x1) + x1); 70 /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */ 71 rfrac = ((double)(y - y_1)) * R_y3_y_1; 72 rc = (int)(rfrac * (t3_t1) + t1); 73 rx = (int)(rfrac * (x3_x1) + x1); 74 /* PetscDraw the line */ 75 rc_lc = rc - lc; 76 rx_lx = rx - lx; 77 if (rx > lx) { 78 for (xx = lx; xx <= rx; xx++) { 79 c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL; 80 PetscDrawXiSetColor(win, c); 81 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, xx, y); 82 } 83 } else if (rx < lx) { 84 for (xx = lx; xx >= rx; xx--) { 85 c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL; 86 PetscDrawXiSetColor(win, c); 87 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, xx, y); 88 } 89 } else { 90 c = lc >> SHIFT_VAL; 91 PetscDrawXiSetColor(win, c); 92 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, lx, y); 93 } 94 } 95 96 /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2. 97 We take advantage of the previous iteration. */ 98 if (y2 >= y3) PetscFunctionReturn(PETSC_SUCCESS); 99 if (y_1 < y2) { 100 t1 = rc; 101 y_1 = y2; 102 x1 = rx; 103 104 t3_t1 = t3 - t1; 105 x3_x1 = x3 - x1; 106 } 107 t3_t2 = t3 - t2; 108 x3_x2 = x3 - x2; 109 if (y3 != y2) R_y3_y2 = 1.0 / ((double)(y3 - y2)); 110 else R_y3_y2 = 0.0; 111 if (y3 != y_1) R_y3_y_1 = 1.0 / ((double)(y3 - y_1)); 112 else R_y3_y_1 = 0.0; 113 114 for (y = y2; y <= y3; y++) { 115 /* PetscDraw a line with the correct color from t2-t3 to t1-t3 */ 116 /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */ 117 lfrac = ((double)(y - y2)) * R_y3_y2; 118 lc = (int)(lfrac * (t3_t2) + t2); 119 lx = (int)(lfrac * (x3_x2) + x2); 120 /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */ 121 rfrac = ((double)(y - y_1)) * R_y3_y_1; 122 rc = (int)(rfrac * (t3_t1) + t1); 123 rx = (int)(rfrac * (x3_x1) + x1); 124 /* PetscDraw the line */ 125 rc_lc = rc - lc; 126 rx_lx = rx - lx; 127 if (rx > lx) { 128 for (xx = lx; xx <= rx; xx++) { 129 c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL; 130 PetscDrawXiSetColor(win, c); 131 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, xx, y); 132 } 133 } else if (rx < lx) { 134 for (xx = lx; xx >= rx; xx--) { 135 c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL; 136 PetscDrawXiSetColor(win, c); 137 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, xx, y); 138 } 139 } else { 140 c = lc >> SHIFT_VAL; 141 PetscDrawXiSetColor(win, c); 142 XDrawPoint(win->disp, PetscDrawXiDrawable(win), win->gc.set, lx, y); 143 } 144 } 145 PetscFunctionReturn(PETSC_SUCCESS); 146 } 147