addUnderneathRect = (curLayerIndex, i, leftX,
  intermediateGap, padding, intermediateNodeMouseOverHandler,
  intermediateNodeMouseLeaveHandler, intermediateNodeClicked) => {
  // Add underneath rects
  let underGroup = svg.select('g.underneath');

  for (let n = 0; n < cnn[curLayerIndex - 1].length; n++) {
    underGroup.append('rect')
      .attr('class', 'underneath-gateway')
      .attr('id', `underneath-gateway-${n}`)
      .attr('x', leftX - padding)
      .attr('y', nodeCoordinate[curLayerIndex - 1][n].y - padding)
      .attr('width', (2 * nodeLength + intermediateGap) + 2 * padding)
      .attr('height', nodeLength + 2 * padding)
      .attr('rx', 10)
      .style('fill', 'rgba(160, 160, 160, 0.2)')
      .style('opacity', 0);
    
    // Register new events for input layer nodes
    svg.select(`g#layer-${curLayerIndex - 1}-node-${n}`)
      .style('pointer-events', 'all')
      .style('cursor', 'pointer')
      .on('mouseover', intermediateNodeMouseOverHandler)
      .on('mouseleave', intermediateNodeMouseLeaveHandler)
      .on('click', (d, ni, g) => intermediateNodeClicked(d, ni, g,
        i, curLayerIndex));
      // .on('click', (d, i) => {console.log(i)});
  }
  underGroup.lower();
}
Append a filled rectangle under a pair of nodes.
@param {number} curLayerIndex Index of the selected layer
@param {number} i Index of the selected node
@param {number} leftX X value of the left border of intermediate layer
@param {number} intermediateGap Inner gap of this intermediate layer
@param {number} padding Padding around the rect
@param {function} intermediateNodeMouseOverHandler Mouse over handler
@param {function} intermediateNodeMouseLeaveHandler Mouse leave handler
@param {function} intermediateNodeClicked Mouse click handler