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