|
|
2009/11/30(Mon) 20:16:38|NO.29079
HSPで、線分(x1,y1 - x2,y2)と長方形・ボックス(x1,y1,x2,y2)の交差判定をとるにはどのようにしたら良いでしょうか?
交点を求める必要はなく、とにかく速度重視であるものを想定しています。
自分でもgoogleを駆使して色々チャレンジしてみたのですが、良い方法が見つかりませんでした・・・
知恵をお持ちの方がいらっしゃいましたら、お力を貸していただきたいです。
|
|
2009/11/30(Mon) 21:57:02|NO.29080
まず質問するときは、良く考えて下さい。
>>HSPで、線分(x1,y1 - x2,y2)と長方形・ボックス(x1,y1,x2,y2)の交差判定を・・・
>>交点を求める必要はなく、とにかく速度重視であるものを想定しています。
→”交差判定””交点”、要は”重なりを判定したい”のでしょうか?
>>自分でもgoogleを駆使して色々チャレンジしてみたのですが、良い方法が・・・
→まず、どう駆使(探して?)してダメだったのか、分かりません。
どういうスクリプトがダメで、どうしたいのかハッキリさせたほうが、回答も得られやすい
でしょう。
|
|
2009/11/30(Mon) 23:40:13|NO.29084
座標計算とかメンドなので、塗りつぶしと座標のカラー取得でどうでしょうか
x_1=10 ; 線分座標
y_1=20
x_2=300
y_2=300
x1=100 ; ボックス座標
y1=100
x2=200
y2=200
;①と長方形・ボックス(x1,y1,x2,y2)をたとえばRGB(0,0,0)boxfで描画して、
;線分の始終点x_1,y_1、x_2,y_2の2点がRGB(0,0,0)なら交わってる
color 0,0,0 ; ボックス色
boxf x1,y1,x2,y2 ; ボックス
pget x_1,y_1 : if ginfo_r == 0 : dialog "アタリ!" : stop
pget x_2,y_2 : if ginfo_r == 0 : dialog "アタリ!" : stop
;②線分(x_1,y_1 - x_2,y_2)をたとえばRGB(0,0,255)で描画してから、
;x1,y1から閉塞領域を任意のブラシ色で塗りつぶして、;x1,y2、x2,y1、x2,y2の3点をpget命令で取得し、ひとつでも塗りつぶし色(ブラシ色)でなければ交わってる。
#uselib "gdi32.dll"
#func GetPixel "GetPixel" sptr,sptr,sptr
; HDC hdc, デバイスコンテキストのハンドル
; int nXPos, ピクセルの x 座標
; int nYPos ピクセルの y 座標
#func CreateSolidBrush "CreateSolidBrush" sptr
; COLORREF crColor ブラシの色を表す値
#func SelectObject "SelectObject" sptr,sptr
; HDC hdc, デバイスコンテキストのハンドル
; HGDIOBJ hgdiobj オブジェクトのハンドル
#func ExtFloodFill "ExtFloodFill" sptr,sptr,sptr,sptr,sptr
; HDC hdc, デバイスコンテキストのハンドル
; int nXStart, 開始点の x 座標
; int nYStart, 開始点の y 座標
; COLORREF crColor 塗りつぶしの色
; UINT fuFillType 塗りつぶしの種類
;#const FLOODFILLBORDER $00000000
#const FLOODFILLSURFACE $00000001
#func DeleteObject "DeleteObject" int
; HGDIOBJ hObject グラフィックオブジェクトのハンドル
#uselib "user32.dll"
#func ReleaseDC "ReleaseDC" sptr,sptr
; HWND hWnd, ウィンドウのハンドル
; HDC hDC デバイスコンテキストのハンドル
#func InvalidateRect "InvalidateRect" int,int,int
; HWND hWnd, ウィンドウのハンドル
; CONST RECT *lpRect, 長方形の座標
; BOOL bErase 消去するかどうかの状態
color 0,0,255 ; 線分色
line x_1,y_1,x_2,y_2 ; 線分
color 255,0,0 ; ブラシ色 ; ブラシ色
GetPixel hdc,x1,y1 : colref=stat
;BMSCR構造体にセットされている色を使いブラシを作成
mref bmscr,67
CreateSolidBrush bmscr(40) : ahBrush=stat
SelectObject hdc,ahBrush : ahOldBrush=stat
;閉塞領域に描画されている色と新規に塗る色とを比較して違うならば新規の色を塗る
ExtFloodFill hdc,x1,y1,colref,0 : ret=stat
if ret!1 {
ExtFloodFill hdc,x1,y1,colref,FLOODFILLSURFACE
}
SelectObject hdc,ahOldBrush
DeleteObject ahBrush
ReleaseDC hwnd,hdc
InvalidateRect hwnd,0,1 ; 再描画
color 0,0,0
pget x1,y2 : if ginfo_r != 255 : dialog "アタリ!" : stop
pget x2,y1 : if ginfo_r != 255 : dialog "アタリ!" : stop
pget x2,y2 : if ginfo_r != 255 : dialog "アタリ!" : stop

| |
|
2009/12/1(Tue) 09:45:14|NO.29093
|
|
2009/12/1(Tue) 23:25:05|NO.29106
|
|
2009/12/2(Wed) 21:09:43|NO.29114
すでに良い回答が出ているみたいですが、せっかく作ったので載せますね。
; ------------------------------------------------------------------------------
; 線分 と 矩形 の交差判定
; programmed by shinkun.
; 2009/12/1
#module
; --------------------------------------------------------------------------
; _IsCross(x,y,x1,y1,x2,y2)
; 線分が矩形の対角線のひとつと交差しているかどうかを返す。
; 引数
; x, y - 線分の端点のひとつを原点Oとした時の、もう一方の端点の座標
; x1, y1 - 線分の端点のひとつを原点Oとした時の、矩形の対角線の点①の座標
; x2, y2 - 線分の端点のひとつを原点Oとした時の、矩形の対角線の点②の座標
; 戻り値
; 1 - 線分と対角線は交差している
; 0 - 線分と対角線は交差していない
; 補足
; この関数では、線分の端点のひとつを原点とする座標系で考える。
#defcfunc _IsCross int x, int y, int x1, int y1, int x2, int y2, local a, local b
; 線分と矩形の対角線が交差しているかどうかの判定
b = x1 * y2 - x2 * y1 ; 分母の計算
if (b == 0): return 0
a = double(x * y2 - x2 * y) / b
b = double(x * y1 - x1 * y) / -b
return (a >= 0.0) && (b >= 0.0) && (a + b >= 1.0)
; この計算の元となる考え方は次の通り。
; ①線分の端点をそれぞれAとBとする。また、矩形の2つある対角線の内
; ひとつを選び、その端点をCとDとする。
; ②ベクトルAC、ADを使って、ベクトルABを表す方程式
; AB=αAC+βAD (α,βは実数)
; を考える。すると、α≧0, β≧0, α+β=1 の時、点Bは対角線CD
; 上に乗っている事になるので、α + β >= 1 だと線分ABは対角線を
; 交差するという事になる。
; ③よって、方程式を x 座標, y 座標でそれぞれ分解して連立方程式とし、
; αとβを解くと上記の計算式となる。
; --------------------------------------------------------------------------
; IsOverlappedPointToRect(px,py,rx,ry,rw,rh)
; (px,py) の点が、(x,y) を左上とし幅 w, 高さ h の矩形内にあるかどうかを
; 返す。
; 引数
; px, py - 点の座標
; rx, ry - 矩形の左上座標
; rw, rh - 矩形の幅と高さ
; 戻り値
; 1 - 点は矩形内にある
; 0 - 点は矩形内にない
#defcfunc IsOverlappedPointToRect int px, int py, int x, int y, int w, int h
if (px < x): return 0
if (py < y): return 0
if (px >= x + w): return 0
if (py >= y + h): return 0
return 1
; --------------------------------------------------------------------------
; IsOverlappedSegmentToRect(x1,y1,x2,y2,x,y,w,h)
; (x1,y1), (x2,y2) で結ばれる線分と (x,y) を左上とし幅 w, 高さ h の矩形が
; 重なっているかどうかを返す。
; 引数
; x1, y1 - 線分の端点①
; x2, y2 - 線分の端点②
; x, y - 矩形の左上座標
; w, h - 矩形の幅と高さ
; 戻り値
; 1 - 線分と矩形は交差している
; 0 - 線分と矩形は交差していない
#defcfunc IsOverlappedSegmentToRect int x1, int y1, int x2, int y2, int x, int y, int w, int h
; 線分の端点が矩形内に存在するかどうかを調べる
if (IsOverlappedPointToRect(x1,y1,x,y,w,h)): return 1
if (IsOverlappedPointToRect(x2,y2,x,y,w,h)): return 1
; ここで検出されるのは、矩形内に ①線分の両端、②線分の一方の端点 が
; 存在する場合である。これ以降は、線分の端点が矩形外にある場合を取り
; 扱う。つまり、①両端とも矩形内には存在しないが、その両端を結ぶ線分
; が矩形上を通過する場合 ②線分も完全に矩形を外れている場合 である。
; 線分が矩形内に存在するかどうかを調べる
if (_IsCross(x2-x1,y2-y1,x-x1,y+h-y1,x+w-x1,y-y1)): return 1
if (_IsCross(x2-x1,y2-y1,x-x1,y-y1,x+w-x1,y+h-y1)): return 1
return 0
#global
; 定数定義
#const KEYCODE_LCLICK 1 ; 左クリックのキーコード
#const KEYCODE_RCLICK 2 ; 右クリックのキーコード
*start
; 変数定義
rect = 200, 200, 240, 80 ; 矩形の x, y 座標と幅と高さ
pt1 = 100, 50 ; 線分の端点① (x,y)
pt2 = 540, 50 ; 線分の端点② (x,y)
result = 0 ; 交差判定の結果
; タイトル設定
title "左・右クリックで線分の端点①・②を移動"
*main
gosub *update
gosub *output
await 20
goto *main
*update
; クリック検出&移動
getkey isClick, KEYCODE_LCLICK
if (isClick): pt1 = mousex, mousey
getkey isClick, KEYCODE_RCLICK
if (isClick): pt2 = mousex, mousey
; 線分と矩形の交差判定
result = IsOverlappedSegmentToRect(pt1(0),pt1(1),pt2(0),pt2(1),rect(0),rect(1),rect(2),rect(3))
return
*output
; 描画反映禁止
redraw 0
; 画面クリア
color 255, 255, 255
boxf
; 矩形描画
color 204, 204, 240
boxf rect(0), rect(1), rect(2)+rect(0)-1, rect(3)+rect(1)-1
; 線分描画
color 0, 0, 0
line pt2(0), pt2(1), pt1(0), pt1(1)
pos pt1(0), pt1(1): mes "①"
pos pt2(0), pt2(1): mes "②"
; 交差判定の結果を描画
pos 0, 0
if (result) {
mes "判定結果: 交差している"
} else {
mes "判定結果: 交差していない"
}
; 描画反映
redraw 1
return

| |
|