xref: /petsc/src/sys/classes/draw/impls/x/xtone.c (revision c90b701ee8da86c6fb76d5aea9fecd2a44e0e5b8)
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) {int _a; _a=a; a=b; b=_a;}
33   if (y_1 > y2) {
34     SWAP(y_1,y2);SWAP(t1,t2); SWAP(x1,x2);
35   }
36   if (y_1 > y3) {
37     SWAP(y_1,y3);SWAP(t1,t3); SWAP(x1,x3);
38   }
39   if (y2 > y3) {
40     SWAP(y2,y3);SWAP(t2,t3); SWAP(x2,x3);
41   }
42   /* This code is decidely non-optimal; it is intended to be a start at
43    an implementation */
44 
45   if (y2 != y_1) R_y2_y_1 = 1.0/((double)(y2-y_1));
46   else R_y2_y_1 = 0.0;
47   if (y3 != y_1) R_y3_y_1 = 1.0/((double)(y3-y_1));
48   else R_y3_y_1 = 0.0;
49   t2_t1 = t2 - t1;
50   x2_x1 = x2 - x1;
51   t3_t1 = t3 - t1;
52   x3_x1 = x3 - x1;
53   for (y=y_1; y<=y2; y++) {
54     /* PetscDraw a line with the correct color from t1-t2 to t1-t3 */
55     /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */
56     lfrac = ((double)(y-y_1)) * R_y2_y_1;
57     lc    = (int)(lfrac * (t2_t1) + t1);
58     lx    = (int)(lfrac * (x2_x1) + x1);
59     /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
60     rfrac = ((double)(y - y_1)) * R_y3_y_1;
61     rc    = (int)(rfrac * (t3_t1) + t1);
62     rx    = (int)(rfrac * (x3_x1) + x1);
63     /* PetscDraw the line */
64     rc_lc = rc - lc;
65     rx_lx = rx - lx;
66     if (rx > lx) {
67       for (xx=lx; xx<=rx; xx++) {
68         c = (((xx-lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
69         PetscDrawXiSetColor(win,c);
70         XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,xx,y);
71       }
72     } else if (rx < lx) {
73       for (xx=lx; xx>=rx; xx--) {
74         c = (((xx-lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
75         PetscDrawXiSetColor(win,c);
76         XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,xx,y);
77       }
78     } else {
79       c = lc >> SHIFT_VAL;
80       PetscDrawXiSetColor(win,c);
81       XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,lx,y);
82     }
83   }
84 
85   /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2.
86      We take advantage of the previous iteration. */
87   if (y2 >= y3) PetscFunctionReturn(0);
88   if (y_1 < y2) {
89     t1  = rc;
90     y_1 = y2;
91     x1  = rx;
92 
93     t3_t1 = t3 - t1;
94     x3_x1 = x3 - x1;
95   }
96   t3_t2 = t3 - t2;
97   x3_x2 = x3 - x2;
98   if (y3 != y2) R_y3_y2 = 1.0/((double)(y3-y2));
99   else R_y3_y2 = 0.0;
100   if (y3 != y_1) R_y3_y_1 = 1.0/((double)(y3-y_1));
101   else R_y3_y_1 = 0.0;
102 
103   for (y=y2; y<=y3; y++) {
104     /* PetscDraw a line with the correct color from t2-t3 to t1-t3 */
105     /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */
106     lfrac = ((double)(y-y2)) * R_y3_y2;
107     lc    = (int)(lfrac * (t3_t2) + t2);
108     lx    = (int)(lfrac * (x3_x2) + x2);
109     /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
110     rfrac = ((double)(y - y_1)) * R_y3_y_1;
111     rc    = (int)(rfrac * (t3_t1) + t1);
112     rx    = (int)(rfrac * (x3_x1) + x1);
113     /* PetscDraw the line */
114     rc_lc = rc - lc;
115     rx_lx = rx - lx;
116     if (rx > lx) {
117       for (xx=lx; xx<=rx; xx++) {
118         c = (((xx-lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
119         PetscDrawXiSetColor(win,c);
120         XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,xx,y);
121       }
122     } else if (rx < lx) {
123       for (xx=lx; xx>=rx; xx--) {
124         c = (((xx-lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
125         PetscDrawXiSetColor(win,c);
126         XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,xx,y);
127       }
128     } else {
129       c = lc >> SHIFT_VAL;
130       PetscDrawXiSetColor(win,c);
131       XDrawPoint(win->disp,PetscDrawXiDrawable(win),win->gc.set,lx,y);
132     }
133   }
134   PetscFunctionReturn(0);
135 }
136