我试图自定义jGraph的布局。我想创建曲线边缘,但我有一个问题。每次我在JGraph上创建一组顶点,并且我触发事件来更新此图形时,边缘与先前状态相比缺少点。这是一个例子:
http://i.stack.imgur.com/QrQIL.png
有人能帮助我吗?任何想法?
这是我的代码:
class CurveGraphView extends mxGraphView {
public CurveGraphView(mxGraph graph) {
super(graph);
}
/* Only override this if you want the label to automatically position itself on the control point */
@Override
public mxPoint getPoint(mxCellState state, mxGeometry geometry) {
double x = state.getCenterX();
double y = state.getCenterY();
if (state.getAbsolutePointCount() == 3) {
mxPoint mid = state.getAbsolutePoint(1);
x = mid.getX();
y = mid.getY();
}
return new mxPoint(x, y);
}
// /* Makes sure that the full path of the curve is included in the bounding box */
@Override
public mxRectangle updateBoundingBox(mxCellState state) {
List<mxPoint> points = state.getAbsolutePoints();
mxRectangle bounds = super.updateBoundingBox(state);
Object style = state.getStyle().get("edgeStyle");
if (CurvedEdgeStyle.KEY.equals(style) && points != null && points.size() == 3) {
Rectangle pathBounds = CurvedShape.createPath(state.getAbsolutePoints()).getBounds();
Rectangle union = bounds.getRectangle().union(pathBounds);
bounds = new mxRectangle(union);
state.setBoundingBox(bounds);
}
return bounds;
}
}
class CurvedEdgeStyle implements mxEdgeStyle.mxEdgeStyleFunction {
public static final String KEY = "curvedEdgeStyle";
@Override
public void apply(mxCellState state, mxCellState source, mxCellState target, List<mxPoint> points, List<mxPoint> result) {
mxPoint pt = (points != null && points.size() > 0) ? points.get(0) : null;
if (source != null && target != null) {
double x = 0;
double y = 0;
if (pt != null) {
result.add(pt);
} else {
x = (target.getCenterX() + source.getCenterX()) / 2;
y = (target.getCenterY() + source.getCenterY()) / 2;
mxPoint point = new mxPoint(x, y);
result.add(point);
}
}
}
}
class CurvedShape extends mxConnectorShape {
public static final String KEY = "curvedEdge";
private GeneralPath path;
@Override
public void paintShape(mxGraphics2DCanvas canvas, mxCellState state) {
List<mxPoint> abs = state.getAbsolutePoints();
int n = state.getAbsolutePointCount();
mxCell aux = (mxCell)state.getCell();
if (n < 3) {
super.paintShape(canvas, state);
} else if (configureGraphics(canvas, state, false)) {
Graphics2D g = canvas.getGraphics();
path = createPath(abs);
g.draw(path);
paintMarker(canvas, state, false);
paintMarker(canvas, state, true);
}
}
/* Code borrowed from here: http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit */
public static GeneralPath createPath(List<mxPoint> abs) {
mxPoint[] knots = abs.toArray(new mxPoint[abs.size()]);
int n = knots.length - 1;
mxPoint[] firstControlPoints = new mxPoint[n];
mxPoint[] secondControlPoints = new mxPoint[n]; // Calculate first Bezier control points // Right hand side vector
double[] rhs = new double[n]; // Set right hand side X values
for (int i = 1; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].getX() + 2 * knots[i + 1].getX();
}
rhs[0] = knots[0].getX() + 2 * knots[1].getX();
rhs[n - 1] = (8 * knots[n - 1].getX() + knots[n].getX()) / 2.0; // Get first control points X-values
double[] x = getFirstControlPoints(rhs); // Set right hand side Y values
for (int i = 1; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].getY() + 2 * knots[i + 1].getY();
}
rhs[0] = knots[0].getY() + 2 * knots[1].getY();
rhs[n - 1] = (8 * knots[n - 1].getY() + knots[n].getY()) / 2.0; // Get first control points Y-values
double[] y = getFirstControlPoints(rhs); // Fill output arrays.
for (int i = 0; i < n; ++i) { // First control point
firstControlPoints[i] = new mxPoint(x[i], y[i]); // Second control point
if (i < n - 1) {
secondControlPoints[i] = new mxPoint(2 * knots[i + 1].getX() - x[i + 1], 2 * knots[i + 1].getY() - y[i + 1]);
} else {
secondControlPoints[i] = new mxPoint((knots[n].getX() + x[n - 1]) / 2, (knots[n].getY() + y[n - 1]) / 2);
}
}
GeneralPath path = new GeneralPath();
path.moveTo(knots[0].getX(), knots[0].getY());
for (int i = 1; i < n + 1; i++) {
path.curveTo(firstControlPoints[i - 1].getX(), firstControlPoints[i - 1].getY(), secondControlPoints[i - 1].getX(), secondControlPoints[i - 1].getY(), knots[i].getX(), knots[i].getY());
}
return path;
}/// <summary>/// Solves a tridiagonal system for one of coordinates (x or y)/// of first Bezier control points./// </summary>/// <param name="rhs">Right hand side vector.</param>/// <returns>Solution vector.</returns>
private static double[] getFirstControlPoints(double[] rhs) {
int n = rhs.length;
double[] x = new double[n]; // Solution vector.
double[] tmp = new double[n]; // Temp workspace.
double b = 2.0;
x[0] = rhs[0] / b;
for (int i = 1; i < n; i++) // Decomposition and forward substitution.
{
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
for (int i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
}
return x;
}
@Override
protected mxLine getMarkerVector(List<mxPoint> points, boolean source, double markerSize) {
if (path == null || points.size() < 3) {
return super.getMarkerVector(points, source, markerSize);
}
double coords[] = new double[6];
double x0 = 0;
double y0 = 0;
double x1 = 0;
double y1 = 0;
PathIterator p = path.getPathIterator(null, 2.0);
if (source) {
p.currentSegment(coords);
x1 = coords[0];
y1 = coords[1];
p.next();
p.currentSegment(coords);
x0 = coords[0];
y0 = coords[1];
} else {
while (!p.isDone()) {
p.currentSegment(coords);
x0 = x1;
y0 = y1;
x1 = coords[0];
y1 = coords[1];
p.next();
}
}
return new mxLine(x0, y0, new mxPoint(x1, y1));
}
}
扩展mxGraph并覆盖构造函数添加:
mxGraphics2DCanvas.putShape(CurvedShape.KEY, new CurvedShape());
mxStyleRegistry.putValue(CurvedEdgeStyle.KEY, new CurvedEdgeStyle());
getStylesheet().getDefaultEdgeStyle().put(mxConstants.STYLE_SHAPE, CurvedShape.KEY);
getStylesheet().getDefaultEdgeStyle().put(mxConstants.STYLE_EDGE, CurvedEdgeStyle.KEY);
并覆盖createGraphView()返回CurveGraphView。
太赫兹,
亚历山大。
消息:我仍然无法解决问题!!!! 告诉我它必须用绝对点做点什么..