fCurves.pas 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. unit fCurves;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Curves Example (based on VPR example)
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Mattias Andersson <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2005
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Christian-W. Budde (GR32 version 2.0 port)
  32. *
  33. * ***** END LICENSE BLOCK ***** *)
  34. interface
  35. {$I GR32.inc}
  36. uses
  37. {$IFDEF FPC} LCLIntf, LResources, Buttons, {$ENDIF}
  38. Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
  39. ExtCtrls, GR32_Image;
  40. type
  41. TMainForm = class(TForm)
  42. BtnDrawCurve: TButton;
  43. CbxUpdate: TCheckBox;
  44. Img: TImage32;
  45. procedure BtnDrawCurveClick(Sender: TObject);
  46. procedure CbxUpdateClick(Sender: TObject);
  47. procedure ApplicationIdleHandler(Sender: TObject; var Done: Boolean);
  48. private
  49. end;
  50. var
  51. MainForm: TMainForm;
  52. implementation
  53. {$IFDEF FPC}
  54. {$R *.lfm}
  55. {$ELSE}
  56. {$R *.dfm}
  57. {$ENDIF}
  58. uses
  59. Math, GR32, GR32_Geometry, GR32_VectorUtils, GR32_Resamplers, GR32_LowLevel,
  60. GR32_Polygons;
  61. function MakeCurve(const Points: TArrayOfFloatPoint; Kernel: TCustomKernel;
  62. Closed: Boolean): TArrayOfFloatPoint;
  63. const
  64. TOLERANCE: TFloat = 20.0;
  65. THRESHOLD: TFloat = 0.5;
  66. var
  67. I, H, R: Integer;
  68. Filter: TFilterMethod;
  69. WrapProc: TWrapProc;
  70. procedure AddPoint(const P: TFloatPoint);
  71. var
  72. L: Integer;
  73. begin
  74. L := Length(Result);
  75. SetLength(Result, L + 1);
  76. Result[L] := P;
  77. end;
  78. function GetPoint(I: Integer; t: TFloat = 0.0): TFloatPoint;
  79. var
  80. f, Index: Integer;
  81. W: TFloat;
  82. begin
  83. Result.X := 0; Result.Y := 0;
  84. for f := -R to R do
  85. begin
  86. Index := WrapProc(I - f, H);
  87. W := Filter(f + t);
  88. Result.X := Result.X + W * Points[Index].X;
  89. Result.Y := Result.Y + W * Points[Index].Y;
  90. end;
  91. end;
  92. procedure Recurse(I: Integer; const P1, P2: TFloatPoint; const t1, t2: TFloat);
  93. var
  94. Temp: TFloat;
  95. P: TFloatPoint;
  96. begin
  97. AddPoint(P1);
  98. Temp := (t1 + t2) * 0.5;
  99. P := GetPoint(I, Temp);
  100. if (Abs(CrossProduct(FloatPoint(P1.X - P.X, P1.Y - P.Y),
  101. FloatPoint(P.X - P2.X, P.Y - P2.Y))) > TOLERANCE) or (t2 - t1 >= THRESHOLD) then
  102. begin
  103. Recurse(I, P1, P, t1, Temp);
  104. Recurse(I, P, P2, Temp, t2);
  105. end
  106. else AddPoint(P);
  107. end;
  108. const
  109. WRAP_PROC: array[Boolean] of TWrapProc = (Clamp, Wrap);
  110. begin
  111. WrapProc := Wrap_PROC[Closed];
  112. Filter := Kernel.Filter;
  113. R := Ceil(Kernel.GetWidth);
  114. H := High(Points);
  115. for I := 0 to H - 1 do
  116. Recurse(I, GetPoint(I), GetPoint(I + 1), 0, 1);
  117. if Closed then
  118. Recurse(H, GetPoint(H), GetPoint(0), 0, 1)
  119. else
  120. AddPoint(GetPoint(H));
  121. end;
  122. procedure TMainForm.BtnDrawCurveClick(Sender: TObject);
  123. var
  124. PX, PY: TArrayOfFloatPoint;
  125. I: Integer;
  126. K: TCustomKernel;
  127. X, Y: Integer;
  128. begin
  129. //Randomize;
  130. Img.SetupBitmap(True, $FF333333);
  131. SetLength(PX, 8);
  132. // create a set of random data points
  133. for I := 0 to High(PX) do
  134. PX[I] := FloatPoint(Random(Img.Width), Random(Img.Height));
  135. // create interpolation kernel
  136. K := TGaussianKernel.Create;
  137. try
  138. // subdivide recursively and interpolate
  139. PY := MakeCurve(PX, K, True);
  140. finally
  141. K.Free;
  142. end;
  143. // draw result polygon
  144. PolygonFS(Img.Bitmap, PY, $FFCC3300, pfWinding);
  145. // draw data points
  146. for I := 0 to High(PY) do
  147. begin
  148. X := Floor(PY[I].X);
  149. Y := Floor(PY[I].Y);
  150. Img.Bitmap.FillRects(X, Y, X + 1, Y + 1, $FF00FF00);
  151. end;
  152. for I := 0 to High(PX) do
  153. begin
  154. PY := Circle(PX[I].X, PX[I].Y, 4);
  155. PolygonFS(Img.Bitmap, PY, $FF000000);
  156. PY := Ellipse(PX[I].X, PX[I].Y, 2.75, 2.75);
  157. PolygonFS(Img.Bitmap, PY, $FF00FF00);
  158. end;
  159. end;
  160. procedure TMainForm.ApplicationIdleHandler(Sender: TObject; var Done: Boolean);
  161. begin
  162. BtnDrawCurveClick(Sender);
  163. end;
  164. procedure TMainForm.CbxUpdateClick(Sender: TObject);
  165. begin
  166. if CbxUpdate.Checked then
  167. Application.OnIdle := ApplicationIdleHandler
  168. else
  169. Application.OnIdle := nil;
  170. end;
  171. end.