public static Shape createEgdeLoopInGraphSpace(Shape edgeLoopShape, Shape vertexShape, double x,
			double y) {

		/*
		 	x, y - vertex coordinates; these are the center of the vertex shape
		 	vertexShape - the is the shape of the vertex; it will be centered over the x,y
		 	
		 		shape x,y
		 				---------
		 				|       |
		 				|  x,y (|)   edge circle, clipped by the vertex
		 				|       |
		 				---------
		 	
		 */

		// note: the edge shape will be drawn around its center
		Rectangle2D b = vertexShape.getBounds2D();
		double vWidth = b.getWidth();
		double vHeight = b.getHeight();

		double scale = .2; // edge size as a proportion of vertex size

		/*
		 	This code allows the edge position to move closer to the shape when not using 
		 	a rectangular shape.   If we ever have unusual shapes, then this may be worth using.
		 	For now, it seems excessive to perform the math, as this code is currently called
		 	for each loop edge, for each paint.   If we ever cache edge info, this is available.
		
		 	
		 	// 
			// The 'endX' is the right edge of the *rectangle bounds* of the vertex.  The actual
			// shape of the vertex may not be rectangular.  So, keep moving the edge shape closer
			// to the vertex until it is slightly obscured (as noted above).
			//
			double move = .1;
			Point2D p = new Point2D.Double(endX, y);
			while (p.getX() > x) {
		
				if (vertexShape.contains(p)) {
					break;
				}
		
				double offset = move * radius;
				p.setLocation(endX - offset, y);
				move += .1;
			}
			double edgeX = p.getX();		  
		 */

		double radius = vHeight * scale;
		double diameter = radius * 2;

		// hide some of the circle so it appears as the edge enters and exits the vertex
		double hiddenAmount = diameter * .30;
		double halfVertex = (vWidth / 2); // divide by 2; the vertex is centered
		double vertexEndX = x + halfVertex;

		double edgeX = vertexEndX + radius - hiddenAmount;
		AffineTransform xform = AffineTransform.getTranslateInstance(edgeX, y);
		xform.scale(radius, radius);
		return xform.createTransformedShape(edgeLoopShape);
	}
Transforms the given edge loop shape to graph space, which includes updating
the size and location of the loop to be relative to the vertex.

@param edgeLoopShape The shape to transform
@param vertexShape The shape of the vertex for which the edge is being created
@param x The x coordinate of the vertex
@param y The y coordinate of the vertex
@return the transformed edge loop shape
Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewerUtils.java