1. 程式人生 > >如何判斷一個點是否在矩形之內及C++的操作符重載

如何判斷一個點是否在矩形之內及C++的操作符重載

ati 優先級 計算 poi math least 代碼實現 check ins

一、常規情況 通常情況下,這個矩形都是和坐標系平行的一個矩形,例如典型的windows系統中,一個窗口總是和屏幕坐標平行的。在這種情況下,判斷一個點是否在矩形之內就非常簡單:只需要判斷該點在x和y軸方向是否在矩形範圍內即可。 簡單代碼如下,當然,如果在確定x1和x2關系的情況,實現可以更加簡潔。 tsecer@harry: cat point.in.rect.cpp struct rect { int x1,y1; int x2,y2; bool InRect(int x, int y) { return (x1 -x) * (x2 - x) <= 0 && (y1 - y) * (y2 - y) <= 0; } }; 二、考慮旋轉之後的矩形
如果把矩形在坐標系中旋轉一下,此時判斷一個給定點是否在舉行內就更加麻煩一些。直觀的想法是把矩形和點都進行坐標系旋轉,旋轉為和坐標軸平行的正經矩形,此時判斷就簡單很多。問題在於,判斷邏輯比較簡單,但是旋轉比較復雜,並且代價很高,需要計算cos、sin等浮點運算。 這個時候,如果利用矩陣點乘的幾何意義,這個判斷就比較簡潔。向量的點乘結果為兩個向量的長度和夾角theta的cos theta的乘積。所以如果一個點在矩形之內,那麽它在矩形一邊上的投影(cos theta)就應該小於另外一邊。 假設說待判斷點為P,一邊為A和B,並且PA與PB之間的夾角為theta,那麽|PA|*cos theta <|AB| 兩遍同時乘以|AB|, |PA||AB| cos theta < |AB| |AB|,由於AB重合,所以cos theta為1,上面的表達式就是 向量 PA 和 AB 的點乘 小於 AB向量自己的點乘。 這個是一個最關鍵的判斷條件,也就是下面的討論所表達的主要觀點https://math.stackexchange.com/questions/190111/how-to-check-if-a-point-is-inside-a-rectangle。我們使用代碼實現下,其中使用的是一個變長為2的正方形,傾斜45度。 tsecer@harry: cat point.in.rect.cpp #include <stdio.h> struct point { int x, y; point(): x(),y() {} point(int ix, int iy) :x(ix),y(iy) {} point operator - (point p) { return point(x - p.x, y - p.y); } int operator *(point p) { return x * p.x + y * p.y; } }; struct rect { point p[3]; rect(point p1, point p0, point p2) { p[0] = p0; p[1] = p1; p[2] = p2; } bool pointinrect(point pp) { for (int i = 1; i < 3; i++) { int iMid = (pp - p[0]) * (p[i] - p[0]); int iUp = (p[i] - p[0]) * (p[i] - p[0]); if (!(0 <= iMid && iMid <= iUp)) { return false; } } return true; } }; int main(int argc, char * argv[]) { rect r(point(0,2), point(2, 0), point(4, 2)); for (int i = 0; i < 6; i++) { for (int j = 0; j < 6; j++) { printf("point x %d y %d %s in rect\n", i, j, r.pointinrect(point(i, j))? "" : "not" ); } } return 0; } tsecer@harry: g++ point.in.rect.cpp tsecer@harry: ./a.out point x 0 y 0 not in rect point x 0 y 1 not in rect point x 0 y 2 in rect point x 0 y 3 not in rect point x 0 y 4 not in rect point x 0 y 5 not in rect point x 1 y 0 not in rect point x 1 y 1 in rect point x 1 y 2 in rect point x 1 y 3 in rect point x 1 y 4 not in rect point x 1 y 5 not in rect point x 2 y 0 in rect point x 2 y 1 in rect point x 2 y 2 in rect point x 2 y 3 in rect point x 2 y 4 in rect point x 2 y 5 not in rect point x 3 y 0 not in rect point x 3 y 1 in rect point x 3 y 2 in rect point x 3 y 3 in rect point x 3 y 4 not in rect point x 3 y 5 not in rect point x 4 y 0 not in rect point x 4 y 1 not in rect point x 4 y 2 in rect point x 4 y 3 not in rect point x 4 y 4 not in rect point x 4 y 5 not in rect point x 5 y 0 not in rect point x 5 y 1 not in rect point x 5 y 2 not in rect point x 5 y 3 not in rect point x 5 y 4 not in rect point x 5 y 5 not in rect tsecer@harry: 代碼中要求iMid >= 0,這個可以保證 PA 和 AB之間的夾角在90以內,由於另外一邊同樣要求 PA 和 AC 之間夾角在90度以內,所以這個邊就PA就不可能在矩形之外(因為BA和CA之間夾角為90)。 三、C++算符的重載
《ANSI C++ Reference.pdf》 13.5 Overloaded operators 6 An operator function shall either be a nonstatic member function or be a nonmember function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration. It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific types by defining operator functions that implement these operators. Operator functions are inherited the same as other functions, but because an instance of operator= is automatically constructed for each class (12.8, 13.5.3), operator= is never inherited by a class from its bases. 這裏的強限制在於,至少要有一個參數的類型是類、類的引用、枚舉、或者枚舉的引用。並且不能改變操作符的優先級、分組或者是操作數的個數。 值得註意的是,這個地方並沒有對操作符的返回值類型進行任何約束,也就是說 == 操作符的結果並不一定需要是返回一個bool值。例如 tsecer@harry: cat -n c++.operator.overload.cpp 1 #include <stdio.h> 2 3 struct S 4 { 5 S operator == (int i) 6 { 7 return *this; 8 } 9 10 int x; 11 12 }; 13 14 int main() 15 { 16 S s; 17 S ss = s==10; 18 19 if (s == 10) 20 { 21 return 0; 22 } 23 } tsecer@harry: g++ c++.operator.overload.cpp c++.operator.overload.cpp: In function ‘int main()’: c++.operator.overload.cpp:19:7: error: could not convert ‘s.S::operator==(10)’ from ‘S’ to ‘bool’ if (s == 10) ^ tsecer@harry: 可以看到,只是在使用的時候出錯,函數返回任意類型都可以通過編譯。

如何判斷一個點是否在矩形之內及C++的操作符重載