/* * ***************************************************************** * * * * * 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 ボロノイ図・ルーチン vrni.c */ /*[作成者]Y.Hori */ /* 目的:ボロノイ図の作成 関数: 履歴: Ver 1.0 99/07/02 注記: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 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 int cursor( WPNT2_T i_data[] ); static void exec( void ); static int random( WPNT2_T point[], int seed ); static void set( void ); static void draw_point( int x, int y ); static int restricted_cursor( WPNT2_T *pnt ); static void prdm_srtpt( int timing, int n, PARADIGM val[] ); static void prdm_size( int timing, int n, PARADIGM val[] ); static void disp_info( void *dscrpt, WPNT2_T *o_data ); /********************************************************* ** メニュー項目 ** *********************************************************/ #define LANG_N 2 #define MAIN_MENU_N 4 static const char *str_main_menu[MAIN_MENU_N][LANG_N] = { { " SET ", " 設 定 " }, { " EXEC ", " 試 行 " }, { " PROC3 ", " 処理3 " }, { " PROC4 ", " 処理4 " } }; #define INIT_CUR_POS_X 255 #define INIT_CUR_POS_Y 239 #define MAX_POINT 1024 /********************************************************* ** グローバル変数 ** *********************************************************/ int rand_or_cursor = 0; int rand_value = 30; int w_start_x = 0, w_start_y = 0; int w_size_x = 512, w_size_y = 480; int on_off = 1; unsigned int time = 0; PVAL pad_value[5]; /********************************************************* ** メイン ** *********************************************************/ void main( void ) { int sts; int xpos; int ypos; int s_xpos; int s_ypos; PRIVATE WORD wXs, wYs, wXe, wYe; /* 初期メッセージ表示 */ 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_input_video_control( GRAY_PLANE ); /* ビデオ出力表示項目制御 */ Lib_display_control( GRAY_PLANE | LINE_PLANE | CHAR_PLANE ); /* ビデオ表示項目クリア */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* カーソル初期化 */ Lib_init_cursor(); Lib_get_stage_window( &wXs, &wYs, &wXe, &wYe ); /* メインメニューの表示 */ main_menu_disp(); /* マウスカーソルの表示 */ Lib_draw_cursor( INIT_CUR_POS_X, INIT_CUR_POS_Y ); Lib_strtclk( ); /* メニュー制御 */ 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 ); set( ); /* 設定 */ 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 ); exec( ); /* 試行 */ 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; /* 終了 */ } } } Lib_set_stage_window( wXs, wYs, wXe, wYe ); } /********************************************************* ** メインメニュー表示 ** *********************************************************/ static 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 ); } /********************************************************* ** ヘルプ表示 ** *********************************************************/ static void disp_help( void ) { int i=8; Lib_chrdisp( 10, i, "【機能\概要】 VRNI" ); i++; Lib_chrdisp( 11, i, "このプログラムはボロノイ図を作成するものです。" ); i++; Lib_chrdisp( 11, i, "設定で乱数を使って点を作り出すか、カーソ\ルによ" ); i++; Lib_chrdisp( 11, i, "って、自ら打ち込むか選択できます。また乱数の場" ); i++; Lib_chrdisp( 11, i, "合、点の個数も設定できます。登録された点でボロ" ); i++; Lib_chrdisp( 11, i, "ノイ図を作成、表示させたあと、カーソ\ル操作で各" ); i++; Lib_chrdisp( 11, i, "母点を囲む面積や直線の本数、その直線の方程式の" ); i++; Lib_chrdisp( 11, i, "表\示を行なうことができます" ); i++; i++; Lib_chrdisp( 10, i, "【注意点】" ); i++; Lib_chrdisp( 11, i, "点が重なっているとボロノイ図が作成できないので" ); i++; Lib_chrdisp( 11, i, "ソ\ートを行なうことによって、重なっている点を除" ); i++; Lib_chrdisp( 11, i, "去しています。これによって、打ちこんだ点の数よ" ); i++; Lib_chrdisp( 11, i, "りも、少なくなることがあります。" ); i++; Lib_chrdisp( 11, i, "また入力できる点の数は最大1024個です。"); } /********************************************************* ** 設定 ** *********************************************************/ static void set( void ) { int pad_level; /* パッドレベル */ int no; /* メニュー実行の戻り値 */ int height, width; /* キーサイズ */ char *boten_select[2] = { " 乱数 ", "カーソ\ル" }; /* 選択属性 */ /* 現在値代入 */ pad_value[0].select_type = rand_or_cursor; pad_value[1].value_type = rand_value; pad_value[2].box_type.x = w_start_x; pad_value[2].box_type.y = w_start_y; pad_value[3].box_type.x = w_size_x; pad_value[3].box_type.y = w_size_y; pad_value[4].on_off_type = on_off; /* 現在のウィンドウ範囲を表示 */ Lib_box( pad_value[2].box_type.x, pad_value[2].box_type.y, pad_value[2].box_type.x+pad_value[3].box_type.x - 1, pad_value[2].box_type.y+pad_value[3].box_type.y - 1, SOLID_LINE ); /* パッドのオープン */ pad_level = Lib_view_open( ); /* メニューサイズの取得 */ Lib_set_pad_maxstring( 12 ); Lib_get_standard_key_size( &width, &height ); /* パッドのタイトル */ Lib_view_set_title( pad_level, "設 定" ); /* メニューの登録 */ Lib_view_set_select( pad_level, 5, 5, "母点作成方法", pad_value[0].select_type, 2, boten_select, 0 ); Lib_view_set_uniq_numeral( pad_level, 5, 8+height, "乱数の母点数", pad_value[1].value_type, 2, 300, 1 ); Lib_view_set_box( pad_level, 5, 11+height*2, "W始点", pad_value[2].box_type.x, pad_value[2].box_type.y, 3, 3, 2 ); Lib_view_set_box( pad_level, 5, 14+height*3, "Wサイズ", pad_value[3].box_type.x, pad_value[3].box_type.y, 3, 2, 3 ); Lib_view_set_uniq_alter( pad_level, 5, 17+height*4, "方程式表\示", pad_value[4].on_off_type, 4 ); /* パラダイムの登録 /*/ Lib_set_paradigm( pad_level, 2, ST_AND_ED_TIMING, prdm_srtpt ); Lib_set_paradigm( pad_level, 3, ST_AND_ED_TIMING, prdm_size ); /* パッドの表示位置 */ Lib_view_set_size( pad_level, 30, 50, 5, 5 ); /* パッドの表示 */ Lib_draw_menu( pad_level ); if(ERROR_RETURN != ( no = Lib_process_menu( pad_level, pad_value )) ) { switch( no ) { /* 実行ボタンが押されたら */ case 101: rand_or_cursor = pad_value[0].select_type; rand_value = pad_value[1].value_type; w_start_x = pad_value[2].box_type.x; w_start_y = pad_value[2].box_type.y; w_size_x = pad_value[3].box_type.x; w_size_y = pad_value[3].box_type.y; on_off = pad_value[4].on_off_type; break; /* 取り消しボタンが押されたら */ case 102: break; /* 異常終了 */ case -1: break; /* 異常終了 */ } } else Lib_display_message( 100, 100, "Error", "Menu Pad Error" ); /* エラー表示 */ Lib_erase_menu(pad_level); /* メニューパッドを消す */ Lib_view_close(pad_level); /* パッドのクローズ */ Lib_memory_clear( LINE_PLANE ); /* ラインを消す */ } /********************************************************* ** パラダイム ボックス始点 ** *********************************************************/ static void prdm_srtpt( int timing, int n, PARADIGM val[] ) { if( timing == START_TIMING ) /* ボックスを消す */ { Lib_box( pad_value[2].box_type.x, pad_value[2].box_type.y, pad_value[2].box_type.x+pad_value[3].box_type.x, pad_value[2].box_type.y+pad_value[3].box_type.y, BLACK_LINE ); } if( timing == END_TIMING ) /* ボックスを描く */ Lib_box( val[0].int_type, val[1].int_type, val[0].int_type + val[2].int_type, val[1].int_type + val[3].int_type, SOLID_LINE ); } /********************************************************* ** パラダイム ボックスサイズ ** *********************************************************/ static void prdm_size( int timing, int n, PARADIGM val[] ) { if( timing == START_TIMING ) /* ボックスを消す */ { Lib_box( pad_value[2].box_type.x, pad_value[2].box_type.y, pad_value[2].box_type.x+pad_value[3].box_type.x, pad_value[2].box_type.y+pad_value[3].box_type.y, BLACK_LINE ); } if( timing == END_TIMING ) /* ボックスを描く */ Lib_box( val[0].int_type, val[1].int_type, val[0].int_type + val[2].int_type, val[1].int_type + val[3].int_type, SOLID_LINE ); } /********************************************************* ** 乱数の発生 ** *********************************************************/ static int random( WPNT2_T point[], int seed ) { int i, j; int bunbo, bunshi, amari; /* 乱数発生の元となる分数を入れる */ int temp; bunshi = 98765; bunbo = 17341; j = 0; for( i = 0; i < seed+rand_value; i++ ) { temp = bunshi / bunbo; amari = bunshi % bunbo; bunshi = amari * 1000; if( i >= seed - 1 ) /* iがseed以上になったら代入をはじめる */ { point[j].x = temp; temp = bunshi / bunbo; amari = bunshi % bunbo; bunshi = amari * 1000; point[j].y = temp; j++; } } for( i=0; i < rand_value; i++ ) /* ウィンドウサイズに収まるように値を変換 */ { point[i].x = point[i].x % w_size_x; point[i].x += w_start_x; point[i].y = point[i].y % w_size_y; point[i].y += w_start_y; } return( rand_value ); /* 点の個数を戻す */ } /********************************************************* ** 試行 ** *********************************************************/ static void exec( void ) { void *dscrpt_vrni; /* ボロノイ図のディスクリプタ */ void *dscrpt_sort; /* 辞書的順序ソートのディスクリプタ */ WPNT2_T *i_data; /* ソート前のデータを格納 */ WPNT2_T *o_data; /* ソート後のデータを格納 */ int pnt_num; /* ソート前の点の数 */ int o_pnt_num; /* ソート後の点の数 */ int *in_to_out_data; /* ソートでどう点を動かしたかの情報 */ int *out_to_in_data; /* ソートでどう点を動かしたかの情報 */ int i; char str[64]; /* ボロノイ図のオープン */ if( NULL != (dscrpt_vrni = Lib_cg_2dVrniDgrm_open( MAX_POINT )) ) { /* 辞書的順序ソートのオープン */ if( NULL != ( dscrpt_sort = Lib_cg_ordering_data_open( MAX_POINT )) ) { /* メモリの確保 */ if(( WPNT2_T * )NULL != ( i_data = ( WPNT2_T * )Lib_mlalloc( sizeof( WPNT2_T )* MAX_POINT )) ) { /* 画像を消す */ Lib_display_control( LINE_PLANE | CHAR_PLANE ); Lib_box( w_start_x, w_start_y, w_start_x+w_size_x-1, w_start_y+w_size_y-1, SOLID_LINE ); if( rand_or_cursor == 0 ) /* 乱数を選択していた場合 */ { time += Lib_readclk( ); while( time > 50000 ) /* timeが50000以上になったら、50000を引く */ { time -= 50000; } pnt_num = random( i_data, time ); /* timeがseedになる */ } else /* カーソルを選択していた場合 */ pnt_num = cursor( i_data ); /* 点が重なっているかもしれないので、ソートを行なう */ Lib_cg_ordering_data_exec( dscrpt_sort, i_data, pnt_num, &o_data, &o_pnt_num, &in_to_out_data, & out_to_in_data ); /* ソートされた後の点を描く */ for( i=0; i= MAX_POINT ) break; } Lib_chrdisp( 1, 30, "CANCELキーで終了" ); Lib_sprintf( str, "i = %d", i ); Lib_chrdisp( 1, 29, str ); } Lib_cls( CHAR_PLANE, BLACK_COLOR ); return(i); } /********************************************************* ** 制限付カーソル(カーソルの動ける範囲を限定) ** *********************************************************/ static int restricted_cursor( WPNT2_T *pnt ) { int key_stts; /* キー押下状況 */ int x, y; /* カーソルの位置 */ /* キー押下状況の初期化 */ key_stts = 0; /* カーソル位置の初期化 */ x = pnt->x; y = pnt->y; /* カーソルの位置を取得 */ key_stts = Lib_see_current_position( &x, &y ); /* カーソルの動きの制限 */ if( x < w_start_x ) x = w_start_x; if( y < w_start_y ) y = w_start_y; if( w_start_x + w_size_x - 1 < x ) x = w_start_x + w_size_x - 1; if( w_start_y + w_size_y - 1 < y ) y = w_start_y + w_size_y - 1; /* カーソルの移動 */ Lib_move_cursor( x, y ); /* カーソルの描画 */ Lib_draw_cursor( x, y ); /* カーソルの位置 */ pnt->x = x; pnt->y = y; /* 返値;キー押下状態 */ return( key_stts ); } /********************************************************* ** 点を書く   ** *********************************************************/ static void draw_point( int x, int y ) { Lib_line( x-1, y-1, x+1, y+1, SOLID_LINE ); Lib_line( x+1, y-1, x-1, y+1, SOLID_LINE ); } /********************************************************* ** 情報を表示 ** *********************************************************/ static void disp_info( void *dscrpt, WPNT2_T *o_data ) { WPNT2_T pnt; /* 点 */ VG_INFO *info; /* 情報 */ int nearest_num; /* 最も近い母点 */ char str[64]; int cursor_rtn; /* カーソルの戻り値 */ int i, j; /* CANCELキーが押されるまで続ける */ while( 2 != cursor_rtn ) { /* カーソルの状態を見る */ cursor_rtn = restricted_cursor( &pnt ); Lib_sprintf( str, "CANCELキーで終了"); Lib_chrdisp( 1, 30, str ); /* EXECUTEキーが押されたら */ if( 1 == cursor_rtn ) { /* もっとも近い母点を探す */ if( -1 != ( nearest_num = Lib_cg_2dVrniDgrm_nearest_gnrt( dscrpt, pnt )) ) { /* 一旦画面を消す */ Lib_cls( CHAR_PLANE | LINE_PLANE, BLACK_COLOR ); /* 枠線を描く */ Lib_box( w_start_x, w_start_y, w_start_x+w_size_x-1, w_start_y+w_size_y-1, SOLID_LINE ); /* ボロノイ図を描写 */ Lib_cg_2dVrniDgrm_draw( dscrpt ); /* 母点の周りを囲む */ Lib_box( o_data[nearest_num].x-5, o_data[nearest_num].y-5, o_data[nearest_num].x+5, o_data[nearest_num].y+5, SOLID_LINE ); /* 母点の情報を得る */ Lib_cg_2dVrniDgrm_get_gnrt_info( dscrpt, nearest_num, &info ); /* 情報の表示 */ Lib_sprintf( str, "隣接母点数 = %d", info->num ); Lib_chrdisp( 40, 3, str ); Lib_sprintf( str, "領域面積  = %.1lf", info->area ); Lib_chrdisp( 40, 4, str ); /* 方程式表示がオンの場合 */ if( on_off == 1 ) { Lib_chrdisp( 40, 6, "母点を囲む直線の方程式" ); j = 7; for( i = 0; i < info->num; i++ ) { if( info->ve_info[i].b < 0 && info->ve_info[i].c > 0 ) Lib_sprintf( str, "%dx%dy+%d = 0", info->ve_info[i].a, info->ve_info[i].b, info->ve_info[i].c ); else if( info->ve_info[i].b > 0 && info->ve_info[i].c < 0 ) Lib_sprintf( str, "%dx+%dy%d = 0", info->ve_info[i].a, info->ve_info[i].b, info->ve_info[i].c ); else if( info->ve_info[i].b < 0 && info->ve_info[i].c < 0 ) Lib_sprintf( str, "%dx%dy%d = 0", info->ve_info[i].a, info->ve_info[i].b, info->ve_info[i].c ); else Lib_sprintf( str, "%dx+ %dy+ %d = 0", info->ve_info[i].a, info->ve_info[i].b, info->ve_info[i].c ); Lib_chrdisp( 40, j, str ); j++; } } } } } }