[幾何計算]


関数

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;
}
処理結果例:
fie_cg_encl_crcl_calc.png

処理結果画像

INT FVALGAPI fnFIE_cg_enclosing_circle_calc_d ( const DPNT_T pnts,
INT  num,
DPNT_T center,
DOUBLE *  radius2 
)

最小外接円(最小包含円)の計算(浮動小数点型)

与えられた点集合の最小包含円を計算します。 アルゴリズムとして、考慮対象とする点をその凸包の頂点に限定することにより、 処理速度の大幅な向上を図っています。

fie_cg_encl_crcl_calc.png

与えられる入力点群は、「順序データ」である必要もありませんし、重複点があっても構いません。 もし、すべてが同一点であった場合は、半径 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 不正なパラメータが渡された
  • 点群によって生成された凸包の頂点が3点未満
  • ヌルポインタが渡された
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;
}
処理結果例:
fie_cg_empty_crcl_calc.png

処理結果画像


Documentation copyright © 2009-2024 FAST Corporation.
Generated on Fri Aug 9 16:38:47 2024 for FIEライブラリ by doxygen 1.5.6-FASTSP-p2