MMPAINT.C
[目次 | 関数]
1|/***************************************************************************
2|* 1. <<< ポリゴン塗りつぶし (MMPaint) >>>
3|****************************************************************************/
4|
5|#include <all.h>
6|
7|#ifndef USES_TYPEX
8|#error need TYPEX
9|#endif
10|
11|/*************************************************************************
12|* 2. <<< 初期化する [MMPaint_init()] >>>
13|*【引数】
14|* ・int* mmBuf; 最大最小値を格納するバッファ配列、要素数は height*2
15|*【補足】
16|*・height には、塗りつぶす可能性がある最大の Y座標 + 1 を指定します。
17|* つまり、塗りつぶす Y座標の範囲は 0〜(height-1) になります。
18|*・X 座標の範囲はありません。
19|**************************************************************************/
20|void MMPaint_init( MMPaint* m, int* mmBuf, size_t mmBuf_sizeof,
21| int height )
22|{
23| #ifdef _CHECKER
24| if ( mmBuf_sizeof < sizeof(int) * height * 2 ) error();
25| #endif
26|
27| m->xmin = &mmBuf[0];
28| m->xmax = &mmBuf[height];
29| m->height = height;
30|}
31|
32|
33|/*************************************************************************
34|* 3. <<< ポリゴンの情報をクリアする [MMPaint_clear()] >>>
35|**************************************************************************/
36|void MMPaint_clear( MMPaint* m )
37|{
38| int i;
39|
40| for ( i = 0; i < m->height; i++ ) {
41| m->xmin[i] = INT_MAX;
42| m->xmax[i] = (int)INT_MIN;
43| }
44| m->ymin = INT_MAX;
45| m->ymax = (int)INT_MIN;
46|}
47|
48|
49|/*************************************************************************
50|* 4. <<< ポリゴンの辺を設定する [MMPaint_setBound()] >>>
51|*【機能】
52|*・点(x1,y1)と点(x2,y2)をむすぶ線分をポリゴンの辺の1つに設定します。
53|*【補足】
54|*・各 Y 座標における X 座標の最小値と最大値を次のようにチェックします。
55|*
56|**************************************************************************/
57|void MMPaint_setBound( MMPaint* m, int x1, int y1, int x2, int y2 )
58|{
59| /* Y 座標の有効範囲(0〜height-1)からはみ出たとき、クリッピングする */
60| if ( y1 < 0 ) {
61| if ( y2 < 0 ) return;
62| x1 = (0 - y2) * (x1 - x2) / (y1 - y2) + x2;
63| y1 = 0;
64| }
65| if ( y2 < 0 ) {
66| x2 = (0 - y1) * (x2 - x1) / (y2 - y1) + x1;
67| y2 = 0;
68| }
69| if ( y1 >= m->height ) {
70| if ( y2 >= m->height ) return;
71| x1 = ((m->height - 1) - y2) * (x1 - x2) / (y1 - y2) + x2;
72| y1 = m->height - 1;
73| }
74| if ( y2 >= m->height ) {
75| x2 = ((m->height - 1) - y1) * (x2 - x1) / (y2 - y1) + x1;
76| y2 = m->height - 1;
77| }
78|
79| /* ymin と ymax をチェックする */
80| if ( y1 < m->ymin ) m->ymin = y1;
81| if ( y1 > m->ymax ) m->ymax = y1;
82| if ( y2 < m->ymin ) m->ymin = y2;
83| if ( y2 > m->ymax ) m->ymax = y2;
84|
85| /* xmin, xmax をチェックする */
86| {
87| int x,y,n;
88| int dx, dy;
89| int cup; /* カウンタ */
90| int plus, minus; /* カウンタの増分、減分 */
91| int flag; /* cup による座標の増減, +1 or -1 */
92|
93| /* 90度〜270度(左向き)の場合 */
94| if ( x1 > x2 ) {
95| n = x1; x1 = x2; x2 = n;
96| n = y1; y1 = y2; y2 = n;
97| }
98|
99| /* dx, dy, flag の設定 */
100| dx = x2 - x1;
101| dy = y2 - y1;
102| if ( dy > 0 )
103| flag = +1;
104| else {
105| flag = -1; dy = -dy;
106| }
107|
108| /* 0度〜45度(水平より右下がり)の場合 */
109| /* 0度〜-45度(水平より右上がり)の場合 */
110| if ( dx >= dy ) {
111| plus = 2 * dy; /* plus = 2dy */
112| cup = plus - dx; /* (dy % dx) * 2 */
113| minus = cup - dx; /* minus = -2dx */
114|
115| if ( x1 < m->xmin[y1] ) m->xmin[y1] = x1; /* 点 */
116| y = y1;
117| for ( x = x1 + 1; x <= x2; x++ ) {
118| if ( cup > 0 ) {
119| if ( x-1 > m->xmax[y] ) m->xmax[y] = x-1; /* 点 */
120| y += flag;
121| if ( x < m->xmin[y] ) m->xmin[y] = x; /* 点 */
122| cup += minus;
123| }
124| else
125| cup += plus;
126| }
127| x--;
128| if ( x > m->xmax[y] ) m->xmax[y] = x; /* 点 */
129| }
130|
131| /* 45度〜90度(垂直より右下がり)の場合 */
132| /* -45度〜-90度(垂直より右上がり)の場合 */
133| else {
134| if ( flag < 0 ) {
135| n = x1; x1 = x2; x2 = n;
136| n = y1; y1 = y2; y2 = n;
137| }
138| plus = 2 * dx;
139| cup = plus - dy;
140| minus = cup - dy;
141|
142| if ( x1 < m->xmin[y1] ) m->xmin[y1] = x1; /* 点 */
143| if ( x1 > m->xmax[y1] ) m->xmax[y1] = x1; /* 点 */
144| x = x1;
145| for ( y = y1 + 1; y <= y2; y ++ ) {
146| if ( cup > 0 )
147| { x += flag; cup += minus; }
148| else
149| cup += plus;
150|
151| if ( x < m->xmin[y] ) m->xmin[y] = x; /* 点 */
152| if ( x > m->xmax[y] ) m->xmax[y] = x; /* 点 */
153| }
154| }
155| }
156|}
157|
158|