2014-02-12 96 views
1

我想通過JGraphx顯示流程圖,並且我需要輸入/輸出塊的平行四邊形。但JGraphx似乎並不知道「形狀=平行四邊形」。在圖形和流程圖的圖書館中沒有平行四邊形似乎很奇怪(它甚至有「演員」形狀,它怎麼沒有平行四邊形?)。也許它只是以其他方式命名?或者在這種情況下確實沒有預定義的平行四邊形形狀,我該如何將頂點變爲平行四邊形?如何在JGraphx中製作一個平行四邊形頂點?

回答

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

現在「形狀=平行四邊形」工作得很好!

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」作爲樣式,現在它不僅用於顯示平行四邊形,還用於正確連接邊。

1

爲了完整:等邊平行四邊形是預定義的:SHAPE_RHOMBUS