GameDev – Vector: Khoảng cách từ điểm đến đoạn thẳng

ruler_triangle_measureDựa vào phép chiếu từ tích vô hướng (Dot product) của hai vector, ta có thể tính được khoảng cách từ một điểm đến một đường thẳng, đoạn thẳng.

Xem Demo.

Bài toán: Tìm khoảng cách từ điểm C đến đoạn thẳng AB.

Giải quyết:
Ta sẽ tính vector chiếu của AC lên AB và gọi là AH. Vì CH vuông góc với AB và khoảng cách từ C đến AB chính là CH. Như vậy ta tính được khoảng cách từ một điểm đến một đường thẳng chứa AB.

Để tìm khoảng cách đến đoạn thẳng, ta cần xác định H có thuộc AB hay không. Ta xem lại một chút về tích vô hướng của hai vector.

Distance Point to Line

Kết quả của tích vô hướng có 3 khoảng giá trị để ta có thể ước lượng được góc giữa hai vector (bỏ qua chiều âm/dương):

Case 1 (Dot product < 0): Góc giữa hai vector lớn hơn 90 độ. Điểm H nằm ngoài AB.

Case 2 (Dot product = 0): Hai vector vuông góc với nhau (90 độ). Điểm H trùng với A.

Case 3 (Dot product > 0): Góc giữa hai vector nhỏ hơn 90 độ. Điểm H có thể nằm trong AB hoặc không. Điểm H sẽ nằm ngoài AB nếu như độ dài AH > AB.

Dot product range

function pointLineDistance(){

	// v1: AC
	// v2: AB
	// v3: AH

	var v1 = _line1.getVector();
	var v2 = _line2.getVector();

	// normalize vector v2
	v2.dx = v2.x/v2.length;
	v2.dy = v2.y/v2.length;

	// dot product
	var dp = v1.x*v2.x + v1.y*v2.y;
	// length of the projection of v1 on v2
	var length = dp/v2.length;

	// the projection vector of v1 on v2
	var v3 = {
		x: length*v2.dx,
		y: length*v2.dy,
	};
	v3.length = Math.sqrt(v3.x*v3.x+v3.y*v3.y);

	// the projection line
	_line3.p2.x = _line3.p1.x+v3.x;
	_line3.p2.y = _line3.p1.y+v3.y;

	var d; // distance
	// d = -1 means H does not lie on AB

	if(dp < 0)
	{
		d = -1;
	}
	else
	{
		if(v3.length > v2.length)
			d = -1;
		else
		{
			var dx = v1.x-v3.x;
			var dy = v1.y-v3.y;
			d = Math.sqrt(dx*dx+dy*dy);
		}
	}

	return d;
}

YinYang’s Blog