自学内容网 自学内容网

使用Java和Proj4j计算两个地理坐标点的最小矩形包围盒

使用Java和Proj4j计算两个地理坐标点的最小矩形包围盒

引言

今天小编碰到个需求,要求通过两个坐标点位向外扩大500米半径,通过这两个500米半径的圆给前端地图提供可画出长方形的四个坐标点

maven引用

        <dependency>
            <groupId>org.osgeo</groupId>
            <artifactId>proj4j</artifactId>
            <version>0.1.0</version>
        </dependency>

代码示例

public class RectangleFromLine {

/**
 * 经纬度地理坐标转面坐标
 * 
 * @param lat
 * @param lng
 * @return
 */
public static double[] coordinateTransformation(double lat, double lng) {
CRSFactory crsFactory = new CRSFactory();
CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326");
CoordinateReferenceSystem webMercator = crsFactory.createFromName("EPSG:3857");

// 创建坐标变换器
CoordinateTransformFactory ctFactory = new CoordinateTransformFactory();
CoordinateTransform transform = ctFactory.createTransform(wgs84, webMercator);
ProjCoordinate srcCoord = new ProjCoordinate(lng, lat);

// 执行转换
ProjCoordinate destCoord = new ProjCoordinate();
transform.transform(srcCoord, destCoord);
return new double[]{destCoord.x, destCoord.y};
}

/**
 * 面坐标转地理坐标
 * 
 * @param x
 * @param y
 * @return
 */
public static double[] coordinateTransformationReversal(double x, double y) {
CRSFactory crsFactory = new CRSFactory();
CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326");
CoordinateReferenceSystem webMercator = crsFactory.createFromName("EPSG:3857");

// 创建坐标变换器
CoordinateTransformFactory ctFactory = new CoordinateTransformFactory();
CoordinateTransform transform = ctFactory.createTransform(webMercator, wgs84);
ProjCoordinate srcCoord = new ProjCoordinate(x, y);
// 执行转换
ProjCoordinate destCoord = new ProjCoordinate();
transform.transform(srcCoord, destCoord);
return new double[]{destCoord.y, destCoord.x};
}

/**
 * 取两圆的最小包围盒(正北方向)
 * 
 * @param startLatitude
 * @param startLongitude
 * @param endLatitude
 * @param endLongitude
 * @param radius
 * @return
 */
public static double[][] calculateRectangleVertices(double startLatitude, double startLongitude, double endLatitude,
double endLongitude, double radius) {
double[] p1 = coordinateTransformation(startLatitude, startLongitude);
double[] p2 = coordinateTransformation(endLatitude, endLongitude);

double[] leftBottom = new double[]{Math.min(p1[0], p2[0]) - radius, Math.min(p1[1], p2[1]) - radius};
//面坐标转地理坐标
double[] leftBottom_1 = coordinateTransformationReversal(leftBottom[0], leftBottom[1]);
double[] leftTop = new double[]{Math.min(p1[0], p2[0]) - radius, Math.max(p1[1], p2[1]) + radius};
//面坐标转地理坐标
double[] leftTop_1 = coordinateTransformationReversal(leftTop[0], leftTop[1]);
double[] rightTop = new double[]{Math.max(p1[0], p2[0]) + radius, Math.max(p1[1], p2[1]) + radius};
//面坐标转地理坐标
double[] rightTop_1 = coordinateTransformationReversal(rightTop[0], rightTop[1]);
double[] rightBottom = new double[]{Math.max(p1[0], p2[0]) + radius, Math.min(p1[1], p2[1]) - radius};
//面坐标转地理坐标
double[] rightBottom_1 = coordinateTransformationReversal(rightBottom[0], rightBottom[1]);
return new double[][]{leftBottom_1, leftTop_1, rightTop_1, rightBottom_1};
}

/**
 * 取两圆的最小包围盒(轴方向)
 *
 * @param startLatitude
 * @param startLongitude
 * @param endLatitude
 * @param endLongitude
 * @param radius
 * @return
 */
public static double[][] calculateRectangleVertices1(double startLatitude, double startLongitude,
double endLatitude, double endLongitude, double radius) {
double[] p1 = coordinateTransformation(startLatitude, startLongitude);
double[] p2 = coordinateTransformation(endLatitude, endLongitude);

double minX = Math.min(p1[0], p2[0]) - radius;
double maxX = Math.max(p1[0], p2[0]) + radius;
double minY = Math.min(p1[1], p2[1]) - radius;
double maxY = Math.max(p1[1], p2[1]) + radius;

// 计算中心点
double centerX = (minX + maxX) / 2.0;
double centerY = (minY + maxY) / 2.0;

// 计算轴方向
double axisDirection = Math.atan2(maxY - minY, maxX - minX);

// 计算宽度和高度
double width = maxX - minX;
double height = maxY - minY;

// 计算四个顶点
double[][] vertices = new double[4][2];
vertices[0] = calculateVertex(centerX, centerY, width / 2, height / 2, axisDirection, -1, -1);
vertices[1] = calculateVertex(centerX, centerY, width / 2, height / 2, axisDirection, -1, 1);
vertices[2] = calculateVertex(centerX, centerY, width / 2, height / 2, axisDirection, 1, 1);
vertices[3] = calculateVertex(centerX, centerY, width / 2, height / 2, axisDirection, 1, -1);

// 将顶点从Web Mercator坐标转回地理坐标
for (int i = 0; i < 4; i++) {
vertices[i] = coordinateTransformationReversal(vertices[i][0], vertices[i][1]);
}

return vertices;
}

/**
 * 计算单个顶点
 *
 * @param centerX
 *            中心点的X坐标
 * @param centerY
 *            中心点的Y坐标
 * @param width
 *            包围盒的宽度
 * @param height
 *            包围盒的高度
 * @param angle
 *            轴方向(弧度)
 * @param dx
 *            X方向的偏移量(-1或1)
 * @param dy
 *            Y方向的偏移量(-1或1)
 * @return 顶点坐标
 */
private static double[] calculateVertex(double centerX, double centerY, double width, double height, double angle,
int dx, int dy) {
double x = centerX + dx * width * Math.cos(angle) - dy * height * Math.sin(angle);
double y = centerY + dx * width * Math.sin(angle) + dy * height * Math.cos(angle);
return new double[]{x, y};
}

}

原文地址:https://blog.csdn.net/weixin_42081445/article/details/143890373

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!