docs: function mxSwimlaneModel(layout, vertices, roots, parent, tightenToSource)
  {
  	var graph = layout.getGraph();
  	this.tightenToSource = tightenToSource;
  	this.roots = roots;
  	this.parent = parent;
  
  	// map of cells to internal cell needed for second run through
  	// to setup the sink of edges correctly
  	this.vertexMapper = new mxDictionary();
  	this.edgeMapper = new mxDictionary();
  	this.maxRank = 0;
  	var internalVertices = [];
  
  	if (vertices == null)
  	{
  		vertices = this.graph.getChildVertices(parent);
  	}
  
  	this.maxRank = this.SOURCESCANSTARTRANK;
  	// map of cells to internal cell needed for second run through
  	// to setup the sink of edges correctly. Guess size by number
  	// of edges is roughly same as number of vertices.
  	this.createInternalCells(layout, vertices, internalVertices);
  
  	// Go through edges set their sink values. Also check the
  	// ordering if and invert edges if necessary
  	for (var i = 0; i < vertices.length; i++)
  	{
  		var edges = internalVertices[i].connectsAsSource;
  
  		for (var j = 0; j < edges.length; j++)
  		{
  			var internalEdge = edges[j];
  			var realEdges = internalEdge.edges;
  
  			// Only need to process the first real edge, since
  			// all the edges connect to the same other vertex
  			if (realEdges != null && realEdges.length > 0)
  			{
  				var realEdge = realEdges[0];
  				var targetCell = layout.getVisibleTerminal(
  						realEdge, false);
  				var internalTargetCell = this.vertexMapper.get(targetCell);
  
  				if (internalVertices[i] == internalTargetCell)
  				{
  					// If there are parallel edges going between two vertices and not all are in the same direction
  					// you can have navigated across one direction when doing the cycle reversal that isn't the same
  					// direction as the first real edge in the array above. When that happens the if above catches
  					// that and we correct the target cell before continuing.
  					// This branch only detects this single case
  					targetCell = layout.getVisibleTerminal(
  							realEdge, true);
  					internalTargetCell = this.vertexMapper.get(targetCell);
  				}
  
  				if (internalTargetCell != null
  						&& internalVertices[i] != internalTargetCell)
  				{
  					internalEdge.target = internalTargetCell;
  
  					if (internalTargetCell.connectsAsTarget.length == 0)
  					{
  						internalTargetCell.connectsAsTarget = [];
  					}
  
  					if (mxUtils.indexOf(internalTargetCell.connectsAsTarget, internalEdge) < 0)
  					{
  						internalTargetCell.connectsAsTarget.push(internalEdge);
  					}
  				}
  			}
  		}
  
  		// Use the temp variable in the internal nodes to mark this
  		// internal vertex as having been visited.
  		internalVertices[i].temp[0] = 1;
  	}
  }