wpf 计算贝塞尔曲线的中点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23596802/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:42:11  来源:igfitidea点击:

Calculate middle point of Bezier Curve

c#wpfpointbezier

提问by morad1n

I have a function to draw Bezier Curvethrough three points. 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.

我有一个函数可以绘制Bezier Curve三个点。我已经有 2 个点(开始和结束)- A 和 B。我如何计算这两个点之间的中点,因为中点总是比这两个点的线性函数略高或略低。

Example:

示例

enter image description here

在此处输入图片说明

Any formulas, ideas would be great!

任何公式,想法都会很棒!

采纳答案by B.K.

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:

如果你真的想进入它,那么我推荐这个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:

...这绝对不适用于贝塞尔曲线。例如,在二次贝塞尔曲线上,要计算一个点,您必须使用:

enter image description here

在此处输入图片说明

Sources: http://en.wikipedia.org/wiki/B%C3%A9zier_curve, Quadratic Bezier Curve: Calculate Point

资料来源:http: //en.wikipedia.org/wiki/B%C3%A9zier_curve二次贝塞尔曲线:计算点

回答by Mark Horgan

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. Basically at the midpoint of the line (whose points are point1 and point2) I work out a perpendicular line with the given length. Clockwise parameter determines which side of the line the point should fall on.

下面是我用来获得四边形贝塞尔曲线控制点的内容。它应该适用于控制点在曲线上的问题。它在 Swift 中,但您应该能够轻松地将其转换为另一种语言。基本上在直线的中点(其点是点 1 和点 2),我计算出具有给定长度的垂直线。顺时针参数确定点应该落在线的哪一侧。

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)

回答by shakram02

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;
}

回答by nomad

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);