Многоцветный краской Трансформатор Draw Draw - PullRequest
0 голосов
/ 25 января 2019

Попытка нарисовать график метро, ​​используя JUNG. Можно ли нарисовать край прямой линии, которая использует 2 или более цветов параллельно, используя трансформатор?

Ответы [ 3 ]

0 голосов
/ 29 января 2019

хорошо, если вы хотите много цветов, попробуйте это:

    vv.getRenderer().setEdgeRenderer(
            new NotSimpleEdgeRenderer(new Color[]{
                    Color.red, Color.blue, Color.pink, Color.green, Color.magenta,
                    Color.cyan, Color.black, Color.orange, Color.yellow
            }));
    vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2)));




public class NotSimpleEdgeRenderer<V,E> extends BasicEdgeRenderer<V,E> {

    Color[] colors;
    Shape[] shapes;

    public NotSimpleEdgeRenderer(Color... colors) {
        int count = colors.length;
        this.colors = colors;
        shapes = new Shape[count];
        for (int i=0; i<count; i++) {
            shapes[i] = new Line2D.Double(0, -count/2+(2*i), 1, -count/2+(2*i));
        }
    }

    protected void drawSimpleEdge(RenderContext<V,E> rc, Layout<V,E> layout, E e) {

        GraphicsDecorator g = 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();

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

        Paint oldPaint = g.getPaint();
        for (int i=0; i<shapes.length; i++) {
            Shape edgeShape = shapes[i];
            edgeShape = xform.createTransformedShape(edgeShape);

            MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW);
            edgeHit = vt.transform(edgeShape).intersects(deviceRectangle);

            if(edgeHit == true) {
                Paint fill_paint = colors[i];
                if (fill_paint != null) {
                    g.setPaint(fill_paint);
                    g.fill(edgeShape);
                }
                Paint draw_paint = colors[i];
                if (draw_paint != null) {
                    g.setPaint(draw_paint);
                    g.draw(edgeShape);
                }
            }
            // restore old paint
            g.setPaint(oldPaint);
        }
    }
}

и это выглядит так: enter image description here

0 голосов
/ 30 января 2019

Я думаю, что вы можете сделать это с небольшими изменениями примеров кода, которые я разместил в предыдущих ответах.Я предполагаю, что вы знаете, какие цвета вы хотите для каждого края.Создайте карту, в которой есть сопоставления от каждого края до цветов, которые вы хотите для этого края.Затем измените код, с которым я ответил, чтобы он выглядел так:

public class NotSimpleEdgeRenderer<V,E> extends BasicEdgeRenderer<V,E> {

    Map<E,Color[]> colorMap;

    public NotSimpleEdgeRenderer(Map<E,Color[]> colorMap) {
        this.colorMap = colorMap;
    }

    protected void drawSimpleEdge(RenderContext<V,E> rc, Layout<V,E> layout, E e) {

        GraphicsDecorator g = 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();

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

        Paint oldPaint = g.getPaint();

        // get the colors for this edge from the map
        Color[] colors = colorMap.get(e);
        int count = colors.length;
        // make the Shapes for this edge here
        Shape[] shapes = new Shape[count];
        for (int i=0; i<count; i++) {
             // this code offsets the lines enough to see the colors
            shapes[i] = new Line2D.Double(0, -count/2+(2*i), 1, -count/2+(2*i));
        }
        // iterate over the edge shapes and draw them with the corresponding colors
        for (int i=0; i<shapes.length; i++) {
            Shape edgeShape = shapes[i];
            edgeShape = xform.createTransformedShape(edgeShape);

            MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW);
            edgeHit = vt.transform(edgeShape).intersects(deviceRectangle);

            if(edgeHit == true) {
                Paint fill_paint = colors[i];
                if (fill_paint != null) {
                    g.setPaint(fill_paint);
                    g.fill(edgeShape);
                }
                Paint draw_paint = colors[i];
                if (draw_paint != null) {
                    g.setPaint(draw_paint);
                    g.draw(edgeShape);
                }
            }
            // restore old paint
            g.setPaint(oldPaint);
        }
    }
}
0 голосов
/ 28 января 2019

Вы можете сделать что-то вроде этого ....

Скопируйте и измените некоторый код из класса EdgeShape (где он принимает форму Боути), модифицированного в прямоугольник, затем установите краску заливки края, нарисуйте краскуи обводка, чтобы выглядеть как вы хотите

public class RectangleEdge<V,E> extends AbstractEdgeShapeTransformer<V,E> {
    private static GeneralPath rectangle;

    public RectangleEdge(int width)  {
        rectangle = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
        rectangle.moveTo(0, width/2); // change points to make rectangle
        rectangle.lineTo(1, width/2);
        rectangle.lineTo(1, -width/2);
        rectangle.lineTo(0, -width/2);
        rectangle.closePath();
    }

    public Shape transform(Context<Graph<V,E>,E> context) {
        return rectangle;
    }
}



    vv.getRenderContext().setEdgeShapeTransformer(new RectangleEdge<>(4));
    vv.getRenderContext().setEdgeFillPaintTransformer(new ConstantTransformer(Color.red));
    vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2)));
    vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.blue));

Вот изображение: enter image description here

...