/* * Sample answer * Author: Programming C teaching group * Date: 2022/09/10 */ #include #include #include /* マクロ定義 */ #define N 256 /* 画像サイズ */ #define RD 64 /* 円盤の半径 */ #define BLACK '1' #define WHITE '0' /* 構造体宣言 */ typedef struct{ int x; int y; }XYdata; /* 関数のプロトタイプ宣言 */ void init(void); void rev(XYdata); void circle(XYdata); void imgout(void); void hline(int, int, int); /* 画像の各ドットを表す外部変数の定義 */ char data[N][N]; int main(int argc, char *argv[]){ XYdata cent; int ncent, i; /* コマンドラインから円の中心座標を何組か入力される */ if(argc < 3 || argc % 2 != 1){ printf("引数の数が違います\n"); exit(0); } /* 入力された中心座標が何組あるか計算 */ ncent = (argc - 1) / 2; /* 画像初期化関数(すべて白くする)をよぶ */ init(); /* 座標の組の数だけ繰り返す */ for(i = 0; i < ncent; i++){ cent.x = atoi(argv[1 + i * 2]); cent.y = atoi(argv[2 + i * 2]); circle(cent); /* 円の内部を白黒反転する */ } /* 表示 */ imgout(); return 0; } /* すべての点を白に初期化する関数 */ void init(void){ int i, j; for(i = 0; i < N; i++){ for(j = 0; j < N; j++){ data[i][j] = WHITE; } } } /* 引数で指示された座標の点一つを白黒反転する関数 */ void rev(XYdata p){ if(data[p.y][p.x] == BLACK){ data[p.y][p.x] = WHITE; } else{ data[p.y][p.x] = BLACK; } } /* 引数で指示された座標を中心に,半径 RD 以内の点を白黒反転する関数 */ void circle(XYdata c){ int i, j, xs, xe, y1, y2, dx, dy; /* * 円の方程式 x^2 + y^2 = r^2 より, * dy が 0~rの位置の円周の座標を求め, * その座標間に線を引く */ for(dy = 0; dy <= RD; dy++){ dx = sqrt(RD * RD - dy * dy); xs = c.x - dx; xe = c.x + dx; y1 = c.y + dy; y2 = c.y - dy; hline(xs, xe, y1); if(dy != 0) hline(xs, xe, y2); /* dy=0のとき、線を2回描かない */ } } /* Plain PBM形式で画像データを出力する関数 */ void imgout(void){ int i, j; printf("P1\n"); printf("%d %d\n", N, N); for(i = 0; i < N; i++){ for(j = 0; j < N; j++){ printf("%c ", data[i][j]); } printf("\n"); } } /* (x1, y)〜(x2, y)の走査線(水平線)を引く(領域外の補正も行う) */ void hline(int x1, int x2, int y){ int i; XYdata p; if(y < 0 || y >= N) return; /* yが領域外のため即return */ p.y = y; if(x1 < 0) x1 = 0; if(x2 >= N) x2 = N - 1; /* 以下、走査線を走らせる */ for(i = x1; i <= x2; i++){ p.x = i; rev(p); } }