Hit*_*tel 16 android bezier cubic android-canvas
我在我的Android应用程序中实现了三次贝塞尔曲线逻辑.
我在自定义视图的onDraw上在画布上实现了三次贝塞尔曲线代码.
// Path to draw cubic bezier curve
Path cubePath = new Path();
// Move to startPoint(200,200) (P0)
cubePath.moveTo(200,200);
// Cubic to with ControlPoint1(200,100) (C1), ControlPoint2(300,100) (C2) , EndPoint(300,200) (P1)
cubePath.cubicTo(200,100,300,100,300,200);
// Draw on Canvas
canvas.drawPath(cubePath, paint);
Run Code Online (Sandbox Code Playgroud)
我在下面的图像中可视化上面的代码.

[更新]
Logic for selecting first control points, I've taken ,
baseX = 200 , baseY = 200 and curve_size = X of Endpoint - X of Start Point
Start Point : x = baseX and y = baseY
Control Point 1 : x = baseX and y = baseY - curve_size
Control Point 2 : x = baseX + curve_size and y = baseY - curve_size
End Point : x = baseX + curve_size and y = baseY
Run Code Online (Sandbox Code Playgroud)
我想允许用户更改上面曲线的EndPoint,并根据新的End点,我使画布无效.
但问题在于,Curve由两个控制点维护,需要在EndPoint发生变化时重新计算.
就像,我只想在EndPoint从(300,200)变为(250,250)时找到新的控制点
如下图所示:

请帮我根据新的终点计算两个新的控制点,曲线形状将与前一个终点保持一致.
我在搜索期间参考以下参考链接:
http://pomax.github.io/bezierinfo/
http://jsfiddle.net/hitesh24by365/jHbVE/3/
http://en.wikipedia.org/wiki/B%C3%A9zier_curve
任何参考链接也在回答这个问题时表示赞赏.
nid*_*ido 12
更改端点意味着两件事,一个是P1的旋转和一个缩放因子.
缩放因子(让我们称之为s)是len(p1-p0)/ len(p2-p0)
对于旋转因子(让我们称之为r),我推迟到计算android中三个点之间的角度,这也给出了一个特定于平台的实现,但你可以通过缩放/旋转p1来检查与p0相关的正确性,你应该得到结果是p2.
接下来,对p0到c1和c2应用缩放和旋转.为方便起见,我将调用新的c1'd1'和新的d2.
d1 = rot(c1 - p0, factor) * s + p0
d2 = rot(c2 - p0, factor) * s + p0
Run Code Online (Sandbox Code Playgroud)
为rot()定义一些伪代码(旋转http://en.wikipedia.org/wiki/Rotation_%28mathematics%29)
rot(point p, double angle){
point q;
q.x = p.x * cos(angle) - p.y * sin(angle);
q.y = p.x * sin(angle) + p.y * cos(angle);
}
Run Code Online (Sandbox Code Playgroud)
您的贝塞尔曲线现在按比例缩放并相对于p0旋转,p1变为p2,
首先,我会请您查看以下文章:
您要实现的是分段复合Bézier曲线.从n个控制点的摘要页面(包括开始/结束),您将获得(n - 1)/ 3个分段贝塞尔曲线.
控制点按字面形成曲线.如果没有给出具有新点的适当控制点,则无法创建平滑连接的贝塞尔曲线.生成它们是行不通的,因为它太复杂而且没有普遍接受的方式.
如果你没有/想要提供额外的控制点,你应该使用Catmull-Rom样条曲线,它通过所有控制点并且将是C1连续的(导数在曲线上的任何点都是连续的).
链接Catmull Rom Spline的java/android:
底线是,如果你没有控制点,不要使用立方贝塞尔曲线.生成它们是一个问题,而不是解决方案.
看起来你在旋转和缩放一个正方形,你知道底部的两个点,需要计算另外两个.两个已知点形成两个三角形,另外两个,所以我们只需要在三角形中找到第三个点.设定终点是x1,y1:
PointF c1 = calculateTriangle(x0, y0, x1, y1, true); //find left third point
PointF c2 = calculateTriangle(x0, y0, x1, y1, false); //find right third point
cubePath.reset();
cubePath.moveTo(x0, y0);
cubePath.cubicTo(c1.x, c1.y, c2.x, c2.y, x1, y1);
private PointF calculateTriangle(float x1, float y1, float x2, float y2, boolean left) {
PointF result = new PointF(0,0);
float dy = y2 - y1;
float dx = x2 - x1;
float dangle = (float) (Math.atan2(dy, dx) - Math.PI /2f);
float sideDist = (float) Math.sqrt(dx * dx + dy * dy); //square
if (left){
result.x = (int) (Math.cos(dangle) * sideDist + x1);
result.y = (int) (Math.sin(dangle) * sideDist + y1);
}else{
result.x = (int) (Math.cos(dangle) * sideDist + x2);
result.y = (int) (Math.sin(dangle) * sideDist + y2);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
...
还有其他方法可以做到这一点,在路径或事件的第一个和最后一个点之间有多少点并不重要.
//Find scale
Float oldDist = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
Float newDist = (float) Math.sqrt((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0));
Float scale = newDist/oldDist;
//find angle
Float oldAngle = (float) (Math.atan2(y1 - y0, x1 - x0) - Math.PI /2f);
Float newAngle = (float) (Math.atan2(y2 - y0, x2 - x0) - Math.PI /2f);
Float angle = newAngle - oldAngle;
//set matrix
Matrix matrix = new Matrix();
matrix.postScale(scale, scale, x0, y0);
matrix.postRotate(angle, x0, y0);
//transform the path
cubePath.transform(matrix);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3354 次 |
| 最近记录: |