java生成线缓冲区的代码

因为项目需要要写一个电子围栏,分析之后其实就是Gis空间分析的线性缓冲区,线缓冲区生成的坐标我放在android手机地图显示,可以直观的看到这个算法的结果是否正确,下面是效果图,有需要的可以看看。

下面是核心代码

public static String getElectricFenceEdgeCoords(List<RoutePoint> points, double radius) {
        // 参数处理
        // 分别生成左侧和右侧的缓冲区边界点坐标串
        List<LatLng> coords = new ArrayList<>();
        for (int i = 0; i < points.size(); i++) {
            coords.add(points.get(i).point);
        }
        String leftBufferCoords = getLeftBufferEdgeCoords(coords, radius);
        // 反序
        Collections.reverse(coords);
        String rightBufferCoords = getLeftBufferEdgeCoords(coords, radius);
        return leftBufferCoords + "," + rightBufferCoords;
    }

    /**
     * 根据给定的一系列有顺序的坐标,逆时针生成轴线左侧的缓冲区边界点
     *
     * @param coords 一系列有顺序的坐标
     * @param radius 缓冲区半径
     * @return 缓冲区的边界坐标
     */
    private static String getLeftBufferEdgeCoords(List<LatLng> coords, double radius) {
        // 参数处理
        if (coords.size() < 1)
            return "";

        // 计算时所需变量
        double alpha = 0.0;// 向量绕起始点沿顺时针方向旋转到X轴正半轴所扫过的角度
        double delta = 0.0;// 前后线段所形成的向量之间的夹角
        double l = 0.0;// 前后线段所形成的向量的叉积

        // 辅助变量
        StringBuilder strCoords = new StringBuilder();
        double startRadian = 0.0;
        double endRadian = 0.0;
        double beta = 0.0;
        double x = 0.0, y = 0.0;

        // 第一节点的缓冲区,在此程序中只生成2点
        {
            alpha = Topology.getQuadrantAngle(coords.get(0), coords.get(1));
            startRadian = alpha + Math.PI;
            endRadian = alpha + (3 * Math.PI) / 2;
            strCoords.append(getBufferCoordsByRadian(coords.get(0), startRadian, endRadian, radius));
        }

        // 中间节点
        for (int i = 1; i < coords.size() - 1; i++) {
            alpha = Topology.getQuadrantAngle(coords.get(i), coords.get(i + 1));
            delta = Topology.getIncludedAngel(coords.get(i - 1), coords.get(i), coords.get(i + 1));
            l = getVectorProduct(coords.get(i - 1), coords.get(i), coords.get(i + 1));
            if (l > 0) {
                startRadian = alpha + (3 * Math.PI) / 2 - delta;
                endRadian = alpha + (3 * Math.PI) / 2;
                if (strCoords.length() > 0)
                    strCoords.append(",");
                strCoords.append(getBufferCoordsByRadian(coords.get(i), startRadian, endRadian, radius));
            } else if (l < 0) {
                beta = alpha - (Math.PI - delta) / 2;
                x = coords.get(i).getLatitude() + radius * Math.cos(beta);
                y = coords.get(i).getLongitude() + radius * Math.sin(beta);
                if (strCoords.length() > 0)
                    strCoords.append(",");
                strCoords.append(x + "," + y);
            }
        }

        // 最后一个点,在此程序中只生成2点

        {
            alpha = Topology.getQuadrantAngle(coords.get(coords.size() - 2), coords.get(coords.size() - 1));
            startRadian = alpha + (3 * Math.PI) / 2;
            endRadian = alpha + 2 * Math.PI;
            if (strCoords.length() > 0)
                strCoords.append(",");
            strCoords.append(getBufferCoordsByRadian(coords.get(coords.size() - 1), startRadian, endRadian, radius));
        }
        return strCoords.toString();
    }

    /**
     * 获取指定弧度范围之间的缓冲区圆弧拟合边界点
     *
     * @param center      指定拟合圆弧的原点
     * @param startRadian 开始弧度
     * @param endRadian   结束弧度
     * @param radius      缓冲区半径
     * @return 缓冲区的边界坐标
     */
    private static String getBufferCoordsByRadian(LatLng center, double startRadian, double endRadian, double radius) {
        double gamma = Math.PI / 9;
        /// 6
        StringBuilder strCoords = new StringBuilder();
        double x = 0.0, y = 0.0;
        for (double phi = startRadian; phi <= endRadian + 0.000000000000001; phi += gamma) {
            x = center.getLatitude() + radius * Math.cos(phi);
            y = center.getLongitude() + radius * Math.sin(phi);
            if (strCoords.length() > 0)
                strCoords.append(",");
            strCoords.append(x + "," + y);
        }
        return strCoords.toString();
    }

    /**
     * 获取相邻三个点所形
     *
     * @param preCoord  第一个节点坐标成的两个向量的交叉乘积
     * @param midCoord  第二个节点坐标
     * @param nextCoord 第三个节点坐标
     * @return 相邻三个点所形成的两个向量的交叉乘积
     */
    private static double getVectorProduct(LatLng preCoord, LatLng midCoord, LatLng nextCoord) {
        return (midCoord.getLatitude() - preCoord.getLatitude()) * (nextCoord.getLongitude() - midCoord.getLongitude())
                - (nextCoord.getLatitude() - midCoord.getLatitude()) * (midCoord.getLongitude() - preCoord.getLongitude());
    }

最后附上完整代码下载的地址,用eclipse可以打开,下载的代码没有可视化,只返回了坐标数据。

下载地址https://download.csdn.net/download/ymszzu/10787035

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值