批量计算点和面的关系时,需要双循环进行遍历,当数据量较大时循环计算效率很低。最好时将地图分成等量的方格,每次只查询单个方格内的数据进行点和面的关系计算能极大的提高计算效率。
/**
* 根据地图范围将地图等量分割成 N*N的方格
* @author LuXiangQi
*
*/
public class Bounds {
/**
* 等分数量,即将地图分割成16*16块区域
*/
public static final int PARTS = 16;
private double minX;
private double maxX;
private double minY;
private double maxY;
private Double dx;
private Double dy;
@Override
public String toString() {
DecimalFormat df = new DecimalFormat("#.000000000000000");
return "Bounds [minX=" + df.format(minX) + ", maxX=" + df.format(maxX) + ", minY=" + df.format(minY)
+ ", maxY=" + df.format(maxY) + "]";
}
public Bounds(double minX, double maxX, double minY, double maxY) {
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
getDx();
getDy();
}
public double getMinX() {
return minX;
}
public void setMinX(double minX) {
this.minX = minX;
}
public double getMaxX() {
return maxX;
}
public void setMaxX(double maxX) {
this.maxX = maxX;
}
public double getMinY() {
return minY;
}
public void setMinY(double minY) {
this.minY = minY;
}
public double getMaxY() {
return maxY;
}
public void setMaxY(double maxY) {
this.maxY = maxY;
}
/**
* 获取X轴增量
* @return
*/
public double getDx() {
if (dx == null) {
dx = (maxX - minX) / PARTS;
}
return dx;
}
/**
* 获取Y轴增量
* @return
*/
public double getDy() {
if (dy == null) {
dy = (maxY - minY) / PARTS;
}
return dy;
}
/**
* 判断坐标是否在范围内
* @param x
* @param y
* @return
*/
public boolean inBounds(double x, double y) {
if (x < minX || maxX < x || y < minY || maxY < y) {
return false;
}
return true;
}
/**
* 获取x坐标所在象限行号
* @param x
* @return
*/
public Integer getRowNum(double x) {
if (x < minX || maxX < x) {
return null;
}
if (x - minX < 0) {
return 0;
}
int result = (int) Math.floor((x - minX) / dx);
if (result >= PARTS) {
return result - 1;
}
return result;
}
/**
* 获取y坐标所在象限列号
* @param y
* @return
*/
public Integer getColNum(double y) {
if (y < minY || maxY < y) {
return null;
}
if (y - minY < 0) {
return 0;
}
int result = (int) Math.floor((y - minY) / dy);
if (result >= PARTS) {
return result - 1;
}
return result;
}
/**
* 获取坐标所在象限编号
* @param x
* @param y
* @return
*/
public int[] getRowColNum(double x, double y) {
Integer rowNum = getRowNum(x);
Integer colNum = getColNum(y);
if (rowNum == null || colNum == null) {
return null;
}
return new int[]{rowNum, colNum};
}
/**
* 获取指定象限的坐标范围
* @param rowNum 行数编号
* @param colNum 列数编号
* @return
*/
public Bounds getRectangle(int rowNum, int colNum) {
double minx = this.minX + this.dx * rowNum;
double maxx = this.minX + this.dx * (rowNum + 1);
double miny = this.minY + this.dy * colNum;
double maxy = this.minY + this.dy * (colNum + 1);
return new Bounds(minx, maxx, miny, maxy);
}
public static void main(String[] args) {
Bounds bounds = new Bounds(1D, 4D, 1D, 4D);
int[] rc = bounds.getRowColNum(4D, 4D);
System.out.println(rc[0]);
System.out.println(rc[1]);
}
}
查询、计算
for (int i = 0; i < Bounds.PARTS; i++) {
for (int j = 0; j < Bounds.PARTS; j++) {
logger.info("i:{}, j:{}", i, j);
// 获取指定象限的范围,用于查询该象限内的点资源和与之相交的网格
queryBounds = areaBounds.getRectangle(i, j);
// 查询该象限内的点资源
pointList = mpointDao.getPointByBounds(tableName, queryBounds);
//查询该象限内的网格
areaList = geoServer.queryAreaByBounds(areaTableName, queryBounds);
for (BldAreaRes point: pointList) {
stp++;
for (Area area: areaList) {
if (area.getGeo().getBounds().getLeft() <= point.getResX()
&& area.getGeo().getBounds().getRight() >= point.getResX()
&& area.getGeo().getBounds().getBottom() <= point.getResY()
&& area.getGeo().getBounds().getTop() >= point.getResY()) {
if (pu.withIn(point.getPoint(), area.getLines())) {
list.add(bart);
break;
}
}
}
if (stp >= 1000 && stp % 1000 == 0) {
logger.info("TABLE:{}, COMPLETE:{}", tableName, stp);
}
// 每超过10000行提交一次,并清空
/******************************/
}
//最后提交一次
/******************************/
}
}