У меня есть четыре точки, по которым я хочу нарисовать овал, проходящий через эти четыре точки
Я не хочу использовать [UIBezierPath bezierPathWithOvalInRect:frame];
, потому что он не может работать с повернутым прямоугольником.
У меня есть четыре точки, по которым я хочу нарисовать овал, проходящий через эти четыре точки
Я не хочу использовать [UIBezierPath bezierPathWithOvalInRect:frame];
, потому что он не может работать с повернутым прямоугольником.
Я предполагаю, что ваши 4 точки не произвольные, а середины граней прямоугольника вокруг эллипса.
Вы можете построить путь из четырех кривых Безье, чтобы аппроксимировать единичную окружность с нулевым центром. Пример кода здесь
Затем примените к контрольным точкам аффинное преобразование, которое преобразует круг в повернутый эллипс с полуосями 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;