• 凸包算法


      -------------------------------------------- 摘要 --------------------------------------------

      本文以平面上若干点为脉络,求解该若干点的凸包及过程分析。首先需对前置输入参数(平面上的若干点)作1点假设,假设

    平面上的点数n>2且各点全都不在一条直线上。下文会提供2种不同的方式求解凸包,当然在最终展示的算法是必然存在优化的可

    能,毕竟现有大多数的最优算法(也许是本身就不存在一个最终的最优算法)的实现不会是一蹴而就的而是一个循序渐进的过程,

    不断的优化,不断地改进实现算法的思想等等,最终成型。总之写下本文的第一目的就是为了充实自己,把我的愚见与大家分享。

      -------------------------------------------- 分析 --------------------------------------------

      这里提供了2种方式实现凸包算法,分别简要分析2种算法实现轮廓而不会太去纠结细节上的考量。下面直接进入分析过程:

      1. 第1种算法把它命名为斜率法,大体思路过程是:首先求出平面上点集在东南西北4各方位的最值点,如图1所示红点就

    是最值点,其次连接2个相邻方位最值点之间线段,就以东北2方位为标准连接线段,过滤掉该线段之下的点集(不包括线上的点),

    剩下候选点集。再次以某起点为基点分别计算与各候选点连线的斜率,显然斜率最大的连线的终点必然是所求凸包包含的点即凸

    包点,并且需把起点换成改凸包点,如图2所示。最后重复上述步骤直到起点为终点为止,那么对应方位的凸包点就求出了,依

    次求解其它方位的凸包点。

      2.对于第2种算法把它暂且命名为试错法吧,思路如下:首先点集作X轴的排序,并选出各方位最值点。其次对某个

    区域进行凸包点搜索,假设对东北方位相间的区域操作,先初始化-获取起点合规方向的点(合规表现为:水平与

    垂直方向的合力作用的方向遇到的第一个点,即在排序好的点集中筛选),然后把该点放入候选凸包点集(以下称凸包点集)

    中,并把起点替换为该点。再次以起点为基点选取合规的点,并判断该点与凸包点集中的最后一个点Dn的斜率和Dn与Dn下一

    个点Dn-1的斜率,如果第一个斜率大于等于第二个斜率,则直接把该点放入凸包点集,否则剔除凸包点集中的Dn,然后又判断

    该点与Dn-1的斜率和Dn-1与Dn-2的斜率,即重复上述过程直到合适后停下(该过程中的边界问题这里没有表述出来,但很好处理),

    当然停下后,继续替换起点为该点。最后重复上述步骤,直到起点与终点重合为止。其他区域过程类似,就不在赘述。

      -------------------------------------------- 源码 --------------------------------------------

      1 package algorithm;
      2 
      3 import java.util.ArrayList;
      4 import java.util.HashMap;
      5 import java.util.List;
      6 import java.util.Map;
      7 
      8 /**
      9  * @author Medusa
     10  * @date 09/12/2021
     11  * @description 凸包算法
     12  */
     13 public class ConvexHullAlgorithm {
     14 
     15     /**
     16      * 通过最大斜率的方式求出凸包点
     17      */
     18     public static List<int[]> slopeMethod(int[][] dotGatherArray) {
     19         // 求出右 上 左 下各方位的边界点集
     20         List<int[]> rightBoundaryDotList = new ArrayList<>();
     21         List<int[]> topBoundaryDotList = new ArrayList<>();
     22         List<int[]> leftBoundaryDotList = new ArrayList<>();
     23         List<int[]> belowBoundaryDotList = new ArrayList<>();
     24         getBoundaryDot(dotGatherArray, rightBoundaryDotList, topBoundaryDotList, leftBoundaryDotList,
     25                 belowBoundaryDotList);
     26         // 定义凸包点集
     27         List<int[]> convexHullDotList = new ArrayList<>();
     28         for (int i = 0; i < rightBoundaryDotList.size(); i++)
     29             convexHullDotList.add(rightBoundaryDotList.get(i));
     30         // 定义局部起止点
     31         int[] startDot = rightBoundaryDotList.get(rightBoundaryDotList.size() - 1);
     32         int[] endDot = topBoundaryDotList.get(topBoundaryDotList.size() - 1);
     33         int startIndex = topBoundaryDotList.size() - 1; // 用于判断重复点的下标
     34         if (startDot[0] == endDot[0])
     35             --startIndex;
     36         else {
     37             // 获取所有(起止点除外)与起点连线斜率不大于起止点连线斜率的候选点
     38             List<int[]> candidateDot = getCandidateDot(dotGatherArray, startDot, endDot, 0);
     39             if (candidateDot.size() > 0)
     40                 getConvexHullDot(convexHullDotList, candidateDot, startDot, endDot, true);
     41         }
     42         for (int i = startIndex; i >= 0; i--)
     43             convexHullDotList.add(topBoundaryDotList.get(i));
     44         startDot = topBoundaryDotList.get(0);
     45         endDot = leftBoundaryDotList.get(leftBoundaryDotList.size() - 1);
     46         startIndex = leftBoundaryDotList.size() - 1;
     47         if (startDot[0] == endDot[0])
     48             --startIndex;
     49         else {
     50             List<int[]> candidateDot = getCandidateDot(dotGatherArray, startDot, endDot, 1);
     51             if (candidateDot.size() > 0)
     52                 getConvexHullDot(convexHullDotList, candidateDot, startDot, endDot, true);
     53         }
     54         for (int i = startIndex; i >= 0; i--)
     55             convexHullDotList.add(leftBoundaryDotList.get(i));
     56         startDot = leftBoundaryDotList.get(0);
     57         endDot = belowBoundaryDotList.get(0);
     58         startIndex = 0;
     59         if (startDot[0] == endDot[0])
     60             ++startIndex;
     61         else {
     62             List<int[]> candidateDot = getCandidateDot(dotGatherArray, startDot, endDot, 2);
     63             if (candidateDot.size() > 0)
     64                 getConvexHullDot(convexHullDotList, candidateDot, startDot, endDot, false);
     65         }
     66         for (int i = startIndex; i < belowBoundaryDotList.size(); i++)
     67             convexHullDotList.add(belowBoundaryDotList.get(i));
     68         startDot = belowBoundaryDotList.get(belowBoundaryDotList.size() - 1);
     69         endDot = rightBoundaryDotList.get(0);
     70         if (startDot[0] == endDot[0])
     71             convexHullDotList.remove(convexHullDotList.size() - 1);
     72         else {
     73             List<int[]> candidateDot = getCandidateDot(dotGatherArray, startDot, endDot, 3);
     74             if (candidateDot.size() > 0)
     75                 getConvexHullDot(convexHullDotList, candidateDot, startDot, endDot, false);
     76         }
     77         return convexHullDotList;
     78     }
     79 
     80     /**
     81      * 生成非重复的点集
     82      */
     83     private static int[][] generateDotGather(long xMax, long yMax, int quantity) {
     84         if (xMax < 0 || yMax < 0) {
     85             System.out.println("X轴或Y轴的值不能小于0");
     86             return null;
     87         }
     88         if ((xMax + 1) * (yMax + 1) < quantity) {
     89             System.out.println("xMax,yMax所确定的最大点集数不能小于生成的点集数");
     90             return null;
     91         }
     92         int[][] dotGatherArray = new int[quantity][2];
     93         Map<String, Boolean> xyValueCounterMap = new HashMap<>(quantity);
     94         ++xMax; ++yMax;
     95         for (int i = 0; i < quantity; i++) {
     96             int xValue, yValue;
     97             Boolean xyValueCounter;
     98             do {
     99                 xValue = (int) (Math.random() * xMax);
    100                 yValue = (int) (Math.random() * yMax);
    101                 xyValueCounter = xyValueCounterMap.get(xValue + "" + yValue);
    102             } while (null != xyValueCounter);
    103             xyValueCounterMap.put(xValue + "" + yValue, true);
    104             dotGatherArray[i][0] = xValue;
    105             dotGatherArray[i][1] = yValue;
    106         }
    107         return dotGatherArray;
    108     }
    109 
    110     private static void getBoundaryDot(int[][] dotGatherArray, List<int[]> rightBoundaryDotList,
    111                                        List<int[]> topBoundaryDotList, List<int[]> leftBoundaryDotList,
    112                                        List<int[]> belowBoundaryDotList) {
    113         int xMax = dotGatherArray[0][0], yMax = dotGatherArray[0][1], xMin = xMax, yMin = yMax;
    114         for (int i = 1; i < dotGatherArray.length; i++) {
    115             int x = dotGatherArray[i][0];
    116             int y = dotGatherArray[i][1];
    117             if (x > xMax)
    118                 xMax = x;
    119             else if (x < xMin)
    120                 xMin = x;
    121             if (y > yMax)
    122                 yMax = y;
    123             else if (y < yMin)
    124                 yMin = y;
    125         }
    126         for (int i = 0; i < dotGatherArray.length; i++) {
    127             int x = dotGatherArray[i][0];
    128             int y = dotGatherArray[i][1];
    129             if (x == xMax)
    130                 rightBoundaryDotList.add(dotGatherArray[i]);
    131             else if (x == xMin)
    132                 leftBoundaryDotList.add(dotGatherArray[i]);
    133             if (y == yMax)
    134                 topBoundaryDotList.add(dotGatherArray[i]);
    135             else if (y == yMin)
    136                 belowBoundaryDotList.add(dotGatherArray[i]);
    137         }
    138         sortBoundaryDot(rightBoundaryDotList, 1);
    139         sortBoundaryDot(topBoundaryDotList, 0);
    140         sortBoundaryDot(leftBoundaryDotList, 1);
    141         sortBoundaryDot(belowBoundaryDotList, 0);
    142     }
    143 
    144     private static void sortBoundaryDot(List<int[]> boundaryDotList, int index) {
    145         for (int i = 1; i < boundaryDotList.size(); i++) {
    146             for (int j = 0; j < boundaryDotList.size() - i; j++) {
    147                 if (boundaryDotList.get(j)[index] > boundaryDotList.get(j + 1)[index]) {
    148                     int[] boundaryDot = boundaryDotList.get(j + 1);
    149                     boundaryDotList.set(j + 1, boundaryDotList.get(j));
    150                     boundaryDotList.set(j, boundaryDot);
    151                 }
    152             }
    153         }
    154     }
    155 
    156     private static List<int[]> getCandidateDot(int[][] dotGatherArray, int[] startDot, int[] endDot, int flag) {
    157         int startX = startDot[0], startY = startDot[1];
    158         int endX = endDot[0], endY = endDot[1];
    159         int yChangeRate = endY - startY, xChangeRate = endX - startX;
    160         List<int[]> candidateDotList = new ArrayList<>();
    161         if (0 == flag) {
    162             for (int i = 0; i < dotGatherArray.length; i++) {
    163                 int[] dot = dotGatherArray[i];
    164                 if (dot[1] > startY && dot[0] > endX &&
    165                     (yChangeRate * (dot[0] - startX) >= (dot[1] - startY) * xChangeRate))
    166                     candidateDotList.add(dot);
    167             }
    168         } else if (1 == flag) {
    169             for (int i = 0; i < dotGatherArray.length; i++) {
    170                 int[] dot = dotGatherArray[i];
    171                 if (dot[0] < startX && dot[1] > endY &&
    172                     (yChangeRate * (dot[0] - startX) >= (dot[1] - startY) * xChangeRate))
    173                     candidateDotList.add(dot);
    174             }
    175         } else if (2 == flag) {
    176             for (int i = 0; i < dotGatherArray.length; i++) {
    177                 int[] dot = dotGatherArray[i];
    178                 if (dot[1] < startY && dot[0] < endX &&
    179                     (yChangeRate * (dot[0] - startX) >= (dot[1] - startY) * xChangeRate))
    180                     candidateDotList.add(dot);
    181             }
    182         } else {
    183             for (int i = 0; i < dotGatherArray.length; i++) {
    184                 int[] dot = dotGatherArray[i];
    185                 if (dot[0] > startX && dot[1] < endY &&
    186                     (yChangeRate * (dot[0] - startX) >= (dot[1] - startY) * xChangeRate))
    187                     candidateDotList.add(dot);
    188             }
    189         }
    190         quickSort(candidateDotList, 0, candidateDotList.size() - 1);
    191         return candidateDotList;
    192     }
    193 
    194     private static void quickSort(List<int[]> list, int left, int right) {
    195         if (left < right) {
    196             int[] temp0Array = list.get(left);
    197             list.set(left, list.get((left + right) >> 1));
    198             list.set((left + right) >> 1, temp0Array);
    199             int[] baseArray = list.get(left);
    200             int i = left, j = right;
    201             while (i != j) {
    202                 while (list.get(j)[0] >= baseArray[0] && i < j) j--;
    203                 while (list.get(i)[0] <= baseArray[0] && i < j) i++;
    204                 if (i < j) {
    205                     int[] temp1Array = list.get(i);
    206                     list.set(i, list.get(j));
    207                     list.set(j, temp1Array);
    208                 }
    209             }
    210             list.set(left, list.get(i));
    211             list.set(i, baseArray);
    212             quickSort(list, left, i - 1);
    213             quickSort(list, i + 1, right);
    214         }
    215     }
    216 
    217     /**
    218      * 根据候选点筛选出凸包点,起点与所有候选点连线斜率的最小值即为凸包点
    219      */
    220     private static void getConvexHullDot(List<int[]> convexHullDotList, List<int[]> candidateDotList,
    221                                          int[] startDot, int[] endDot, boolean flag) {
    222         if (flag) {
    223             for (int i = 0; i < candidateDotList.size() >> 1; i++) {
    224                 int[] tempArray = candidateDotList.get(i);
    225                 candidateDotList.set(i, candidateDotList.get(candidateDotList.size() - 1 - i));
    226                 candidateDotList.set(candidateDotList.size() - 1 - i, tempArray);
    227             }
    228         }
    229         int startX = startDot[0], startY = startDot[1];
    230         int endX = endDot[0];
    231         candidateDotList.add(endDot);
    232         List<Integer> convexHullDotIndex = new ArrayList<>();
    233         int index = 0;
    234         while (startX != endX) {
    235             int y1ChangeRate = candidateDotList.get(index)[1] - startY;
    236             int x1ChangeRate = candidateDotList.get(index)[0] - startX;
    237             convexHullDotIndex.add(index);
    238             for (int i = index + 1; i < candidateDotList.size(); i++) {
    239                 int y2ChangeRate = candidateDotList.get(i)[1] - startY;
    240                 int x2ChangeRate = candidateDotList.get(i)[0] - startX;
    241                 int value0 = y1ChangeRate * x2ChangeRate;
    242                 int value1 = y2ChangeRate * x1ChangeRate;
    243                 if (value0 > value1) {
    244                     convexHullDotIndex.clear();
    245                     convexHullDotIndex.add(i);
    246                     y1ChangeRate = y2ChangeRate;
    247                     x1ChangeRate = x2ChangeRate;
    248                 }
    249                 else if (value0 == value1)
    250                     convexHullDotIndex.add(i);
    251             }
    252             index = convexHullDotIndex.get(convexHullDotIndex.size() - 1);
    253             startX = candidateDotList.get(index)[0];
    254             startY = candidateDotList.get(index)[1];
    255             ++index;
    256             for (int i = 0; i < convexHullDotIndex.size(); i++)
    257                 convexHullDotList.add(candidateDotList.get(convexHullDotIndex.get(i)));
    258             convexHullDotIndex.clear();
    259         }
    260         convexHullDotList.remove(convexHullDotList.size() - 1);
    261     }
    262 
    263     /**
    264      * 以x轴降序的方式寻找边界
    265      */
    266     public static List<int[]> searchBoundary(int[][] dotGather) {
    267         quickSort(dotGather, 0, dotGather.length - 1);
    268         List<int[]> rightBoundaryDotList = new ArrayList<>();
    269         rightBoundaryDotList.add(dotGather[dotGather.length - 1]);
    270         for (int i = dotGather.length - 2; i >= 0; i--) {
    271             if (dotGather[dotGather.length - 1][0] == dotGather[i][0])
    272                 rightBoundaryDotList.add(dotGather[i]);
    273             else
    274                 break;
    275         }
    276         sortBoundaryDot(rightBoundaryDotList, 1);
    277         List<int[]> leftBoundaryDotList = new ArrayList<>();
    278         leftBoundaryDotList.add(dotGather[0]);
    279         for (int i = 1; i < dotGather.length; i++) {
    280             if (dotGather[0][0] == dotGather[i][0])
    281                 leftBoundaryDotList.add(dotGather[i]);
    282             else
    283                 break;
    284         }
    285         sortBoundaryDot(leftBoundaryDotList, 1);
    286         List<int[]> topBoundaryDotList = new ArrayList<>();
    287         List<int[]> belowBoundaryDotList = new ArrayList<>();
    288         int maxY = dotGather[0][1], minY = maxY;
    289         for (int i = 1; i < dotGather.length; i++) {
    290             if (maxY < dotGather[i][1])
    291                 maxY = dotGather[i][1];
    292             else if (minY > dotGather[i][1])
    293                 minY = dotGather[i][1];
    294         }
    295         for (int i = 0; i < dotGather.length; i++) {
    296             if (maxY == dotGather[i][1])
    297                 topBoundaryDotList.add(dotGather[i]);
    298             else if (minY == dotGather[i][1])
    299                 belowBoundaryDotList.add(dotGather[i]);
    300         }
    301         sortBoundaryDot(topBoundaryDotList, 0);
    302         sortBoundaryDot(belowBoundaryDotList, 0);
    303         List<int[]> convexHullDotList = new ArrayList<>();
    304         for (int i = 0; i < rightBoundaryDotList.size(); i++)
    305             convexHullDotList.add(rightBoundaryDotList.get(i));
    306         int[] startDot = rightBoundaryDotList.get(rightBoundaryDotList.size() - 1);
    307         int[] endDot = topBoundaryDotList.get(topBoundaryDotList.size() - 1);
    308         int startIndex = topBoundaryDotList.size() - 1;
    309         if (startDot[0] == endDot[0])
    310             --startIndex;
    311         else
    312             search(dotGather, convexHullDotList, startDot, endDot, 0);
    313         for (int i = startIndex; i >= 0; i--)
    314             convexHullDotList.add(topBoundaryDotList.get(i));
    315         startDot = leftBoundaryDotList.get(leftBoundaryDotList.size() - 1);
    316         endDot = topBoundaryDotList.get(0);
    317         startIndex = leftBoundaryDotList.size() - 1;
    318         if (startDot[0] == endDot[0])
    319             --startIndex;
    320         else
    321             search(dotGather, convexHullDotList, startDot, endDot, 1);
    322         for (int i = startIndex; i >= 0; i--)
    323             convexHullDotList.add(leftBoundaryDotList.get(i));
    324         startDot = leftBoundaryDotList.get(0);
    325         endDot = belowBoundaryDotList.get(0);
    326         startIndex = 0;
    327         if (startDot[0] == endDot[0])
    328             ++startIndex;
    329         else
    330             search(dotGather, convexHullDotList, startDot, endDot, 2);
    331         for (int i = startIndex; i < belowBoundaryDotList.size(); i++)
    332             convexHullDotList.add(belowBoundaryDotList.get(i));
    333         startDot = rightBoundaryDotList.get(0);
    334         endDot = belowBoundaryDotList.get(belowBoundaryDotList.size() - 1);
    335         if (startDot[0] == endDot[0])
    336             convexHullDotList.remove(convexHullDotList.size() - 1);
    337         else
    338             search(dotGather, convexHullDotList, startDot, endDot, 3);
    339         return convexHullDotList;
    340     }
    341 
    342     private static void quickSort(int[][] array, int left, int right) {
    343         if (left < right) {
    344             int[] temp0Array = array[left];
    345             array[left] = array[(left + right) >> 1];
    346             array[(left + right) >> 1] = temp0Array;
    347             int[] baseArray = array[left];
    348             int i = left, j = right;
    349             while (i != j) {
    350                 while (array[j][0] >= baseArray[0] && i < j) j--;
    351                 while (array[i][0] <= baseArray[0] && i < j) i++;
    352                 if (i < j) {
    353                     int[] temp1Array = array[i];
    354                     array[i] = array[j];
    355                     array[j] = temp1Array;
    356                 }
    357             }
    358             array[left] = array[i];
    359             array[i] = baseArray;
    360             quickSort(array, left, i - 1);
    361             quickSort(array, i + 1, right);
    362         }
    363     }
    364 
    365     private static void search(int[][] dotGather, List<int[]> convexHullDotList, int[] startDot,
    366                                int[] endDot, int flag) {
    367         int startX = startDot[0], startY = startDot[1];
    368         int endX = endDot[0], endY = endDot[1];
    369         if (flag == 0) {
    370             // 1.dot[1] - nowConvexHullDot[1] / dot[0] - nowConvexHullDot[0]
    371             // <
    372             // nowConvexHullDot[1] - nextConvexHullDot[1] / nowConvexHullDot[0] - nextConvexHullDot[0]
    373             // yt - y1/0 < y1 - y2/x1 - x2
    374             int pointer = convexHullDotList.size() - 1, limit = pointer, index = dotGather.length - 1;
    375             do {
    376                 int[] dot = dotGather[index--];
    377                 if (dot[1] > startY && dot[0] >= endX && dot[1] <= endY) {
    378                     for (int i = pointer; i > limit; i--) {
    379                         int[] nowConvexHullDot = convexHullDotList.get(i);
    380                         int[] nextConvexHullDot = convexHullDotList.get(i - 1);
    381                         if ((dot[1] - nowConvexHullDot[1]) * (nowConvexHullDot[0] - nextConvexHullDot[0]) <
    382                             (nowConvexHullDot[1] - nextConvexHullDot[1]) * (dot[0] - nowConvexHullDot[0]))
    383                             convexHullDotList.remove(i);
    384                         else
    385                             break;
    386                     }
    387                     convexHullDotList.add(dot);
    388                     pointer = convexHullDotList.size() - 1;
    389                     startX = dot[0];
    390                     startY = dot[1];
    391                 }
    392             } while (startX != endX && startY != endY);
    393             convexHullDotList.remove(convexHullDotList.size() - 1);
    394         } else if (flag == 1) {
    395             // 2.dot[1] - nowConvexHullDot[1] / dot[0] - nowConvexHullDot[0]
    396             // >
    397             // nowConvexHullDot[1] - nextConvexHullDot[1] / nowConvexHullDot[0] - nextConvexHullDot[0]
    398             // yt - y1/0 > y1 - y2/x1 - x2
    399             List<int[]> tempList = new ArrayList<>();
    400             tempList.add(startDot);
    401             int pointer = 0, index = 0;
    402             do {
    403                 int[] dot = dotGather[index++];
    404                 if (dot[1] > startY && dot[0] <= endX && dot[1] <= endY) {
    405                     for (int i = pointer; i > 0; i--) {
    406                         int[] nowConvexHullDot = tempList.get(i);
    407                         int[] nextConvexHullDot = tempList.get(i - 1);
    408                         if ((dot[1] - nowConvexHullDot[1]) * (nowConvexHullDot[0] - nextConvexHullDot[0]) >
    409                             (nowConvexHullDot[1] - nextConvexHullDot[1]) * (dot[0] - nowConvexHullDot[0]))
    410                             tempList.remove(i);
    411                         else
    412                             break;
    413                     }
    414                     tempList.add(dot);
    415                     pointer = tempList.size() - 1;
    416                     startX = dot[0];
    417                     startY = dot[1];
    418                 }
    419             } while (startX != endX && startY != endY);
    420             for (int i = tempList.size() - 2; i > 0; i--)
    421                 convexHullDotList.add(tempList.get(i));
    422         } else if (flag == 2) {
    423             // 3.dot[1] - nowConvexHullDot[1] / dot[0] - nowConvexHullDot[0]
    424             // <
    425             // nowConvexHullDot[1] - nextConvexHullDot[1] / nowConvexHullDot[0] - nextConvexHullDot[0]
    426             // yt - y1/0 < y1 - y2/x1 - x2
    427             int pointer = convexHullDotList.size() - 1, limit = pointer, index = 0;
    428             do {
    429                 int[] dot = dotGather[index++];
    430                 if (dot[1] < startY && dot[0] <= endX && dot[1] >= endY) {
    431                     for (int i = pointer; i > limit; i--) {
    432                         int[] nowConvexHullDot = convexHullDotList.get(i);
    433                         int[] nextConvexHullDot = convexHullDotList.get(i - 1);
    434                         if ((dot[1] - nowConvexHullDot[1]) * (nowConvexHullDot[0] - nextConvexHullDot[0]) <
    435                             (nowConvexHullDot[1] - nextConvexHullDot[1]) * (dot[0] - nowConvexHullDot[0]))
    436                             convexHullDotList.remove(i);
    437                         else
    438                             break;
    439                     }
    440                     convexHullDotList.add(dot);
    441                     pointer = convexHullDotList.size() - 1;
    442                     startX = dot[0];
    443                     startY = dot[1];
    444                 }
    445             } while (startX != endX && startY != endY);
    446             convexHullDotList.remove(convexHullDotList.size() - 1);
    447         } else {
    448             // 4.dot[1] - nowConvexHullDot[1] / dot[0] - nowConvexHullDot[0]
    449             // >
    450             // nowConvexHullDot[1] - nextConvexHullDot[1] / nowConvexHullDot[0] - nextConvexHullDot[0]
    451             // yt - y1/0 > y1 - y2/x1 - x2
    452             List<int[]> tempList = new ArrayList<>();
    453             tempList.add(startDot);
    454             int pointer = 0, index = dotGather.length - 1;;
    455             do {
    456                 int[] dot = dotGather[index--];
    457                 if (dot[1] < startY && dot[0] >= endX && dot[1] >= endY) {
    458                     for (int i = pointer; i > 0; i--) {
    459                         int[] nowConvexHullDot = tempList.get(i);
    460                         int[] nextConvexHullDot = tempList.get(i - 1);
    461                         if ((dot[1] - nowConvexHullDot[1]) * (nowConvexHullDot[0] - nextConvexHullDot[0]) >
    462                             (nowConvexHullDot[1] - nextConvexHullDot[1]) * (dot[0] - nowConvexHullDot[0]))
    463                             tempList.remove(i);
    464                         else
    465                             break;
    466                     }
    467                     tempList.add(dot);
    468                     pointer = tempList.size() - 1;
    469                     startX = dot[0];
    470                     startY = dot[1];
    471                 }
    472             } while (startX != endX && startY != endY);
    473             for (int i = tempList.size() - 2; i > 0; i--)
    474                 convexHullDotList.add(tempList.get(i));
    475         }
    476     }
    477 }
    View Code
  • 相关阅读:
    php 替换二维数组的 key
    全选功能
    向数组中添加含有下标的元素
    判断一个进程是否在执行中
    初识 Nginx
    原生JS中DOM节点相关API合集
    工作中经常用到github上优秀、实用、轻量级、无依赖的插件和库
    Unsupported major.minor version ... JDK具体对应版本
    Scala常用命令
    使用nexus搭建maven私服教程详解
  • 原文地址:https://www.cnblogs.com/nearWind/p/16358300.html
Copyright © 2020-2023  润新知