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