import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.RenderingHints;
import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
import java.io.Serializable;
/**
final double branchPointRadius;
final Stroke lineStroke;
final Stroke routeLineStroke;
- final double degenerateLineLength;
+ final double degenerateLineLength;
+ final double rounding;
transient Line2D line = new Line2D.Double();
transient Ellipse2D ellipse = new Ellipse2D.Double();
- public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {
+ public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength,
+ double rounding) {
this.lineColor = lineColor;
this.branchPointColor = branchPointColor;
this.branchPointRadius = branchPointRadius;
this.lineStroke = lineStroke;
this.routeLineStroke = routeLineStroke;
this.degenerateLineLength = degenerateLineLength;
+ this.rounding = rounding;
+ }
+
+ public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {
+ this(lineColor, branchPointColor, branchPointRadius, lineStroke, routeLineStroke, degenerateLineLength, 0.0);
}
public Color getLineColor() {
g.setColor(lineColor);
if (lineStroke != null)
g.setStroke(lineStroke);
- g.draw(path);
+ if(rounding > 0.0) {
+ Object oldRenderingHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.draw(round(path));
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldRenderingHint);
+ }
+ else
+ g.draw(path);
+ }
+
+ private Path2D round(Path2D path) {
+ Path2D newPath = new Path2D.Double();
+ PathIterator it = path.getPathIterator(new AffineTransform());
+ double[] coords = new double[6];
+ double newX=0.0, newY=0.0;
+ double curX=0.0, curY=0.0;
+ double oldX=0.0, oldY=0.0;
+ int state = 0;
+ while(!it.isDone()) {
+ int type = it.currentSegment(coords);
+ if(type == PathIterator.SEG_LINETO) {
+ newX = coords[0];
+ newY = coords[1];
+ if(state == 1) {
+ double dx1 = curX-oldX;
+ double dy1 = curY-oldY;
+ double dx2 = curX-newX;
+ double dy2 = curY-newY;
+ double r1 = Math.sqrt(dx1*dx1 + dy1*dy1);
+ double r2 = Math.sqrt(dx2*dx2 + dy2*dy2);
+ double maxRadius = 0.5 * Math.min(r1, r2);
+ double radius = Math.min(rounding, maxRadius);
+ double dx1Normalized = r1 > 0 ? dx1 / r1 : 0;
+ double dy1Normalized = r1 > 0 ? dy1 / r1 : 0;
+ double dx2Normalized = r2 > 0 ? dx2 / r2 : 0;
+ double dy2Normalized = r2 > 0 ? dy2 / r2 : 0;
+ newPath.lineTo(curX - radius*dx1Normalized, curY - radius*dy1Normalized);
+ newPath.curveTo(curX, curY,
+ curX, curY,
+ curX - radius*dx2Normalized, curY - radius*dy2Normalized);
+ }
+ else
+ ++state;
+ oldX = curX;
+ oldY = curY;
+ curX = newX;
+ curY = newY;
+ }
+ else {
+ if(state > 0) {
+ newPath.lineTo(curX, curY);
+ state = 0;
+ }
+ switch(type) {
+ case PathIterator.SEG_MOVETO:
+ curX = coords[0];
+ curY = coords[1];
+ newPath.moveTo(curX, curY);
+ break;
+ case PathIterator.SEG_QUADTO:
+ curX = coords[2];
+ curY = coords[3];
+ newPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ curX = coords[4];
+ curY = coords[5];
+ newPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ newPath.closePath();
+ break;
+ }
+ }
+ it.next();
+ }
+ if(state > 0)
+ newPath.lineTo(curX, curY);
+ return newPath;
}
@Override
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode());
result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode());
+ temp = Double.doubleToLongBits(rounding);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode());
return result;
}
return false;
} else if (!lineStroke.equals(other.lineStroke))
return false;
+ if (Double.doubleToLongBits(rounding) != Double.doubleToLongBits(other.rounding))
+ return false;
if (routeLineStroke == null) {
if (other.routeLineStroke != null)
return false;
return true;
}
+ public double getRounding() {
+ return rounding;
+ }
+
}