zengh
2021-06-04 c926acaadc3d98fd8ba8926466b842f1edb3aee3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
package org.springblade.jfpt.attendance.util;
 
import org.springblade.jfpt.attendance.entity.Attendance;
import org.springblade.jfpt.enclosure.entity.Enclosure;
import org.springblade.jfpt.enclosure.service.IEnclosureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import javax.annotation.PostConstruct;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 判断当前坐标点是否在多边形区域内
 * @author zhongrj
 * @time 2021--5-14
 */
@Component
public class PointMapUtil {
 
    public static PointMapUtil pointMapUtil;
 
    @Autowired
    private IEnclosureService iEnclosureService;
 
    @PostConstruct
    public void init(){
        pointMapUtil=this;
    }
 
    public static void main(String[] args) {
        Attendance attendance = new Attendance();
        attendance.setNumber("32165165");
        attendance.setJd("114.9161");
        attendance.setWd("25.85101");
        Enclosure enclosure = new Enclosure();
        enclosure.setAnumber(attendance.getNumber());
        //查询当前处警人员的电子围栏信息
        Enclosure enclosureDetail = pointMapUtil.iEnclosureService.selectEnclosureDetail(enclosure);
        //取出经纬度
        Boolean onArea = PointMapUtil.isOnArea(Double.parseDouble(attendance.getJd()),
            Double.parseDouble(attendance.getWd()),
            enclosureDetail.getCoordinate());
        System.out.println("onArea = " + onArea);
    }
 
    /**
     * 判断坐标点是否在多边形区域内
     * @return
     */
    public static Boolean isOnArea(Double x,Double y,String partitionLocation){
        /**
         * 定义一个点
         */
        Point2D.Double point = new Point2D.Double(x, y);
        List<Point2D.Double> pointList= new ArrayList();
        //坐标数据处理
        int i = partitionLocation.indexOf("(");
        int j = partitionLocation.indexOf(")");
        String split = partitionLocation.substring(i+1, j);
        System.out.println("split = " + split);
 
        //读取多边形区域中的顶点
        String[] strList = split.split(",");
 
        //遍历形成多边形区域的顶点
        for (String str : strList){
            String[] points = str.split(" ");
            System.out.println("points[0] = " + points[0]);
            System.out.println("points[1] = " + points[1]);
            double polygonPoint_x=Double.parseDouble(points[1]);
            double polygonPoint_y=Double.parseDouble(points[0]);
            Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x,polygonPoint_y);
            pointList.add(polygonPoint);
        }
        return IsPtInPoly(point,pointList);
    }
 
 
    /**
     * 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
     * @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 = (p.x - p1.x) * (p2.y - p1.y) / (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;
 
        }
 
    }
 
 
    /**
 
     * 返回一个点是否在一个多边形区域内, 如果点位于多边形的顶点或边上,不算做点在多边形内,返回false
 
     * @param point
 
     * @param polygon
 
     * @return
 
     */
 
    public static boolean checkWithJdkGeneralPath(Point2D.Double point, List<Point2D.Double> polygon) {
        java.awt.geom.GeneralPath p = new java.awt.geom.GeneralPath();
 
        Point2D.Double first = polygon.get(0);
 
        p.moveTo(first.x, first.y);
 
        polygon.remove(0);
 
        for (Point2D.Double d : polygon) {
            p.lineTo(d.x, d.y);
 
        }
 
        p.lineTo(first.x, first.y);
 
        p.closePath();
 
        return p.contains(point);
 
    }
 
 
//    public static boolean isPtInPoly (double ALon , double ALat , Point[] ps) {
//        int iSum, iCount, iIndex;
//        double dLon1 = 0, dLon2 = 0, dLat1 = 0, dLat2 = 0, dLon;
//        if (ps.length < 3) {
//            return false;
//        }
//        iSum = 0;
//        iCount = ps.length;
//        for (iIndex = 0; iIndex<iCount;iIndex++) {
//            if (iIndex == iCount - 1) {
//                dLon1 = ps[iIndex].getX();
//                dLat1 = ps[iIndex].getY();
//                dLon2 = ps[0].getX();
//                dLat2 = ps[0].getY();
//            } else {
//                dLon1 = ps[iIndex].getX();
//                dLat1 = ps[iIndex].getY();
//                dLon2 = ps[iIndex + 1].getX();
//                dLat2 = ps[iIndex + 1].getY();
//            }
//            // 以下语句判断A点是否在边的两端点的水平平行线之间,在则可能有交点,开始判断交点是否在左射线上
//            if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
//                if (Math.abs(dLat1 - dLat2) > 0) {
//                    //得到 A点向左射线与边的交点的x坐标:
//                    dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat) ) / (dLat1 - dLat2);
//                    // 如果交点在A点左侧(说明是做射线与 边的交点),则射线与边的全部交点数加一:
//                    if (dLon < ALon) {
//                        iSum++;
//                    }
//                }
//            }
//        }
//        if ((iSum % 2) != 0) {
//            return true;
//        }
//        return false;
//    }
}