代碼地址:
原理
開發 -> Web服務 API -> 開發指南 -> API文檔 -> 地理圍欄
使用規則
配置好數據庫
global:
datasource:
service:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://90service:2019/geo-fencing?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
geo-fencing-backend:
server-name: geo-fencing-backend
port: 8081
配置前端地址:
const url = 'http://192.168.30.95:8081';
export default {url}
啓動前端:
使用命令
npm start
瀏覽器打開地址 http://localhost:3333/#/ 可以查看界面
啓動後端
配置好數據庫後,啓動系統
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GeoFencingBackendApplication {
public static void main(String[] args) {
SpringApplication.run(GeoFencingBackendApplication.class, args);
}
}
使用
打開界面後,首先點擊編輯圍欄
開始畫區域,雙擊鼠標完成畫圖,點擊結束編輯圍欄後,數據後傳輸到後臺
最後,拖動座標,可以查看座標是不是在多邊形裏面。
核心算法
import java.awt.geom.Point2D;
import java.util.List;
public class InOrOutPolygonUtils {
/**
* 判斷點是否在多邊形內
* @param point 檢測點
* @param pts 多邊形的頂點
* @return 點在多邊形內返回true,否則返回false
*/
public static boolean IsPtInPoly(Point2D.Double point, List<Point2D.Double> pts){
int N = pts.size();
boolean boundOrVertex = true; //如果點位於多邊形的頂點或邊上,也算做點在多邊形內,直接返回true
int intersectCount = 0;//cross points count of x
double precision = 2e-10; //浮點類型計算時候與0比較時候的容差
Point2D.Double p1, p2;//neighbour bound vertices
Point2D.Double p = point; //當前點
p1 = pts.get(0);//left vertex
for(int i = 1; i <= N; ++i){//check all rays
if(p.equals(p1)){
return boundOrVertex;//p is an vertex
}
p2 = pts.get(i % N);//right vertex
if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){//ray is outside of our interests
p1 = p2;
continue;//next ray left point
}
if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){//ray is crossing over by the algorithm (common part of)
if(p.y <= Math.max(p1.y, p2.y)){//x is before of ray
if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){//overlies on a horizontal ray
return boundOrVertex;
}
if(p1.y == p2.y){//ray is vertical
if(p1.y == p.y){//overlies on a vertical ray
return boundOrVertex;
}else{//before ray
++intersectCount;
}
}else{//cross point on the left side
double xinters = (NumberUtils.sub(p.x , p1.x)) * (NumberUtils.sub(p2.y , p1.y)) / (NumberUtils.sub(p2.x , p1.x)) + p1.y;//cross point of y
if(Math.abs(p.y - xinters) < precision){//overlies on a ray
return boundOrVertex;
}
if(p.y < xinters){//before ray
++intersectCount;
}
}
}
}else{//special case when ray is crossing through the vertex
if(p.x == p2.x && p.y <= p2.y){//p crossing over p2
Point2D.Double p3 = pts.get((i+1) % N); //next vertex
if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){//p.x lies between p1.x & p3.x
++intersectCount;
}else{
intersectCount += 2;
}
}
}
p1 = p2;//next ray left point
}
if(intersectCount % 2 == 0){//偶數在多邊形外
return false;
} else { //奇數在多邊形內
return true;
}
}
}