判断顶点凹凸性、判断多边形的凹凸性、填充凹坑将凹多边形处理为凸多边形【java实现+原理讲解】

简介: 判断顶点凹凸性、判断多边形的凹凸性、填充凹坑将凹多边形处理为凸多边形【java实现+原理讲解】

问题

  1. 如何识别多边形中一个顶点的凹凸性
  2. 如何判断一个多边形的凹凸性(若多边形有一个点为凹的,则多边形为凹的)
  3. 如何通过填充凹坑的方式将凹多边形转化为凸多边形


方法

将多边形点集顺序修改为逆时针顺序

判断多边形点击顺序的方法可以参考判断多边形点集顺序,如果判断出多边形点击顺序为顺时针的话,直接将集合反转一下即可


判断一个点是否为凹点


注意:使用这方法判断的前提是多边形点击顺序是逆时针的才行

最终实现


/**
* 将凹多边形转化为凸多边形
*/
public class ConcaveToConvexApi {
   /**
    * 将凹多边形转化为凸多边形
    *
    * @param pointList
    * @return
    */
   public List<Point> concaveToConvex(List<Point> pointList) {
       List<Point> pointListClone = (List<Point>) deepClone(pointList);
       将点集方向转化为逆时针方向
       this.correctPolygonDirection(pointListClone);
       删除掉凹点
       int j = 0;
       while (j < pointListClone.size()) {
           int i = (j - 1 + pointListClone.size()) % pointListClone.size();
           int k = (j + 1) % pointListClone.size();
           double x1 = pointListClone.get(j).getX() - pointListClone.get(i).getX();
           double y1 = pointListClone.get(j).getY() - pointListClone.get(i).getY();
           double x2 = pointListClone.get(k).getX() - pointListClone.get(i).getX();
           double y2 = pointListClone.get(k).getY() - pointListClone.get(i).getY();
           //叉积
           double crossProduct = x1 * y2 - x2 * y1;
           if (crossProduct > 0) {
               //凸顶点
               j++;
           } else {
               //凹顶点或者共线
               pointListClone.remove(j);
               if (j == pointListClone.size()) {
                   /*
                   一开始是 A B C D E F G 开始时j=0,GAB不触发删除
                   但是FGA触发删除之后,序列变成A B C D E F,可能FAB也会触发删除,因此需要将j重置于0
                    */
                   j = 0;
               } else {
                   if (j > 0) {
                      //这里为什么j--,可以看程序下面的图
                       j--;
                   }
               }
           }
       }
       return pointListClone;
   }
   /**
    * 修正零件的点位方向
    * 先找出最高那个点的索引i,然后在对{i.x-(i-1).x,i.y-(i-1).y}和{(i+1).x-(i-1).x,(i+1).y-(i-1).y}来求叉积,看正负就知道了
    *
    * @param pointList
    */
   private void correctPolygonDirection(List<Point> pointList) {
       if (pointList.size() == 0) {
           return;
       }
       找到零件的最高点
       int highestPointIndex = -1;
       double highestY = -Double.MAX_VALUE;
       for (int i = 0; i < pointList.size(); i++) {
           if (pointList.get(i).getY() > highestY) {
               highestY = pointList.get(i).getY();
               highestPointIndex = i;
           }
       }
       纠正坐标
       ///判断随着索引的进位,夹角是否为正数
       //存储方向,1:顺时针;-1:逆时针
       int direction = 0;
       Point lastPoint = pointList.get((highestPointIndex - 1 + pointList.size()) % pointList.size());
       Point curPoint = pointList.get(highestPointIndex);
       Point nextPoint = pointList.get((highestPointIndex + 1) % pointList.size());
       double x1 = curPoint.getX() - lastPoint.getX();
       double y1 = curPoint.getY() - lastPoint.getY();
       double x2 = nextPoint.getX() - lastPoint.getX();
       double y2 = nextPoint.getY() - lastPoint.getY();
       //计算向量的叉积
       double crossProduct = x1 * y2 - x2 * y1;
       if (crossProduct > 0) {
           direction = -1;
       } else if (crossProduct < 0) {
           direction = 1;
       }
       //如果是顺时针的话,需要改为逆时针
       if (direction == 1) {
           //将集合的元素反转
           Collections.reverse(pointList);
       }
   }
}

ac54ee3a5202475d8e9001ed12b95efe.png


测试


目录
相关文章
|
4天前
|
Java 数据库连接 Spring
K8S+Docker理论与实践深度集成java面试jvm原理
K8S+Docker理论与实践深度集成java面试jvm原理
|
5天前
|
算法 安全 Java
深入探索Java中的并发编程:CAS机制的原理与应用
总之,CAS机制是一种用于并发编程的原子操作,它通过比较内存中的值和预期值来实现多线程下的数据同步和互斥,从而提供了高效的并发控制。它在Java中被广泛应用于实现线程安全的数据结构和算法。
26 0
|
5天前
|
存储 监控 安全
JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。
12 0
|
5天前
|
搜索推荐 Java Shell
8大Java排序方法(由简入繁),有代码详解和原理指导
8大Java排序方法(由简入繁),有代码详解和原理指导
33 0
|
5天前
|
存储 安全 Java
【Java EE】CAS原理和实现以及JUC中常见的类的使用
【Java EE】CAS原理和实现以及JUC中常见的类的使用
|
5天前
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
|
5天前
|
监控 搜索推荐 算法
Java排序:原理、实现与应用
【4月更文挑战第28天】本文探讨了Java中的排序算法,包括原理和实现。Java利用Comparator接口进行元素比较,通过Arrays和Collections类的sort方法对数组和列表进行排序。示例展示了使用这些方法的基本代码。此外,还讨论了冒泡排序算法和自定义排序场景,以适应不同需求。理解这些排序机制有助于提升程序效率。
13 1
|
5天前
|
设计模式 消息中间件 Java
Java 设计模式:探索发布-订阅模式的原理与应用
【4月更文挑战第27天】发布-订阅模式是一种消息传递范式,被广泛用于构建松散耦合的系统。在 Java 中,这种模式允许多个对象监听和响应感兴趣的事件。
39 2
|
5天前
|
设计模式 算法 Java
Java 设计模式:深入模板方法模式的原理与应用
【4月更文挑战第27天】模板方法模式是一种行为设计模式,主要用于定义一个操作中的算法的框架,允许子类在不改变算法结构的情况下重定义算法的某些特定步骤。
23 1
|
5天前
|
安全 Java 开发者
Java编程:深入探索其原理、特性与实战代码
Java编程:深入探索其原理、特性与实战代码
15 1