function connectRectangles(source, target, start, end, hints) {

  var preferredLayouts = hints && hints.preferredLayouts || [];

  var preferredLayout = without(preferredLayouts, 'straight')[0] || 'h:h';

  var threshold = ORIENTATION_THRESHOLD[preferredLayout] || 0;

  var orientation = getOrientation(source, target, threshold);

  var directions = getDirections(orientation, preferredLayout);

  start = start || getMid(source);
  end = end || getMid(target);

  var directionSplit = directions.split(':');

  // compute actual docking points for start / end
  // this ensures we properly layout only parts of the
  // connection that lies in between the two rectangles
  var startDocking = getDockingPoint(start, source, directionSplit[0], invertOrientation(orientation)),
      endDocking = getDockingPoint(end, target, directionSplit[1], orientation);

  return connectPoints(startDocking, endDocking, directions);
}
Connect two rectangles using a manhattan layouted connection.

@param {Rect} source source rectangle
@param {Rect} target target rectangle
@param {Point} [start] source docking
@param {Point} [end] target docking
@param {Object} [hints]
@param {string} [hints.preserveDocking=source] preserve docking on selected side
@param {string[]} [hints.preferredLayouts]
@param {Point|boolean} [hints.connectionStart] whether the start changed
@param {Point|boolean} [hints.connectionEnd] whether the end changed

@return {Point[]} connection points