道格拉斯·普克算法 JAVA实现

道格拉斯·普克算法 JAVA实现

作用:

假如现在有个需求,后端计算出来一条路线规划,路线是由无数个坐标点组成,但是其中大部分连起来都是直线,那直线中有用的点也就起始点和终点,中间的全部点都是可以省略的。

原理:

对一条路径的起点和终点做一条直线,计算其余全部点到直线的距离,并找出最大距离,若最大距离比阈值小,则去掉全部中间点,若距离比阈值大,则保留当前点,以当前点为界,分成左右两条路径,重复前面的过程,直到所有的距离都小于阈值,就完事了,所以阈值越大,点越稀少,阈值越小,路径越接近真实的。
在这里插入图片描述
在这里插入图片描述

1、坐标点实体

package com.pet.utils;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
class Coordinate {
    private double x;
    private double y;
}

2、抽稀

阈值应大于等于1,阈值越大,路径越简单,阈值越小,路径越全。

package com.pet.utils;

import java.util.ArrayList;
import java.util.List;

public class DouglasUtil {
    public static void main(String[] args) {
        List<Coordinate> points = new ArrayList<>();
        points.add(new Coordinate(1, 2));
        points.add(new Coordinate(2, 2));
        points.add(new Coordinate(3, 4));
        points.add(new Coordinate(4, -5));
        points.add(new Coordinate(5, 3));
        points.add(new Coordinate(6, 3));
        points.add(new Coordinate(7, 5));
        points.add(new Coordinate(8, 2));
        points.add(new Coordinate(9, 0));
        points.add(new Coordinate(10, 9));
        points.add(new Coordinate(11, 5));

        for (Coordinate p : douglas(points, 1)) {
            System.out.print("(" + p.getX() + "," + p.getY() + ") ");
        }
    }

    private static List<Coordinate> douglas(List<Coordinate> points, int threshold) {
        List<Coordinate> result = new ArrayList<>();

        // 找到最大阈值点
        double maxH = 0;
        int index = 0;
        int end = points.size();
        for (int i = 1; i < end - 1; i++) {
            // 计算点到起点和终点组成线段的高
            double h = getDistance(points.get(i), points.get(0), points.get(end - 1));
            if (h > maxH) {
                maxH = h;
                index = i;
            }
        }

        // 如果存在最大阈值点,就进行递归遍历出所有最大阈值点
        return getCoordinates(points, threshold, maxH, index, end, result);
    }

    private static List<Coordinate> getCoordinates(List<Coordinate> points, int epsilon, double maxH, int index, int end, List<Coordinate> result) {
        if (maxH > epsilon) {
            List<Coordinate> leftPoints = new ArrayList<>();
            List<Coordinate> rightPoints = new ArrayList<>();
            // 分成两半 继续找比阈值大的
            for (int i = 0; i < end; i++) {
                if (i < index) {
                    leftPoints.add(points.get(i));
                } else {
                    rightPoints.add(points.get(i));
                }
            }
            List<Coordinate> leftResult = douglas(leftPoints, epsilon);
            List<Coordinate> rightResult = douglas(rightPoints, epsilon);

            rightResult.remove(0);
            leftResult.addAll(rightResult);
            result = leftResult;
        } else {
            result.add(points.get(0));
            result.add(points.get(end - 1));
        }
        return result;
    }

    /**
     * 计算点到直线的距离
     */
    private static double getDistance(Coordinate p, Coordinate s, Coordinate e) {
        double AB = distance(s, e);
        double CB = distance(p, s);
        double CA = distance(p, e);
        // 三角形面积
        double S = helen(CB, CA, AB);
        // 三角形面积 = AB(底) * 高 / 2
        // 所以 高 = 2 * 三角形面积 / AB(底)
        return 2 * S / AB;
    }

    /**
     * 计算两点之间的距离
     */
    private static double distance(Coordinate p1, Coordinate p2) {
        double x1 = p1.getX();
        double y1 = p1.getY();
        double x2 = p2.getX();
        double y2 = p2.getY();
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    /**
     * 三角形面积
     */
    private static double helen(double CB, double CA, double AB) {
        double p = (CB + CA + AB) / 2;
        return Math.sqrt(p * (p - CB) * (p - CA) * (p - AB));
    }
}

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
根据您提供的引用内容,道格拉斯-普克算法是一种将曲线近似表示为一系列,并减少的数量的算法。如果您想在Java中使用道格拉斯-普克算法,可以考虑使用以下工具包: 1. JTS Topology Suite:JTS是一个Java库,提供了一套用于处理地理空间数据的工具。它包含了道格拉斯-普克算法实现,可以用于抽稀经纬度路径。您可以通过以下代码示例来使用JTS Topology Suite进行抽稀: ```java import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.simplify.DouglasPeuckerSimplifier; public class DouglasPeuckerExample { public static void main(String[] args) { // 输入的经纬度路径 Coordinate[] inputPoints = new Coordinate[] { new Coordinate(0, 0), new Coordinate(1, 1), new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(4, 4) }; // 创建GeometryFactory对象 GeometryFactory geometryFactory = new GeometryFactory(); // 创建LineString对象 org.locationtech.jts.geom.LineString lineString = geometryFactory.createLineString(inputPoints); // 使用Douglas-Peucker算法进行抽稀 double tolerance = 0.5; // 抽稀的容差值 DouglasPeuckerSimplifier simplifier = new DouglasPeuckerSimplifier(lineString); simplifier.setDistanceTolerance(tolerance); org.locationtech.jts.geom.LineString simplifiedLineString = (org.locationtech.jts.geom.LineString) simplifier.getResultGeometry(); // 输出抽稀后的经纬度路径 Coordinate[] simplifiedPoints = simplifiedLineString.getCoordinates(); for (Coordinate point : simplifiedPoints) { System.out.println("Latitude: " + point.x + ", Longitude: " + point.y); } } } ``` 2. GeoTools:GeoTools是一个开源的Java库,用于处理地理空间数据。它提供了许多空间分析和地理信息系统功能,包括道格拉斯-普克算法实现。您可以使用以下代码示例来使用GeoTools进行抽稀: ```java import org.geotools.geometry.jts.JTSFactoryFinder; import org.geotools.simplify.DouglasPeuckerSimplifier; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; public class DouglasPeuckerExample { public static void main(String[] args) { // 输入的经纬度路径 Coordinate[] inputPoints = new Coordinate[] { new Coordinate(0, 0), new Coordinate(1, 1), new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(4, 4) }; // 创建GeometryFactory对象 GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(); // 创建LineString对象 Geometry lineString = geometryFactory.createLineString(inputPoints); // 使用Douglas-Peucker算法进行抽稀 double tolerance = 0.5; // 抽稀的容差值 DouglasPeuckerSimplifier simplifier = new DouglasPeuckerSimplifier(lineString); simplifier.setDistanceTolerance(tolerance); Geometry simplifiedGeometry = simplifier.getResultGeometry(); // 输出抽稀后的经纬度路径 Coordinate[] simplifiedPoints = simplifiedGeometry.getCoordinates(); for (Coordinate point : simplifiedPoints) { System.out.println("Latitude: " + point.x + ", Longitude: " + point.y); } } } ``` 请注意,以上示例代码仅为演示如何使用Java工具包实现道格拉斯-普克算法进行抽稀。您可以根据自己的需求进行调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值