2

我正在尝试通过 JGraphx 显示流程图,并且我需要一个平行四边形作为输入/输出块。但是 JGraphx 似乎不知道“shape=parallelogram”。在图形和流程图库中没有平行四边形似乎很奇怪(它甚至有“演员”形状,为什么它没有平行四边形?)。也许它只是以其他方式命名?或者在确实没有预定义的平行四边形形状的情况下,我该怎么做才能将顶点变成平行四边形?

4

2 回答 2

3

最后,我找到了制作平行四边形的方法,耶!这是我如何使它工作的。
首先,要制作自定义形状,我必须创建自己的扩展 mxBasicShape 的类并覆盖 createShape 方法。

public class Parallelogram extends mxBasicShape {
public Shape createShape(mxGraphics2DCanvas canvas, mxCellState state){
    mxCell cell = (mxCell)state.getCell();
    Polygon polygon = new Polygon();
    if(cell != null && cell.getGeometry() != null) {
        mxGeometry g = cell.getGeometry();
        int dx = (int) (cell.getGeometry().getHeight()/4.0);
        polygon.addPoint((int)(g.getX()+dx), (int)g.getY());
        polygon.addPoint((int)(g.getX()+g.getWidth()+dx), (int)g.getY());
        polygon.addPoint((int)(g.getX()+g.getWidth()-dx), (int)(g.getY()+g.getHeight()));
        polygon.addPoint((int)((int)g.getX()-dx), (int)(g.getY()+g.getHeight()));
    }
    return polygon;

}

}

第二步是将其添加到似乎存储在 mxGraphics2DCanvas 中的形状列表中。

mxGraphics2DCanvas.putShape("parallelogram", new Parallelogram());

现在“shape=parallelogram”工作得很好!

UPD
看起来仅仅创建一个形状是不够的,还要创建一个周长。这就是我的做法:

public class ParallelogramPerimeter implements mxPerimeterFunction {
    @Override
    public mxPoint apply(mxRectangle bounds, mxCellState vertex, mxPoint next,
            boolean orthogonal) {
        double cx = bounds.getCenterX();
        double cy = bounds.getCenterY();
        double nx = next.getX();
        double ny = next.getY();
        double pi = Math.PI;
        double pi2 = Math.PI/2.0;
        double h = bounds.getHeight();
        double w = bounds.getWidth();
        double alpha = Math.atan2(h/2.0, w/2.0+h/4.0);
        double beta = Math.atan2(h/2.0, w/2.0-h/4.0);
        double t = Math.atan2(ny-cy, nx-cx);

        mxPoint p = new mxPoint();

        //Left
        if (t > pi - alpha || t < (-pi)+beta){
            Line border = new Line(cx-w/2.0+h/4.0, cy-h/2.0, cx-w/2.0-h/4.0, cy+h/2.0);
            Line line = new Line(cx, cy, nx, ny);
            p = Line.intersection(border, line);
        }
        //Top
        else if (t > (-pi)+beta && t < (0-alpha)){
            p.setY(cy-h/2.0);
            p.setX(cx + h/2.0*Math.tan(pi2+t));
        }
        //Right
        else if (t > (0-alpha) && t < beta){
            Line border = new Line(cx+w/2.0+h/4.0, cy-h/2.0, cx+w/2.0-h/4.0, cy+h/2.0);
            Line line = new Line(cx, cy, nx, ny);
            p = Line.intersection(border, line);
        }
        //Bottom
        else {
            p.setY(cy+h/2.0);
            p.setX(cx + h/2.0*Math.tan(pi2-t));
        }

        if (orthogonal){
            //Top
            if (nx >= cx-w/2.0+h/4.0 && nx <= cx+w/2.0+h/4.0 && ny <= cy-h/2.0){
                p.setX(nx);
            }
            //Bottom
            else if (nx >= cx - w/2.0-h/4.0 && nx <= cx+w/2.0-h/4.0 && ny >= cy+h/2.0){
                p.setX(nx);
            }
            //Left or right
            else{
                Line left = new Line(cx-w/2.0+h/4.0, cy-h/2.0, cx-w/2.0-h/4.0, cy+h/2.0);
                Line right = new Line(cx+w/2.0+h/4.0, cy-h/2.0, cx+w/2.0-h/4.0, cy+h/2.0);
                p = left.projection(nx, ny);
                mxPoint p1 = right.projection(nx, ny);
                boolean r = false;
                if (distance(nx, ny, p.getX(), p.getY()) > distance(nx, ny, p1.getX(), p1.getY()))
                    {
                        p = p1;
                        r = true;
                    }
                //Upper corners
                if (p.getY() < cy-h/2.0){
                    p.setY(cy-h/2.0);
                    if(r){
                        p.setX(cx+w/2.0+h/4.0);
                    }
                    else
                    {
                        p.setX(cx-w/2.0+h/4.0);
                    }
                }
                //Lower corners
                else if (p.getY() > cy+h/2.0){
                    p.setY(cy+h/2.0);
                    if(r){
                        p.setX(cx+w/2.0-h/4.0);
                    }
                    else
                    {
                        p.setX(cx-w/2.0-h/4.0);
                    }
                }
            }
        }

        return p;

    }

    private double distance(double x1, double y1, double x2, double y2){
        return Math.sqrt(Math.pow(x2-x1, 2)+Math.pow(y2-y1, 2));
    }

}

class Line{
private double a;
private double b;
private double c;

Line(double x1, double y1, double x2, double y2){
    a = y1-y2;
    b = x2-x1;
    c = x1*y2-x2*y1;
}

private Line(double a, double b, double c){
    this.a = a;
    this.b = b;
    this.c = c;
}

static private double determinant(double i, double j, double k, double l){
    return i*l - k*j;
}

static mxPoint intersection(Line first, Line second){
    double x,y;
    double denominator = determinant(first.a, first.b, second.a, second.b);
    x = 0 - determinant(first.c, first.b, second.c, second.b)/denominator;
    y = 0 - determinant(first.a, first.c, second.a, second.c)/denominator;
    return new mxPoint(x,y);
}

mxPoint projection(double x, double y){
    double a,b,c;
    if (this.b!=0){
        a=1;
        b=-(this.a*a)/this.b;
    }
    else{
        b = 1;
        a=-(this.b*b)/this.a;
    }
    c = -(a*x+b*y);
    Line line = new Line(a,b,c);
    return intersection(this, line);
}
}

然后我不得不将它添加到正在使用的周长中,其列表似乎与形状不在同一个位置,而是在 mxStyleRegistry 中:

mxStyleRegistry.putValue("parallelogramPerimeter", new ParallelogramPerimeter());

最后,我使用“shape=parallelogram;perimeter=parallelogramPerimeter”作为样式,现在不仅可以显示平行四边形,还可以正确连接边缘。

于 2014-02-14T03:31:33.870 回答
1

为了完整起见:预定义等边平行四边形:SHAPE_RHOMBUS.

于 2016-03-16T15:19:49.743 回答