JGraphX - Custom Layoult - Curved Edges

2019-05-30 19:56发布

I'm trying to customize a layout of jGraph. i Want to create curve edges, but I have a problem. Every time i create a group of vertex on JGraph, and I firing an event to update this graph, the edge is missing points compared to the previous state. Here is a exemple:

http://i.stack.imgur.com/QrQIL.png

Can someone help me? any idea?

Here my codes:

    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));
    }

}

extends mxGraph and Override the constructor adding:

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);

and Override createGraphView() returning CurveGraphView.

Thz,

Alexandre.

news: I still can not solve the problem!!!! Have told me it has to do something with absolute points..

0条回答
登录 后发表回答