code: private static Direction direction(Point2d centerXy, Point2d substituentXy, Point2d horizontalXy, boolean haworth) {
          double deltaX = substituentXy.x - centerXy.x;
          double deltaY = substituentXy.y - centerXy.y;
  
          // normalise vector length so threshold is independent of length 
          double mag = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
          deltaX /= mag;
          deltaY /= mag;
  
          // account for an offset horizontal reference and re-normalise,
          // we presume no vertical chairs and use the deltaX +ve or -ve to
          // determine direction, the horizontal offset should be deltaX > 0.
          if (deltaX > 0) {
              deltaX -= horizontalXy.x;
              deltaY -= horizontalXy.y;
          } else {
              deltaX += horizontalXy.x;
              deltaY += horizontalXy.y;
          }
          mag = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
          deltaX /= mag;
          deltaY /= mag;
  
          if (haworth && Math.abs(deltaX) > CARDINALITY_THRESHOLD)
              return Direction.Other;
          
          return deltaY > 0 ? Direction.Up : Direction.Down;
      }
docs: Obtain the direction of a substituent relative to the center location. In
  a Haworth projection the substituent must be directly above or below
  (with threshold) the center.
  
  @param centerXy      location of center
  @param substituentXy location fo substituent
  @param horizontalXy  horizontal offset, x > 0
  @param haworth       is Haworth project (substituent must be directly up
  or down)
  @return the direction (up, down, other)