code: public static double[] shiftReactionVertical(IReaction reaction, double[] bounds, double[] last, double gap) {
          assert bounds.length == 4;
          assert last.length == 4;
  
          final double boundsMinX = bounds[0];
          final double boundsMinY = bounds[1];
          final double boundsMaxX = bounds[2];
          final double boundsMaxY = bounds[3];
  
          final double lastMinY = last[1];
          final double lastMaxY = last[3];
  
          final double boundsHeight = boundsMaxY - boundsMinY;
          final double lastHeight = lastMaxY - lastMinY;
  
          // determine if the reactions are overlapping
          if (lastMaxY + gap >= boundsMinY) {
              double yShift = boundsHeight + lastHeight + gap;
              Vector2d shift = new Vector2d(0, yShift);
              List<IAtomContainer> containers = ReactionManipulator.getAllAtomContainers(reaction);
              for (IAtomContainer container : containers) {
                  translate2D(container, shift);
              }
              return new double[]{boundsMinX, boundsMinY + yShift, boundsMaxX, boundsMaxY + yShift};
          } else {
              // the reactions were not overlapping
              return bounds;
          }
      }
docs: Shift the containers in a reaction vertically upwards to not overlap with the reference
  rectangle. The shift is such that the given gap is realized, but only if the reactions are
  actually overlapping. To avoid dependence on Java AWT, rectangles are described by
  arrays of double. Each rectangle is specified by {minX, minY, maxX, maxY}.
  
  @param reaction the reaction to shift
  @param bounds   the bounds of the reaction to shift
  @param last     the bounds of the last reaction
  @return the rectangle of the shifted reaction