判断点是否在多边形内部有多种算法,这里主要参考了 http://blog.youkuaiyun.com/hgl868/article/details/7947272 用C语言编写的射线法
然后将C的算法改成了scala编写,用于实际工作需要_(:зゝ∠)_,主要是地图区域数据处理用的,效果还不错
点的类
class myPoint { var x: Double = 0 var y: Double = 0 }
线的类
class LineSegment { var pt1: myPoint = new myPoint() var pt2: myPoint = new myPoint() }
工具类
import java.util /** * Created by luojie on 2017/1/26. */ class polygonServer { val INFINITY: Double = 1e10 val ESP: Double = 1e-5 // 判断点在多边形内 def inPolygon(polygon: util.ArrayList[myPoint], point: myPoint): Boolean = { //顶点数 val n = polygon.size() //射线与多边形交点数 var count = 0 //定义射线 val line: LineSegment = new LineSegment line.pt1 = point line.pt2.y = point.y line.pt2.x = -INFINITY for (i <- 0 to n - 1) { // 得到多边形的一条边 val side: LineSegment = new LineSegment() side.pt1 = polygon.get(i) side.pt2 = polygon.get((i + 1) % n) if (isOnline(point, side)) { return true } // 如果side平行x轴则不作考虑 if (dabs(side.pt1.y - side.pt2.y) < ESP) { } // if (isOnline(side.pt1, line)) { if (side.pt1.y > side.pt2.y) count += 1 } else if (isOnline(side.pt2, line)) { if (side.pt2.y > side.pt1.y) count += 1 } else if (intersect(line, side)) { count += 1 } } if (count % 2 == 1) { return true } else {return flase }} // 计算叉乘 |P0P1| × |P0P2| def multiply(p1: myPoint, p2: myPoint, p0: myPoint): Double = (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) // 判断线段是否包含点point def isOnline(point: myPoint, line: LineSegment): Boolean = (dabs(multiply(line.pt1, line.pt2, point)) < ESP) && ((point.x - line.pt1.x) * (point.x - line.pt2.x) <= 0) && ((point.y - line.pt1.y) * (point.y - line.pt2.y) <= 0) // 判断线段相交 def intersect(L1: LineSegment, L2: LineSegment): Boolean = (maxBy(L1.pt1.x, L1.pt2.x) >= minBy(L2.pt1.x, L2.pt2.x)) && (maxBy(L2.pt1.x, L2.pt2.x) >= minBy(L1.pt1.x, L1.pt2.x)) && (maxBy(L1.pt1.y, L1.pt2.y) >= minBy(L2.pt1.y, L2.pt2.y)) && (maxBy(L2.pt1.y, L2.pt2.y) >= minBy(L1.pt1.y, L1.pt2.y)) && (multiply(L2.pt1, L1.pt2, L1.pt1) * multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) && (multiply(L1.pt1, L2.pt2, L2.pt1) * multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)//绝对值 def dabs(x: Double): Double = if (x > 0) x else 0 - x //取较大值 def maxBy(x: Double, y: Double): Double = if (x > y) x else y //取较小值 def minBy(x: Double, y: Double): Double = if (x < y) x else y }