参考资料:
题目: https://blog.csdn.net/dongtinghong/article/details/78657403
符号重载: https://blog.csdn.net/cdlwhm1217096231/article/details/89326480#commentBox
const: https://blog.csdn.net/kaida1234/article/details/80403534
题目:
已知平面中1个点P和平面内1个三角形(3个顶点坐标A、B、C),判断该点的位置(三角形内,三角形边上,三角形外)。
三种解题思路:
1)
P点落在三角形内或者边上,P与各顶点的连线和三角形各边的夹角之和等于180°。
P点落在三角形外,P与各顶点的连线和三角形各边的夹角之和不等于180°。
2)
P点在三角形内,沿着A-B-C-A方向走,P点都在三角形边的左侧 / 右侧。
3)
选取A点作为顶点,以AB、AC边作为基,平面内所有点都可以写成 P = A + m(B-A) + n(C-A)的形式。
若 m = [0,1], n = [0,1],且m+n = 1,则该点落在三角形内部和边上。
由上式可知,AP = mAB + nAC,其中AP、AB和AC均为向量。
向量方程组:
AP AB = (mAB + nAC)AB
AP AC = (mAB + nAC)AC
解方程组得到m、n。
#include <iostream> #include <vector> using namespace std; typedef int type; class point { public: point(type x_, type y_) :x(x_), y(y_) { } point() { x = 0; y = 0; }; friend ostream &operator<<(ostream &out, point &p); // subtract point operator - (const point &v) const { return point(x-v.x, y-v.y); } // dot product type dot(point v) { return x*v.x + y*v.y; } private: type x; type y; }; ostream &operator<<(ostream &out, point &p) { out << p.x << ", " << p.y; return out; } int wherePoint(vector<point> triP, point tar) { point p0 = triP[0]; point p1 = triP[1]; point p2 = triP[2]; cout << "p0 : " << p0 << endl; cout << "p1 : " << p1 << endl; cout << "p2 : " << p2 << endl; point l0 = p1 - p0; point l1 = p2 - p0; point l2 = tar - p0; type dot00 = l0.dot(l0); type dot01 = l0.dot(l1); type dot11 = l1.dot(l1); type dot02 = l0.dot(l2); type dot12 = l1.dot(l2); double temp = dot01*dot01 - dot11*dot00; double n = (dot02*dot01 - dot00*dot12) / temp; // int / int = int if(n > 1 || n < 0) { cout << "out of range!" << endl; return -1; } double m = (dot02*dot11 - dot01*dot12) / temp * (-1.0); if(m > 1 || m < 0) { cout << "out of range!" << endl; return -1; } if (m == 0 || n == 0) { cout << "on the edge!" << endl; return 0; } if ( m+n <= 1 ){ cout << "in the range!" << endl; return 1; }
else {
return 0;
} } int main (int argc, char** argv){ cout << "Input 3 tri points and 1 point" << endl; vector<point> tripPoints; type a, b; for(int i = 0; i < 3; ++i) { cin >> a; cin >> b; point p(a,b); tripPoints.push_back(p); } cin >> a; cin >> b; point target(a,b); int result = wherePoint(tripPoints, target); return 0; }
C++ 知识点:
1. const修饰成员函数。const放在函数体之前,形参之后,修饰成员函数。该成员函数不能修改对象的成员变量,也不能调用非const的成员函数。
2. const修饰函数形参。当函数形参是指针或引用变量时,const才有意义。若为普通传值形参,由于该形参是对实参的一个拷贝,在函数体内修改了形参对实参没有影响。
在重载 ”-“ 的成员函数中,底层const作用于形参上(常量引用),不能改变引用v的源值。
// subtract point operator - (const point &v) const { return point(x-v.x, y-v.y); }
顶层const修饰的变量,如下所示,
const int ci = 42; // 顶层const,不能修改ci int i = ci; // 正确,当拷贝ci时,忽略ci的顶层const int * const pi = &i; // 顶层const,不能给pi赋值 *pi = 0; // 正确。顶层const,可以通过pi改变对象的内容
函数形参有顶层const修饰时,传给他常量对象或者非常量对象都是可以的。
3. 重载输出符号 <<
cin是istream类的对象,cout是ostream类的对象。如果想实现符号重载,就必须以全局函数(友元函数)的形式重载,或者到标准库中修改相应的函数定义。
ostream &operator<<(ostream &out, point &p) { out << p.x << ", " << p.y; return out; }
由于上述重载函数用到了point类的private变量,因此必须在point类中将该重载函数声明为友元函数。
4. int = int / int ;
double = int / double;