xref: /petsc/src/sys/classes/draw/impls/x/xtone.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
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