涉及技术

  • 腾讯地图
  • jdk1.8

问题描述

开发一款应用,前端在地图上标记经纬度坐标点集合形成一个多边形,现需要在后端将多边形做一个等距外扩或者收缩。

在网上查了好多的算法,经过尝试验证,在小经度多边形进行收缩外扩都或多或少存在一些问题,因此自己参考写出了

一个多边形外扩收缩的算法。

JAVA代码

坐标点实体(Point)

/*** 地图上一个点的经纬度** @author yanggl* @version 1.0* @date 2022/5/9 15:03*/
public class Point implements Serializable {private static final long serialVersionUID = 45122365987322547L;/*** 经度*/private Double longitude;/*** 纬度*/private Double latitude;public Double getLongitude() {return longitude;}public void setLongitude(Double longitude) {this.longitude = longitude;}public Double getLatitude() {return latitude;}public void setLatitude(Double latitude) {this.latitude = latitude;}@Overridepublic String toString() {final StringBuilder sb = new StringBuilder("{");sb.append("longitude=").append(longitude);sb.append(", latitude=").append(latitude);sb.append('}');return sb.toString();}}

向量工具类 (VectorUtil)

/*** 向量工具类** @author yanggl* @version 1.0* @date 2022/7/8 10:29*/
public class VectorUtil {/*** 向量求模数*/public static double norm(Point point) {return Math.sqrt(point.getLongitude() * point.getLongitude() + point.getLatitude() * point.getLatitude());}/*** 向量加法*/public static Point add(Point point1, Point point2) {Point point = new Point();point.setLongitude(point1.getLongitude() + point2.getLongitude());point.setLatitude(point1.getLatitude() + point2.getLatitude());return point;}/*** 向量减法*/public static Point sub(Point point1, Point point2) {Point point = new Point();point.setLongitude(point1.getLongitude() - point2.getLongitude());point.setLatitude(point1.getLatitude() - point2.getLatitude());return point;}/*** 向量乘法*/public static Point mul(Point p, double d) {Point point = new Point();point.setLongitude(p.getLongitude() * d);point.setLatitude(p.getLatitude() * d);return point;}/*** 向量叉乘*/public static double cross(Point p1, Point p2) {return p1.getLongitude() * p2.getLatitude() - p1.getLatitude() * p2.getLongitude();}}

核心工具类 (DistanceUtil)

/*** 工具类** @author yanggl* @version 1.0* @date 2022/7/8 10:23*/
public class DistanceUtil {/*** 操作多边形扩张/收缩** @param points 待扩/收缩张多边形* @param dist   距离 正数扩张,负数收缩* @return 扩张/收缩后的多边形*/public static List<Point> expansion(List<Point> points, double dist) {if (points.size() < 3) {throw new RuntimeException("not enough 3 point");}List<Point> npList = new LinkedList<>();List<Double> lngList = new LinkedList<>();List<Double> latList = new LinkedList<>();for (Point point : points) {lngList.add(point.getLongitude());latList.add(point.getLatitude());}Double minLng = Collections.min(lngList);Double minLat = Collections.min(latList);for (Point point : points) {Point p = new Point();p.setLongitude(point.getLongitude() - minLng);p.setLatitude(point.getLatitude() - minLat);npList.add(p);}List<Point> list = enlarge(npList, dist);LinkedList<Point> resultList = new LinkedList<>();for (Point point : list) {Point np = new Point();np.setLongitude(point.getLongitude() + minLng);np.setLatitude(point.getLatitude() + minLat);resultList.add(np);}return resultList;}/*** 多边形外扩/收缩*/private static List<Point> enlarge(List<Point> points, double dist) {LinkedList<Point> resultList = new LinkedList<>();int size = points.size();double angle = dist * dmi();angle = isConvex(points) ? angle : -angle;for (int i = 0; i < size; i++) {Point pi = points.get(i);Point v1 = VectorUtil.sub(points.get((i - 1 + size) % size), pi);Point v2 = VectorUtil.sub(points.get((i + 1) % size), pi);double norm1 = VectorUtil.norm(v1);double norm2 = VectorUtil.norm(v2);if (norm1 <= 0 || norm2 <= 0) {// 剔除重复点(或距离极近的点)points.remove(i);return enlarge(points, dist);}Point normalizeV1 = VectorUtil.mul(v1, 1 / norm1);Point normalizeV2 = VectorUtil.mul(v2, 1 / norm2);double sinTheta = VectorUtil.cross(normalizeV1, normalizeV2);Point qi = VectorUtil.add(pi, VectorUtil.mul(VectorUtil.add(normalizeV1, normalizeV2), angle / sinTheta));resultList.add(qi);}return resultList;}/*** 计算1米代表的角度 这里只是近似计算,事实上随着纬度的变化其变动范围将受到影响*/private static double dmi() {double s = 6378.137 * 1000;return 1 / (Math.PI / 180 * s);}/*** 判断是否凸多边形*/private static boolean isConvex(List<Point> points) {double area = 0;Point p1 = VectorUtil.sub(points.get(1), points.get(0));Point p2;for (int i = 2; i < points.size(); i++) {p2 = VectorUtil.sub(points.get(i), points.get(0));area += VectorUtil.cross(p1, p2);p1 = p2;}return area > 0;}/*** 多边形周长*/private static double perimeter(List<Point> points) {int size = points.size();double perimeter = 0.0d;Point point;for (int i = 0; i < size; i++) {point = points.get(i);perimeter += VectorUtil.norm(VectorUtil.sub(points.get((i - 1 + size) % size), point));}return perimeter;}}

经测试,对于小经度多边形的外扩是能够正常的。

JAVA实现小精度多边形等距外扩相关推荐

  1. java微信小程序的校园外卖点餐平台 uniapp

    美食是人类永恒的话题,无论是在古代还是现代人们对美食都有一种非常的热爱在里面,但是随着时代的发展,人们可能没有更多的时间去研究美食,很多时候人们在下班或者放学之后更希望通过网络来进行订餐,为此我开发了 ...

  2. 图形/多段线内缩外扩思路

    图形/多段线内缩外扩思路 前言 我在网上找了很多关于多边形内缩外扩的资料,也测试了一些算法库,如Clipper,boost::geometry::buffer,其实都可以得到不错的结果. Clippe ...

  3. 非自交多边形的轮廓内缩外扩算法

    文章目录 1. 项目介绍 2. 算法步骤 2.1 内缩点的生成 2.2 无效内缩线段的处理 2.3 全局无效环的处理 3. 使用方法及结果演示 3.1 使用方法 3.2 结果演示 4. 不足之处 5. ...

  4. opencv 实现多边形内缩/外扩(平移)指定距离

    实现多边形内缩,内缩以后的每边仍与内缩前平行. Note: 确保函数种pList的点按逆时针顺序排列好! 此外,使用Point2f类型可以获得亚像素精度. 功能函数: /* @作用:多边形内缩 @pL ...

  5. 多边形或轮廓等距离外扩或收缩

    参考:多边形或轮廓等距离外扩或收缩_hjk61314的博客-CSDN博客_多边形外扩 1. 需求 已知:给定一个简单多边形,多边形按照顺时针或者逆时针的数组排列, 求:内部等距离缩小或者外部放大的多边 ...

  6. ROS::向量法外扩多边形

    ROS::向量法外扩多边形 将多边形区域的灭个边向外移动一定距离然后组成的新多边形 如上图所示针对每一个顶点分别计算外扩后的新顶点, c为当前点,p为前一个点,n为下一个点 分两种情况:1.pn中点在 ...

  7. 多边形轮廓 等距离外扩

    多边形(轮廓点)等距离外扩 1.需要安装一个python包 安装 pyclipper python 的话,直接pip install pyclipper 地址:https://pypi.org/pro ...

  8. 实现凹凸多边形外扩与内缩, 无内缩外扩混乱问题

    用于测试的三组数据点 // polygon 1pointlist.append(QVector3D( 395, 188, 0 ));pointlist.append(QVector3D( 353, 6 ...

  9. java连接stk外部接口_SLWSTK无线开发工具上的外扩串口如何使用(虚拟串口/VCOM)...

    标题:   SLWSTK无线开发工具上的外扩串口如何使用(虚拟串口/VCOM) 关键词:ZigBee, 串口,VCOM,虚拟串口,外扩串口,EFR32, PCB4001,  EFR32MG13P732 ...

最新文章

  1. windows 7 unmountable boot volume 解决方法
  2. Python 正则匹配(re)组的应用
  3. Python之pandas:pandas.set_option函数的参数详细解释
  4. [网络流24题]太空飞行计划
  5. ASP.NET Core 3.x启动时运行异步任务(二)
  6. Spring MVC Formatter(数据格式化)详解
  7. http服务器和application服务器区别
  8. 华为交换机初始化和配置SSH和TELNET远程登录方法
  9. laravel添加语言包
  10. 微波雷达人体感应技术,智能镜子感应雷达模块应用,让生活更有趣
  11. 存算一体文献阅读笔记二:XNOR-RRAM architecture for BNN from Shimeng Yu in ASU 2017
  12. 视频编码的守望者--Jason Garrett-Glaser
  13. TypeScript从入门到放弃
  14. 企业品牌私域化运营,私域流量只是起步
  15. 我竟然被淘口令骗了500大洋...
  16. 3-python 函数篇
  17. Android源代码编译的准备工作
  18. 【英语-同义词汇词组】by、through、via的用法及区别
  19. iconfont 转换为图标字体。
  20. HIT软件构造Lab1--过程分析

热门文章

  1. 失联近116个小时:MH370客机谜题仍待解
  2. 零基础如何学习ps?
  3. Flyway的简单介绍及使用
  4. Trip.com W1D5
  5. 学习 | 针对学生及刚从业建筑人员对常用三款建筑建模软件的用户体验调研和竞品分析
  6. 学习笔记(01):Fiddler抓包实战【小强测试品牌】-移动app端抓包
  7. Xflow学习笔记(一)操作界面
  8. 008:vue+openlayers加载6种形式google地图(代码示例)
  9. Windows查看 Cuda、Cudnn 版本、以及自己电脑需要安装哪个版本的 Cuda
  10. 在哪能免费学习python