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
| /** * 判断点是否在边上 * * @param lineList * @param targetPoint * @return */ public static boolean isOnLine(List<Line2D> lineList, Point2D targetPoint) { for (int i = 0; i < lineList.size(); i++) { Line2D line = lineList.get(i); if (line.isIn(targetPoint)) { return true; } } return false; }
/** * 点是否在线段内 * @param tPoint * @return */ public boolean isIn(Point2D tPoint) { if (startPoint!=null&&endPoint!=null){ Vector2D tVector = new Vector2D(tPoint.x - startPoint.x, tPoint.y - startPoint.y); Vector2D startVector = new Vector2D(endPoint.x - startPoint.x, endPoint.y - startPoint.y); double v = startVector.crossProduct(tVector); double yDis = Math.abs(v / startVector.getLength()); if (yDis<RANGE){//tPoint在直线上 if (contain(tPoint)){//tPoint在线段上 return true; } } } return false; }
public class IntersectData implements Cloneable { public Point2D point2D; public int polygonLineIndex;//此处值为-1表示边界点 -5表示障碍区的边 -4表示额外增加的障碍区点
public IntersectData(Point2D point2D, int crossLineIndex, int polygonLineIndex) { this.point2D = point2D; this.crossLineIndex = crossLineIndex; this.polygonLineIndex = polygonLineIndex; } }
/** * 获取点到直线的距离,正值表示在startVector直线上方,负值表示在startVector直线下方 * * @param startPoint * @param endPoint * @param targetPoint * @return */ public static double getRealYDis(Point2D startPoint, Point2D endPoint, Point2D targetPoint) { Vector2D startVector = new Vector2D(endPoint.x - startPoint.x, endPoint.y - startPoint.y); Vector2D endVector = new Vector2D(targetPoint.x - startPoint.x, targetPoint.y - startPoint.y); double v = startVector.crossProduct(endVector); double dis = v / startVector.getLength(); double angle = startVector.getAngle(); if (angle >= -90 && angle < 90) { dis = dis; } else { dis = -dis; } return dis; }
//点与直线x轴上的距离 public static double getXDis(Point2D startPoint, Point2D endPoint, Point2D targetPoint) { Vector2D startVector = new Vector2D(endPoint.x - startPoint.x, endPoint.y - startPoint.y); Vector2D endVector = new Vector2D(targetPoint.x - startPoint.x, targetPoint.y - startPoint.y); double v = startVector.dotProduct(endVector); return v / startVector.getLength(); }
/** * 判断目标点是否在指定多边形内,适应全部多边形 * * @param target * @param latLongList * @return */ public static boolean isInPolygon(LatLong target, List<LatLong> latLongList) { //目标点 Point2D targetPoint = loc2Point2D(latLongList.get(0), target, -1);
//多边形的点 List<Point2D> pointList = loc2Point2D(latLongList.get(0), latLongList);
//多边形的边 List<Line2D> lineList = point2Line(pointList);
Point2D toPoint = new Point2D(targetPoint.x + 100, targetPoint.y, -1); Line2D crossLine = new Line2D(targetPoint, toPoint);
//判断点是否在多边形的边上 if (isOnLine(lineList, targetPoint)) {//点在边上 return true; } //交点集合 ArrayList<IntersectData> intersectPoint2DList = new ArrayList<>(); for (int i = 0; i < lineList.size(); i++) { //平行 if (crossLine.isParallel(lineList.get(i))){ //判断是否重合 if (Math.abs(crossLine.a * lineList.get(i).startPoint.x + crossLine.b * lineList.get(i).startPoint.y + crossLine.c) < 0.1) { int next = (i+1)%lineList.size(); int first = (lineList.size()+i-1)%lineList.size(); int temp; if (next < first){ temp = next; next = first; first = temp; } //左右邻边 Line2D firstLine = lineList.get(first); Line2D nextLine = lineList.get(next); //判断这两点是否在横截线同一边 Point2D startPoint = new Point2D((firstLine.startPoint.x + firstLine.endPoint.x) / 2, (firstLine.startPoint.y + firstLine.endPoint.y) / 2, -1); Point2D endPoint = new Point2D((nextLine.startPoint.x + nextLine.endPoint.x) / 2, (nextLine.startPoint.y + nextLine.endPoint.y) / 2, -1);
double startYDis = getRealYDis(targetPoint, toPoint, startPoint); double endYDis = getRealYDis(targetPoint, toPoint, endPoint);
if (startYDis > -0.1 && startYDis < 0.1) { startYDis = 0; } if (endYDis > -0.1 && endYDis < 0.1) { endYDis = 0; }
if (startYDis * endYDis < 0) {//邻边在射线两端 intersectPoint2DList.add(new IntersectData(new Point2D((lineList.get(i).startPoint.x+lineList.get(i).endPoint.x)/2, (lineList.get(i).startPoint.y+lineList.get(i).endPoint.y)/2,-1),-1,i)); } } }else { Point2D intersectPoint = crossLine.getIntersectPoint(lineList.get(i)); if (intersectPoint != null) {//targetLine与多边形的边相交 intersectPoint2DList.add(new IntersectData(intersectPoint, -1, i)); } } } ArrayList<Pair<Integer, Integer>> pairList = new ArrayList<>(); for (int i = 1; i < intersectPoint2DList.size(); i++) { IntersectData first = intersectPoint2DList.get(i - 1); IntersectData next = intersectPoint2DList.get(i); double firstDis = getXDis(targetPoint, toPoint, first.point2D); double nextDis = getXDis(targetPoint, toPoint, next.point2D); if (Math.abs(nextDis - firstDis) < 0.1) {//交点重合 int firstLineIndex = first.polygonLineIndex; int nextLineIndex = next.polygonLineIndex; Line2D firstLine = lineList.get(firstLineIndex);//交点i - 1对应的线段 Line2D nextLine = lineList.get(nextLineIndex);//交点i对应的线段
//判断这两点是否在横截线同一边 Point2D startPoint = new Point2D((firstLine.startPoint.x + firstLine.endPoint.x) / 2, (firstLine.startPoint.y + firstLine.endPoint.y) / 2, -1); Point2D endPoint = new Point2D((nextLine.startPoint.x + nextLine.endPoint.x) / 2, (nextLine.startPoint.y + nextLine.endPoint.y) / 2, -1);
double startYDis = getRealYDis(targetPoint, toPoint, startPoint); double endYDis = getRealYDis(targetPoint, toPoint, endPoint);
if (startYDis > -0.1 && startYDis < 0.1) { startYDis = 0; } if (endYDis > -0.1 && endYDis < 0.1) { endYDis = 0; } if (startYDis * endYDis >= 0) {//同一边 //不用处理,直接当两个交点 } else {//dis1*dis2<0 在两端 //把两交点合并一点 pairList.add(Pair.create(i - 1, i)); } } } for (int i = 0; i < pairList.size(); i++) { Pair<Integer, Integer> pair = pairList.get(i); int first = pair.first; int second = pair.second; //移除其中一个即可 intersectPoint2DList.remove(first); } //去除在targetPoint点负方向的点(去除正方向也行,只要取一个方向的交点即可) Iterator<IntersectData> iterator = intersectPoint2DList.iterator(); while (iterator.hasNext()) { IntersectData next = iterator.next(); Point2D point2D = next.point2D; double xDis1 = getXDis(targetPoint, toPoint, point2D);//交点到原点的X轴距离 if (xDis1 < -0.1) { iterator.remove(); } } if (intersectPoint2DList.size() % 2 != 0) {//交点数为奇数 targetPoint点在多边形内 return true; } return false; }
|