docs: function (state, source, target, points, result)
  	 {
  		var view = state.view;
  	 	var graph = view.graph;
  	 	var segment = mxUtils.getValue(state.style,
  	 			mxConstants.STYLE_SEGMENT,
  	 			mxConstants.ENTITY_SEGMENT) * view.scale;
  	 	
  		var pts = state.absolutePoints;
  		var p0 = pts[0];
  		var pe = pts[pts.length-1];
  
  	 	var isSourceLeft = false;
  
  		if (p0 != null)
  		{
  			source = new mxCellState();
  			source.x = p0.x;
  			source.y = p0.y;
  		}
  		else if (source != null)
  		{
  			var constraint = mxUtils.getPortConstraints(source, state, true, mxConstants.DIRECTION_MASK_NONE);
  			
  			if (constraint != mxConstants.DIRECTION_MASK_NONE && constraint != mxConstants.DIRECTION_MASK_WEST +
  				mxConstants.DIRECTION_MASK_EAST)
  			{
  				isSourceLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
  			}
  			else
  			{
  			 	var sourceGeometry = graph.getCellGeometry(source.cell);
  		
  			 	if (sourceGeometry.relative)
  			 	{
  			 		isSourceLeft = sourceGeometry.x <= 0.5;
  			 	}
  			 	else if (target != null)
  			 	{
  			 		isSourceLeft = target.x + target.width < source.x;
  			 	}
  			}
  		}
  		else
  		{
  			return;
  		}
  	 	
  	 	var isTargetLeft = true;
  
  		if (pe != null)
  		{
  			target = new mxCellState();
  			target.x = pe.x;
  			target.y = pe.y;
  		}
  		else if (target != null)
  	 	{
  			var constraint = mxUtils.getPortConstraints(target, state, false, mxConstants.DIRECTION_MASK_NONE);
  
  			if (constraint != mxConstants.DIRECTION_MASK_NONE && constraint != mxConstants.DIRECTION_MASK_WEST +
  				mxConstants.DIRECTION_MASK_EAST)
  			{
  				isTargetLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
  			}
  			else
  			{
  			 	var targetGeometry = graph.getCellGeometry(target.cell);
  	
  			 	if (targetGeometry.relative)
  			 	{
  			 		isTargetLeft = targetGeometry.x <= 0.5;
  			 	}
  			 	else if (source != null)
  			 	{
  			 		isTargetLeft = source.x + source.width < target.x;
  			 	}
  			}
  	 	}
  		
  		if (source != null && target != null)
  		{
  			var x0 = (isSourceLeft) ? source.x : source.x + source.width;
  			var y0 = view.getRoutingCenterY(source);
  			
  			var xe = (isTargetLeft) ? target.x : target.x + target.width;
  			var ye = view.getRoutingCenterY(target);
  	
  			var seg = segment;
  	
  			var dx = (isSourceLeft) ? -seg : seg;
  			var dep = new mxPoint(x0 + dx, y0);
  					
  			dx = (isTargetLeft) ? -seg : seg;
  			var arr = new mxPoint(xe + dx, ye);
  	
  			// Adds intermediate points if both go out on same side
  			if (isSourceLeft == isTargetLeft)
  			{
  				var x = (isSourceLeft) ?
  					Math.min(x0, xe)-segment :
  					Math.max(x0, xe)+segment;
  	
  				result.push(new mxPoint(x, y0));
  				result.push(new mxPoint(x, ye));
  			}
  			else if ((dep.x < arr.x) == isSourceLeft)
  			{
  				var midY = y0 + (ye - y0) / 2;
  	
  				result.push(dep);
  				result.push(new mxPoint(dep.x, midY));
  				result.push(new mxPoint(arr.x, midY));
  				result.push(arr);
  			}
  			else
  			{
  				result.push(dep);
  				result.push(arr);
  			}
  		}
  	 }