Calculate middle point of Bezier Curve

守給你的承諾、 提交于 2019-12-04 06:14:26
B.K.

I think this is what you're looking for:

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

If you really want to get into it, then I suggest this Primer:

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

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.

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#

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);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!