/* * ***************************************************************** * * * * * Copyright (c) Fast Corporation, 1997 * * * * * * All Rights Reserved. Unpublished rights reserved under * * * the copyright laws of the Japan. * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Fast * * * Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Fast Corporation. * * * * * ***************************************************************** */ /* CSC90X 計算幾何学「最小外接円/最大内接円」サンプル 90xcgcp.c */ /*[作成者]G.Ochiai & A.Sekimori */ /*[概要] 乱数またはトラックボール操作にて作成した点群より計算幾何学によって */ /* 最小外接円及び最大内接円求め、モニタに表示します。 */ /* 目的: 関数: 履歴: Ver 1.0 98/08/11 注記:m_menu.hをインクルードして下さい。 m_menu.c及びm_note.cをリンクして下さい。 */ /* Include compiler runtime library */ #include #include /* 乱数 */ /* Include CSC90X library */ #include "f_stdlib.h" #include "f_time.h" #include "f_gui.h" #include "f_stdio.h" #include "f_graph.h" #include "f_image.h" #include "f_pinf.h" #include "f_video.h" #include "f_system.h" #include "f_cmpgeo.h" #include "f_math.h" #include "f_file.h" /* Include CSC90X common local */ #include "m_menu.h" /* プロトタイプ宣言 */ void main( void ); void main_menu_disp( void ); void disp_help( void ); extern int message_note( void ); static void execute( int ); static void display_result( int, int, char *, WPNT2_T, int ); static int make_points_data( int, WPNT2_T[ ] ); static int make_data_at_random( WPNT2_T[ ] ); static int make_data_by_manual( WPNT2_T[ ] ); /* メニュー項目 */ #define LANG_N 2 #define MAIN_MENU_N 2 static const char *str_main_menu[MAIN_MENU_N][LANG_N] = { { " MANUAL ", " 手動実行 " }, { " RANDOM ", " 乱数実行 " }, }; #define INIT_CUR_POS_X 255 #define INIT_CUR_POS_Y 239 #define MAX_PNT_NUM 2048 /* 点の最大数 */ #define RANDOM_MODE 0 /* 点データを乱数で決める */ #define MANUAL_MODE 1 /* 点データをカーソルで決める */ #define CURSOR_INDEFINITE 0 /* カーソルのどちらのキーも押下されていない */ #define MX 15 /* 処理範囲のX方向マージン */ #define MY 40 /* 処理範囲のY方向マージン */ #define PX 40 /* 点の数表示のx方向位置 */ #define PY 28 /* 点の数表示のy方向位置 */ #define SR 100 /* ランダムな点集合の基準半径 */ #define WR 20 /* ランダムな点集合の基準半径からの幅 */ /* メイン */ void main( void ) { int sts; int xpos; int ypos; int s_xpos; int s_ypos; /* 初期メッセージ表示 */ if( NORMAL_RETURN != message_note() ) return; /* パラメタ初期化 */ xpos = INIT_CUR_POS_X; ypos = INIT_CUR_POS_Y; s_xpos = INIT_CUR_POS_X; s_ypos = INIT_CUR_POS_Y; /* ビデオ出力表示項目制御 */ Lib_display_control( LINE_PLANE | CHAR_PLANE ); /* ビデオ表示項目クリア */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* カーソル初期化 */ Lib_init_cursor(); /* メインメニューの表示 */ main_menu_disp(); /* マウスカーソルの表示 */ Lib_draw_cursor( INIT_CUR_POS_X, INIT_CUR_POS_Y ); /* メニュー制御 */ for (;;) { sts = 0; /* マウス位置読みとり */ sts = Lib_see_current_position( &xpos, &ypos ); if ( s_xpos != xpos || s_ypos != ypos ) { /* マウス表示位置移動 */ Lib_move_cursor( xpos, ypos ); s_xpos = xpos; s_ypos = ypos; } /* 処理振り分け */ if( CURSOR_EXECUTE == sts ) { if ( xpos > MENU_1_XS && xpos < MENU_1_XE && ypos > MENU_1_YS && ypos < MENU_1_YE ) { /*「手動実行」が選択された */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); execute( MANUAL_MODE ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_2_XS && xpos < MENU_2_XE && ypos > MENU_2_YS && ypos < MENU_2_YE ) { /*「乱数実行」が選択された */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); execute( RANDOM_MODE ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_H_XS && xpos < MENU_H_XE && ypos > MENU_H_YS && ypos < MENU_H_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); disp_help(); /* ヘルプ */ main_menu_disp(); } else if ( xpos > MENU_E_XS && xpos < MENU_E_XE && ypos > MENU_E_YS && ypos < MENU_E_YE ) { break; /* 終了 */ } } } } /* メインメニュー表示 */ void main_menu_disp( void ) { int iLanguage; /* 日本語/英語表示文字列切替情報取得 */ iLanguage = Lib_get_disp_language(); /* 整列キー表示 -> ( m_menu.c ) */ SUB_menu_disp4he( (char *)str_main_menu[0][iLanguage], (char *)str_main_menu[1][iLanguage], (char *)NULL, (char *)NULL ); } /* ヘルプ表示 */ void disp_help( void ) { Lib_chrdisp( 4, 8, "【機能\概要】 90XCGCP" ); Lib_chrdisp( 5, 10, "ビジョンツールライブラリ計算幾何学のサンプルソ\フトです。" ); Lib_chrdisp( 5, 12, "乱数またはトラックボール操作にて作成した点群より" ); Lib_chrdisp( 5, 14, "計算幾何学によって最小外接円及び最大内接円求め" ); Lib_chrdisp( 5, 16, "モニタに表\示します。" ); Lib_chrdisp( 5, 18, "【手動実行】トラックボール操作により点群を作成し実行します。" ); Lib_chrdisp( 5, 20, "【乱数実行】乱数により点群を作成し実行します。" ); } /***** 実行 *****/ static void execute( mode ) int mode; { void *encl_crcl; /* 最小包含円識別子 */ WPNT2_T encl_cntr; /* 最小包含円の中心 */ int encl_rds; /* 最小包含円の半径(の2乗) */ void *empty_crcl; /* 最大空円識別子 */ WPNT2_T empty_cntr; /* 最大空円の中心 */ int empty_rds; /* 最大空円の半径(の2乗) */ WPNT2_T *pnts; /* 点データ */ int pnt_num; /* 点データの点数 */ /* メモリの確保 */ if( NULL != ( pnts = ( WPNT2_T * )Lib_mlalloc( sizeof( WPNT2_T )* MAX_PNT_NUM ) ) ) { /* 最小包含円(最小外接円)のオープン */ if( NULL != ( encl_crcl = Lib_cg_encl_crcl_open( MAX_PNT_NUM ) ) ) { /* 最大空円のオープン */ if( NULL != ( empty_crcl = Lib_cg_empty_crcl_open( MAX_PNT_NUM ) ) ) { /* 画面のクリア */ Lib_cls( LINE_PLANE | CHAR_PLANE, BLACK_COLOR ); /* 点集合を決める */ pnt_num = make_points_data( mode, pnts ); /* 処理時間測定開始 */ Lib_strtclk_count( ); /* 最小包含円の試行 */ Lib_cg_encl_crcl_calc( encl_crcl, pnts, pnt_num, &encl_cntr, &encl_rds ); /* 処理時間測定終了・結果表示 */ display_result( 5, 29, "最小包含円", encl_cntr, encl_rds ); /* 処理時間測定開始 */ Lib_strtclk_count( ); /* 最大空円の試行 */ Lib_cg_empty_crcl_calc( empty_crcl, pnts, pnt_num, &empty_cntr, &empty_rds ); /* 処理時間測定終了・結果表示 */ display_result( 5, 30, "最大空円 ", empty_cntr, empty_rds ); Lib_display_keyinput( 460, 0, "確認" ); /* 最大空円のクローズ */ Lib_cg_empty_crcl_close( empty_crcl ); } else { /* オープン失敗 */ Lib_display_message( 80, 200, "エラー", "最大空円のオープンに失敗したため試行できません" ); } /* 最小包含円のクローズ */ Lib_cg_encl_crcl_close( encl_crcl ); } else { /* オープン失敗 */ Lib_display_message( 80, 200, "エラー", "最小包含円のオープンに失敗したため試行できません" ); } /* メモリ解放 */ Lib_lfree( ( char * )pnts ); } else { /* メモリ不足 */ Lib_display_message( 100, 200, "エラー", "メモリ不足のため試行できません" ); } } /***** 処理時間測定終了・結果表示 *****/ static void display_result( x, y, title, cntr, rds ) int x; int y; /* 表示位置(64×30) */ char *title; /* 表示タイトル */ WPNT2_T cntr; /* 回答の円の中心 */ int rds; /* 回答の円の半径(の2乗) */ { int time; /* 処理時間 */ char str[ 64 ]; /* 表示文字列 */ /* 時間測定終了 */ time = Lib_readclk_count( ); time = ( time * 8318 )/ 10000; /* msec に直す */ /* 半径(100倍するのは精度を出来るだけ保つため) */ rds = ( Lib_sqrt32( rds * 10000 ) + 50 )/ 100; /* 表示文字列 */ Lib_sprintf( str, "%s : %5d(ミリ秒), 中心( %3d, %3d ), 半径 %3d", title, time, cntr.x, cntr.y, rds ); /* 表示 */ Lib_chrdisp( x, y, str ); Lib_pset( cntr.x, cntr.y, GRAPH_DRAW ); Lib_drawcircle( cntr.x, cntr.y, 1 ); /* 円の中心 */ Lib_drawcircle( cntr.x, cntr.y, rds ); } /***** 点データを決める *****/ static int make_points_data( mode, pnts ) int mode; WPNT2_T pnts[ ]; /* 点データ */ { int pnt_num; /* データの点の数 */ if( RANDOM_MODE == mode ) /* 点データを乱数で決める場合 */ pnt_num = make_data_at_random( pnts ); else if( MANUAL_MODE == mode ) /* 点データをカーソルで決める場合 */ pnt_num = make_data_by_manual( pnts ); return( pnt_num ); } /***** 点データを乱数を用いて決定する *****/ static int make_data_at_random( data ) WPNT2_T data[ ]; /* 点データ */ { int pnt_num; /* 点の数 */ int cx, cy; /* 点分布の中心 */ int r, theta; int crs_x, crs_y; /* カーソル */ char str[ 64 ]; /* 点の数を表示 */ int i; /* 点分布の中心 */ cx = Lib_get_fx_size( )/ 2; cy = Lib_get_fy_size( )/ 2; /* 点の数を決める */ Lib_chrdisp( 1, 1, " 点の数を決めて下さい " ); pnt_num = Lib_get_value_by_ten_keyboad( 80, 130, MAX_PNT_NUM / 2, 1L, MAX_PNT_NUM ); Lib_chrdisp( 1, 1, " " ); /* カーソル消去 */ Lib_look_current_position( &crs_x, &crs_y ); Lib_erase_cursor( ); for( i = 0 ; i < pnt_num ; i ++ ) { /* 点データの決定 */ r = SR + rand( )%( 2 * WR ) - WR; theta = rand( )% 3600; data[ i ].x = cx + r * Lib_cosfunc( theta )/ 32767; data[ i ].y = cx + r * Lib_sinfunc( theta )/ 32767; /* 点の表示 */ Lib_pset( data[ i ].x, data[ i ].y, GRAPH_DRAW ); } /* 点の数を表示 */ Lib_sprintf( str, "Points Num = %4d", pnt_num ); Lib_chrdisp( PX, PY, str ); /* カーソル復帰 */ Lib_draw_cursor( crs_x, crs_y ); /* 点の数を決める */ return( pnt_num ); } /***** 点データをカーソルで決める *****/ static int make_data_by_manual( data ) WPNT2_T data[ ]; /* 点データ */ { int status; /* カーソルのキー押下状況 */ int pnt_num; /* 点の数 */ char str[ 64 ]; /* 点の数を表示 */ int sx, sy, ex, ey; /* 点の取りうる範囲 */ int ax,ay,bx,by; status = CURSOR_INDEFINITE; /* 点の数の初期化 */ pnt_num = 0; /* 点の取りうる範囲 */ sx = MX; sy = MY; ex = Lib_get_fx_size( ) - MX - 1; ey = Lib_get_fy_size( ) - MY - 1; /* 操作の説明 */ Lib_chrdisp( 1, 1, " 点の登録→実行キー、終了→取消キー " ); /* カーソル位置の初期化 */ ax = ( sx + ex + 1 )/ 2; ay = ( sy + ey + 1 )/ 2; bx = ax; by = ay; for ( ; ; ) { status = Lib_see_current_position( &ax, &ay ); /* カーソルの動きの制限 */ if ( ax < sx ) ax = sx; else if ( ex < ax ) ax = ex; if ( ay < sy ) ay = sy; else if ( ey < ay ) ay = ey; if ( bx != ax || by != ay ) /* カーソルは移動したか? */ { Lib_move_cursor( ax, ay ); bx = ax; /* カーソルの位置情報の更新(X座標)*/ by = ay; /* カーソルの位置情報の更新(Y座標)*/ } if ( CURSOR_EXECUTE == status ) /* 実行キーが押されたら、その時のカーソル位置を点の位置として登録 */ { data[ pnt_num ].x = ax; data[ pnt_num ].y = ay; Lib_pset( data[ pnt_num ].x, data[ pnt_num ].y, GRAPH_DRAW ); pnt_num ++; /* 点の数を表示 */ Lib_sprintf( str, "Points Num = %4d", pnt_num ); Lib_chrdisp( PX, PY, str ); /* 点の数が MAX_PNT_NUM に達したら登録を終了する */ if( MAX_PNT_NUM == pnt_num ) { Lib_display_message( 100, 200, "エラー", "これ以上点を登録することはできません" ); break; } } else if ( CURSOR_CANCEL == status && 0 != pnt_num ) /* 取消キーが押され、点が0個でなければ終了 */ break; } /* 点の数を決める */ return( pnt_num ); }