private GridLocationMap<FcgVertex, FcgEdge> layoutFunctionCallGraph(FunctionCallGraph g) {

		GridLocationMap<FcgVertex, FcgEdge> grid = new GridLocationMap<>();

		FcgVertex source = Objects.requireNonNull(g.getSource());

		//
		// Incoming nodes on top
		// 	-sorted by address
		//
		List<FcgEdge> inEdges = new ArrayList<>(g.getInEdges(source));
		List<FcgVertex> inVertices =
			inEdges.stream().map(e -> e.getStart()).collect(Collectors.toList());
		inVertices.sort((v1, v2) -> v1.getAddress().compareTo(v2.getAddress()));
		int row = 0; // first row
		for (int col = 0; col < inVertices.size(); col++) {
			FcgVertex v = inVertices.get(col);
			grid.set(v, row, col);
		}

		//
		// Source node
		//
		row = 1; // middle row
		grid.set(source, row, 0);

		// Outgoing nodes on the bottom
		// 	-sorted by address
		// 
		List<FcgEdge> outEdges = new ArrayList<>(g.getOutEdges(source));
		List<FcgVertex> outVertices =
			outEdges.stream().map(e -> e.getEnd()).collect(Collectors.toList());

		// leave already processed vertices in the top row; this can happen if the in vertex is
		// also called by the source function, creating a cycle
		outVertices.removeAll(inVertices);
		outVertices.sort((v1, v2) -> v1.getAddress().compareTo(v2.getAddress()));
		row = 2; // last
		for (int col = 0; col < outVertices.size(); col++) {
			FcgVertex v = outVertices.get(col);
			grid.set(v, row, col);
		}

		grid.centerRows();

		return grid;
	}
A layout that will arrange vertices around a single vertex, with the incoming and outgoing
vertices above and below the source vertex, respectively.

<p>The result will look loosely like this:
<pre>
                  In1    In2   In3
                     \    |    /
                      \   |   /
                          V
                        / |  \
                       /  |   \
                 Out1    Out2  Out3

</pre>
Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/layout/BowTieLayout.java