Google Interview - 判断点是否在凸多边形内的O(logn)解法 - 我的博客 - ITeye技术网站
补充知识:向量叉积,向量P = (x1, y1); Q = (x2, y2); P×Q = (x1*y2 - x2*y1);
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
若 P × Q > 0 , 则P在Q的顺时针方向。
若 P × Q < 0 , 则P在Q的逆时针方向。
若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。
叉积的方向与进行叉积的两个向量都垂直,所以叉积向量即为这两个向量构成平面的法向量。
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
若 P × Q > 0 , 则P在Q的顺时针方向。
若 P × Q < 0 , 则P在Q的逆时针方向。
若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。
叉积的方向与进行叉积的两个向量都垂直,所以叉积向量即为这两个向量构成平面的法向量。
我们来考虑题目,假设凸多边形各个定点坐标按照逆时针方向存储于一个数组中,那么可以通过计算0-i与0-P两个向量之间的左右关系确定点P于某两个相邻的顶点构成的向量之间,如O-x与o-(x-1),然后看是否(x-1)-p向量位于(x-1)-x向量的逆时针方向,如果是顺时针方向则不在凸多边形内。
- double multiply(Point& p1, Point& p2, Point& p0) {
- return (p1.x - p0.x) * (p2.y - p0.y)*1.0 - (p1.y - p0.y) * (p2.x - p0.x)*1.0;
- }
- bool inConvexPolygon(vector<Point> Polygon, Point target) {
- int len = Polygon.size();
- if (multiply(target, Polygon[1], Polygon[0]) > 0 && multiply(target, Polygon[len - 1], Polygon[0]) < 0) {
- return false;
- }
- int s = 1, e = len -1;
- int line = -1;
- while (s <= e) {
- int m = s + ((e-s) >> 1);
- if (multiply(target, Polygon[m], Polygon[0]) > 0) { // target在m顺时针方向
- line = m; // line保存的是m逆时针方向后的第一个点
- e = m -1;
- } else { // target在m逆时针方向
- s = m + 1;
- }
- }
- return multiply(Polygon[line], target, Polygon[line -1]) > 0;
- }