我想在两个形状(为了这个问题的目的的矩形)之间生成贝塞尔曲线,使得曲线在90度角处满足形状。这是MS Paint生成的示例:
就我的目的而言,可以假设角度只需垂直于轴,而不是任意的。换句话说,端点处曲线的角度只需要为0度,90度,180度或270度。
我对贝塞尔曲线的理解告诉我,我需要2个端点和2个控制点。端点很容易计算,但我对如何操作控制点只有基本的了解。
有没有方便的公式来实现这一目标?我很难找到相关的教程。
我正在使用Java,目前正在使用java.awt.geom.Path2D.Double.curveTo()绘制曲线。如果有预先构建的Java类或方法来实现这一点,那将是理想的,但我愿意在需要时自己实现算法或方程。
答案 0 :(得分:2)
根据Sage的优秀答案,在与http://www.openprocessing.org/sketch/2123玩了一段时间后,这就是我最终的结果。
将控制点与您要创建的角度共线,将曲线拉向该方向。控制点离端点越远,效果就越明显。因为我只处理90度角,这意味着我可以改变控制点的x或y坐标一个设定的距离(我称之为像Sage那样的delta)以产生所需的效果。我没有使用任何想要发现delta的东西 - 我只是尝试了几个值,直到找到一个我很满意的。
这是我最终代码的片段。
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);
}
}
它处理顶部,底部,右侧和左侧的每种情况。
以下是代码的截图。
答案 1 :(得分:1)
智能使用Class CubicCurve2D
应该能够达到你想要的效果:CubicCurve2D类实现了Shape
接口。此类表示(x, y)
坐标空间中的三次参数曲线段。 CubicCurve2D.Float
和CubicCurve2D.Double
子类以float
和double
精度指定三次曲线。
此类的setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
允许设置两个控制点。如果我们在曲线开始(ctrlx1, ctrly1)
之前和曲线结束(ctrlx2, ctrly2)
之后设置控制点。要保持曲线的角度为90
度的倍数,
我们可以类似地计算控制点(对90 deegree
计算):
ctrlx1 = x1; // curve start x
ctrly1 = y2 - delta; // curve start y
ctrlx2 = x1 + delta; // curve end x
ctrly2 = y2; // curve end y
在以下示例中,我假设delta = 10
;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
CubicCurve2D c = new CubicCurve2D.Double();
int x1 = 150, y1 = 150; //p1
int x2 = 350, y2 = 300;//p3
int ctrlx1, ctrly1, ctrlx2, ctrly2;
int delta = 10;
ctrlx1 = x1; // curve start x
ctrly1 = y2 - delta; // curve start y
ctrlx2 = x1 + delta; // curve end x
ctrly2 = y2;
g2d.drawRect(x1-50, y1-100, 100, 100);
c.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
g2d.drawRect(x2, y2-50, 100, 100);
g2d.draw(c);
}