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
PetscDrawInterpolatedTriangle_X(PetscDraw_X * win,int x1,int y_1,int t1,int x2,int y2,int t2,int x3,int y3,int t3)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 / ((PetscReal)(y2 - y_1));
57 else R_y2_y_1 = 0.0;
58 if (y3 != y_1) R_y3_y_1 = 1.0 / ((PetscReal)(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 = ((PetscReal)(y - y_1)) * R_y2_y_1;
68 lc = (int)(lfrac * ((PetscReal)t2_t1) + (PetscReal)t1);
69 lx = (int)(lfrac * ((PetscReal)x2_x1) + (PetscReal)x1);
70 /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
71 rfrac = ((PetscReal)(y - y_1)) * R_y3_y_1;
72 rc = (int)(rfrac * ((PetscReal)t3_t1) + (PetscReal)t1);
73 rx = (int)(rfrac * ((PetscReal)x3_x1) + (PetscReal)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 / ((PetscReal)(y3 - y2));
110 else R_y3_y2 = 0.0;
111 if (y3 != y_1) R_y3_y_1 = 1.0 / ((PetscReal)(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 = ((PetscReal)(y - y2)) * R_y3_y2;
118 lc = (int)(lfrac * ((PetscReal)t3_t2) + (PetscReal)t2);
119 lx = (int)(lfrac * ((PetscReal)x3_x2) + (PetscReal)x2);
120 /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
121 rfrac = ((PetscReal)(y - y_1)) * R_y3_y_1;
122 rc = (int)(rfrac * ((PetscReal)t3_t1) + (PetscReal)t1);
123 rx = (int)(rfrac * ((PetscReal)x3_x1) + (PetscReal)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