如果已经熟悉 mongodb-spring在java中的操作,就继续往下看
如果比较陌生,可以先看一下
首先要在reposity中增加方法:
public List<ProjectInfo> searchByRang(float latbegin, float latend, float lngbegin, float lngend) { Query query=new Query(); query.addCriteria(Criteria.where("lat").gt(latbegin).lt(latend)); query.addCriteria(Criteria.where("lng").gt(lngbegin).lt(lngend)); return find(query,ProjectInfo.class); }
新建点的class
package action.projectinfo; public class MapPoint { private float lng; private float lat; public MapPoint(float lng , float lat){ this.lng = lng; this.lat = lat; } public MapPoint(){ } public float getLng() { return lng; } public void setLng(float lng) { this.lng = lng; } public float getLat() { return lat; } public void setLat(float lat) { this.lat = lat; } }
新建线的class
package action.projectinfo; public class Line { private float k; private float c; private MapPoint pointa; private MapPoint pointb; private int plus; //1是正 -1是负 public Line(){ } public Line(MapPoint pointa, MapPoint pointb){ this.pointa = pointa; this.pointb = pointb; this.k = (pointb.getLng() - pointa.getLng()) / (pointb.getLat() - pointa.getLat()); this.c = k * pointa.getLat() - pointa.getLng(); } public float getK() { return k; } public void setK(float k) { this.k = k; } public float getC() { return c; } public void setC(float c) { this.c = c; } public MapPoint getPointa() { return pointa; } public void setPointa(MapPoint pointa) { this.pointa = pointa; } public MapPoint getPointb() { return pointb; } public void setPointb(MapPoint pointb) { this.pointb = pointb; } public int getPlus() { return plus; } public void setPlus(int plus) { this.plus = plus; } public float calculatePoint(MapPoint mapPoint) { return mapPoint.getLng() - getK()* mapPoint.getLat() + getC(); } }
package action.projectinfo; import java.util.List; public class Polygon { private List<Line> lines; private List<MapPoint> points; public List<Line> getLines() { return lines; } public void setLines(List<Line> lines) { this.lines = lines; } public List<MapPoint> getPoints() { return points; } public void setPoints(List<MapPoint> points) { this.points = points; } /** * (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1); * @param index * @return true 是凸多边形 */ public boolean isConcave(int index) { Line lineA = lines.get(index); Line lineB = lines.get(index+1); MapPoint point1 = lineA.getPointa(); MapPoint point2 = lineA.getPointb(); MapPoint point3 = lineB.getPointb(); float x2x1 = point2.getLng() - point1.getLng(); float y3y1 = point3.getLat() - point1.getLat(); float y2y1 = point2.getLat() - point1.getLat(); float x3x1 = point3.getLng() - point1.getLng(); float temp = (x2x1*y3y1)-(y2y1*x3x1); if(temp>0){ return true; }else{ return false; } } /** * 寻找初始节点- */ public int initCurvePoint(){ int size = points.size(); boolean flag = true; boolean plus = true; MapPoint point0 = points.get(0); for(Line line :lines){ } for(int i = 0 ; i < size ; i++){ MapPoint mapPoint = points.get(i); for(Line line : lines){ if(line.calculatePoint(mapPoint)<0){ flag = false; plus = false; break; }else{ } } if(flag){ return i; } flag = true; } return -1; } public void removePoint(int j) { Line line = new Line(points.get(j-1),points.get(j+1)); points.remove(j); lines.remove(j); lines.remove(j-1); lines.add(j-1, line); } }
查询的方法:
查询四边形
/** * points为四边形的四个顶点 *latmin 是左上角的X坐标,lngmax 是左上角的Y坐标 *latmax 是右下角的X坐标,lngmin 是右下角的Y坐标 * @param projectInfos * @return */ private void getQuadProjectInfos(List<ProjectInfo> pls) { String[] pstr = points.split(";"); String[] pts0 = pstr[0].split(" "); String[] pts1 = pstr[1].split(" "); String[] pts2 = pstr[2].split(" "); float lngmax = Float.valueOf(pts0[0]); float lngmin = Float.valueOf(pts1[0]); float latmax = Float.valueOf(pts0[1]); float latmin = Float.valueOf(pts2[1]); float templng; float templat; if (lngmax < lngmin) { templng = lngmax; lngmax = lngmin; lngmin = templng; } if (latmax < latmin) { templat = latmax; latmax = latmin; latmin = templat; } List<ProjectInfo> pis = projectInfoReposity.searchByRang(latmin, latmax, lngmin, lngmax); for (ProjectInfo pi : pis) { pls.add(pi); } }
查询圆的范围的坐标:
private static double EARTH_RADIUS = 6378.137; //坐标和距离之间转化需要的值 private void getCircleProjectInfos(List<ProjectInfo> projectInfos) { float r = Float.valueOf(raidus) / 1000; float flat = Float.valueOf(lat); float flng = Float.valueOf(lng); float maxLat = calMaxLat(flat, r); float minLat = calMinLat(flat, r); float maxLng = calMaxLng(flng, r); float minLng = calMinLng(flng, r); List<ProjectInfo> allPis = projectInfoReposity.searchByRang(minLat, maxLat, minLng, maxLng); System.out.println(flat + " " + flng); System.out.println(r); //上面得到的是 圆外的四边形区域的点的范围,所以要再判断一轮点到圆心的距离是否在半径内 for (ProjectInfo projectInfo : allPis) { double s1 = calDistance(projectInfo.getLat(), flat, projectInfo.getLng(), flng); if (s1 < r) { projectInfos.add(projectInfo); } } allPis = null; allCommers = null; } //通过圆心坐标以及半径,算出圆外的四边形的左上角和右下角的坐标 private float calMinLng(float lng, double s) { s = s * 1.15d; s = calMeters(s); double a = rad(lng) - s; return (float) (a * 180d / Math.PI); } private float calMaxLng(float lng, double s) { s = s * 1.16d; s = calMeters(s); double a = rad(lng) + s; return (float) (a * 180d / Math.PI); } private float calMaxLat(float lat, double s) { s = s / EARTH_RADIUS; s = s / 2d; s = Math.asin(Math.sin(s)) * 2d; double a = rad(lat) + s; return (float) (a * 180d / Math.PI); } private float calMinLat(float lat, double s) { s = s / EARTH_RADIUS; s = s / 2d; s = Math.asin(Math.sin(s)) * 2d; double a = rad(lat) - s; return (float) (a * 180d / Math.PI); } private double calMeters(double s) { s = s / EARTH_RADIUS; s = s / 2d; s = Math.asin(Math.sin(s)) * 2d; return s; } private double rad(double d) { return d * Math.PI / 180.0; } private double calDistance(float beginlat, float endlat, float beginlng, float endlng) { double radLat1 = rad(beginlat); double radLat2 = rad(endlat); double a = radLat1 - radLat2; double b = rad(beginlng) - rad(endlng); double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * EARTH_RADIUS; s = Math.round(s * 10000) / (double) 10000; return s; }
查询多边形的范围的坐标:
private void getPolyProjectInfos(List<ProjectInfo> npis) { String[] pstr = points.split(";"); MapPoint[] mapPoints = translateMapPoints(pstr); int length = mapPoints.length; float maxLat = 0.0f; float maxLng = 0.0f; float minLat = mapPoints[0].getLat(); float minLng = mapPoints[0].getLng(); List<Line> lines = new ArrayList<Line>(); for (int i = 0; i < mapPoints.length - 1; i++) { if (mapPoints[i].getLat() > maxLat) { maxLat = mapPoints[i].getLat(); } if (mapPoints[i].getLng() > maxLng) { maxLng = mapPoints[i].getLng(); } if (mapPoints[i].getLat() < minLat) { minLat = mapPoints[i].getLat(); } if (mapPoints[i].getLng() < minLng) { minLng = mapPoints[i].getLng(); } try { Line line = getLineByPoints(mapPoints[i], mapPoints[i + 1]); if (i < length - 2) { if (mapPoints[i + 2].getLng() - line.getK() * mapPoints[i + 2].getLat() + line.getC() < 0) { line.setPlus(-1); } else { line.setPlus(1); } } else { if (mapPoints[1].getLng() - line.getK() * mapPoints[1].getLat() + line.getC() < 0) { line.setPlus(-1); } else { line.setPlus(1); } } lines.add(line); } catch (Exception e) { e.printStackTrace(); } } for (Line line : lines) { System.out.println(line.getK()); } List<ProjectInfo> pls = projectInfoReposity.searchByRang(minLat, maxLat, minLng, maxLng); for (ProjectInfo pl : pls) { float lat = pl.getLat(); float lng = pl.getLng(); MapPoint mapPoint3 = new MapPoint(lng, lat); MapPoint mapPoint4 = new MapPoint(maxLng, lat); //我们得到的是多边形外的四边形的范围的点,还要判断它是否在多边形内,可以向量差积来进行判断 boolean flag = isInArea(lines, mapPoint3, mapPoint4); if (flag) { npis.add(pl); } } } private MapPoint[] translateMapPoints(String[] pstrs) { MapPoint[] mapPoints = new MapPoint[pstrs.length + 1]; for (int i = 0; i < pstrs.length; i++) { String pstr = pstrs[i]; MapPoint mapPoint = new MapPoint(); String[] pts = pstr.split(" "); mapPoint.setLat(Float.valueOf(pts[1])); mapPoint.setLng(Float.valueOf(pts[0])); mapPoints[i] = mapPoint; } MapPoint mapPoint = new MapPoint(); mapPoint.setLat(mapPoints[0].getLat()); mapPoint.setLng(mapPoints[0].getLng()); mapPoints[pstrs.length] = mapPoint; return mapPoints; } private Line getLineByPoints(MapPoint pointa, MapPoint pointb) { float k = (pointb.getLng() - pointa.getLng()) / (pointb.getLat() - pointa.getLat()); float c = k * pointa.getLat() - pointa.getLng(); Line line = new Line(); line.setC(c); line.setPointa(pointa); line.setPointb(pointb); line.setK(k); return line; } // ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) ≥ 0 // (x1*y2-x2*y1)*(x1*y3-x3*y1)<0 // 计算AB(为(x1b-x1a,y1b-y1a))向量与AC(为(x2a-x1a,y2a-y1a))向量的差积 // (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) private boolean isInArea(List<Line> lines, MapPoint point3, MapPoint point4) { int num = 0; for (Line line : lines) { MapPoint point1 = line.getPointa(); MapPoint point2 = line.getPointb(); float x1 = point1.getLng(); float x2 = point2.getLng(); float x3 = point3.getLng(); float x4 = point4.getLng(); float y1 = point1.getLat(); float y2 = point2.getLat(); float y3 = point3.getLat(); float y4 = point4.getLat(); float t1 = (x1 - x3) * (y4 - y3) - (y1 - y3) * (x4 - x3); float t2 = (x4 - x3) * (y2 - y3) - (y4 - y3) * (x2 - x3); if (t1 * t2 >= 0) { float t3 = (x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2); float t4 = (x1 - x2) * (y1 - y4) - (y1 - y2) * (x1 - x4); if (t3 * t4 >= 0) { num++; } } } if (num > 0 && num % 2 != 0) { return true; } return false; }