HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0416
名無し画像の拡大で誤差が生じる13解決


名無し

リンク

2020/4/16(Thu) 10:28:16|NO.90115

画像を左クリックで拡大、右クリックで縮小するスクリプトを作ったんですけど
何故か拡大を続けるとマウスの基点と誤差が生じてしまいます
どうすればよろしいでしょうかよろしくお願いします


; ウィンドウの作成 screen 0, GINFO_DISPX, GINFO_DISPY, SCREEN_HIDE ; 変数宣言 baseZoom = 3.0 nowZoom = 1.0 ; 画像の読み込み #const imageId 1 celload strf( "%s/sample/basic/fontchr.bmp", DIR_EXE ), imageId gsel imageId ; 画像の大きさ imageSizeX = GINFO_WINX imageSizeY = GINFO_WINY gsel 0 ; ウィンドウのサイズを変更 gsel 0, 1 width ( baseZoom * imageSizeX ), ( baseZoom * imageSizeY ), 0 width GINFO_WINX, GINFO_WINY, ( 0.5 * ( GINFO_DISPX - GINFO_WINX ) ), ( 0.5 * ( GINFO_DISPY - GINFO_WINY ) ) repeat ; stick key ; 倍率を上げる if ( key == 256 ) { ; 適用 nowZoom += 1.0 ; マウス座標 _mousex = mousex _mousey = mousey } ; 倍率を下げる if ( key == 512 ) { ; 適用 nowZoom -= 1.0 } ; 適用範囲 nowZoom = limitf( nowZoom, 1.0, 10.0 ) ; 描画開始 redraw 0 ; 背景 color 0, 0, 0 boxf ; 画像 pos -( 1.0 * _mousex * ( nowZoom - 1.0 ) ), -( 1.0 * _mousey * ( nowZoom - 1.0 ) ) celput imageId, 0, ( baseZoom * nowZoom ), ( baseZoom * nowZoom ), 0.0 ; 描画終了 redraw 1 ; 情報 title strf( "表示座標( %.0f, %.0f ) 表示拡大率:%.0f%% 拡大率: %.0f%%", GINFO_CX, GINFO_CY, ( 100.0 * ( baseZoom * nowZoom ) ), ( 100.0 * nowZoom ) ) ; 時間 await 16 loop



この記事に返信する


名無し

リンク

2020/4/16(Thu) 10:30:06|NO.90116


stick key, ( 256 + 512 ) ; 倍率を上げる if ( key == 256 ) { ; 適用 nowZoom += 0.1 ; ズームアップした時のマウス座標 _mousex = mousex _mousey = mousey } ; 倍率を下げる if ( key == 512 ) { ; 適用 nowZoom -= 0.1 }
にスクリプトを置換したら分かりやすいかもしれません。



沢渡

リンク

2020/4/16(Thu) 11:15:34|NO.90117

拡大にcelputではなく、gzoomを使ってはどうでしょうか。
拡大もしくは回転ありのcelputは、内部では(gzoomではなく)grotateと同様の処理を
行っているようで、回転ができる分拡大処理については厳密さに欠けるようです。

; ウィンドウの作成 screen 0, GINFO_DISPX, GINFO_DISPY, SCREEN_HIDE ; 変数宣言 baseZoom = 3.0 nowZoom = 1.0 ; 画像の読み込み #const imageId 1 celload strf( "%s/sample/basic/fontchr.bmp", DIR_EXE ), imageId gsel imageId ; 画像の大きさ imageSizeX = GINFO_WINX imageSizeY = GINFO_WINY gsel 0 ; ウィンドウのサイズを変更 gsel 0, 1 width ( baseZoom * imageSizeX ), ( baseZoom * imageSizeY ), 0 width GINFO_WINX, GINFO_WINY, ( 0.5 * ( GINFO_DISPX - GINFO_WINX ) ), ( 0.5 * ( GINFO_DISPY - GINFO_WINY ) ) flag=1 //拡大率を変更したフラグ(初回の描画を行うため、初期値は1) _mousex=0 : _mousey=0 repeat ; stick key ; 倍率を上げる if ( key == 256 ) { ; 適用 nowZoom += 1.0 ; マウス座標 _mousex = mousex _mousey = mousey flag=1 } ; 倍率を下げる if ( key == 512 ) { ; 適用 nowZoom -= 1.0 flag=1 } if flag { ; 適用範囲 nowZoom = limitf( nowZoom, 1.0, 10.0 ) ; 描画開始 redraw 0 ; 背景 color 0, 0, 0 boxf ; 画像 pos -( 1.0 * _mousex * ( nowZoom - 1.0 ) ), -( 1.0 * _mousey * ( nowZoom - 1.0 ) ) gzoom imageSizeX*baseZoom * nowZoom,imageSizeY*baseZoom * nowZoom,imageID,0,0,imageSizeX,imageSizeY ; 描画終了 redraw 1 ; 情報 title strf( "表示座標( %.0f, %.0f ) 表示拡大率:%.0f%% 拡大率: %.0f%%", GINFO_CX, GINFO_CY, ( 100.0 * ( baseZoom * nowZoom ) ), ( 100.0 * nowZoom ) ) flag=0 } ; 時間 await 16 loop



名無し

リンク

2020/4/16(Thu) 15:44:50|NO.90118

ありがとうございます無事できました
もう一つ質問がありますが内容がほぼ同じなのでここでさせていただきます
今度は画像バージョンから座標バージョンの拡大縮小方法について教えてほしいです
例としては


; ウィンドウの作成 screen 0, 640, 480, SCREEN_NORMAL ; 初期処理 randomize ; 変数宣言 baseZoom = 3.0 dim ball, 100 foreach ball ballX(cnt) = rnd(GINFO_WINX) ballY(cnt) = rnd(GINFO_WINX) loop repeat ; stick key, ( 256 + 512 ) ; 倍率を上げる if ( key == 256 ) { ; 適用 nowZoom += 0.1 ; マウス座標 _mousex = mousex _mousey = mousey } ; 倍率を下げる if ( key == 512 ) { ; 適用 nowZoom -= 0.1 } ; 適用範囲 nowZoom = limitf( nowZoom, 1.0, 10.0 ) ; 描画開始 redraw 0 ; 背景 color 255, 255, 255 boxf ; いろいろ color 255, 0, 0 ballR = 4.0 foreach ball bx = ballX(cnt) by = ballY(cnt) circle ( bx - ballR ), ( by - ballR ), ( bx + ballR ), ( by + ballR ), 1 loop ; 描画終了 redraw 1 ; 情報 title strf( "拡大率: %.0f%%", ( 100.0 * nowZoom ) ) ; 時間 await 16 loop

のような一つ一つに座標を持つボールたちの拡大縮小の方法を知りたいです
できればバッファーを使わずただの計算式で教えてほしいです
わがままで申し訳ないですがよろしくお願いします



名無し

リンク

2020/4/16(Thu) 15:45:48|NO.90119

すいません

ballX(cnt) = rnd(GINFO_WINX) ballY(cnt) = rnd(GINFO_WINY)
でした



沢渡

リンク

2020/4/16(Thu) 17:01:53|NO.90120

こんな感じでいいでしょうか?

; ウィンドウの作成 screen 0, 640, 480, SCREEN_NORMAL ; 初期処理 randomize ; 変数宣言 baseZoom = 3.0 dim ball, 100 foreach ball ballX(cnt) = rnd(GINFO_sx) ballY(cnt) = rnd(GINFO_sy) loop adj_x=0.0 //現在の倍率で、画面の左方向にどのくらいはみ出すか adj_y=0.0 //現在の倍率で、画面の上方向にどのくらいはみ出すか preZoom=1.0 //倍率変更前の倍率 nowZoom=1.0 flag=1 //倍率を変更したフラグ _mousex=0.0 : _mousey=0.0 repeat ; stick key, ( 256 + 512 ) ; 倍率を上げる if ( key == 256 )&(nowZoom<10.0) { ; 適用 preZoom=nowZoom nowZoom += 0.1 ; マウス座標 _mousex = double(mousex) _mousey = double(mousey) flag=1 } ; 倍率を下げる if ( key == 512 )&(nowZoom>1.0) { ; 適用 preZoom=nowZoom nowZoom -= 0.1 ; マウス座標 _mousex = double(mousex) _mousey = double(mousey) flag=1 } if flag { ; 描画開始 redraw 0 ; 背景 color 255, 255, 255 boxf ; いろいろ color 255, 0, 0 ballR = baseZoom*nowZoom adj_x=(_mousex+adj_x)*nowZoom/preZoom-_mousex //新しい倍率に合わせてはみ出す範囲を修正 adj_y=(_mousey+adj_y)*nowZoom/preZoom-_mousey foreach ball bx = int((double(ballX(cnt)))*nowZoom-adj_x) by = int((double(ballY(cnt)))*nowZoom-adj_y) circle ( bx - ballR ), ( by - ballR ), ( bx + ballR ), ( by + ballR ), 1 loop ; 描画終了 redraw 1 ; 情報 title strf( "拡大率: %.0f%%", ( 100.0 * nowZoom ) ) flag=0 } ; 時間 await 16 loop



名無し

リンク

2020/4/16(Thu) 20:02:08|NO.90121

沢渡様、
私のわがままに付き合ってくれて本当にありがとうございました!



名無し

リンク

2020/4/16(Thu) 20:22:48|NO.90122

あ、でもすいません。
マウスを移動しながら拡大縮小を行うと座標がズレちゃいます。



沢渡

リンク

2020/4/16(Thu) 22:10:40|NO.90123

「ズレちゃいます」とは上下左右に妙に広い空白ができてしまうことでしょうか?
とりあえず、adj_xとadj_yに上限と下限を設けて対処しましたが、これでどうでしょうか?

; ウィンドウの作成 screen 0, 640, 480, SCREEN_NORMAL ; 初期処理 randomize ; 変数宣言 baseZoom = 3.0 dim ball, 100 foreach ball ballX(cnt) = rnd(GINFO_sx) ballY(cnt) = rnd(GINFO_sy) loop adj_x=0.0 //現在の倍率で、画面の左方向にどのくらいはみ出すか adj_y=0.0 //現在の倍率で、画面の上方向にどのくらいはみ出すか preZoom=1.0 //倍率変更前の倍率 nowZoom=1.0 flag=1 //倍率を変更したフラグ _mousex=0.0 : _mousey=0.0 repeat ; stick key, ( 256 + 512 ) ; 倍率を上げる if ( key == 256 )&(nowZoom<10.0) { ; 適用 preZoom=nowZoom nowZoom += 0.1 ; マウス座標 _mousex = double(mousex) _mousey = double(mousey) flag=1 } ; 倍率を下げる if ( key == 512 )&(nowZoom>1.0) { ; 適用 preZoom=nowZoom nowZoom -= 0.1 ; マウス座標 _mousex = double(mousex) _mousey = double(mousey) flag=1 } if flag { ; 描画開始 redraw 0 ; 背景 color 255, 255, 255 boxf ; いろいろ color 255, 0, 0 ballR = baseZoom*nowZoom adj_x=(_mousex+adj_x)*nowZoom/preZoom-_mousex //新しい倍率に合わせてはみ出す範囲を修正 adj_x=limitf(adj_x,0.0,640.0*(nowZoom-1.0)) adj_y=(_mousey+adj_y)*nowZoom/preZoom-_mousey adj_y=limitf(adj_y,0.0,480.0*(nowZoom-1.0)) foreach ball bx = int((double(ballX(cnt)))*nowZoom-adj_x) by = int((double(ballY(cnt)))*nowZoom-adj_y) circle ( bx - ballR ), ( by - ballR ), ( bx + ballR ), ( by + ballR ), 1 loop ; 描画終了 redraw 1 ; 情報 title strf( "拡大率: %.0f%%", ( 100.0 * nowZoom ) ) flag=0 } ; 時間 await 16 loop



あらや

リンク

2020/4/16(Thu) 23:56:14|NO.90124

横から失礼します。

double型は沢渡さんの手法ではときどき微妙な誤差が出て来るので
何度も拡大縮小していると
nowZoomの値が『1.0』ではなく『1.0000000000000009』になってしまう場合があり
誤判定されて縮小時に0.9倍になったり拡大時に10.1倍になることがあります。

なので元の名無しさんのやり方のように
>nowZoom = limitf( nowZoom, 1.0, 10.0 )
この行は残した方が良いかと思います。



それとズレに対応するソースですが、
右及び下だけだと1倍とそれ以外の倍率でいきなり座標が飛んでしまうので
左と上にも対応させて

adj_x=(_mousex+adj_x)*nowZoom/preZoom-_mousex //新しい倍率に合わせてはみ出す範囲を修正 adj_x=limitf(adj_x,-640.0*(nowZoom-1.0),640.0*(nowZoom-1.0)) adj_y=(_mousey+adj_y)*nowZoom/preZoom-_mousey adj_y=limitf(adj_y,-480.0*(nowZoom-1.0),480.0*(nowZoom-1.0))
このように0ではなくマイナス方向も考慮した方が良いかと。

以上です。
横から揚げ足取りのような形となり失礼いたしました。



あらや

リンク

2020/4/17(Fri) 00:20:16|NO.90125

すみません確認ミスしました。

ズレが生じるのは誤差が出来てからでした。(0.9倍とそれ以外の時)
>nowZoom = limitf( nowZoom, 1.0, 10.0 )
この行を残しておけばズレる事はなさそうなので
先述の後半は無視してください。

たびたび失礼いたしました。



沢渡

リンク

2020/4/17(Fri) 00:36:56|NO.90126

なるほど。実数は使い慣れてないもので、計算の繰り返しによる誤差の拡大を甘く見ていました。
申し訳ない。



名無し

リンク

2020/4/17(Fri) 10:33:51|NO.90127

あらや様、沢渡様、ありがとうございました
無事自分の望み通りになりました



匿名希望

リンク

2020/4/19(Sun) 09:31:52|NO.90134

横から失礼。NO.90117のソースもNO.90122で言っているようなことが起きていないか?



ONION software Copyright 1997-2023(c) All rights reserved.