edgerenderer.java
来自「用applet实现很多应用小程序」· Java 代码 · 共 523 行 · 第 1/2 页
JAVA
523 行
package prefuse.render;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import prefuse.Constants;
import prefuse.util.ColorLib;
import prefuse.util.GraphicsLib;
import prefuse.util.StrokeLib;
import prefuse.visual.EdgeItem;
import prefuse.visual.VisualItem;
/**
* <p>Renderer that draws edges as lines connecting nodes. Both
* straight and curved lines are supported. Curved lines are drawn using
* cubic Bezier curves. Subclasses can override the
* {@link #getCurveControlPoints(EdgeItem, Point2D[], double, double, double, double)}
* method to provide custom control point assignment for such curves.</p>
*
* <p>This class also supports arrows for directed edges. See the
* {@link #setArrowType(int)} method for more.</p>
*
* @version 1.0
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class EdgeRenderer extends AbstractShapeRenderer {
public static final String EDGE_TYPE = "edgeType";
protected static final double HALF_PI = Math.PI / 2;
protected Line2D m_line = new Line2D.Float();
protected CubicCurve2D m_cubic = new CubicCurve2D.Float();
protected int m_edgeType = Constants.EDGE_TYPE_LINE;
protected int m_xAlign1 = Constants.CENTER;
protected int m_yAlign1 = Constants.CENTER;
protected int m_xAlign2 = Constants.CENTER;
protected int m_yAlign2 = Constants.CENTER;
protected double m_width = 1;
protected float m_curWidth = 1;
protected Point2D m_tmpPoints[] = new Point2D[2];
protected Point2D m_ctrlPoints[] = new Point2D[2];
protected Point2D m_isctPoints[] = new Point2D[2];
// arrow head handling
protected int m_edgeArrow = Constants.EDGE_ARROW_FORWARD;
protected int m_arrowWidth = 8;
protected int m_arrowHeight = 12;
protected Polygon m_arrowHead = updateArrowHead(
m_arrowWidth, m_arrowHeight);
protected AffineTransform m_arrowTrans = new AffineTransform();
protected Shape m_curArrow;
/**
* Create a new EdgeRenderer.
*/
public EdgeRenderer() {
m_tmpPoints[0] = new Point2D.Float();
m_tmpPoints[1] = new Point2D.Float();
m_ctrlPoints[0] = new Point2D.Float();
m_ctrlPoints[1] = new Point2D.Float();
m_isctPoints[0] = new Point2D.Float();
m_isctPoints[1] = new Point2D.Float();
}
/**
* Create a new EdgeRenderer with the given edge type.
* @param edgeType the edge type, one of
* {@link prefuse.Constants#EDGE_TYPE_LINE} or
* {@link prefuse.Constants#EDGE_TYPE_CURVE}.
*/
public EdgeRenderer(int edgeType) {
this(edgeType, Constants.EDGE_ARROW_FORWARD);
}
/**
* Create a new EdgeRenderer with the given edge and arrow types.
* @param edgeType the edge type, one of
* {@link prefuse.Constants#EDGE_TYPE_LINE} or
* {@link prefuse.Constants#EDGE_TYPE_CURVE}.
* @param arrowType the arrow type, one of
* {@link prefuse.Constants#EDGE_ARROW_FORWARD},
* {@link prefuse.Constants#EDGE_ARROW_REVERSE}, or
* {@link prefuse.Constants#EDGE_ARROW_NONE}.
* @see #setArrowType(int)
*/
public EdgeRenderer(int edgeType, int arrowType) {
this();
setEdgeType(edgeType);
setArrowType(arrowType);
}
/**
* @see prefuse.render.AbstractShapeRenderer#getRenderType(prefuse.visual.VisualItem)
*/
public int getRenderType(VisualItem item) {
return RENDER_TYPE_DRAW;
}
/**
* @see prefuse.render.AbstractShapeRenderer#getRawShape(prefuse.visual.VisualItem)
*/
protected Shape getRawShape(VisualItem item) {
EdgeItem edge = (EdgeItem)item;
VisualItem item1 = edge.getSourceItem();
VisualItem item2 = edge.getTargetItem();
int type = m_edgeType;
getAlignedPoint(m_tmpPoints[0], item1.getBounds(),
m_xAlign1, m_yAlign1);
getAlignedPoint(m_tmpPoints[1], item2.getBounds(),
m_xAlign2, m_yAlign2);
m_curWidth = (float)(m_width * getLineWidth(item));
// create the arrow head, if needed
EdgeItem e = (EdgeItem)item;
if ( e.isDirected() && m_edgeArrow != Constants.EDGE_ARROW_NONE ) {
// get starting and ending edge endpoints
boolean forward = (m_edgeArrow == Constants.EDGE_ARROW_FORWARD);
Point2D start = null, end = null;
start = m_tmpPoints[forward?0:1];
end = m_tmpPoints[forward?1:0];
// compute the intersection with the target bounding box
VisualItem dest = forward ? e.getTargetItem() : e.getSourceItem();
int i = GraphicsLib.intersectLineRectangle(start, end,
dest.getBounds(), m_isctPoints);
if ( i > 0 ) end = m_isctPoints[0];
// create the arrow head shape
AffineTransform at = getArrowTrans(start, end, m_curWidth);
m_curArrow = at.createTransformedShape(m_arrowHead);
// update the endpoints for the edge shape
// need to bias this by arrow head size
Point2D lineEnd = m_tmpPoints[forward?1:0];
lineEnd.setLocation(0, -m_arrowHeight);
at.transform(lineEnd, lineEnd);
} else {
m_curArrow = null;
}
// create the edge shape
Shape shape = null;
double n1x = m_tmpPoints[0].getX();
double n1y = m_tmpPoints[0].getY();
double n2x = m_tmpPoints[1].getX();
double n2y = m_tmpPoints[1].getY();
switch ( type ) {
case Constants.EDGE_TYPE_LINE:
m_line.setLine(n1x, n1y, n2x, n2y);
shape = m_line;
break;
case Constants.EDGE_TYPE_CURVE:
getCurveControlPoints(edge, m_ctrlPoints,n1x,n1y,n2x,n2y);
m_cubic.setCurve(n1x, n1y,
m_ctrlPoints[0].getX(), m_ctrlPoints[0].getY(),
m_ctrlPoints[1].getX(), m_ctrlPoints[1].getY(),
n2x, n2y);
shape = m_cubic;
break;
default:
throw new IllegalStateException("Unknown edge type");
}
// return the edge shape
return shape;
}
/**
* @see prefuse.render.Renderer#render(java.awt.Graphics2D, prefuse.visual.VisualItem)
*/
public void render(Graphics2D g, VisualItem item) {
// render the edge line
super.render(g, item);
// render the edge arrow head, if appropriate
if ( m_curArrow != null ) {
g.setPaint(ColorLib.getColor(item.getFillColor()));
g.fill(m_curArrow);
}
}
/**
* Returns an affine transformation that maps the arrowhead shape
* to the position and orientation specified by the provided
* line segment end points.
*/
protected AffineTransform getArrowTrans(Point2D p1, Point2D p2,
double width)
{
m_arrowTrans.setToTranslation(p2.getX(), p2.getY());
m_arrowTrans.rotate(-HALF_PI +
Math.atan2(p2.getY()-p1.getY(), p2.getX()-p1.getX()));
if ( width > 1 ) {
double scalar = width/4;
m_arrowTrans.scale(scalar, scalar);
}
return m_arrowTrans;
}
/**
* Update the dimensions of the arrow head, creating a new
* arrow head if necessary. The return value is also set
* as the member variable <code>m_arrowHead</code>
* @param w the width of the untransformed arrow head base, in pixels
* @param h the height of the untransformed arrow head, in pixels
* @return the untransformed arrow head shape
*/
protected Polygon updateArrowHead(int w, int h) {
if ( m_arrowHead == null ) {
m_arrowHead = new Polygon();
} else {
m_arrowHead.reset();
}
m_arrowHead.addPoint(0, 0);
m_arrowHead.addPoint(-w/2, -h);
m_arrowHead.addPoint( w/2, -h);
m_arrowHead.addPoint(0, 0);
return m_arrowHead;
}
/**
* @see prefuse.render.AbstractShapeRenderer#getTransform(prefuse.visual.VisualItem)
*/
protected AffineTransform getTransform(VisualItem item) {
return null;
}
/**
* @see prefuse.render.Renderer#locatePoint(java.awt.geom.Point2D, prefuse.visual.VisualItem)
*/
public boolean locatePoint(Point2D p, VisualItem item) {
Shape s = getShape(item);
if ( s == null ) {
return false;
} else {
double width = Math.max(2, getLineWidth(item));
double halfWidth = width/2.0;
return s.intersects(p.getX()-halfWidth,
p.getY()-halfWidth,
width,width);
}
}
/**
* @see prefuse.render.Renderer#setBounds(prefuse.visual.VisualItem)
*/
public void setBounds(VisualItem item) {
if ( !m_manageBounds ) return;
Shape shape = getShape(item);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?