関数 | |
INT FVALGAPI | fnFIE_cg_enclosing_circle_calc (const PNT_T *pnts, INT num, PNT_T *center, INT *radius2) |
最小外接円の計算 | |
INT FVALGAPI | fnFIE_cg_enclosing_circle_calc_d (const DPNT_T *pnts, INT num, DPNT_T *center, DOUBLE *radius2) |
最小外接円(最小包含円)の計算(浮動小数点型) | |
INT FVALGAPI | fnFIE_cg_empty_circle_calc (const PNT_T *pnts, INT num, PNT_T *center, INT *radius2) |
最大空円(最大内接円)の計算 |
INT FVALGAPI fnFIE_cg_enclosing_circle_calc | ( | const PNT_T * | pnts, | |
INT | num, | |||
PNT_T * | center, | |||
INT * | radius2 | |||
) |
最小外接円の計算
与えられた点集合の最小外接円(最小包含円)を計算します。 アルゴリズムとして、考慮対象とする点をその凸包の頂点に限定することにより、 処理速度の大幅な向上を図っています。
与えられる入力点群は,「順序データ」である必要もありませんし、重複点があっても構いません。 ただし、異なる点が2点以上あることが必要です。
厳密な回答は中心座標、半径とも整数の値であるとは限りませんが、処理時間を考慮して、整数値による近似解としました。 よって計算誤差を若干含みます。 なお、radius2 の半径は2乗値であるので注意してください。
pnts の要素数は2点以上の値を入力してください。
また、[-1024, 1024] または、 [0, 2048]の座標範囲の taPnt を入力してください。 範囲外の値を入力した場合、オーバーフローのため正しい値を得られない場合があります。
[in] | pnts | 点群 |
[in] | num | 点の数( pnts の要素数) |
[out] | center | 外接円中心 |
[out] | radius2 | 外接円半径の2乗 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
// エラー処理は省略しているので注意して下さい。 #include "fie.h" #include <math.h> //出力画像の幅と高さ及び,入力点数 #define WIDTH 206 #define HEIGHT 204 #define PNTS_NUM 20 VOID cg_enclosing_circle_calc() { //変数宣言部 INT i; //ループ変数 //最小外接円の計算用変数 PNT_T pnts[PNTS_NUM]; //点群 INT pnts_num = PNTS_NUM; //点の数( pnts の要素数) PNT_T icenter; //外接円中心 INT radius2; //外接円半径の2乗 //描画用変数 DOUBLE val=0; //描画用矩形,線分,円の濃度値 DOUBLE radius; //外接円の半径 DPNT_T dcenter; //外接円の中心 DPNT_T dpnts[PNTS_NUM]; //点群 DPNT_T center_start; //円の中心を描画する線分の始点1 DPNT_T center_end; //円の中心を描画する線分の終点1 DPNT_T center_start2; //円の中心を描画する線分の始点2 DPNT_T center_end2; //円の中心を描画する線分の終点2 FHANDLE hdst = NULL; //結果画像 //チャイルド画像 FHANDLE hrgb_r = NULL; FHANDLE hrgb_g = NULL; FHANDLE hrgb_b = NULL; //処理部 //出力画像の領域を確保します hdst = fnFIE_img_root_alloc( F_IMG_UC8, 3, WIDTH, HEIGHT ); //チャイルド画像の領域を確保 hrgb_r = fnFIE_img_child_alloc_single_ch(hdst, 0, 0, 0, WIDTH, HEIGHT); hrgb_g = fnFIE_img_child_alloc_single_ch(hdst, 1, 0, 0, WIDTH, HEIGHT); hrgb_b = fnFIE_img_child_alloc_single_ch(hdst, 2, 0, 0, WIDTH, HEIGHT); //出力画像を白色(255)で塗りつぶす fnFIE_img_clear(hdst, 255); //入力点群 pnts[0].x=50,pnts[0].y=60; pnts[1].x=15,pnts[1].y=96; pnts[2].x=35,pnts[2].y=52; pnts[3].x=22,pnts[3].y=106; pnts[4].x=55,pnts[4].y=116; pnts[5].x=65,pnts[5].y=126; pnts[6].x=101,pnts[6].y=168; pnts[7].x=19,pnts[7].y=65; pnts[8].x=66,pnts[8].y=55; pnts[9].x=182,pnts[9].y=98; pnts[10].x=152,pnts[10].y=78; pnts[11].x=36,pnts[11].y=124; pnts[12].x=45,pnts[12].y=156; pnts[13].x=150,pnts[13].y=180; pnts[14].x=147,pnts[14].y=100; pnts[15].x=170,pnts[15].y=170; pnts[16].x=132,pnts[16].y=78; pnts[17].x=111,pnts[17].y=50; pnts[18].x=111,pnts[18].y=5; pnts[19].x=44,pnts[19].y=84; //入力点の描画 for(i=0; i<pnts_num; i++) { //PNT_TからDPNT_Tへ変換 dpnts[i].x = pnts[i].x; dpnts[i].y = pnts[i].y; //入力点を半径2の円で描画する fnFIE_draw_circle(hrgb_r, &val, F_DRAW_FILL_IN, dpnts[i], 2); fnFIE_draw_circle(hrgb_g, &val, F_DRAW_FILL_IN, dpnts[i], 2); fnFIE_draw_circle(hrgb_b, &val, F_DRAW_FILL_IN, dpnts[i], 2); } //最小外接円の計算 fnFIE_cg_enclosing_circle_calc(pnts, pnts_num, &icenter, &radius2); //パラメータの型を描画関数用に変換 radius=sqrt((DOUBLE)radius2); //半径の2乗->半径 dcenter.x = icenter.x; //PNT_TからDPNT_Tへ変換 dcenter.y = icenter.y; //PNT_TからDPNT_Tへ変換 //中心点の描画(2つの線分を用いて×印を描画する) //線分1 center_start.x = dcenter.x-5; //始点X座標 center_start.y = dcenter.y-5; //始点Y座標 center_end.x = dcenter.x+5; //終点X座標 center_end.y = dcenter.y+5; //終点Y座標 fnFIE_draw_line_seg(hrgb_g, &val, center_start, center_end); //描画 fnFIE_draw_line_seg(hrgb_b, &val, center_start, center_end); //描画 //線分2 center_start2.x = dcenter.x+5; //始点X座標 center_start2.y = dcenter.y-5; //始点Y座標 center_end2.x = dcenter.x-5; //終点X座標 center_end2.y = dcenter.y+5; //終点Y座標 fnFIE_draw_line_seg(hrgb_g, &val, center_start2, center_end2); //描画 fnFIE_draw_line_seg(hrgb_b, &val, center_start2, center_end2); //描画 //最小外接円の描画 fnFIE_draw_circle(hrgb_g, &val, F_DRAW_LINE, dcenter, radius); fnFIE_draw_circle(hrgb_b, &val, F_DRAW_LINE, dcenter, radius); //結果画像を保存します fnFIE_save_png("result.png", hdst, -1); //画像領域の解放 fnFIE_free_object( hdst ); fnFIE_free_object( hrgb_r ); fnFIE_free_object( hrgb_g ); fnFIE_free_object( hrgb_b ); } INT main(VOID) { // FIEライブラリの使用前に必ずコールする必要があります。 fnFIE_setup(); cg_enclosing_circle_calc(); // 終了処理 fnFIE_teardown(); return 0; }
![]() 処理結果画像 |
INT FVALGAPI fnFIE_cg_enclosing_circle_calc_d | ( | const DPNT_T * | pnts, | |
INT | num, | |||
DPNT_T * | center, | |||
DOUBLE * | radius2 | |||
) |
最小外接円(最小包含円)の計算(浮動小数点型)
与えられた点集合の最小包含円を計算します。 アルゴリズムとして、考慮対象とする点をその凸包の頂点に限定することにより、 処理速度の大幅な向上を図っています。
与えられる入力点群は、「順序データ」である必要もありませんし、重複点があっても構いません。 もし、すべてが同一点であった場合は、半径 radius2 = 0 で返ります。
pnts の要素数は2点以上の値を入力してください。
また、出力する半径 radius2 は2乗値であるので注意してください。
[in] | pnts | 点群 |
[in] | num | 点の数( pnts の要素数) |
[out] | center | 包含円中心 |
[out] | radius2 | 包含円半径の2乗 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_cg_empty_circle_calc | ( | const PNT_T * | pnts, | |
INT | num, | |||
PNT_T * | center, | |||
INT * | radius2 | |||
) |
最大空円(最大内接円)の計算
与えられた点集合の最大空円(最大内接円)を計算します。 ただし、その中心は点集合の凸包の内部にあるものとします。
与えられる入力点群に制限はありません。 つまり、「順序データ」である必要もありませんし、重複点があっても構いません。 厳密な回答は中心座標、半径とも整数の値であるとは限りませんが、処理時間を考えて、整数値による近似解としました。 よって計算誤差を若干含みます。 なお、radius2 の半径は2乗値であるので注意してください。
また、pnts の要素数は3点以上の値を入力してください。
[in] | pnts | 点群 |
[in] | num | 点の数( pnts の要素数) |
[out] | center | 外接円中心 |
[out] | radius2 | 外接円半径の2乗 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_CALC_IMPOSSIBLE | 計算不能
| |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
// エラー処理は省略しているので注意して下さい。 #include "fie.h" #include <math.h> //出力画像の幅と高さ及び,入力点数 #define WIDTH 206 #define HEIGHT 204 #define PNTS_NUM 20 VOID cg_empty_circle_calc() { //変数宣言部 INT i; //ループ変数 //最大空円(最大内接円)計算用変数 PNT_T pnts[PNTS_NUM]; //点群 INT pnts_num = PNTS_NUM; //点の数( pnts の要素数) PNT_T icenter; //外接円中心 INT radius2; //外接円半径の2乗 //描画用変数 DOUBLE val=0; //描画用矩形,線分,円の濃度値 DOUBLE radius; //外接円の半径 DPNT_T dcenter; //外接円の中心 DPNT_T dpnts[PNTS_NUM]; //点群 DPNT_T center_start; //円の中心を描画する線分の始点1 DPNT_T center_end; //円の中心を描画する線分の終点1 DPNT_T center_start2; //円の中心を描画する線分の始点2 DPNT_T center_end2; //円の中心を描画する線分の終点2 //結果画像 FHANDLE hdst = NULL; //チャイルド画像 FHANDLE hrgb_r = NULL; FHANDLE hrgb_g = NULL; FHANDLE hrgb_b = NULL; //処理部 //出力画像の領域を確保します hdst = fnFIE_img_root_alloc( F_IMG_UC8, 3, WIDTH, HEIGHT ); //チャイルド画像の領域を確保 hrgb_r = fnFIE_img_child_alloc_single_ch(hdst, 0, 0, 0, WIDTH, HEIGHT); hrgb_g = fnFIE_img_child_alloc_single_ch(hdst, 1, 0, 0, WIDTH, HEIGHT); hrgb_b = fnFIE_img_child_alloc_single_ch(hdst, 2, 0, 0, WIDTH, HEIGHT); //出力画像を白色(255)で塗りつぶす fnFIE_img_clear(hdst, 255); //入力点群 pnts[0].x=50,pnts[0].y=60; pnts[1].x=15,pnts[1].y=96; pnts[2].x=35,pnts[2].y=52; pnts[3].x=22,pnts[3].y=106; pnts[4].x=55,pnts[4].y=116; pnts[5].x=65,pnts[5].y=126; pnts[6].x=101,pnts[6].y=168; pnts[7].x=19,pnts[7].y=65; pnts[8].x=66,pnts[8].y=55; pnts[9].x=182,pnts[9].y=98; pnts[10].x=152,pnts[10].y=78; pnts[11].x=36,pnts[11].y=124; pnts[12].x=45,pnts[12].y=156; pnts[13].x=150,pnts[13].y=180; pnts[14].x=147,pnts[14].y=100; pnts[15].x=170,pnts[15].y=170; pnts[16].x=132,pnts[16].y=78; pnts[17].x=111,pnts[17].y=50; pnts[18].x=111,pnts[18].y=5; pnts[19].x=44,pnts[19].y=84; //入力点の描画 for(i=0; i<pnts_num; i++) { //PNT_TからDPNT_Tへ変換 dpnts[i].x = pnts[i].x; dpnts[i].y = pnts[i].y; //入力点を半径2の円で描画する fnFIE_draw_circle(hrgb_r, &val, F_DRAW_FILL_IN, dpnts[i], 2); fnFIE_draw_circle(hrgb_g, &val, F_DRAW_FILL_IN, dpnts[i], 2); fnFIE_draw_circle(hrgb_b, &val, F_DRAW_FILL_IN, dpnts[i], 2); } //最大空円(最大内接円)の計算 fnFIE_cg_empty_circle_calc(pnts, pnts_num, &icenter, &radius2); //パラメータの型を描画関数用に変換 radius=sqrt((DOUBLE)radius2); //半径の2乗->半径 dcenter.x = icenter.x; //PNT_TからDPNT_Tへ変換 dcenter.y = icenter.y; //PNT_TからDPNT_Tへ変換 //中心点の描画(2つの線分を用いて×印を描画する) //線分1 center_start.x = dcenter.x-5; //始点X座標 center_start.y = dcenter.y-5; //始点Y座標 center_end.x = dcenter.x+5; //終点X座標 center_end.y = dcenter.y+5; //終点Y座標 fnFIE_draw_line_seg(hrgb_g, &val, center_start, center_end); //描画 fnFIE_draw_line_seg(hrgb_b, &val, center_start, center_end); //描画 //線分2 center_start2.x = dcenter.x+5; //始点X座標 center_start2.y = dcenter.y-5; //始点Y座標 center_end2.x = dcenter.x-5; //終点X座標 center_end2.y = dcenter.y+5; //終点Y座標 fnFIE_draw_line_seg(hrgb_g, &val, center_start2, center_end2); //描画 fnFIE_draw_line_seg(hrgb_b, &val, center_start2, center_end2); //描画 //最大空円(最大内接円)の描画 fnFIE_draw_circle(hrgb_g, &val, F_DRAW_LINE, dcenter, radius); fnFIE_draw_circle(hrgb_b, &val, F_DRAW_LINE, dcenter, radius); //結果画像を保存します fnFIE_save_png("result.png", hdst, -1); //画像領域の解放 fnFIE_free_object( hdst ); fnFIE_free_object( hrgb_r ); fnFIE_free_object( hrgb_g ); fnFIE_free_object( hrgb_b ); } INT main(VOID) { // FIEライブラリの使用前に必ずコールする必要があります。 fnFIE_setup(); cg_empty_circle_calc(); // 終了処理 fnFIE_teardown(); return 0; }
![]() 処理結果画像 |