Processingでスクリーン座標系とローカル座標系の相互変換を行う
translate()やrotate()などの幾何変換によって移動・変形された座標系(ローカル座標系)と、スクリーンの左上隅を原点とするスクリーン座標系の相互変換を行う方法について説明します。
スクリーン座標系からローカル座標系への変換
スクリーン座標系における座標値を、現在の座標系での座標値に変換します。
PVector screenToLocal(float x, float y) { PVector in = new PVector(x, y); PVector out = new PVector(); PMatrix2D current_matrix = new PMatrix2D(); getMatrix(current_matrix); current_matrix.invert(); current_matrix.mult(in, out); return out; }
ローカル座標系からスクリーン座標系への変換
現在の座標系における座標値を、スクリーン座標系での座標値に変換します。
PVector localToScreen(float x, float y) { PVector in = new PVector(x, y); PVector out = new PVector(); PMatrix2D current_matrix = new PMatrix2D(); getMatrix(current_matrix); current_matrix.mult(in, out); return out; }
使いどころ
このような変換は、移動や回転をしている図形をマウスカーソルで操作するような場合に有用です。以下に具体例を示します。
マウスカーソルの当り判定は長方形のローカル座標上で計算したほうが楽なので、マウスカーソルの座標値(mouseX, mouseY)をいったんローカル座標系での値(mx, my)に変換した後、長方形の中にいるかどうかをif文で判定しています。ちなみにmouseXとmouseYは幾何変換の影響を受けず、つねにスクリーン座標系での値になるようです。
円もまた長方形と同じく回転と平行移動の影響を受けるローカル座標系の中で描かれています。この円の中心とスクリーン座標上の原点(0, 0)との間に線を引くために、ローカルな座標値 (local_x, local_y)をいったんスクリーン座標(screen_x, screen_y)に変換しています。
float rot_angle = 0; float rect_width = 200; float rect_height = 100; void setup() { size(400, 300); } void draw() { background(200); pushMatrix(); translate(width/2, height/2); rotate(rot_angle); translate(-rect_width/2, -rect_height/2); PVector local_mouse = screenToLocal(mouseX, mouseY); float mx = local_mouse.x; float my = local_mouse.y; if ( 0<=mx && mx<=rect_width && 0<=my && my<=rect_height ) { fill(255, 0, 0); } else { fill(0, 255, 0); } rect(0, 0, rect_width, rect_height); float local_x = 30; float local_y = 50; fill(255); ellipse( local_x, local_y, 30, 30 ); PVector screen_pos = localToScreen( local_x, local_y ); float screen_x = screen_pos.x; float screen_y = screen_pos.y; popMatrix(); line(0, 0, screen_x, screen_y ); rot_angle += 0.01; } PVector screenToLocal(float x, float y) { PVector in = new PVector(x, y); PVector out = new PVector(); PMatrix2D current_matrix = new PMatrix2D(); getMatrix(current_matrix); current_matrix.invert(); current_matrix.mult(in, out); return out; } PVector localToScreen(float x, float y) { PVector in = new PVector(x, y); PVector out = new PVector(); PMatrix2D current_matrix = new PMatrix2D(); getMatrix(current_matrix); current_matrix.mult(in, out); return out; }