Based on Sage's excellent answer and after playing around with http://www.openprocessing.org/sketch/2123 for a while, here's what I ended up with.
Putting the control point collinear with the angle you want to create pulls the curve in that direction. The farther the control point is from the endpoint, the more pronounced the effect becomes. Since I only deal with 90 degree angles, this means I can just alter the x or y coordinates of the control points by a set distance (which I call delta like Sage did) to produce the desired effect. I didn't use anything fancy to find delta - I just tried several values until I found one I was happy with.
Here's a snippet of my final code.
public class BezierCurve {
private CubicCurve2D curve;
private static final int delta = 100;
private double x1, y1, x2, y2;
private double ctrlx1, ctrly1, ctrlx2, ctrly2;
public BezierCurve(Point p1, Side side1, Point p2, Side side2) {
this.x1 = p1.x;
this.y1 = p1.y;
this.x2 = p2.x;
this.y2 = p2.y;
Point ctrl1 = getControlPoint(p1, side1);
Point ctrl2 = getControlPoint(p2, side2);
ctrlx1 = ctrl1.x;
ctrly1 = ctrl1.y;
ctrlx2 = ctrl2.x;
ctrly2 = ctrl2.y;
curve = new CubicCurve2D.Double();
curve.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
}
private Point getControlPoint(Point p, Side s) {
int x = p.x;
int y = p.y;
switch (s) {
case Left:
x -= delta;
break;
case Right:
x += delta;
break;
case Bottom:
y += delta;
break;
case Top:
y -= delta;
break;
}
return new Point(x, y);
}
public void draw(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.draw(curve);
}
}
This handles each case of top, bottom, right, and left.
Here's a screenshot of the code in action.