package com.c2kernel.gui.graph.view; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import com.c2kernel.graph.model.DirectedEdge; import com.c2kernel.graph.model.GraphPoint; public class DefaultDirectedEdgeRenderer implements DirectedEdgeRenderer { private GeneralPath mArrowTemplate = new GeneralPath(); private Paint mLinePaint = null; public DefaultDirectedEdgeRenderer(Paint linePaint) { mLinePaint = linePaint; mArrowTemplate.moveTo(-5, 5); mArrowTemplate.lineTo( 0, 0); mArrowTemplate.lineTo( 5, 5); } @Override public void draw(Graphics2D g2d, DirectedEdge directedEdge) { GraphPoint originPoint = directedEdge.getOriginPoint(); GraphPoint terminusPoint = directedEdge.getTerminusPoint(); GraphPoint midPoint = new GraphPoint(); AffineTransform transform = new AffineTransform(); Shape arrow = null; g2d.setPaint(mLinePaint); g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y); midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x)/2; midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y)/2; transform.translate(midPoint.x, midPoint.y); transform.rotate(calcArrowAngle(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y)); arrow = mArrowTemplate.createTransformedShape(transform); g2d.draw(arrow); } private static double calcArrowAngle(int originX, int originY, int terminusX, int terminusY) { double width = terminusX - originX; double height = terminusY - originY; if((width == 0) && (height > 0)) return Math.PI; if((width == 0) && (height < 0)) return 0; if((width > 0) && (height == 0)) return Math.PI/2.0; if((width < 0) && (height == 0)) return -1.0 * Math.PI/2.0; if((width > 0) && (height > 0)) return Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width)); if((width > 0) && (height < 0)) return Math.atan(Math.abs(width)/Math.abs(height)); if((width < 0) && (height < 0)) return -1.0 * Math.atan(Math.abs(width)/Math.abs(height)); if((width < 0) && (height > 0)) return -1.0 * (Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width))); return 0.0; } }