123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- 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 Vectorial Polygon Rasterizer for Graphics32
- *
- * The Initial Developer of the Original Code is
- * Christian-W. Budde
- *
- * Portions created by the Initial Developer are Copyright (C) 2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- {$include GR32.inc}
- uses
- {$IFDEF FPC}LCLIntf, {$ELSE}Windows, {$ENDIF} SysUtils, Classes, Graphics,
- Controls, Forms, Dialogs, GR32, GR32_Image, GR32_Polygons, GR32_Paths;
- type
- TFormBezier = class(TForm)
- PaintBox32: TPaintBox32;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure PaintBox32PaintBuffer(Sender: TObject);
- procedure PaintBox32DblClick(Sender: TObject);
- procedure PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X,
- Y: Integer);
- procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
- private
- FRenderer: TPolygonRenderer32VPR;
- FCurrentIndex: Integer;
- FVertices: TArrayOfFloatPoint;
- procedure RandomizeVertices;
- end;
- var
- FormBezier: TFormBezier;
- implementation
- {$R *.dfm}
- uses
- Math,
- Types,
- GR32_Math,
- GR32_LowLevel,
- GR32_VectorUtils;
- { TFormBezier }
- procedure TFormBezier.FormCreate(Sender: TObject);
- begin
- FRenderer := TPolygonRenderer32VPR.Create(PaintBox32.Buffer);
- SetLength(FVertices, 6);
- RandomizeVertices;
- FCurrentIndex := -1;
- end;
- procedure TFormBezier.FormDestroy(Sender: TObject);
- begin
- FRenderer.Free;
- end;
- procedure TFormBezier.FormKeyDown(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- begin
- case Key of
- 27: Close;
- 13:
- begin
- RandomizeVertices;
- PaintBox32.Invalidate;
- end;
- 187:
- begin
- SetLength(FVertices, Length(FVertices) + 1);
- with PaintBox32 do
- FVertices[Length(FVertices) - 1] := FloatPoint(Random * Width,
- Random * Height);
- PaintBox32.Invalidate;
- end;
- 189:
- if Length(FVertices) > 5 then
- begin
- SetLength(FVertices, Length(FVertices) - 1);
- PaintBox32.Invalidate;
- end;
- end;
- end;
- function CubicInterpolation(const Fractional: TFloat;
- const Data0, Data1, Data2, Data3: TFloat): TFloat;
- begin
- Result := Data1 + 0.5 * Fractional * (Data2 - Data0 + Fractional *
- (4 * Data2 + 2 * Data0 - 5 * Data1 - Data3 + Fractional *
- (3 * (Data1 - Data2) - Data0 + Data3)));
- end;
- procedure TFormBezier.RandomizeVertices;
- var
- Index: Integer;
- begin
- with PaintBox32 do
- for Index := 0 to High(FVertices) do
- FVertices[Index] := FloatPoint(Random * Width, Random * Height);
- end;
- procedure TFormBezier.PaintBox32DblClick(Sender: TObject);
- begin
- RandomizeVertices;
- PaintBox32.Invalidate;
- end;
- procedure TFormBezier.PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- var
- Index: Integer;
- Dist, MinDist: TFloat;
- MinDistIndex: Integer;
- begin
- FCurrentIndex := -1;
- for Index := 0 to Length(FVertices) - 1 do
- if Sqr(FVertices[Index].X - X) + Sqr(FVertices[Index].Y - Y) < 25 then
- begin
- if (Length(FVertices) > 5) and (Button = mbRight) then
- begin
- if Index < Length(FVertices) - 1 then
- Move(FVertices[Index + 1], FVertices[Index],
- (Length(FVertices) - Index - 1) * SizeOf(TFloatPoint));
- SetLength(FVertices, Length(FVertices) - 1);
- PaintBox32.Invalidate;
- end
- else
- FCurrentIndex := Index;
- Exit;
- end;
- if Button = mbLeft then
- begin
- MinDistIndex := 0;
- MinDist := Sqr(X - FVertices[0].X) + Sqr(Y - FVertices[0].Y);
- for Index := 1 to High(FVertices) do
- begin
- Dist := Sqr(X - FVertices[Index].X) + Sqr(Y - FVertices[Index].Y);
- if Dist < MinDist then
- begin
- MinDistIndex := Index;
- MinDist := Dist;
- end;
- end;
- SetLength(FVertices, Length(FVertices) + 1);
- Move(FVertices[MinDistIndex], FVertices[MinDistIndex + 1],
- (Length(FVertices) - MinDistIndex) * SizeOf(TFloatPoint));
- FCurrentIndex := MinDistIndex;
- FVertices[FCurrentIndex] := FloatPoint(X, Y);
- PaintBox32.Invalidate;
- end;
- end;
- procedure TFormBezier.PaintBox32MouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- begin
- if FCurrentIndex >= 0 then
- begin
- FVertices[FCurrentIndex] := FloatPoint(X, Y);
- PaintBox32.Invalidate;
- end;
- end;
- procedure TFormBezier.PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- if FCurrentIndex >= 0 then
- with PaintBox32 do
- begin
- FVertices[FCurrentIndex].X := EnsureRange(FVertices[FCurrentIndex].X,
- 0, Width);
- FVertices[FCurrentIndex].Y := EnsureRange(FVertices[FCurrentIndex].Y,
- 0, Height);
- end;
- FCurrentIndex := -1;
- PaintBox32.Invalidate;
- end;
- procedure TFormBezier.PaintBox32PaintBuffer(Sender: TObject);
- var
- Index: Integer;
- Val: Double;
- Fractional: Double;
- Indices: array [0..3] of Integer;
- PolyCount: Integer;
- Outline: TArrayOfArrayOfFloatPoint;
- const
- CVertexCountStep = 64;
- begin
- PaintBox32.Buffer.Clear($FFFFFFFF);
- Outline := BuildPolyPolyLine(PolyPolygon(FVertices), True, 2);
- PolyCount := Length(Outline);
- SetLength(Outline, PolyCount + Length(FVertices));
- for Index := 0 to Length(FVertices) - 1 do
- Outline[PolyCount + Index] := Circle(FVertices[Index].X, FVertices[Index].Y, 5, 32);
- FRenderer.Color := $80000080;
- FRenderer.PolyPolygonFS(Outline);
- SetLength(Outline, 1, CVertexCountStep);
- Outline[0, 0] := FVertices[0];
- Index := 0;
- Val := 0;
- while Val < Length(FVertices) do
- begin
- Indices[0] := (Length(FVertices) + Trunc(Val) - 2 + 1) mod Length(FVertices);
- Indices[1] := (Indices[0] + 1) mod Length(FVertices);
- Indices[2] := (Indices[1] + 1) mod Length(FVertices);
- Indices[3] := (Indices[2] + 1) mod Length(FVertices);
- Fractional := Frac(Val);
- Inc(Index);
- if Index = Length(Outline[0]) then
- SetLength(Outline[0], Length(Outline[0]) + CVertexCountStep);
- Outline[0, Index] := FloatPoint(
- CubicInterpolation(Fractional, FVertices[Indices[0]].X,
- FVertices[Indices[1]].X, FVertices[Indices[2]].X,
- FVertices[Indices[3]].X),
- CubicInterpolation(Fractional, FVertices[Indices[0]].Y,
- FVertices[Indices[1]].Y, FVertices[Indices[2]].Y,
- FVertices[Indices[3]].Y));
- Val := Val + 0.03;
- end;
- SetLength(Outline[0], Index + 1);
- FRenderer.Color := $FF000000;
- FRenderer.PolyPolygonFS(BuildPolyPolyline(Outline, True, 2));
- end;
- end.
|