MainUnit.pas 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. unit MainUnit;
  2. interface
  3. {$include GR32.inc}
  4. uses
  5. {$IFDEF FPC}LCLIntf, {$ELSE}Windows, {$ENDIF} SysUtils, Classes, Graphics,
  6. Controls, Forms, Dialogs, GR32, GR32_Image, GR32_Polygons;
  7. type
  8. TScatterPoint = record
  9. X, Y, Z: TFloat;
  10. Color: TColor32;
  11. end;
  12. TFmScatterPlot = class(TForm)
  13. Image32: TImage32;
  14. procedure FormCreate(Sender: TObject);
  15. procedure Image32PaintStage(Sender: TObject; Buffer: TBitmap32;
  16. StageNum: Cardinal);
  17. procedure Image32Click(Sender: TObject);
  18. private
  19. FPoints: array of TScatterPoint;
  20. FRadius: TFloat;
  21. FSelection: TFloat;
  22. FCircle: TArrayOfFloatPoint;
  23. FBounds: array [0..1] of TFloat;
  24. FRenderer: TPolygonRenderer32VPR;
  25. procedure Generate;
  26. procedure Draw;
  27. public
  28. procedure ApplicationIdleHandler(Sender: TObject; var Done: Boolean);
  29. end;
  30. var
  31. FmScatterPlot: TFmScatterPlot;
  32. implementation
  33. {$R *.dfm}
  34. uses
  35. Math, GR32_Math, GR32_LowLevel, GR32_VectorUtils;
  36. procedure TFmScatterPlot.FormCreate(Sender: TObject);
  37. var
  38. NumPoints: Integer;
  39. begin
  40. Image32.Bitmap.SetSize(Image32.Width, Image32.Height);
  41. FRenderer := TPolygonRenderer32VPR.Create;
  42. FRenderer.Bitmap := Image32.Bitmap;
  43. FRadius := 2;
  44. FSelection := 0.5;
  45. FBounds[0] := 0.1;
  46. FBounds[1] := 0.2;
  47. FCircle := Circle(0, 0, FRadius, 8);
  48. Application.OnIdle := ApplicationIdleHandler;
  49. if TryStrToInt(ParamStr(1), NumPoints) then
  50. NumPoints := EnsureRange(NumPoints, 1, 20000)
  51. else
  52. NumPoints := 10000;
  53. SetLength(FPoints, NumPoints);
  54. Generate;
  55. Draw;
  56. end;
  57. procedure TFmScatterPlot.Generate;
  58. var
  59. Index: Cardinal;
  60. Radius: TFloatPoint;
  61. Z, Dist: TFloat;
  62. ScatterPnt, Pnt: TFloatPoint;
  63. begin
  64. Radius.X := Image32.Width / 3.5;
  65. Radius.Y := Image32.Height / 3.5;
  66. for Index := 0 to Length(FPoints) - 1 do
  67. begin
  68. Z := Random;
  69. FPoints[Index].Z := Z;
  70. GR32_Math.SinCos(2 * Pi * Z, Radius.X, Radius.Y, Pnt.Y, Pnt.X);
  71. Dist := 0.5 * Radius.X * Random;
  72. GR32_Math.SinCos(2 * Pi * Random, ScatterPnt.Y, ScatterPnt.X);
  73. FPoints[Index].X := 0.5 * Image32.Width + Pnt.X + ScatterPnt.X * Dist;
  74. FPoints[Index].Y := 0.5 * Image32.Height + Pnt.Y + ScatterPnt.Y * Dist;
  75. FPoints[Index].Color := HSLtoRGB(Z, 0.7, 0.5);
  76. end;
  77. end;
  78. procedure TFmScatterPlot.Image32Click(Sender: TObject);
  79. begin
  80. Generate;
  81. Draw;
  82. end;
  83. procedure TFmScatterPlot.Image32PaintStage(Sender: TObject; Buffer: TBitmap32;
  84. StageNum: Cardinal);
  85. begin
  86. // Buffer.Clear($FFFFFFFF);
  87. end;
  88. procedure TFmScatterPlot.ApplicationIdleHandler(Sender: TObject;
  89. var Done: Boolean);
  90. var
  91. Index: Cardinal;
  92. begin
  93. Done := False;
  94. for Index := 0 to Length(FPoints) - 1 do
  95. begin
  96. FPoints[Index].X := FPoints[Index].X + FSelection * (Random - 0.5);
  97. FPoints[Index].Y := FPoints[Index].Y + FSelection * (Random - 0.5);
  98. FPoints[Index].Z := FPoints[Index].Z + FSelection * (0.01 * Random - 0.005);
  99. if FPoints[Index].Z < 0.0 then
  100. FPoints[Index].Z := 0.0;
  101. if FPoints[Index].Z > 1.0 then
  102. FPoints[Index].Z := 1.0;
  103. end;
  104. FBounds[0] := FBounds[0] + 0.001 * Random;
  105. FBounds[1] := FBounds[1] + 0.001 * Random;
  106. FSelection := EnsureRange(FSelection + 0.02 * Random - 0.01, 0, 1);
  107. if FBounds[0] > 1 then
  108. FBounds[0] := 0;
  109. if FBounds[1] > 1 then
  110. FBounds[1] := 0;
  111. Draw;
  112. end;
  113. procedure TFmScatterPlot.Draw;
  114. var
  115. Index: Cardinal;
  116. Alpha: TFloat;
  117. begin
  118. Image32.Bitmap.Clear($FFFFFFFF);
  119. for Index := 0 to Length(FPoints) - 1 do
  120. begin
  121. Alpha := 1.0;
  122. if FBounds[1] < FBounds[0] then
  123. begin
  124. if (FPoints[Index].Z < FBounds[0]) and (FPoints[Index].Z > FBounds[1]) then
  125. begin
  126. if FBounds[0] - FPoints[Index].Z < FPoints[Index].Z - FBounds[1] then
  127. Alpha := 1.0 - (FBounds[0] - FPoints[Index].Z) * FSelection * 100.0
  128. else
  129. Alpha := 1.0 - (FPoints[Index].Z - FBounds[1]) * FSelection * 100.0;
  130. end;
  131. end
  132. else
  133. begin
  134. if FPoints[Index].Z < FBounds[0] then
  135. Alpha := 1.0 - (FBounds[0] - FPoints[Index].Z) * FSelection * 100.0;
  136. if FPoints[Index].Z > FBounds[1] then
  137. Alpha := 1.0 - (FPoints[Index].Z - FBounds[1]) * FSelection * 100.0;
  138. end;
  139. if Alpha < 0.0 then
  140. Continue;
  141. if Alpha > 1.0 then
  142. Alpha := 1.0;
  143. FRenderer.Color := SetAlpha(FPoints[Index].Color, Round(Alpha * $FF));
  144. FRenderer.PolygonFS(TranslatePolygon(FCircle, FPoints[Index].X,
  145. FPoints[Index].Y));
  146. end;
  147. end;
  148. end.