简体   繁体   English

计算贝塞尔曲线的中点

[英]Calculate middle point of Bezier Curve

I have a function to draw Bezier Curve through three points. 我具有通过三个点绘制Bezier Curve的功能。 I have already 2 points (start and end) - A and B. How do I calculate middle point between those two points as middle point would be always a little higher or lower than linear function of those two points. 我已经有2个点(起点和终点)-A和B。如何计算这两个点之间的中间点,因为中间点总是比这两个点的线性函数高一点或低一点。

Example : 范例

在此处输入图片说明

Any formulas, ideas would be great! 任何公式,想法都很棒!

I think this is what you're looking for: 我认为这是您要寻找的:

http://blog.sklambert.com/finding-the-control-points-of-a-bezier-curve/ http://blog.sklambert.com/finding-the-control-points-of-a-bezier-curve/

It goes into detail on calculating the various points on a Bezier curve. 它详细介绍了计算贝塞尔曲线上的各个点。

You may also be interested in this more specific example for your application: 您可能也对您的应用程序的以下更具体示例感兴趣:

http://www.codeproject.com/Articles/223159/Midpoint-Algorithm-Divide-and-Conquer-Method-for-D http://www.codeproject.com/Articles/223159/Midpoint-Algorithm-Divide-and-Conquer-Method-for-D

If you really want to get into it, then I suggest this Primer: 如果您真的想了解它,那么我建议使用此入门手册:

http://pomax.github.io/bezierinfo/ http://pomax.github.io/bezierinfo/

Bezier curves are a bit more complicated than simple arcs. 贝塞尔曲线比简单弧稍微复杂一些。 For an arc, you can just use this formula: 对于圆弧,您可以使用以下公式:

R = H/2 + W^2/8H

...which definitely won't work for a Bezier curve. ...对于贝塞尔曲线绝对不起作用。 On a Quadratic Bezier curve, for example, to calculate a point, you must use: 例如,在二次贝塞尔曲线上,要计算一个点,必须使用:

在此处输入图片说明

Sources: http://en.wikipedia.org/wiki/B%C3%A9zier_curve , Quadratic Bezier Curve: Calculate Point 资料来源: http : //en.wikipedia.org/wiki/B%C3%A9zier_curve二次贝塞尔曲线:计算点

Below is what I use to get the control point of a quad bezier curve. 下面是我用来获取四倍贝塞尔曲线的控制点的方法。 It should work for your problem where the control point is on the curve. 控制点在曲线上时,它应该可以解决您的问题。 It's in Swift but you should be able to convert it to another language easily. 它在Swift中,但是您应该能够轻松地将其转换为另一种语言。 Basically at the midpoint of the line (whose points are point1 and point2) I work out a perpendicular line with the given length. 基本上在直线的中点(其点分别是point1和point2),我计算出具有给定长度的垂直线。 Clockwise parameter determines which side of the line the point should fall on. 顺时针方向参数确定该点应落在线的哪一侧。

func getControlPointWithPoint1(point1:CGPoint, point2:CGPoint, length:CGFloat, clockwise:Bool) -> CGPoint {
  let angle = getAngleWithPoint1(point1, point2:point2)
  let direction = clockwise ? 1 : -1
  let perpendicularAngle = angle + (CGFloat(direction) * CGFloat((M_PI / 2)))
  let midPoint = getMidPointWithPoint1(point1, point2:point2)
  return CGPointMake(midPoint.x + (cos(perpendicularAngle) * length), midPoint.y + (sin(perpendicularAngle) * length))
}

func getAngleWithPoint1(point1:CGPoint, point2:CGPoint) -> CGFloat {
  return atan2((point2.y - point1.y), (point2.x - point1.x))
}

func getMidPointWithPoint1(point1:CGPoint, point2:CGPoint) -> CGPoint {
  return CGPointMake((point1.x + point2.x) / 2, (point1.y + point2.y) / 2)
}

Below is how it would map to your diagram letters: 下面是它如何映射到您的图表字母:

c = getControlPointWithPoint1(a, point2:b, length:h, clockwise:true)

following Mark's answer, here is the snippet in C# 按照Mark的回答,这是C#中的代码段

public static Path DrawBezeireUsingTwoPoints(Point startPoint, Point endPoint)
{
  Path path = new Path();
  PathFigure pathFigure = new PathFigure();
  // Set up the Path to insert the segments
  PathGeometry pathGeometry = new PathGeometry();
  BezierSegment bezeireSeg;
  // Draw an ellipse passing by the 2 points and let the path cross it
  Point beziereMidPoint = CalculateBezierePoint(startPoint, endPoint, true);
  bezeireSeg = new BezierSegment(startPoint, beziereMidPoint, endPoint, true);

  pathFigure.StartPoint = startPoint;
  pathFigure.IsClosed = false;
  pathFigure.Segments.Add(bezeireSeg);

  pathGeometry.Figures.Add(pathFigure);
  path.Data = pathGeometry;
  path.Stroke = Brushes.Brown;
  path.StrokeThickness = 2;
  return path;
}

I would be happy if help you. 如果能帮助您,我会很高兴。

It is my solution. 这是我的解决方案。

    Vector2 posA = sphereA.transform.position;
    Vector2 posB = sphereB.transform.position;

    Gizmos.color = Color.blue;
    Gizmos.DrawLine(posA, posB);

    float distance = Vector2.Distance(posA, posB);
    Vector2 direction = (posB - posA).normalized;

    Vector2 v2 = end - start;
    var angle = Mathf.Atan2(v2.y, v2.x) * Mathf.Rad2Deg;      

    var midStartPos = posA + direction * (distance / 2f);

    Gizmos.color = Color.red;
    Gizmos.DrawSphere(midStartPos, 0.02f);

    var height = 0.3f;

    height = Mathf.Clamp(height, 0f, Vector2.Distance(posA, posB) * 0.5f);

    angle = 90f + angle;

    var goalDirection = new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad));

    if (goalDirection.y < 0f)
    {
        goalDirection.x = -goalDirection.x;
        goalDirection.y = Mathf.Abs(goalDirection.y);
    }

    var midEndPos = midStartPos + goalDirection * height;

    Gizmos.color = Color.blue;
    Gizmos.DrawLine(midStartPos, midEndPos);

    Gizmos.color = Color.red;
    Gizmos.DrawSphere(midEndPos, 0.02f);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM