unit Bezier; interface uses Math; type BezierPoint = record x, y: double; end; BezierRect = record x0, y0, x1, y1: double; end; BezierPoints = array [0..3] of BezierPoint; BezierWeights = array [0..3] of double; procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints); procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect); procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect); procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint); function BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double; implementation procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints); var i, n: integer; begin n := Length(src); for i := 0 to n - 1 do tgt[i] := src[i]; end; procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect); var i, n: integer; f: double; begin n := Length(points); for i := 0 to n - 1 do begin if (flip) then f := 1 - points[i].y else f := points[i].y; points[i].x := points[i].x * (rect.x1 - rect.x0) + rect.x0; points[i].y := f * (rect.y1 - rect.y0) + rect.y0; end; end; procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect); var i, n: integer; f: double; begin if ((rect.x1 - rect.x0) = 0) or ((rect.y1 - rect.y0) = 0) then Exit; n := Length(points); for i := 0 to n - 1 do begin points[i].x := (points[i].x - rect.x0) / (rect.x1 - rect.x0); points[i].y := (points[i].y - rect.y0) / (rect.y1 - rect.y0); if (flip) then points[i].y := 1 - points[i].y; end; end; procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint); var s, s2, s3, t2, t3, nom_x, nom_y, denom: double; begin s := 1 - t; s2 := s * s; s3 := s * s * s; t2 := t * t; t3 := t * t * t; nom_x := w[0] * s3 * src[0].x + w[1] * s2 * 3 * t * src[1].x + w[2] * s * 3 * t2 * src[2].x + w[3] * t3 * src[3].x; nom_y := w[0] * s3 * src[0].y + w[1] * s2 * 3 * t * src[1].y + w[2] * s * 3 * t2 * src[2].y + w[3] * t3 * src[3].y; denom := w[0] * s3 + w[1] * s2 * 3 * t + w[2] * s * 3 * t2 + w[3] * t3; if (IsNaN(nom_x)) or (IsNaN(nom_y)) or (IsNaN(denom)) then Exit; if denom = 0 then Exit; solution.x := nom_x / denom; solution.y := nom_y / denom; end; function BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double; var p: BezierPoint; begin BezierSolve(t, src, w, p); Result := p.y; end; end.