123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- unit MainUnit;
- (* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1 or LGPL 2.1 with linking exception
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * Alternatively, the contents of this file may be used under the terms of the
- * Free Pascal modified version of the GNU Lesser General Public License
- * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
- * of this license are applicable instead of those above.
- * Please see the file LICENSE.txt for additional information concerning this
- * license.
- *
- * The Original Code is Clipper grow example
- *
- * The Initial Developer of the Original Code is
- * Angus Johnson (http://www.angusj.com)
- *
- * Portions created by the Initial Developer are Copyright (C) 2000-2005
- * the Initial Developer. All Rights Reserved.
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- {$include GR32.inc}
- uses
- {$IFDEF FPC}LCLIntf, LResources, {$ENDIF}
- Windows, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
- ExtCtrls, Math, Vcl.ExtDlgs, Vcl.Menus, System.Actions, Vcl.ActnList,
- GR32,
- GR32_Polygons,
- GR32_VectorUtils,
- GR32_Image;
- type
- TFormGrow = class(TForm)
- Image: TImage32;
- MainMenu: TMainMenu;
- MenuItemFile: TMenuItem;
- N1: TMenuItem;
- MenuItemExit: TMenuItem;
- MenuItemRefresh: TMenuItem;
- MenuItemOptions: TMenuItem;
- MenuItemOptionsInflatePolygon: TMenuItem;
- MenuItemOptionsInflatePolyLine: TMenuItem;
- ActionList: TActionList;
- ActionRefresh: TAction;
- ActionFileExit: TAction;
- ActionOptionShapePolygon: TAction;
- ActionOptionShapePolyLine: TAction;
- Joinstyle1: TMenuItem;
- N2: TMenuItem;
- Endstyle1: TMenuItem;
- Miterjoin1: TMenuItem;
- Beveljoin1: TMenuItem;
- Beveljoin2: TMenuItem;
- RoundExjoin1: TMenuItem;
- ActionOptionJoinMiter: TAction;
- ActionOptionJoinBevel: TAction;
- ActionOptionJoinRound: TAction;
- ActionOptionJoinSquare: TAction;
- ActionOptionEndButt: TAction;
- ActionOptionEndSquare: TAction;
- ActionOptionEndRound: TAction;
- Action51: TMenuItem;
- Action52: TMenuItem;
- Action71: TMenuItem;
- ActionOptionJoinStyle: TAction;
- ActionOptionEndStyle: TAction;
- ActionOptionGrowClipper: TAction;
- ActionOptionGrowGraphics32: TAction;
- N3: TMenuItem;
- Growusing1: TMenuItem;
- Graphics321: TMenuItem;
- Clipper1: TMenuItem;
- ActionOptionGrowAngus: TAction;
- Image321: TMenuItem;
- ActionOptionJoinRoundEx: TAction;
- RoundExjoin2: TMenuItem;
- procedure ImageClick(Sender: TObject);
- procedure ImageResize(Sender: TObject);
- procedure ActionFileExitExecute(Sender: TObject);
- procedure ActionOptionShapeExecute(Sender: TObject);
- procedure ActionOptionJoinStyleExecute(Sender: TObject);
- procedure ActionOptionEndStyleExecute(Sender: TObject);
- procedure ActionDummyExecute(Sender: TObject);
- procedure ActionOptionEndStylesUpdate(Sender: TObject);
- procedure ActionOptionJoinStyleUpdate(Sender: TObject);
- procedure ActionOptionEndStyleUpdate(Sender: TObject);
- procedure ActionRefreshExecute(Sender: TObject);
- procedure ActionRedrawExecute(Sender: TObject);
- private
- FJoinStyle: TJoinStyle;
- FEndStyle: TEndStyle;
- FPolyPoints: TArrayOfArrayOfFloatPoint;
- function GeneratePolygon(MaxWidth, MaxHeight, EdgeCount: integer): TArrayOfFloatPoint;
- procedure ApplyOptionsAndRedraw;
- procedure CreateNewPolygonAndApplyOptions;
- function PolyLineBuilderClass: TPolyLineBuilderClass;
- public
- end;
- var
- FormGrow: TFormGrow;
- implementation
- {$IFDEF FPC}
- {$R *.lfm}
- {$ELSE}
- {$R *.dfm}
- {$ENDIF}
- uses
- GR32_Clipper,
- GR32_Paths,
- GR32_VectorUtils.Reference,
- GR32_VectorUtils.Angus,
- GR32_VectorUtils.Clipper2;
- const
- MARGIN = 40;
- //------------------------------------------------------------------------------
- function Area(const Path: TArrayOfFloatPoint): Single;
- var
- i, j, HighI: Integer;
- d: Single;
- begin
- Result := 0.0;
- HighI := High(Path);
- if (HighI < 2) then Exit;
- j := HighI;
- for i := 0 to HighI do
- begin
- d := (Path[j].X + Path[i].X);
- Result := Result + d * (Path[j].Y - Path[i].Y);
- j := i;
- end;
- Result := -Result * 0.5;
- end;
- //------------------------------------------------------------------------------
- function MakeRandomPath(MaxWidth, MaxHeight, Count: Integer): TArrayOfFloatPoint;
- var
- i: Integer;
- begin
- Setlength(Result, Count);
- for i := 0 to Count -1 do
- begin
- Result[i].X := MARGIN + Random(MaxWidth - MARGIN * 2);
- Result[i].Y := MARGIN + Random(MaxHeight - MARGIN * 2);
- end;
- end;
- //------------------------------------------------------------------------------
- function TFormGrow.GeneratePolygon(MaxWidth, MaxHeight, EdgeCount: integer): TArrayOfFloatPoint;
- function Union(const Paths: TArrayOfArrayOfFloatPoint; FillRule: TFillRule = frEvenOdd): TArrayOfArrayOfFloatPoint;
- var
- Clipper: TClipper;
- begin
- Clipper := TClipper.Create;
- try
- Clipper.AddPaths(Paths, ptSubject, False);
- Clipper.Execute(ctUnion, FillRule, Result);
- finally
- Clipper.Free;
- end;
- end;
- var
- PolyPts: TArrayOfArrayOfFloatPoint;
- i,j: integer;
- Area, a: Single;
- begin
- Setlength(PolyPts, 1);
- PolyPts[0] := MakeRandomPath(MaxWidth, MaxHeight, EdgeCount);
- // NOTE: INFLATEPATHS WILL BEHAVE IN AN UNDETERMINED FASHION
- // WHENEVER SELF-INTERSECTING POLYGONS ARE ENCOUNTERED.
- // so, remove self-intersections
- PolyPts := Union(PolyPts);
- if (Length(PolyPts) = 0) then
- // Most likely user has resized window to zero size
- Abort;
- // and find the largest polygon ...
- j := 0;
- Area := Abs(MainUnit.Area(PolyPts[0]));
- for i := 1 to high(PolyPts) do
- begin
- a := Abs(MainUnit.Area(PolyPts[i]));
- if a <= Area then
- Continue;
- j := i;
- Area := a;
- end;
- Result := PolyPts[j];
- end;
- //------------------------------------------------------------------------------
- function TFormGrow.PolyLineBuilderClass: TPolyLineBuilderClass;
- begin
- if (ActionOptionGrowClipper.Checked) then
- Result := PolyLineBuilderClipper
- else
- if (ActionOptionGrowAngus.Checked) then
- Result := PolyLineBuilderAngus
- else
- Result := PolyLineBuilderReference;
- end;
- //------------------------------------------------------------------------------
- procedure TFormGrow.ActionOptionEndStylesUpdate(Sender: TObject);
- begin
- TAction(Sender).Enabled := not ActionOptionShapePolygon.Checked;
- end;
- procedure TFormGrow.ActionDummyExecute(Sender: TObject);
- begin
- //
- end;
- procedure TFormGrow.ActionFileExitExecute(Sender: TObject);
- begin
- Close;
- end;
- procedure TFormGrow.ActionOptionEndStyleUpdate(Sender: TObject);
- begin
- TAction(Sender).Enabled := (TEndStyle(TAction(Sender).Tag) in PolyLineBuilderClass.SupportedEndStyles);
- TAction(Sender).Checked := (FEndStyle = TEndStyle(TAction(Sender).Tag));
- end;
- procedure TFormGrow.ActionOptionEndStyleExecute(Sender: TObject);
- begin
- FEndStyle := TEndStyle(TAction(Sender).Tag);
- ApplyOptionsAndRedraw;
- end;
- procedure TFormGrow.ActionOptionShapeExecute(Sender: TObject);
- begin
- CreateNewPolygonAndApplyOptions;
- end;
- procedure TFormGrow.ActionOptionJoinStyleUpdate(Sender: TObject);
- begin
- TAction(Sender).Enabled := (TJoinStyle(TAction(Sender).Tag) in PolyLineBuilderClass.SupportedJoinStyles);
- TAction(Sender).Checked := (FJoinStyle = TJoinStyle(TAction(Sender).Tag));
- end;
- procedure TFormGrow.ActionRedrawExecute(Sender: TObject);
- begin
- ApplyOptionsAndRedraw;
- end;
- procedure TFormGrow.ActionRefreshExecute(Sender: TObject);
- begin
- CreateNewPolygonAndApplyOptions;
- end;
- procedure TFormGrow.ActionOptionJoinStyleExecute(Sender: TObject);
- begin
- FJoinStyle := TJoinStyle(TAction(Sender).Tag);
- ApplyOptionsAndRedraw;
- end;
- procedure TFormGrow.ApplyOptionsAndRedraw;
- var
- PolyPts: TArrayOfArrayOfFloatPoint;
- Closed: boolean;
- Builder: TPolyLineBuilderClass;
- begin
- // Apply options to existing polyline/polygon and repaint
- Closed := not ActionOptionShapePolyLine.Checked;
- Image.Bitmap.Clear(clWhite32);
- if (Closed) then
- PolyPolygonFS(image.Bitmap, FPolyPoints, $100000FF, pfNonZero);
- PolyPolylineFS(image.Bitmap, FPolyPoints, clBlack32, Closed, 1);
- Builder := PolyLineBuilderClass;
- PolyPts := Builder.BuildPolyPolyLine(FPolyPoints, Closed, 20, FJoinStyle, FEndStyle);
- PolyPolylineFS(image.Bitmap, PolyPts, clRed32, True, 1);
- PolyPolygonFS(image.Bitmap, PolyPts, $10FF0000, pfNonZero);
- end;
- procedure TFormGrow.ImageResize(Sender: TObject);
- begin
- Image.Bitmap.SetSize(Image.ClientWidth, Image.ClientHeight);
- CreateNewPolygonAndApplyOptions;
- end;
- procedure TFormGrow.CreateNewPolygonAndApplyOptions;
- begin
- if (Image.Bitmap.Width < 2*MARGIN) or (Image.Bitmap.Height < 2*MARGIN) then
- begin
- Image.Bitmap.Clear(clRed32);
- exit;
- end;
- Caption := IntToStr(RandSeed);
- Setlength(FPolyPoints, 1);
- if ActionOptionShapePolyLine.Checked then
- // Generate a polyline
- FPolyPoints[0] := MakeRandomPath(Image.Bitmap.Width, Image.Bitmap.Height, 7)
- else
- // Generate a closed polygon
- repeat
- FPolyPoints[0] := GeneratePolygon(Image.Bitmap.Width, Image.Bitmap.Height, 5);
- until Length(FPolyPoints[0]) > 3;
- ApplyOptionsAndRedraw;
- end;
- procedure TFormGrow.ImageClick(Sender: TObject);
- begin
- CreateNewPolygonAndApplyOptions;
- end;
- end.
|