fGrow.pas 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. unit fGrow;
  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 Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  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. * Andre Beckedorf <[email protected]>
  32. *
  33. * ***** END LICENSE BLOCK ***** *)
  34. interface
  35. {$I GR32.inc}
  36. uses
  37. {$IFDEF FPC}LCLIntf, LResources, {$ENDIF}
  38. Windows, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
  39. ExtCtrls, Math, Vcl.ExtDlgs, Vcl.Menus, GR32_Paths, GR32_Polygons,
  40. GR32_VectorUtils, GR32, GR32_Gamma, GR32_Blend, GR32_Image, Gr32_Clipper;
  41. type
  42. TFormGrow = class(TForm)
  43. Image: TImage32;
  44. PnlImage: TPanel;
  45. MainMenu1: TMainMenu;
  46. File1: TMenuItem;
  47. N1: TMenuItem;
  48. Exit1: TMenuItem;
  49. Refresh1: TMenuItem;
  50. Options1: TMenuItem;
  51. mnuInflatePolygon: TMenuItem;
  52. mnuInflatePolyLine: TMenuItem;
  53. procedure Exit1Click(Sender: TObject);
  54. procedure ImageClick(Sender: TObject);
  55. procedure ImageResize(Sender: TObject);
  56. procedure Refresh1Click(Sender: TObject);
  57. procedure FormCreate(Sender: TObject);
  58. procedure mnuInflatePolygonClick(Sender: TObject);
  59. public
  60. savedBmp: TBitmap32;
  61. end;
  62. var
  63. FormGrow: TFormGrow;
  64. implementation
  65. {$IFDEF FPC}
  66. {$R *.lfm}
  67. {$ELSE}
  68. {$R *.dfm}
  69. {$ENDIF}
  70. {$IFDEF Darwin}
  71. uses
  72. MacOSAll;
  73. {$ENDIF}
  74. //------------------------------------------------------------------------------
  75. //------------------------------------------------------------------------------
  76. function Area(const path: TArrayOfFloatPoint): single;
  77. var
  78. i, j, highI: Integer;
  79. d: single;
  80. begin
  81. Result := 0.0;
  82. highI := High(path);
  83. if (highI < 2) then Exit;
  84. j := highI;
  85. for i := 0 to highI do
  86. begin
  87. d := (path[j].X + path[i].X);
  88. Result := Result + d * (path[j].Y - path[i].Y);
  89. j := i;
  90. end;
  91. Result := -Result * 0.5;
  92. end;
  93. //------------------------------------------------------------------------------
  94. function MakePath(const pts: array of integer): TArrayOfFloatPoint;
  95. var
  96. i, len: Integer;
  97. begin
  98. Result := nil;
  99. len := length(pts) div 2;
  100. setlength(Result, len);
  101. for i := 0 to len -1 do
  102. Result[i] := FloatPoint(pts[i*2], pts[i*2 +1]);
  103. end;
  104. //------------------------------------------------------------------------------
  105. function MakeRandomPath(maxWidth, maxHeight, count: Integer): TArrayOfFloatPoint;
  106. var
  107. i: Integer;
  108. begin
  109. setlength(Result, count);
  110. for i := 0 to count -1 do
  111. with Result[i] do
  112. begin
  113. X := 20 + Random(maxWidth - 40);
  114. Y := 20 + Random(maxHeight - 40);
  115. end;
  116. end;
  117. //------------------------------------------------------------------------------
  118. function Union(const paths: TArrayOfArrayOfFloatPoint;
  119. fillRule: TFillRule = frEvenOdd): TArrayOfArrayOfFloatPoint;
  120. begin
  121. with TClipper.Create do
  122. try
  123. AddPaths(paths, ptSubject, false);
  124. Execute(ctUnion, fillRule, Result);
  125. finally
  126. Free;
  127. end;
  128. end;
  129. //------------------------------------------------------------------------------
  130. function GeneratePolygon(maxWidth,
  131. maxHeight, edgeCount: integer): TArrayOfFloatPoint;
  132. var
  133. PolyPts: TArrayOfArrayOfFloatPoint;
  134. i,j: integer;
  135. area, a: single;
  136. begin
  137. setLength(polyPts, 1);
  138. polyPts[0] := MakeRandomPath(maxWidth, maxHeight, edgeCount);
  139. // NOTE: INFLATEPATHS WILL BEHAVE IN AN UNDERTERMINED FASHION
  140. // WHENEVER SELF-INTERSECTING POLYGONS ARE ENCOUNTERED.
  141. // so, remove self-intersections
  142. PolyPts := Union(PolyPts);
  143. // and find the largest polygon ...
  144. j := 0;
  145. area := Abs(MainUnit.Area(polyPts[0]));
  146. for i := 1 to high(polyPts) do
  147. begin
  148. a := Abs(MainUnit.Area(polyPts[i]));
  149. if a <= area then Continue;
  150. j := i;
  151. area := a;
  152. end;
  153. Result := polyPts[j];
  154. end;
  155. //------------------------------------------------------------------------------
  156. procedure TFormGrow.FormCreate(Sender: TObject);
  157. begin
  158. SetGamma(1.4);
  159. end;
  160. procedure TFormGrow.Exit1Click(Sender: TObject);
  161. begin
  162. Close;
  163. end;
  164. procedure TFormGrow.ImageResize(Sender: TObject);
  165. begin
  166. Image.Bitmap.SetSize(PnlImage.ClientWidth, PnlImage.ClientHeight);
  167. Refresh1Click(nil);
  168. end;
  169. procedure TFormGrow.mnuInflatePolygonClick(Sender: TObject);
  170. begin
  171. if not TMenuItem(sender).Checked then
  172. begin
  173. mnuInflatePolygon.Checked := not mnuInflatePolygon.Checked;
  174. mnuInflatePolyLine.Checked := not mnuInflatePolyLine.Checked;
  175. end;
  176. Refresh1Click(nil);
  177. end;
  178. procedure TFormGrow.ImageClick(Sender: TObject);
  179. begin
  180. Refresh1Click(nil);
  181. end;
  182. procedure TFormGrow.Refresh1Click(Sender: TObject);
  183. var
  184. i: integer;
  185. polyPts: TArrayOfArrayOfFloatPoint;
  186. begin
  187. Image.Bitmap.Clear(clWhite32);
  188. if mnuInflatePolyLine.Checked then
  189. begin
  190. // INFLATE (GROW / OFFSET) A POLYLINE ...
  191. setLength(polyPts, 1);
  192. polyPts[0] := MakeRandomPath(Image.Bitmap.Width, Image.Bitmap.Height, 7);
  193. PolyPolylineFS(image.Bitmap, polyPts, clBlack32, false, 1);
  194. polyPts := InflatePaths(polyPts, 20, jtRoundEx, etOpenRound);
  195. PolyPolylineFS(image.Bitmap, polyPts, clRed32, true, 1);
  196. PolyPolygonFS(image.Bitmap, polyPts, $10FF0000);
  197. end else
  198. begin
  199. // INFLATE (GROW / OFFSET) A POLYGON ...
  200. setLength(polyPts, 1);
  201. repeat
  202. polyPts[0] := GeneratePolygon(Image.Bitmap.Width, Image.Bitmap.Height, 5);
  203. until Length(polyPts[0]) > 3;
  204. PolyPolygonFS(image.Bitmap, polyPts, $100000FF);
  205. PolyPolylineFS(image.Bitmap, polyPts, clBlack32, true, 1);
  206. polyPts := InflatePaths(polyPts, 10, jtRoundEx, etPolygon, 1);
  207. PolyPolylineFS(image.Bitmap, polyPts, clRed32, true, 1);
  208. PolyPolygonFS(image.Bitmap, polyPts, $10FF0000);
  209. end;
  210. end;
  211. end.