RoadCutDoubleName.java 16.6 KB
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 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
package com.bsth.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsth.entity.LonLatName;
import com.bsth.util.CoordinateConverter.Location;
import com.bsth.util.CoordinateConverter;

import java.net.URLEncoder;
import java.util.*;

public class RoadCutDoubleName {

	// 存放获取交点的经纬度,路段名字
	static ArrayList<LonLatName> al = new ArrayList<LonLatName>();

	public static Map<String, Object> start(String sectionStr) throws Exception {

		al.clear();
		// 存放过滤后返还会来的list集合
		ArrayList dl = new ArrayList();

		String fy = URLEncoder.encode("|", "utf-8");
		String lL = baiduToGoogle(sectionStr);
		String[] lonLat = lL.split(";");

		int number = 0;
		if (lonLat.length % 20 == 0) {
			number = lonLat.length / 20;
		} else {
			number = lonLat.length / 20 + 1;
		}
		int middle = 0;
		int max = 20;
		if (lonLat.length >= 20) {
			for (int NOT = 1; NOT <= number; NOT++) {
				String Ol = "";
				if (NOT < number) {
					for (int min = middle; min < max; min++) {
						if (min < max - 1) {
							Ol += lonLat[min] + fy;
						} else {
							Ol += lonLat[min];
						}
					}
					dl = getData(Ol,al);
					middle = max;
					max += 20;
				} else {
					for (int min = middle; min < lonLat.length; min++) {
						if (min < lonLat.length - 1) {
							Ol += lonLat[min] + fy;
						} else {
							Ol += lonLat[min];
						}
					}
					dl = getData(Ol,al);
				}
			}
		} else {
			String Ol = "";
			for (int min = middle; min < lonLat.length; min++) {
				if (min < lonLat.length - 1) {
					Ol += lonLat[min] + fy;
				} else {
					Ol += lonLat[min];
				}
			}
			dl = getData(Ol,al);
		}
		// 将原有的经纬度数组转换为list集合
		ArrayList<Location> el = new ArrayList<>();
		for (int j = 0; j < lonLat.length; j++) {
			String lon[] = lonLat[j].split(",");
			Location point = new Location();
			point.setLng(Double.valueOf(lon[0]));
			point.setLat(Double.valueOf(lon[1]));
			el.add(point);
		}
		ArrayList<Location> gl = new ArrayList<>();
		for (int k = 0; k < dl.size(); k += 4) {
			Location point = new Location();
			String object = (String) dl.get(k);
			String[] split = object.split(",");
			point.setLng(Double.valueOf(split[0]));
			point.setLat(Double.valueOf(split[1]));
			gl.add(point);
		}
		// 将做过处理的百度坐标与过滤后的交点坐标存入,传给垂足获取方法
		ArrayList fl = new ArrayList();
		// 路的坐标点
		fl.add(0, el);
		// 路的交点
		fl.add(1, gl);
		List returnData = returnData(fl);
		ArrayList<Location> pointList = new ArrayList<>();
		for (int x = 0; x < returnData.size(); x++) {
			List<Location> aList = new ArrayList<>();
			aList = (List<Location>) returnData.get(x);
			for (int z = 0; z < aList.size(); z++) {
				Location point = new Location();
				Location location = aList.get(z);
				point.setLng(location.getLng());
				point.setLat(location.getLat());
				pointList.add(point);
			}
		}
		/*
		 * 垂足返还的数据中每三条为一个交点,第一经纬度为前,第二为后,第三为原交点的垂足
		 * 下面循环会将返还的数据按前经纬度与返还数据的第一经纬度相匹配 将返还数据的第三个经纬度按顺序插入进去
		 */
		// lonLat:转换为高德的坐标点数组
		for (int t = 0; t < pointList.size(); t += 3) {
			Location pl = (Location) pointList.get(t);
			Location newPl = (Location) pointList.get(t + 1);
			// 判断切点是否添加成功
			boolean type = false;
			// pointList:包含前后垂足的集合,每三个一个轮回
			for (int o = 0; o < el.size() - 1; o++) {
				Location location1 = el.get(o);
				Location location2 = el.get(o + 1);
				if (location1.getLng() == pl.getLng() && location1.getLat() == pl.getLat()
						&& location2.getLng() == newPl.getLng() && location2.getLat() == newPl.getLat()) {
					if (o < el.size() - 1) {
						// el:存放原始坐标Location对象的集合
						el.add(o + 1, (Location) pointList.get(t + 2));
						type = true;
						break;
					} else {
						el.add(o, (Location) pointList.get(t + 2));
						type = true;
						break;
					}
				}
			}
			// 防止在同一线段下的两个切点会只添加一个
			if (!type) {
				for (int o = 0; o < el.size(); o++) {
					Location location = el.get(o);
					if (location.getLng() == newPl.getLng() && location.getLat() == newPl.getLat()) {
						el.add(o, (Location) pointList.get(t + 2));
						type = true;
						break;
					}
				}
			}
		}
		// 通过返还的垂足数据,将原有的中间点给替换掉
		int w = 0;
		for (int q = 2; q < pointList.size(); q += 3) {
			Location pL = (Location) pointList.get(q);
			dl.set(w, pL.getLng() + "," + pL.getLat());
			w += 4;
		}
		// 对替换后的location进行路名拼接,十个点则应拼接出九个路段路名
		// 若location获取的路名不符合规则,则返还“(-)”
		int maxOne = 2;
		int maxTwo = 6;
		int minOne = 1;
		int minTwo = 5;
		String theMainRoad = "";
		String theFirstRoad = "";
		String theSecondRoad = "";
		List<String> roadName = new ArrayList<>();
		for (int d = maxTwo; d < dl.size();) {
			boolean buff = false;
			// 若两段路名中含有相同的路名,则此路名作为主路名
			for (int h = minOne; h <= maxOne; h++) {
				for (int f = minTwo; f <= maxTwo; f++) {
					if (dl.get(h).equals(dl.get(f))) {
						theMainRoad = dl.get(h).toString();
						buff = true;
						break;
					} else {
						theMainRoad = "";
					}
				}
				if (buff) {
					break;
				}
			}
			// 获取主路名后,将主路名不为空的进行拼接
			// 规则为:两段路名的firstName和secondName不与主路名相同
			// 存入roadName列表且按数序包含无法进行拼接的路名返回值为“(-)”
			for (int h = minOne; h <= maxOne; h++) {
				for (int f = minTwo; f <= maxTwo; f++) {
					if (!theMainRoad.equals("")) {
						if (!dl.get(h).equals(theMainRoad)) {
							theFirstRoad = dl.get(h).toString();
							if (!dl.get(f).equals(theMainRoad)) {
								theSecondRoad = dl.get(f).toString();
							}
						}
					} else {
						theFirstRoad = "";
						theSecondRoad = "";
					}
				}
			}
			minOne += 4;
			minTwo += 4;
			maxOne += 4;
			maxTwo += 4;
			d = maxTwo;
			roadName.add(theMainRoad + "(" + theFirstRoad + "-" + theSecondRoad + ")");
		}
		// 将所有经纬度列表进行重复过滤
		for (int i = 0; i < el.size() - 1; i++) {
			Location location = el.get(i);
			for (int j = i + 1; j < el.size(); j++) {
				Location location2 = el.get(j);
				if (location.getLng() == location2.getLng() && location.getLat() == location2.getLat()) {
					el.remove(j);
					break;
				}
			}
		}
		// 用来区分此线路的开始是否等于location的第一个点
		boolean buff = false;
		//将路名roadName与路段roadNumber添加进theFrontDesk返还给前台
		Map<String, Object> theFrontDesk = new HashMap<>();
		// 若坐标组的第一个坐标与交点的第一个不相同,就说明实际规划出的线路条数+1
		// 此方法的作用就是用来避免线路名称与线路不对称
		if(dl.size() != 0) {
			String firstLocation = (String) dl.get(0);
			String[] firstLocationSplit = firstLocation.split(",");
			Location firstOfAll = el.get(0);
			if (firstOfAll.getLng() != Double.valueOf(firstLocationSplit[0])
					&& firstOfAll.getLat() != Double.valueOf(firstLocationSplit[1])) {
				roadName.add(0, "(-)");
				buff = true;
			}
			String lastLocation = (String) dl.get(dl.size() - 4);
			String[] lastLocationSplit = lastLocation.split(",");
			Location lastOfAll = el.get(el.size() - 1);
			if (lastOfAll.getLng() != Double.valueOf(lastLocationSplit[0])
					&& lastOfAll.getLat() != Double.valueOf(lastLocationSplit[1])) {
				roadName.add(roadName.size(), "(-)");
			}
			//切分路段,有两种情况,路段的第一个经纬度既是切点,则从第二个点开始计算
			//路段的前几个点是多余的点 则将其保留,并且上面的方法就是用来防止第一个路段路名错误
			List roadNumber = new ArrayList();
			if (buff) {
				int logo = 0;
				for (int j = 0; j < dl.size(); j += 4) {
					List wayNumber = new ArrayList();
					String object = (String) dl.get(j);
					String[] split = object.split(",");
					for (int i = logo; i < el.size(); i++) {
						Location location = el.get(i);
						wayNumber.add(el.get(i));
						if (location.getLng() == Double.valueOf(split[0])
								&& location.getLat() == Double.valueOf(split[1])) {
							logo = i;
							roadNumber.add(wayNumber);
							break;
						}
						if(i == el.size()-1){
							logo = i;
							roadNumber.add(wayNumber);
						}
					}
				}
			}else{
				int logo = 0;
				for (int j = 4; j < dl.size(); j += 4) {
					List wayNumber = new ArrayList();
					String object = (String) dl.get(j);
					String[] split = object.split(",");
					for (int i = logo; i < el.size(); i++) {
						Location location = el.get(i);
						wayNumber.add(el.get(i));
						if (location.getLng() == Double.valueOf(split[0])
								&& location.getLat() == Double.valueOf(split[1])) {
							logo = i;
							roadNumber.add(wayNumber);
							break;
						}
						if(i == el.size()-1){
							logo = i;
							roadNumber.add(wayNumber);
						}
					}
				}
			}
			List bSections = googleToBaidu(roadNumber);
			//将路名roadName与路段roadNumber添加进theFrontDesk返还给前台
//			List theFrontDesk = new ArrayList();
			theFrontDesk.put("roadName",roadName);
			theFrontDesk.put("bSections",bSections);
			for(int i =0;i<bSections.size();i++){
				List<Location> rn = new ArrayList<>();
				rn = (List<Location>) bSections.get(i);
				System.out.println("第"+(i+1)+"条路");
				System.out.println(roadName.get(i));
				for(int j=0;j<rn.size();j++){
					Location object = (Location) rn.get(j);
					System.out.println(object.getLng()+" "+object.getLat()+";");
				}
			}
		}

        return theFrontDesk;
	}

	public static ArrayList<LonLatName> getData(String Ol,ArrayList<LonLatName> al) throws Exception {
		// 将去重后的list列表添加进来
		ArrayList cl = new ArrayList();
		StringBuilder sb = HttpClientUtils.get("http://restapi.amap.com/v3/geocode/regeo?output=json&location=" + Ol
				+ "&key=ae7b43460cab274a8702b55640f9a5a7&radius=0&extensions=all&batch=true&roadlevel=1");
		JSONObject jsonarr = JSON.parseObject(sb.toString());
		JSONArray regeocodes = jsonarr.getJSONArray("regeocodes");

		for (int a = 0; a < regeocodes.size(); a++) {
			LonLatName lln = new LonLatName();
			JSONObject json = (JSONObject) regeocodes.get(a);
			JSONArray roadinters = json.getJSONArray("roadinters");
			JSONArray roads = json.getJSONArray("roads");
			JSONObject jsonObject = roadinters.getJSONObject(0);
			JSONObject roadsObject = roads.getJSONObject(0);
			lln.setFirst_name(jsonObject.getString("first_name"));
			lln.setSecond_name(jsonObject.getString("second_name"));
			lln.setLocation(jsonObject.getString("location"));
			lln.setWay_name(roadsObject.getString("name"));
			al.add(lln);
		}
		int a = 0;
		for (int b = 1; b < al.size(); b++) {
			if (al.get(b).getWay_name().equals(al.get(b).getFirst_name())
					|| al.get(b).getWay_name().equals(al.get(b).getSecond_name())) {
				if (b == 1) {
					cl.add(al.get(a).getLocation());
					cl.add(al.get(a).getFirst_name());
					cl.add(al.get(a).getSecond_name());
					cl.add(al.get(a).getWay_name());
				}
				if (!al.get(a).getLocation().equals(al.get(b).getLocation())) {

					cl.add(al.get(b).getLocation());
					cl.add(al.get(b).getFirst_name());
					cl.add(al.get(b).getSecond_name());
					cl.add(al.get(b).getWay_name());
					a = b;
				}
			}
		}
		return cl;
	}

	// 处理所有的切点(用每个切点去匹配到整条路段上最近的点)
	public static List returnData(ArrayList twoList) {
//		List<Location> aList = new ArrayList<>();
//		List<Location> wip = new ArrayList<>();
		// 路的坐标点
		List<Location> aList = (List<Location>) twoList.get(0);
		// 路的交点
		List<Location> wip = (List<Location>) twoList.get(1);
		List<List<Location>> list = new ArrayList<>();
		for (int j = 0; j < wip.size(); j++) {
			Map<Double, List<Location>> points = new HashMap<>();
			for (int i = 1; i < aList.size(); i++) {
				// 获取最近点为切点
				points.putAll(ClosestPoint.GetNearestDistance(aList.get(i - 1), aList.get(i), wip.get(j)));
			}
			// points 为返回的所有切点的集合
			Object[] obj = points.keySet().toArray();
			Arrays.sort(obj);
			list.add(j,points.get(obj[0]));
		}
		return list;
	}

	// 百度坐标解密位高德
	public static String baiduToGoogle(String sectionStr) {
		String gdLL="";
//		String lL = "121.531301,31.211823;121.532438,31.213784;121.532438,31.213784;121.535025,31.213764;121.535095,31.213765;121.535702,31.213757;121.536388,31.21375;121.537383,31.213699;121.53802,31.213711;121.538408,31.213709;121.538478,31.21371;121.538955,31.213699;121.540289,31.213714;121.540826,31.213724;121.541543,31.213718;121.542867,31.213552;121.542976,31.213534;121.543245,31.213489;121.544787,31.213256;121.546102,31.213059;121.546221,31.213041;121.546898,31.212892;121.547445,31.212691;121.547724,31.212566;121.54855,31.212099;121.549466,31.211432;121.550113,31.210802;121.550402,31.210576;121.551437,31.20911;121.551486,31.209031;121.551795,31.208585;121.552282,31.207861;121.552641,31.207316;121.5528,31.207088;121.552959,31.20685;121.553009,31.20678;121.553357,31.206235;121.553626,31.205898;121.553696,31.205939;121.553696,31.205936;121.554105,31.206171;121.555941,31.207121;121.555941,31.207121;121.556021,31.207202;121.556719,31.207589;121.557458,31.208006;121.557538,31.208116;121.557538,31.208116;121.558047,31.208401;121.559076,31.208909;121.559625,31.209182;121.559865,31.209304;121.560744,31.209599;121.560904,31.20966;121.562362,31.209967;121.563621,31.210132;121.563951,31.210132;121.56675,31.210135;121.569371,31.210191;121.570593,31.210377;121.573087,31.211114;121.573437,31.211241;121.57461,31.211763;121.577197,31.21297;121.577458,31.213077;121.577458,31.213077;121.57805,31.213351;121.57805,31.213351;121.58085,31.214638;121.58097,31.214686;121.58097,31.214686;121.583581,31.21581;121.584605,31.216194;121.584967,31.216339;121.585961,31.216703;121.586393,31.216806;121.587398,31.217059;121.588342,31.217293;121.588744,31.217386;121.58998,31.217694;121.590814,31.217889;121.590915,31.217918;121.591548,31.218056;121.591648,31.218084;121.593065,31.218388;121.593517,31.21854;121.59393,31.218762;121.594704,31.219287;121.596986,31.220814;121.59766,31.221212;121.598001,31.221375;121.600474,31.222169;121.600544,31.222198;121.600574,31.222207;121.600685,31.222245;121.603348,31.223057;121.605639,31.223607;121.605638,31.223607;121.605648,31.223537;121.605698,31.222176;121.605787,31.221004;121.606055,31.216939;121.606324,31.213734;121.606373,31.212813;121.606522,31.21086;121.606611,31.210048;121.606621,31.209968;121.606772,31.209986;121.606772,31.209985;121.608479,31.210248;121.60864,31.210265;121.60864,31.210265;121.60871,31.210014";
		System.out.println(sectionStr);
		String lonLat[] = sectionStr.split(";");
		for (int a = 0; a < lonLat.length; a++) {
			String[] split = lonLat[a].split(",");
			Location locationMake = CoordinateConverter.LocationMake(Double.valueOf(split[0]), Double.valueOf(split[1]));
			Location gd_decrypt = CoordinateConverter.bd_decrypt(locationMake);
			if (a < lonLat.length - 1) {
				gdLL += gd_decrypt.getLng() + "," + gd_decrypt.getLat() + ";";
			} else {
				gdLL += gd_decrypt.getLng() + "," + gd_decrypt.getLat();
			}

		}

		return gdLL;
	}

	// 高德坐标加密位百度
	public static List googleToBaidu(List list) {
		List roadNumber = new ArrayList();
		for(int i =0;i<list.size();i++){
			String lL = "";
			List wayNumber = new ArrayList();
			List<Location> rn = new ArrayList<>();
			rn = (List<Location>) list.get(i);
			for(int j=0;j<rn.size();j++){
				Location object = (Location) rn.get(j);
				if(j<rn.size()-1){
					lL += object.getLng()+","+object.getLat()+";";
				}else{
					lL += object.getLng()+","+object.getLat();
				}
			}
			String lonLat[] = lL.split(";");
			for (int a = 0; a < lonLat.length; a++) {
				String[] split = lonLat[a].split(",");
				Location locationMake = CoordinateConverter.LocationMake(Double.valueOf(split[0]), Double.valueOf(split[1]));
				Location bd_encrypt = CoordinateConverter.bd_encrypt(locationMake);
				wayNumber.add(bd_encrypt);
			}
			roadNumber.add(wayNumber);
		}

		return roadNumber;
	}
}