Вычислить среднюю точку кривой Безье

У меня есть функция для рисования Bezier Curve через три точки. У меня уже есть 2 точки (начало и конец) - A и B. Как мне рассчитать среднюю точку между этими двумя точками, поскольку средняя точка всегда будет немного выше или ниже, чем линейная функция этих двух точек.

Пример:

введите здесь описание изображения

Любые формулы, идеи были бы велики!


person morad1n    schedule 11.05.2014    source источник
comment
Если кто-то использует кубический Безье с двумя контрольными точками, я нашел этот кодовый пост очень полезен для нахождения середины.   -  person tkit    schedule 16.05.2019


Ответы (4)


Я думаю, это то, что вы ищете:

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

Он подробно описывает расчет различных точек на кривой Безье.

Вас также может заинтересовать этот более конкретный пример для вашего приложения:

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

Если вы действительно хотите вникнуть в это, то я предлагаю этот учебник для начинающих:

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

Кривые Безье немного сложнее, чем простые дуги. Для дуги вы можете просто использовать эту формулу:

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

... что определенно не будет работать для кривой Безье. Например, на квадратичной кривой Безье для вычисления точки необходимо использовать:

введите здесь описание изображения

Источники: http://en.wikipedia.org/wiki/B%C3%A9zier_curve, Квадратичная кривая Безье: расчет точки

person B.K.    schedule 11.05.2014
comment
Спасибо за ваше время. Очень интересная информация, но, на мой взгляд, она не поможет мне вычислить точку C. Я имею в виду, что хочу создать программу, в которой я могу соединить две точки, не прямые, а кривые (используя кривую Безье), поэтому мне нужно вычислить третью точку C. автоматически из A и B. Я хочу, чтобы это освободило место для второго соединения под этим более высоким соединением. Все происходит на Canvas так, используя свойство Left, Top. Извините за английский кстати. :) - person morad1n; 12.05.2014
comment
@ morad1n Если это не простая дуга, а скорее кривая Безье, вам необходимо прочитать предоставленную мной информацию. Вам необходимо рассчитать расположение точек ручек. Primer подробно описывает это. Вы уверены, что кривая Безье — это то, что вам нужно? - person B.K.; 12.05.2014

Ниже показано, что я использую, чтобы получить контрольную точку квадратной кривой Безье. Это должно работать для вашей проблемы, где контрольная точка находится на кривой. Это в 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)
}

Ниже показано, как это будет отображаться на буквы вашей диаграммы:

c = getControlPointWithPoint1(a, point2:b, length:h, clockwise:true)
person Mark Horgan    schedule 20.11.2014

после ответа Марка вот фрагмент на С#

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;
}
person shakram02    schedule 31.03.2016

Буду рад, если помогу.

Это мое решение.

    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);
person nomad    schedule 15.10.2019