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 maxRadius = 0.5 * Math.min(Math.sqrt(dx1*dx1 + dy1*dy1), Math.sqrt(dx2*dx2 + dy2*dy2));
+ double radius = Math.min(rounding, maxRadius);
+ newPath.lineTo(curX + radius*Math.signum(oldX-curX), curY + radius*Math.signum(oldY-curY));
+ newPath.curveTo(curX, curY,
+ curX, curY,
+ curX + radius*Math.signum(newX-curX), curY + radius*Math.signum(newY-curY));
+
+ //newPath.lineTo(curX + round*Math.signum(oldX-curX), curY + round*Math.signum(oldY-curY));
+ //newPath.lineTo(curX + round*Math.signum(newX-curX), curY + round*Math.signum(newY-curY));
+ //newPath.lineTo(curX, curY);
+ }
+ 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
return true;
}
+ public double getRounding() {
+ return rounding;
+ }
+
}