docs: private void grahamScan() {
      if(points.size() < 3) {
        return;
      }
      Iterator<double[]> iter = points.iterator();
      Stack<double[]> stack = new Stack<>();
      // Start with the first two points on the stack
      final double[] first = iter.next();
      stack.add(first);
      while(iter.hasNext()) {
        double[] n = iter.next();
        if(mdist(first, n) > 0) {
          stack.add(n);
          break;
        }
      }
      while(iter.hasNext()) {
        double[] next = iter.next();
        double[] curr = stack.pop();
        double[] prev = stack.peek();
        while((stack.size() > 1) && (mdist(curr, next) == 0 || !isConvex(prev, curr, next))) {
          curr = stack.pop();
          prev = stack.peek();
        }
        stack.add(curr);
        stack.add(next);
      }
      points = stack;
    }