* is scaled in the x-direction so that its width is equal to the distance between
* <code>(x1,y1)</code> and <code>(x2,y2)</code>.
*/
protected void drawSimpleEdge(RenderContext<V,E> rc, Layout<V,E> layout, E e) {
TransformingGraphics g = (TransformingGraphics)rc.getGraphicsContext();
Graph<V,E> graph = layout.getGraph();
Pair<V> endpoints = graph.getEndpoints(e);
V v1 = endpoints.getFirst();
V v2 = endpoints.getSecond();
Point2D p1 = layout.transform(v1);
Point2D p2 = layout.transform(v2);
p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1);
p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2);
float x1 = (float) p1.getX();
float y1 = (float) p1.getY();
float x2 = (float) p2.getX();
float y2 = (float) p2.getY();
float flatness = 0;
MutableTransformer transformer = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW);
if(transformer instanceof LensTransformer) {
LensTransformer ht = (LensTransformer)transformer;
RectangularShape lensShape = ht.getLensShape();
if(lensShape.contains(x1,y1) || lensShape.contains(x2,y2)) {
flatness = .05f;
}
}
boolean isLoop = v1.equals(v2);
Shape s2 = rc.getVertexShapeTransformer().transform(v2);
Shape edgeShape = rc.getEdgeShapeTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
boolean edgeHit = true;
boolean arrowHit = true;
Rectangle deviceRectangle = null;
JComponent vv = rc.getScreenDevice();
if(vv != null) {
Dimension d = vv.getSize();
deviceRectangle = new Rectangle(0,0,d.width,d.height);
}
AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);
if(isLoop) {
// this is a self-loop. scale it is larger than the vertex
// it decorates and translate it so that its nadir is
// at the center of the vertex.
Rectangle2D s2Bounds = s2.getBounds2D();
xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());
xform.translate(0, -edgeShape.getBounds2D().getWidth()/2);
} else {
// this is a normal edge. Rotate it to the angle between
// vertex endpoints, then scale it to the distance between
// the vertices
float dx = x2-x1;
float dy = y2-y1;
float thetaRadians = (float) Math.atan2(dy, dx);
xform.rotate(thetaRadians);
float dist = (float) Math.sqrt(dx*dx + dy*dy);
xform.scale(dist, 1.0);
}
edgeShape = xform.createTransformedShape(edgeShape);
MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW);
if(vt instanceof LensTransformer) {
vt = ((LensTransformer)vt).getDelegate();
}
edgeHit = vt.transform(edgeShape).intersects(deviceRectangle);
if(edgeHit == true) {
Paint oldPaint = g.getPaint();
// get Paints for filling and drawing
// (filling is done first so that drawing and label use same Paint)
Paint fill_paint = rc.getEdgeFillPaintTransformer().transform(e);
if (fill_paint != null)
{
g.setPaint(fill_paint);
g.fill(edgeShape, flatness);
}
Paint draw_paint = rc.getEdgeDrawPaintTransformer().transform(e);
if (draw_paint != null)
{
g.setPaint(draw_paint);
g.draw(edgeShape, flatness);
}
float scalex = (float)g.getTransform().getScaleX();
float scaley = (float)g.getTransform().getScaleY();
// see if arrows are too small to bother drawing
if(scalex < .3 || scaley < .3) return;
if (rc.getEdgeArrowPredicate().evaluate(Context.<Graph<V,E>,E>getInstance(graph, e))) {
Shape destVertexShape =
rc.getVertexShapeTransformer().transform(graph.getEndpoints(e).getSecond());
AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2);
destVertexShape = xf.createTransformedShape(destVertexShape);
arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(destVertexShape).intersects(deviceRectangle);
if(arrowHit) {
AffineTransform at =
edgeArrowRenderingSupport.getArrowTransform(rc, new GeneralPath(edgeShape), destVertexShape);
if(at == null) return;
Shape arrow = rc.getEdgeArrowTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
arrow = at.createTransformedShape(arrow);
g.setPaint(rc.getArrowFillPaintTransformer().transform(e));
g.fill(arrow);
g.setPaint(rc.getArrowDrawPaintTransformer().transform(e));
g.draw(arrow);
}
if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) {
Shape vertexShape =
rc.getVertexShapeTransformer().transform(graph.getEndpoints(e).getFirst());
xf = AffineTransform.getTranslateInstance(x1, y1);
vertexShape = xf.createTransformedShape(vertexShape);
arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(vertexShape).intersects(deviceRectangle);
if(arrowHit) {
AffineTransform at = edgeArrowRenderingSupport.getReverseArrowTransform(rc, new GeneralPath(edgeShape), vertexShape, !isLoop);
if(at == null) return;
Shape arrow = rc.getEdgeArrowTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
arrow = at.createTransformedShape(arrow);
g.setPaint(rc.getArrowFillPaintTransformer().transform(e));
g.fill(arrow);
g.setPaint(rc.getArrowDrawPaintTransformer().transform(e));
g.draw(arrow);
}
}
}
// use existing paint for text if no draw paint specified
if (draw_paint == null)
g.setPaint(oldPaint);
// String label = edgeStringer.getLabel(e);
// if (label != null) {
// labelEdge(g, graph, e, label, x1, x2, y1, y2);
// }
// restore old paint
g.setPaint(oldPaint);
}
}