JGraphX - 自定义Layoult - 弯曲边缘

时间:2014-03-30 16:21:26

标签: layout curve edge jgraphx jgraph

我试图自定义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。

太赫兹,

亚历山大。

消息:我仍然无法解决问题!!!! 告诉我它必须用绝对点做点什么..

0 个答案:

没有答案