2016-12-08 3 views
0

У меня есть четыре точки, которые я хочу нарисовать овал, что путь через эти четыре точки Oval path through four pointsDrawing овального путь через четыре точки

Я не хочу использовать [UIBezierPath bezierPathWithOvalInRect:frame]; Потому что он не может работать с повернутым прямоугольником.

+0

Мне интересно, если у вас есть подпрограммы для выполнения следующего (и если это работает, потому что я нашел ответ на обмен математического стека, требуя, чтобы для определения эллипса потребовалось пять очков). 1. Уравнение можно было бы сделать похожим на x^2 + на^2 + cxy + dx + ey + f = 0. Поэтому подключите каждую из четырех пар координат к этому уравнению, чтобы получить четыре линейных уравнения относительно b, c, d, e и f. 2. Я думаю, вам нужно пять пар. Потому что с пятью уравнениями вы бы решили систему (неплохо, если у вас есть библиотека, которая делает матрицы) или решает системы. 3) подключите обратно и нарисуйте связь (снова нужна рутина). –

+0

См. Http://math.stackexchange.com/questions/880258/minimal-number-of-points-to-define-a-rotated-ellipse/880292#comment4207125_880292, который утверждает, что вам нужно пять очков. Может быть, какой-то умный читатель может нарисовать второй эллипс через ваши четыре. –

+0

Или вы даете нам конечные точки осей, как изображено? –

ответ

0

Я полагаю, что ваши 4 точки не являются произвольными, а серединками краев прямоугольника вокруг эллипса.

Вы можете построить путь из четырех кривых Безье, чтобы приблизиться к нулевому центру круга. Пример кода here

Затем примените к аффинному преобразованию контрольных точек, которые преобразуют круг в повернутый эллипс с полуосями A и B, центром (CX, CY) и углом поворота Alpha.

В вашем случае, если точки P0..P3, то

 A = |P0P2| (distance) 
    B = |P1P3| 
    CX = (P0.X + P2.X)/2 
    CY = (P0.Y + P2.Y)/2 
    Alpha = ArcTan2(P0.Y - P2.Y, P0.X - P2.X) 

У меня есть Delphi код для этой проблемы, надеюсь, что это может помочь. Обратите внимание, что замкнутый путь Безье содержит 13 точек (последнее совпадает с первым).

procedure CalcRotatedEllipse(CX, CY, A, B: Integer; Alpha: Double; var BezPts: array of TPoint); 
const 
    MP = 0.55228475; 
var 
    CA, SA, ACA, ASA, BCA, BSA: Double; 
    i, CX2, CY2: Integer; 

function TransformPoint(X, Y: Double): TPoint; 
begin 
    Result.X := Round(CX + X * ACA + Y * BSA); 
    Result.Y := Round(CY - X * ASA + Y * BCA); 
end; 

begin 
    Assert(Length(BezPts) = 13); 
    CA:= Cos(Alpha); SA := Sin(Alpha); 
    ACA := A * CA; ASA := A * SA; 
    BCA := B * CA; BSA := B * SA; 
    CX2 := 2 * CX; CY2 := 2 * CY; 
    BezPts[0] := TransformPoint(1, 0); 
    BezPts[1] := TransformPoint(1, MP); 
    BezPts[2] := TransformPoint(MP, 1); 
    BezPts[3] := TransformPoint(0, 1); 
    BezPts[4] := TransformPoint(- MP, 1); 
    BezPts[5] := TransformPoint(-1, MP); 
    for i := 0 to 5 do 
    BezPts[i + 6] := Point(CX2 - BezPts[i].X, CY2 - BezPts[i].Y); 
    BezPts[12] := BezPts[0]; 
end; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    Pts: array[0..12] of TPoint; 
begin 
    CalcRotatedEllipse(200, 200, 200, 70, Pi/6, Pts); 
    Canvas.PolyBezier(Pts); 
end;