Стартовый пул
This commit is contained in:
BIN
bgrabitmap/test/rationalbezier/rationalbezier.ico
Normal file
BIN
bgrabitmap/test/rationalbezier/rationalbezier.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
80
bgrabitmap/test/rationalbezier/rationalbezier.lpi
Normal file
80
bgrabitmap/test/rationalbezier/rationalbezier.lpi
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
<General>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<Title Value="rationalbezier"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<XPManifest>
|
||||
<DpiAware Value="True"/>
|
||||
</XPManifest>
|
||||
<Icon Value="0"/>
|
||||
</General>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="BGRABitmapPack"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="rationalbezier.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="Form1"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="Unit1"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<Target>
|
||||
<Filename Value="rationalbezier"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Linking>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
21
bgrabitmap/test/rationalbezier/rationalbezier.lpr
Normal file
21
bgrabitmap/test/rationalbezier/rationalbezier.lpr
Normal file
@@ -0,0 +1,21 @@
|
||||
program rationalbezier;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, Unit1;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
RequireDerivedFormResource:=True;
|
||||
// Application.Scaled:=True;
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TForm1, Form1);
|
||||
Application.Run;
|
||||
end.
|
||||
|
92
bgrabitmap/test/rationalbezier/unit1.lfm
Normal file
92
bgrabitmap/test/rationalbezier/unit1.lfm
Normal file
@@ -0,0 +1,92 @@
|
||||
object Form1: TForm1
|
||||
Left = 533
|
||||
Height = 365
|
||||
Top = 210
|
||||
Width = 533
|
||||
Caption = 'Rational Bezier Curve'
|
||||
ClientHeight = 365
|
||||
ClientWidth = 533
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
OnMouseDown = FormMouseDown
|
||||
OnMouseMove = FormMouseMove
|
||||
OnMouseUp = FormMouseUp
|
||||
OnPaint = FormPaint
|
||||
LCLVersion = '1.6.0.4'
|
||||
object Panel1: TPanel
|
||||
Left = 0
|
||||
Height = 37
|
||||
Top = 0
|
||||
Width = 533
|
||||
Align = alTop
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 37
|
||||
ClientWidth = 533
|
||||
TabOrder = 0
|
||||
object Label1: TLabel
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideRight.Control = Owner
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 248
|
||||
Height = 17
|
||||
Top = 0
|
||||
Width = 37
|
||||
Caption = 'Label1'
|
||||
ParentColor = False
|
||||
end
|
||||
object Label2: TLabel
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Label1
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = Owner
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 248
|
||||
Height = 17
|
||||
Top = 17
|
||||
Width = 37
|
||||
Caption = 'Label2'
|
||||
ParentColor = False
|
||||
end
|
||||
object FloatSpinEdit1: TFloatSpinEdit
|
||||
Left = 52
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 50
|
||||
Increment = 0.05
|
||||
MaxValue = 5
|
||||
MinValue = 0
|
||||
OnChange = FloatSpinEdit1Change
|
||||
TabOrder = 0
|
||||
Value = 2
|
||||
end
|
||||
object Label3: TLabel
|
||||
Left = 8
|
||||
Height = 17
|
||||
Top = 5
|
||||
Width = 39
|
||||
Caption = 'Weight'
|
||||
ParentColor = False
|
||||
end
|
||||
object Label4: TLabel
|
||||
Left = 116
|
||||
Height = 17
|
||||
Top = 5
|
||||
Width = 51
|
||||
Caption = 'Precision'
|
||||
ParentColor = False
|
||||
end
|
||||
object FloatSpinEdit2: TFloatSpinEdit
|
||||
Left = 180
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 50
|
||||
Increment = 0.05
|
||||
MaxValue = 5
|
||||
MinValue = 0.1
|
||||
OnChange = FloatSpinEdit2Change
|
||||
TabOrder = 1
|
||||
Value = 0.4
|
||||
end
|
||||
end
|
||||
end
|
222
bgrabitmap/test/rationalbezier/unit1.pas
Normal file
222
bgrabitmap/test/rationalbezier/unit1.pas
Normal file
@@ -0,0 +1,222 @@
|
||||
unit Unit1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Spin,
|
||||
ExtCtrls, BGRABitmapTypes, BGRABitmap, BGRACanvas2D;
|
||||
|
||||
type
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
TForm1 = class(TForm)
|
||||
FloatSpinEdit1: TFloatSpinEdit;
|
||||
FloatSpinEdit2: TFloatSpinEdit;
|
||||
Label1: TLabel;
|
||||
Label2: TLabel;
|
||||
Label3: TLabel;
|
||||
Label4: TLabel;
|
||||
Panel1: TPanel;
|
||||
procedure FloatSpinEdit1Change(Sender: TObject);
|
||||
procedure FloatSpinEdit2Change(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||||
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure FormPaint(Sender: TObject);
|
||||
private
|
||||
Center: TPoint;
|
||||
B, B2: TRationalQuadraticBezierCurve;
|
||||
CurPoint: integer;
|
||||
PrevMouse: TPoint;
|
||||
Img : TBGRABitmap;
|
||||
procedure UpdateLength;
|
||||
public
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
Form1: TForm1;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
B:=BezierCurve(PointF(-150,80), PointF(0,0), PointF(150,80), FloatSpinEdit1.Value);
|
||||
B2:=BezierCurve(PointF(-150,80), PointF(0,0), PointF(150,80), -FloatSpinEdit1.Value);
|
||||
UpdateLength;
|
||||
Img := TBGRABitmap.Create;
|
||||
CurPoint := -1;
|
||||
end;
|
||||
|
||||
procedure TForm1.FloatSpinEdit1Change(Sender: TObject);
|
||||
begin
|
||||
B.weight := FloatSpinEdit1.Value;
|
||||
B2.weight := -FloatSpinEdit1.Value;
|
||||
UpdateLength;
|
||||
invalidate;
|
||||
end;
|
||||
|
||||
procedure TForm1.FloatSpinEdit2Change(Sender: TObject);
|
||||
begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
Img.free
|
||||
end;
|
||||
|
||||
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
MinDist: single;
|
||||
|
||||
function TryPoint(APoint: TPointF): boolean;
|
||||
var
|
||||
dist: single;
|
||||
begin
|
||||
dist:= sqr(APoint.x-x)+sqr(APoint.y-y);
|
||||
if dist < MinDist then
|
||||
begin
|
||||
MinDist := dist;
|
||||
exit(true)
|
||||
end
|
||||
else exit(false);
|
||||
end;
|
||||
|
||||
begin
|
||||
dec(y, Center.Y);
|
||||
dec(x, Center.X);
|
||||
if Button = mbLeft then
|
||||
begin
|
||||
CurPoint:= -1;
|
||||
MinDist := sqr(15);
|
||||
if TryPoint(B.p1) then CurPoint := 0;
|
||||
if TryPoint(B.c) then CurPoint := 1;
|
||||
if TryPoint(B.p2) then CurPoint := 2;
|
||||
PrevMouse := Point(X,Y);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
|
||||
Y: Integer);
|
||||
var
|
||||
d: TPointF;
|
||||
begin
|
||||
dec(y, Center.Y);
|
||||
dec(x, Center.X);
|
||||
if CurPoint <> -1 then
|
||||
begin
|
||||
d := PointF(X-PrevMouse.x,Y-PrevMouse.y);
|
||||
case CurPoint of
|
||||
0: begin B.p1.Offset(d); B2.p1.Offset(d); end;
|
||||
1: begin B.c.Offset(d); B2.c.Offset(d); end;
|
||||
2: begin B.p2.Offset(d); B2.p2.Offset(d); end;
|
||||
end;
|
||||
PrevMouse := Point(X,Y);
|
||||
UpdateLength;
|
||||
Invalidate;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
begin
|
||||
if Button = mbLeft then CurPoint := -1;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormPaint(Sender: TObject);
|
||||
var
|
||||
f: TBGRACanvas2D;
|
||||
R, boundsF: TrectF;
|
||||
Aleft, Aright : TRationalQuadraticBezierCurve;
|
||||
precision: single;
|
||||
begin
|
||||
precision := FloatSpinEdit2.Value;
|
||||
Img.SetSize(ClientWidth,ClientHeight-Panel1.Height);
|
||||
Img.Fill(clWhite);
|
||||
f := Img.Canvas2D;
|
||||
Center := Point(ClientWidth div 2, (ClientHeight - Panel1.Height) div 2 + Panel1.Height);
|
||||
boundsF := RectF(0,0, Img.Width,Img.Height);
|
||||
boundsF.Offset(-Center.X, -Center.Y + Panel1.Height);
|
||||
f.resetTransform;
|
||||
f.translate(Center.X,Center.Y - Panel1.Height);
|
||||
f.lineJoinLCL:= pjsBevel;
|
||||
// arc d'ellipse en rouge, poids 0.4 (petit arc)
|
||||
f.beginPath;
|
||||
f.moveto(B.p1);
|
||||
f.lineTo(B.c);
|
||||
f.lineTo(B.p2);
|
||||
f.moveto(B2.p1);
|
||||
f.lineTo(B2.c);
|
||||
f.lineTo(B2.p2);
|
||||
f.moveto(B.p1.x+5,B.p1.y);
|
||||
f.circle(B.p1.x,B.p1.y,5);
|
||||
f.moveto(B.c.x+5,B.c.y);
|
||||
f.circle(B.c.x,B.c.y,5);
|
||||
f.moveto(B.p2.x+5,B.p2.y);
|
||||
f.circle(B.p2.x,B.p2.y,5);
|
||||
f.strokeStyle(clblack);
|
||||
f.linewidth := 1;
|
||||
f.stroke();
|
||||
f.beginPath;
|
||||
f.lineWidth := 4;
|
||||
f.strokeStyle(BGRA(255,0,96,255));
|
||||
f.moveTo(B.p1);
|
||||
f.polylineTo(B.ToPoints(boundsF,precision));
|
||||
f.stroke();
|
||||
// arc d'ellipse en vert, poids -0.4 (grand arc, complétant le précédent)
|
||||
f.beginPath;
|
||||
f.strokeStyle(BGRA(96,160,0,255));
|
||||
f.polylineTo(B2.ToPoints(boundsF,precision));
|
||||
f.stroke();
|
||||
if not B2.IsInfinite then
|
||||
begin
|
||||
// arc en bleu, c'est la deuxième moitié de l'arc en vert
|
||||
B2.Split(Aleft, Aright);
|
||||
f.strokeStyle(BGRA(0,96,255,255));
|
||||
f.beginPath;
|
||||
f.moveTo(Aright.p1);
|
||||
f.polylineTo(Aright.ToPoints(boundsF,precision*2));
|
||||
f.stroke;
|
||||
|
||||
// bounding box de l'arc en vert
|
||||
R:=B2.GetBounds();
|
||||
f.beginPath;
|
||||
f.rect(round(R.Left)-1, round(R.Top)-1, round(R.Width)+2, round(R.Height)+2);
|
||||
f.strokeStyle(BGRABlack);
|
||||
f.lineWidth := 1;
|
||||
f.stroke();
|
||||
end;
|
||||
Img.draw(Canvas,0,Panel1.Height)
|
||||
end;
|
||||
|
||||
procedure TForm1.UpdateLength;
|
||||
var
|
||||
len: Single;
|
||||
begin
|
||||
len := B2.ComputeLength;
|
||||
if len = EmptySingle then
|
||||
Label1.caption:='Green arc length = infinity'
|
||||
else
|
||||
Label1.caption:='Green arc length = '+FloatToStrF(len, ffFixed, 7,1);
|
||||
len := B.ComputeLength;
|
||||
if len = EmptySingle then
|
||||
Label2.caption:='Red arc length = infinity'
|
||||
else
|
||||
Label2.caption:='Red arc length = '+FloatToStrF(len, ffFixed, 7,1);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Reference in New Issue
Block a user