/**
*
*/
package org.seqcode.viz.graphs;
import java.util.*;
import java.awt.*;
import java.awt.geom.*;
/**
* @author Shaun Mahony
*/
public class SubEdgeView extends EdgeView {
private int totalWidth;
private int numSubEdges;
private int subEdgeWidths[];
private Color subEdgeColors[];
public SubEdgeView(GraphView g, NodeView s, NodeView f) {
super(g,s,f);
numSubEdges=0;
subEdgeWidths = new int [50];
subEdgeColors = new Color [50];
}
public SubEdgeView(ObjectView defs, GraphView g, NodeView s, NodeView f) {
super(defs,g,s,f);
numSubEdges=0;
subEdgeWidths = new int [50];
subEdgeColors = new Color [50];
}
public int getTotalWidth(){return totalWidth;}
public int getNumSubEdges(){return numSubEdges;}
public int getSubWidth(int x){if(x>=0 && x<numSubEdges){return subEdgeWidths[x];}else{return -1;}}
public Color getSubColor(int x){if(x>=0 && x<numSubEdges){return subEdgeColors[x];}else{return Color.black;}}
public void setTotalWidth(int w){totalWidth=w;}
public void addSubEdge(int w, Color c){
subEdgeWidths[numSubEdges]=w;
subEdgeColors[numSubEdges]=c;
numSubEdges++;
}
public void reset(){
numSubEdges=0;
}
public void paintView(Graphics2D g2) {
if(containsOption("self") && (Boolean)getOption("self")==true) {
double angle = (Double)getOption("selfAngle");
paintSelfSubEdges(g2, angle);
}else if(containsOption("curved")&& (Boolean)getOption("curved")==true) {
paintCurvedSubEdges(g2);
} else {
paintSubEdges(g2);
}
}
public void paintSubEdges(Graphics2D g2) {
NodeView first = getStart(), last = getFinish();
int sr = first.getWidth()/2;
int er = last.getWidth()/2;
int sx = first.getX(), sy = first.getY();
int ex = last.getX(), ey = last.getY();
double omega = Math.atan2((sy-ey),(sx-ex));
Stroke oldStroke = g2.getStroke();
int totalWidth = getTotalWidth();
int cumul=0;
for(int i=0; i < getNumSubEdges(); i++){
int ewidth = getSubWidth(i);
g2.setStroke(new BasicStroke((float)ewidth));
int offset = (totalWidth/2)-(cumul)-(ewidth/2)+1;
sx = first.getX() -(new Double((ewidth/2)*Math.cos(omega)).intValue());
ex = last.getX() +(new Double((ewidth/2)*Math.cos(omega)).intValue());
sy = first.getY() -(new Double((ewidth/2)*Math.sin(omega)).intValue());
ey = last.getY() +(new Double((ewidth/2)*Math.sin(omega)).intValue());
sx = sx + (new Double(offset*Math.sin(omega)).intValue());
ex = ex + (new Double(offset*Math.sin(omega)).intValue());
sy = sy - (new Double(offset*Math.cos(omega)).intValue());
ey = ey - (new Double(offset*Math.cos(omega)).intValue());
g2.setColor(getSubColor(i));
g2.drawLine(sx, sy, ex, ey);
cumul+=ewidth;
}
//Sub edges cannot be directed
g2.setStroke(oldStroke);
}
public void paintCurvedSubEdges(Graphics2D g2) {
NodeView first = getStart(), last = getFinish();
int sx = first.getX(), sy = first.getY();
int ex = last.getX(), ey = last.getY();
double omega = Math.atan2((sy-ey),(sx-ex));
Stroke oldStroke = g2.getStroke();
AffineTransform currTrans = g2.getTransform();
int totalWidth = getTotalWidth();
int cumul=0;
for(int i=0; i < getNumSubEdges(); i++){
sx = first.getX(); sy = first.getY();
ex = last.getX(); ey = last.getY();
int ewidth = getSubWidth(i);
g2.setStroke(new BasicStroke((float)ewidth));
int offset = (totalWidth/2)-(cumul)-(ewidth/2);
double vx = 0;
double vy = 250; //Controls how "bent" the curve is
Point oldCent = new Point(sx+(ex-sx)/2, sy+(ey-sy)/2);
g2.translate(sx+(ex-sx)/2, sy+(ey-sy)/2);
Point nP = GraphPaintable.rotate(
new Point(new Double(vx).intValue(),new Double(vy).intValue()), omega);
double sPhi = Math.atan2(new Double(nP.getY()).intValue()+(ey-sy)/2, new Double(nP.getX()).intValue()+(ex-sx)/2)-Math.toRadians(90);
double ePhi = Math.atan2(new Double(nP.getY()).intValue()-(ey-sy)/2, new Double(nP.getX()).intValue()-(ex-sx)/2)+Math.toRadians(90);
g2.setTransform(currTrans);
sx = sx +(new Double(offset*Math.cos(sPhi)).intValue());
ex = ex +(new Double(offset*Math.cos(ePhi)).intValue());
sy = sy +(new Double(offset*Math.sin(sPhi)).intValue());
ey = ey +(new Double(offset*Math.sin(ePhi)).intValue());
Point newCent = new Point(sx+(ex-sx)/2, sy+(ey-sy)/2);
double old2newDist = oldCent.distance(newCent);
g2.translate(sx+(ex-sx)/2, sy+(ey-sy)/2);
double vyb = ((125-old2newDist+totalWidth/2-(ewidth/2)-(cumul))*2)+1;
Point nPb = GraphPaintable.rotate(
new Point(new Double(vx).intValue(),new Double(vyb).intValue()), omega);
QuadCurve2D.Double curve =
new QuadCurve2D.Double(-(ex-sx)/2, -(ey-sy)/2, new Double(nPb.getX()).intValue(), new Double(nPb.getY()).intValue(), (ex-sx)/2, (ey-sy)/2);
g2.setColor(getSubColor(i));
cumul+=ewidth;
g2.draw(curve);
g2.setTransform(currTrans);
}
g2.setTransform(currTrans);
g2.setStroke(oldStroke);
}
public void paintSelfSubEdges(Graphics2D g2, double angle) {
double offset = 200;
double offsetAngle = Math.toRadians(50);
double omega = angle;
NodeView first = getStart(), last = getFinish();
int sx = first.getX(), sy = first.getY();
int ex = first.getX(), ey = first.getY();
Stroke oldStroke = g2.getStroke();
if(containsOption("edgeWidth")) {
int ewidth = (Integer)getOption("edgeWidth");
g2.setStroke(new BasicStroke((float)ewidth));
}
int totalWidth = getTotalWidth();
int cumul=0;
for(int i=0; i < getNumSubEdges(); i++){
sx = first.getX(); sy = first.getY();
ex = last.getX(); ey = last.getY();
int ewidth = getSubWidth(i);
g2.setStroke(new BasicStroke((float)ewidth));
int startOffset = (totalWidth/2)-(cumul)-(ewidth/2);
AffineTransform currTrans = g2.getTransform();
g2.translate(sx, sy);
Point basePoint = GraphPaintable.rotate(new Point(-startOffset, -startOffset), omega+Math.toRadians(45));
Point cpmain = GraphPaintable.rotate(new Point(0,new Double(offset).intValue()), omega);
Point cpm1 = GraphPaintable.rotate(new Point(0,new Double(offset).intValue()), omega-offsetAngle);
Point cpm2 = GraphPaintable.rotate(new Point(0,new Double(offset).intValue()), omega+offsetAngle);
int cpmidx = (int)Math.round((cpm1.getX()+cpm2.getX())/2);
int cpmidy = (int)Math.round((cpm1.getY()+cpm2.getY())/2);
int newapexx = (cpmidx*3/4) - new Double((((totalWidth-ewidth)/2)-cumul)*Math.sin(omega)).intValue();
int newapexy = (cpmidy*3/4) + new Double((((totalWidth-ewidth)/2)-cumul)*Math.cos(omega)).intValue();
double apexRatio = cpmain.distance(0,0)/(new Point(cpmidx,cpmidy).distance(0,0));
int newcpmainX =new Double((newapexx*4/3)*apexRatio).intValue();
int newcpmainY =new Double((newapexy*4/3)*apexRatio).intValue();
int newDist = new Double(new Point(newcpmainX, newcpmainY).distance(basePoint.getX(), basePoint.getY())).intValue();
Point cp1 = GraphPaintable.rotate(new Point(0, newDist), omega-offsetAngle);
Point cp2 = GraphPaintable.rotate(new Point(0, newDist), omega+offsetAngle);
CubicCurve2D.Double curve =
new CubicCurve2D.Double(new Double(basePoint.getX()).intValue(), new Double(basePoint.getY()).intValue(), new Double(cp1.getX()).intValue(), new Double(cp1.getY()).intValue(), new Double(cp2.getX()).intValue(), new Double(cp2.getY()).intValue(), new Double(basePoint.getX()).intValue(), new Double(basePoint.getY()).intValue());
g2.setColor(getSubColor(i));
cumul+=ewidth;
g2.draw(curve);
g2.setTransform(currTrans);
}
g2.setStroke(oldStroke);
}
}