MathgeomGLS
1259 строк · 34.0 Кб
1unit faGraf2d;
2
3interface
4
5uses
6Winapi.Windows,
7Winapi.Messages,
8System.SysUtils,
9System.Variants,
10System.Classes,
11System.IniFiles,
12System.DateUtils,
13System.UITypes,
14System.Math,
15Vcl.Graphics,
16Vcl.Controls,
17Vcl.Forms,
18Vcl.Dialogs,
19Vcl.ComCtrls,
20Vcl.Menus,
21Vcl.ExtDlgs,
22
23GLS.OpenGLTokens,
24GLS.PersistentClasses,
25GLS.Scene,
26GLS.VectorTypes,
27GLS.GeomObjects,
28GLS.HUDObjects,
29GLS.Objects,
30GLS.Graph,
31GLS.Coordinates,
32
33GLS.SceneViewer,
34GLS.BitmapFont,
35GLS.WindowsFont,
36GLS.Particles,
37GLS.Color,
38GLS.BaseClasses,
39GLS.VectorGeometry,
40GLS.State,
41GLS.Material,
42
43Graf.Global2d,
44Graf.Parser2d,
45faEvaluate,
46faGridColors,
47faAddPlotColors,
48faCoordOptions,
49faGridOptions,
50faDerivativeOptions,
51faPlotColors,
52fAbout;
53
54type
55TFormPlotStars = class(TForm)
56GLSViewer: TGLSceneViewer;
57GLScene: TGLScene;
58GLLight: TGLLightSource;
59CameraCube: TGLDummyCube;
60Camera: TGLCamera;
61GLxyGrid: TGLXYZGrid;
62Fields: TGLDummyCube;
63GLWinBmpFont: TGLWindowsBitmapFont;
64StatusBar: TStatusBar;
65MainMenu: TMainMenu;
66miFile: TMenuItem;
67miNew: TMenuItem;
68miOptions: TMenuItem;
69miDefaultLayout: TMenuItem;
70miOpenFile: TMenuItem;
71miSave: TMenuItem;
72miSaveas: TMenuItem;
73miExit: TMenuItem;
74miGrid: TMenuItem;
75miGridColours: TMenuItem;
76miEvaluate: TMenuItem;
77GLxzGrid: TGLXYZGrid;
78GLyzGrid: TGLXYZGrid;
79TargetCube: TGLDummyCube;
80xCoordLine: TGLLines;
81yCoordLine: TGLLines;
82zCoordLine: TGLLines;
83BoxLine1: TGLLines;
84BoxLine2: TGLLines;
85BoxLine3: TGLLines;
86BoxLine4: TGLLines;
87miCoordText: TMenuItem;
88YCoordsCube: TGLDummyCube;
89XCoordsCube: TGLDummyCube;
90ZCoordsCube: TGLDummyCube;
91xArrow: TGLArrowLine;
92yArrow: TGLArrowLine;
93miRecent: TMenuItem;
94miDerivativeOps: TMenuItem;
95AddedField: TGLDummyCube;
96AddXLine: TGLLines;
97AddYLine: TGLLines;
98AddZLine: TGLLines;
99miPlotColours: TMenuItem;
100miDerivativePlotColours: TMenuItem;
101VolumeLines: TGLDummyCube;
102N2: TMenuItem;
103N3: TMenuItem;
104N4: TMenuItem;
105miHelp: TMenuItem;
106miAbout: TMenuItem;
107miView: TMenuItem;
108miGraf1d: TMenuItem;
109miGraf2d: TMenuItem;
110miRuwiki: TMenuItem;
111N1: TMenuItem;
112procedure FormCreate(Sender: TObject);
113procedure FormShow(Sender: TObject);
114procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
115procedure GLSViewerMouseDown(Sender: TObject; Button: TMouseButton;
116Shift: TShiftState; X, Y: Integer);
117procedure GLSViewerMouseMove(Sender: TObject; Shift: TShiftState;
118X, Y: Integer);
119procedure GLSViewerMouseUp(Sender: TObject; Button: TMouseButton;
120Shift: TShiftState; X, Y: Integer);
121procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
122WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
123procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
124procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
125procedure miDefaultLayoutClick(Sender: TObject);
126procedure miExitClick(Sender: TObject);
127procedure miGridClick(Sender: TObject);
128procedure miGridColoursClick(Sender: TObject);
129procedure miEvaluateClick(Sender: TObject);
130procedure miNewClick(Sender: TObject);
131procedure miOpenFileClick(Sender: TObject);
132procedure miSaveClick(Sender: TObject);
133procedure miSaveasClick(Sender: TObject);
134procedure FormDestroy(Sender: TObject);
135procedure FormActivate(Sender: TObject);
136procedure miCoordTextClick(Sender: TObject);
137procedure RecentFilesClick(Sender: TObject);
138procedure FormClose(Sender: TObject; var Action: TCloseAction);
139procedure miDerivativeOpsClick(Sender: TObject);
140procedure miPlotColoursClick(Sender: TObject);
141procedure miDerivativePlotColoursClick(Sender: TObject);
142procedure miAboutClick(Sender: TObject);
143private
144AtStart: Boolean;
145SelectedData: TPlotData; // data used to evaluate dz/dx or dz/dy
146procedure ShowCameraLocation;
147procedure ShowFocalLength;
148procedure ShowLightLocation;
149procedure DefaultView;
150procedure DefaultLayout;
151procedure Formulate(const X, Y: Single; var z: Single;
152var Color: TGLColorVector; var texPoint: TTexPoint);
153procedure CreateHeightFields(const n: Integer);
154procedure PlotFunctions;
155procedure CreateAddedField;
156procedure PlotDerivativeField;
157procedure PlotIntegralField;
158public
159MousePoint: TPoint;
160procedure ShowDisplacement;
161procedure UpdatePlot;
162procedure UpdateAdded;
163procedure ClearAddedField;
164procedure ClearAddedLines;
165end;
166
167const
168crLightxz = 1;
169crLightyz = 2;
170crLightxy = 3;
171crSlidexy = 4;
172crSlideyz = 5;
173crSlidexz = 6;
174crRotate = 7;
175crZoom = 8;
176crHandMove = 9;
177crSlidezy = 10;
178
179var
180FormPlotStars: TFormPlotStars;
181
182// =====================================================================
183implementation
184// =====================================================================
185
186{$R *.dfm}
187
188uses
189faFunctions;
190
191procedure TFormPlotStars.FormCreate(Sender: TObject);
192begin
193BinPath := ExtractFilePath(ParamStr(0));
194BinPath := IncludeTrailingPathDelimiter(BinPath);
195// PlotPath := BinPath;
196// Delete(PlotPath, Length(PlotPath) - 4, 4);
197DataPath := BinPath + 'data\plot2d\';
198SetCurrentDir(DataPath);
199ImagePath := BinPath + 'data\images\';
200LayoutFName := BinPath + 'Layout2d.lay';
201RecentFName := BinPath + 'Recent.ini';
202
203Screen.Cursors[crLightxy] := LoadCursor(HInstance, 'LIGHTXY');
204Screen.Cursors[crLightyz] := LoadCursor(HInstance, 'LIGHTYZ');
205Screen.Cursors[crLightxz] := LoadCursor(HInstance, 'LIGHTXZ');
206Screen.Cursors[crSlidexy] := LoadCursor(HInstance, 'SLIDEXY');
207Screen.Cursors[crSlidexz] := LoadCursor(HInstance, 'SLIDEXZ');
208Screen.Cursors[crSlideyz] := LoadCursor(HInstance, 'SLIDEYZ');
209Screen.Cursors[crRotate] := LoadCursor(HInstance, 'ROTATE');
210Screen.Cursors[crZoom] := LoadCursor(HInstance, 'ZOOM');
211Screen.Cursors[crSlidezy] := LoadCursor(HInstance, 'SLIDEZY');
212AtStart := True;
213end;
214
215procedure TFormPlotStars.FormShow(Sender: TObject);
216var
217LayFile: File of TLayout;
218ini: TIniFile;
219i, c: Integer;
220s: string;
221
222begin
223if FileExists(LayoutFName) then
224begin
225try
226AssignFile(LayFile, LayoutFName);
227try
228Reset(LayFile);
229Read(LayFile, Layout);
230finally
231CloseFile(LayFile);
232end;
233with Layout do
234begin
235if IsMaximize then
236WindowState := wsMaximized
237else
238begin
239WindowState := wsNormal;
240Left := MainLeft;
241Top := MainTop;
242Width := MainWidth;
243Height := MainHeight;
244end;
245GraphFName := CurrentGraphFName;
246DataPath := CurrentDataPath;
247ImagePath := CurrentImagePath;
248// ����� �������
249FunctionsForm.Left := FuncLeft;
250FunctionsForm.Top := FuncTop;
251FunctionsForm.Width := FuncWidth;
252FunctionsForm.Height := FuncHeight;
253// ����� ���������� �����
254if GridsVisible then
255FormGridOptions.Show;
256FormGridOptions.Left := GridsLeft;
257FormGridOptions.Top := GridsTop;
258// ����� ����� �����
259GridColorsForm.Left := GridColorsLeft;
260GridColorsForm.Top := GridColorsTop;
261// ����� ����� �������
262PlotColorsForm.Left := PlotColorsLeft;
263PlotColorsForm.Top := PlotColorsTop;
264// ����� ������ �������
265if EvaluateVisible then
266EvaluateForm.Show;
267EvaluateForm.Left := EvaluateLeft;
268EvaluateForm.Top := EvaluateTop;
269// ����� ���������
270if CoordVisible then
271CoordsForm.Show;
272CoordsForm.Left := CoordLeft;
273CoordsForm.Top := CoordTop;
274// ����� �����������
275DerivativesForm.Left := DerivLeft;
276DerivativesForm.Top := DerivTop;
277// ����� �������������� ������ �������
278AddPlotColorsForm.Left := AddColorsLeft;
279AddPlotColorsForm.Top := AddColorsTop;
280end;
281FunctionsForm.EditMinX.SetFocus;
282except
283MessageDlg('������ ������ �����!' +
284#13#10'"' + LayoutFName + '".' +
285#13#10'����� ������������ �������� ���������', mtError, [mbOK], 0);
286DefaultLayout;
287end;
288end
289else
290DefaultLayout;
291
292ShowCameraLocation;
293// focallength: right mouse drag up/down
294ShowFocalLength;
295(* displace origin: x axis: ctrl/left mouse drag left/right
296y axis: alt/left mouse drag up/down
297z axis: ctrl/left mouse drag up/down *)
298ShowDisplacement;
299(* move light: x axis: ctrl right mouse drag left/right
300y axis: alt right mouse drag up/down
301z axis: ctrl right mouse drag up/down *)
302ShowLightLocation;
303
304FunctionsForm.ReadAndShowInitialData;
305Caption := GraphFName;
306Altered := False;
307CreateHeightFields(FunctionsForm.CheckListBox.Count);
308
309ini := TIniFile.Create(RecentFName);
310with ini do
311try
312c := ReadInteger(Name, 'RecentCount', 0);
313for i := 0 to c - 1 do
314begin
315miRecent.Add(TMenuItem.Create(Self));
316miRecent.Items[i].Caption := ReadString(Name, IntToStr(i), '');
317miRecent.Items[i].OnClick := RecentFilesClick;
318end;
319finally
320Free;
321end;
322end;
323
324procedure TFormPlotStars.FormActivate(Sender: TObject);
325begin
326if AtStart then
327begin
328PlotFunctions;
329if GridColorsForm.Visible then
330GridColorsForm.ShowGridColorData;
331if PlotColorsForm.Visible then
332PlotColorsForm.ShowPlotColorData;
333AtStart := False;
334end;
335end;
336
337procedure TFormPlotStars.FormClose(Sender: TObject; var Action: TCloseAction);
338var
339ini: TIniFile;
340i: Integer;
341begin
342ini := TIniFile.Create(RecentFName);
343try
344ini.WriteInteger(Name, 'RecentCount', miRecent.Count);
345for i := 0 to miRecent.Count - 1 do
346ini.WriteString(Name, IntToStr(i), miRecent.Items[i].Caption);
347finally
348ini.Free;
349end;
350end;
351
352procedure TFormPlotStars.FormDestroy(Sender: TObject);
353begin
354while Fields.Count > 0 do
355TGLHeightField(Fields.Children[0]).Free;
356ClearAddedField;
357ClearAddedLines;
358end;
359
360procedure TFormPlotStars.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
361var
362f: File of TLayout;
363
364begin
365with Layout do
366begin
367IsMaximize := (Width >= Screen.Width) and (Height >= Screen.Height);
368MainLeft := Left;
369MainTop := Top;
370MainWidth := Width;
371MainHeight := Height;
372if GraphFName = '' then
373GraphFName := NewFName;
374CurrentGraphFName := GraphFName;
375CurrentDataPath := DataPath;
376CurrentImagePath := ImagePath;
377
378FuncLeft := FunctionsForm.Left;
379FuncTop := FunctionsForm.Top;
380FuncWidth := FunctionsForm.Width;
381FuncHeight := FunctionsForm.Height;
382
383GridsVisible := FormGridOptions.Visible;
384GridsLeft := FormGridOptions.Left;
385GridsTop := FormGridOptions.Top;
386
387GridColorsLeft := GridColorsForm.Left;
388GridColorsTop := GridColorsForm.Top;
389
390PlotColorsLeft := PlotColorsForm.Left;
391PlotColorsTop := PlotColorsForm.Top;
392
393EvaluateVisible := EvaluateForm.Visible;
394EvaluateLeft := EvaluateForm.Left;
395EvaluateTop := EvaluateForm.Top;
396
397CoordVisible := CoordsForm.Visible;
398CoordLeft := CoordsForm.Left;
399CoordTop := CoordsForm.Top;
400
401DerivLeft := DerivativesForm.Left;
402DerivTop := DerivativesForm.Top;
403if DerivativesForm.Visible then
404DerivativesForm.Close;
405
406AddColorsLeft := AddPlotColorsForm.Left;
407AddColorsTop := AddPlotColorsForm.Top;
408if AddPlotColorsForm.Visible then
409AddPlotColorsForm.Close;
410end;
411
412try
413AssignFile(f, LayoutFName);
414try
415Rewrite(f);
416write(f, Layout);
417finally
418CloseFile(f);
419end;
420except
421MessageDlg('������ ������ �����!' +
422#13#10'��� ������ � "' + LayoutFName + '".', mtError,
423[mbOK], 0);
424end;
425
426if Altered or GridColorsAltered or DerivativeAltered then
427begin
428case MessageDlg('��������� ������� ���� ��������.' +
429#13#10'��������� ��������� ?', mtConfirmation,
430[mbYes, mbNo, mbCancel], 0) of
431mrYes:
432FunctionsForm.miSaveClick(Sender);
433mrCancel:
434begin
435CanClose := False;
436Exit;
437end;
438end;
439end;
440end;
441
442//---------------------------------------------------------------
443procedure TFormPlotStars.FormKeyDown(Sender: TObject; var Key: Word;
444Shift: TShiftState);
445var
446d: Integer;
447begin
448d := 0;
449case Key of
450VK_ADD:
451d := -1; // zoom in
452VK_SUBTRACT:
453d := 1; // zoom out
454end;
455if Key in [VK_ADD, VK_SUBTRACT] then
456begin
457Screen.Cursor := crZoom;
458GLSViewer.SetFocus;
459// each step adjusts target distance by 2.5% another method to zoom in or out
460Camera.AdjustDistanceToTarget(Power(1.025, d));
461ShowCameraLocation;
462end
463else
464case Key of
465VK_HOME, VK_NUMPAD7, 72:
466DefaultView; // 'H'/'h' key
467(* -> = 39
468<- = 37
469^ = 38
470| = 40
471-> and ^ = 33
472<- and | = 35 *)
473end;
474Key := 0;
475end;
476
477//---------------------------------------------------------------
478procedure TFormPlotStars.FormKeyUp(Sender: TObject; var Key: Word;
479Shift: TShiftState);
480begin
481Screen.Cursor := crDefault;
482end;
483
484procedure TFormPlotStars.FormMouseWheel(Sender: TObject; Shift: TShiftState;
485WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
486begin
487if (MousePoint.X >= GLSViewer.Left) and
488(MousePoint.X <= GLSViewer.Left + GLSViewer.Width) and
489(MousePoint.Y >= GLSViewer.Top) and
490(MousePoint.Y <= GLSViewer.Top + GLSViewer.Height) then
491begin
492(*
493a wheel step = WheelDelta/300; each step adjusts target distance by 2.5%
494another method to zoom in or out
495*)
496GLSViewer.SetFocus;
497Camera.AdjustDistanceToTarget(Power(1.025, WheelDelta / 300));
498ShowCameraLocation;
499end;
500end;
501
502//---------------------------------------------------------------
503procedure TFormPlotStars.GLSViewerMouseDown(Sender: TObject; Button: TMouseButton;
504Shift: TShiftState; X, Y: Integer);
505begin
506MousePoint.X := X;
507MousePoint.Y := Y;
508if ssShift in Shift then // Shift key down
509begin
510if ssLeft in Shift then
511Screen.Cursor := crZoom;
512end
513else if ssCtrl in Shift then // Ctrl key down
514begin
515if ssLeft in Shift then
516Screen.Cursor := crSlidexz
517else if ssRight in Shift then
518Screen.Cursor := crLightxz;
519end
520else if ssAlt in Shift then // Alt key down
521begin
522if ssLeft in Shift then
523Screen.Cursor := crSlidezy
524else if ssRight in Shift then
525Screen.Cursor := crLightxy;
526end
527else // no shift, ctrl or alt key
528begin
529if Shift = [ssLeft] then
530Screen.Cursor := crRotate
531else if Shift = [ssRight] then
532Screen.Cursor := crZoom;
533end;
534end;
535
536//---------------------------------------------------------------
537procedure TFormPlotStars.GLSViewerMouseMove(Sender: TObject; Shift: TShiftState;
538X, Y: Integer);
539var
540dx, dy: Integer;
541
542begin // refer GLScene\Demos\interface\camera\Camera.dpr
543if MousePoint.X = MaxInt then // FileOpenDialog is visible
544begin
545MousePoint.X := X;
546Exit;
547end;
548
549dx := MousePoint.X - X;
550dy := MousePoint.Y - Y;
551
552if ssShift in Shift then // shift key down
553begin
554if ssLeft in Shift then // shift - left mouse button
555begin
556(* dy = a step which adjusts target distance by 1.25%; zoom in or out *)
557Camera.AdjustDistanceToTarget(Power(1.0125, dy));
558ShowCameraLocation;
559end;
560end
561else if ssCtrl in Shift then // Ctrl key down
562begin
563if ssLeft in Shift then // Ctrl - left mouse button
564begin
565TargetCube.Position.X := TargetCube.Position.X - dx *
566GLxzGrid.XSamplingScale.Step / 10;
567TargetCube.Position.z := TargetCube.Position.z - dy *
568GLxzGrid.ZSamplingScale.Step * ViewData.xyGrid.zScale / 10;
569ShowDisplacement;
570end;
571if ssRight in Shift then // Ctrl - right mouse button
572begin
573GLLight.Position.z := GLLight.Position.z + dy / 10;
574GLLight.Position.X := GLLight.Position.X + dx / 10;
575ShowLightLocation;
576end;
577end
578else if ssAlt in Shift then // Alt key down
579begin
580if ssRight in Shift then // Alt - right mouse button
581begin
582GLLight.Position.X := GLLight.Position.X + dx / 10;
583GLLight.Position.Y := GLLight.Position.Y + dy / 10;
584ShowLightLocation;
585end
586else if ssLeft in Shift then // Alt - left mouse button
587begin
588TargetCube.Position.Y := TargetCube.Position.Y + dx *
589GLyzGrid.YSamplingScale.Step / 10;
590TargetCube.Position.z := TargetCube.Position.z - dy *
591GLyzGrid.ZSamplingScale.Step * ViewData.xyGrid.zScale / 10;
592ShowDisplacement;
593end;
594end
595else // no shift key
596begin
597if Shift = [ssLeft] then
598(* Left mouse button changes camera angle by moving around target *)
599begin
600Camera.MoveAroundTarget(dy, dx);
601ShowCameraLocation;
602end;
603if Shift = [ssRight] then
604begin
605(*
606Right mouse button alters the camera's focal length;
607zoom out or in by moving cursor up or down
608*)
609Camera.FocalLength := Camera.FocalLength - dy;
610if Camera.FocalLength > 3000 then
611Camera.FocalLength := 3000; // max focal length
612if Camera.FocalLength < 10 then
613Camera.FocalLength := 10; // min focal length
614
615ShowFocalLength; // display in statusbar palel
616end;
617end;
618MousePoint.X := X; // update mouse position
619MousePoint.Y := Y;
620end;
621
622//---------------------------------------------------------------
623procedure TFormPlotStars.GLSViewerMouseUp(Sender: TObject; Button: TMouseButton;
624Shift: TShiftState; X, Y: Integer);
625begin
626Screen.Cursor := crDefault;
627end;
628
629procedure TFormPlotStars.miNewClick(Sender: TObject);
630begin
631FunctionsForm.miNewClick(Sender);
632end;
633
634procedure TFormPlotStars.miOpenFileClick(Sender: TObject);
635begin
636FunctionsForm.miOpenFileClick(Sender);
637end;
638
639procedure TFormPlotStars.miSaveClick(Sender: TObject);
640begin
641FunctionsForm.miSaveClick(Sender);
642end;
643
644procedure TFormPlotStars.miSaveasClick(Sender: TObject);
645begin
646FunctionsForm.miSaveAsClick(Sender);
647end;
648
649procedure TFormPlotStars.ShowCameraLocation;
650begin
651StatusBar.Panels[0].Text := '������: ' +
652FloatToStrF(Camera.Position.X, ffNumber, 5, 2) + ', ' +
653FloatToStrF(Camera.Position.Y, ffNumber, 5, 2) + ', ' +
654FloatToStrF(Camera.Position.Z, ffNumber, 5, 2);
655end;
656
657procedure TFormPlotStars.miGridColoursClick(Sender: TObject);
658begin
659GridColorsForm.Show;
660end;
661
662procedure TFormPlotStars.miCoordTextClick(Sender: TObject);
663begin
664CoordsForm.Show;
665end;
666
667procedure TFormPlotStars.ShowFocalLength;
668begin
669StatusBar.Panels[1].Text := 'f = ' + FloatToStrF(Camera.FocalLength,
670ffNumber, 5, 2);
671end;
672
673procedure TFormPlotStars.ShowDisplacement;
674begin
675StatusBar.Panels[2].Text := 'Displaced: ' +
676FloatToStrF(-TargetCube.Position.X, ffNumber, 5, 2) + ', ' +
677FloatToStrF(-TargetCube.Position.Y, ffNumber, 5, 2) + ', ' +
678FloatToStrF(-TargetCube.Position.Z, ffNumber, 5, 2);
679end;
680
681procedure TFormPlotStars.miEvaluateClick(Sender: TObject);
682begin
683EvaluateForm.Show;
684end;
685
686procedure TFormPlotStars.ShowLightLocation;
687begin
688StatusBar.Panels[3].Text := '����: ' +
689FloatToStrF(GLLight.Position.X, ffNumber, 5, 2) + ', ' +
690FloatToStrF(GLLight.Position.Y, ffNumber, 5, 2) + ', ' +
691FloatToStrF(GLLight.Position.Z, ffNumber, 5, 2);
692end;
693
694procedure TFormPlotStars.miGridClick(Sender: TObject);
695begin
696FormGridOptions.Show;
697end;
698
699procedure TFormPlotStars.miDefaultLayoutClick(Sender: TObject);
700begin
701DefaultLayout;
702end;
703
704procedure TFormPlotStars.DefaultView;
705begin
706CameraCube.Position.SetPoint(0, 0, 0);
707ShowDisplacement;
708Camera.FocalLength := 200;
709ShowFocalLength;
710Camera.Position.SetPoint(50, 50, 30);
711Camera.DepthOfView := 1000;
712ShowCameraLocation;
713GLLight.Position.SetPoint(50, 50, 50);
714ShowLightLocation;
715TargetCube.Position.SetPoint(0, 0, 0);
716end;
717
718procedure TFormPlotStars.RecentFilesClick(Sender: TObject);
719begin
720FunctionsForm.OpenRecentFile(TMenuItem(Sender).Caption);
721end;
722
723procedure TFormPlotStars.miExitClick(Sender: TObject);
724begin
725Close;
726end;
727
728procedure TFormPlotStars.DefaultLayout;
729begin
730WindowState := wsNormal;
731FormPlotStars.Left := 0;
732FormPlotStars.Top := 0;
733FunctionsForm.Width := 335;
734FunctionsForm.Height := 387;
735FormPlotStars.Width := Screen.Width - FunctionsForm.Width + 18;
736FormPlotStars.Height := Screen.Height - 40;
737FunctionsForm.Left := FormPlotStars.Left + FormPlotStars.Width - 14;
738FunctionsForm.Top := FormPlotStars.Top;
739FormGridOptions.Left := FunctionsForm.Left + 5;
740FormGridOptions.Top := FunctionsForm.Top + FunctionsForm.Height - 6;
741EvaluateForm.Left := FormGridOptions.Left;
742EvaluateForm.Top := FormGridOptions.Top + FormGridOptions.Height - 3;
743EvaluateForm.Show;
744FormGridOptions.Show;
745GridColorsForm.Left := 20;
746GridColorsForm.Top := 80;
747PlotColorsForm.Left := 30;
748PlotColorsForm.Top := 100;
749AddPlotColorsForm.Left := 40;
750AddPlotColorsForm.Top := 120;
751FunctionsForm.EditMinX.SetFocus;
752end;
753
754procedure TFormPlotStars.miDerivativeOpsClick(Sender: TObject);
755begin
756if PlotColorsForm.Visible then
757PlotColorsForm.Close;
758miPlotColours.Enabled := False;
759miDerivativePlotColours.Enabled := True;
760DerivativesForm.Show;
761end;
762
763procedure TFormPlotStars.miDerivativePlotColoursClick(Sender: TObject);
764begin
765if PlotColorsForm.Visible then
766PlotColorsForm.Close;
767miPlotColours.Enabled := False;
768AddPlotColorsForm.Show;
769end;
770
771procedure TFormPlotStars.PlotFunctions;
772
773procedure PlotFunction(i: Integer);
774begin
775with PlotData do
776begin
777with TGLHeightField(Fields.Children[i]) do
778begin
779XSamplingScale.Step := xInc;
780XSamplingScale.Min := xMin;
781XSamplingScale.Max := xMax;
782
783YSamplingScale.Step := yInc;
784YSamplingScale.Min := yMin;
785YSamplingScale.Max := yMax;
786
787case ViewMode of
788vmAmbient:
789ColorMode := hfcmAmbient;
790vmAmbientandDiffuse:
791ColorMode := hfcmAmbientAndDiffuse;
792vmDiffuse:
793ColorMode := hfcmDiffuse;
794vmEmmision:
795ColorMode := hfcmEmission;
796vmNone:
797ColorMode := hfcmNone;
798end;
799
800case fxyMode of
801fxyFill:
802Material.PolygonMode := pmFill;
803fxyLines:
804Material.PolygonMode := pmLines;
805fxyPoints:
806Material.PolygonMode := pmPoints;
807end;
808OnGetHeight := Formulate;
809end;
810GLSViewer.Refresh; // needed to display each zField data in list
811end;
812end;
813
814var
815i: Integer;
816fxyParser: TfxyParser;
817PD: TPlotData; // save the current PlotData of selected function
818
819begin // PlotFunctions
820Screen.Cursor := crHourGlass;
821PD := PlotData;
822fxyParser := TfxyParser.Create(0, 0);
823try
824with FunctionsForm.CheckListBox do
825for i := 0 to Items.Count - 1 do
826if Checked[i] then
827begin
828// an item is checked; get the plot data
829PlotData := TPlotDataObject(Items.Objects[i]).Data;
830PlotFunction(i);
831end;
832finally
833Screen.Cursor := crDefault;
834fxyParser.Destroy;
835PlotData := PD; // restor the current PlotData
836end;
837end;
838
839procedure TFormPlotStars.Formulate(const X, Y: Single; var z: Single;
840var Color: TGLColorVector; var texPoint: TTexPoint);
841var
842e: byte;
843MaxZ, MinZ: TGLFloat;
844x1, x2, y1, y2, z1, z2: extended;
845
846begin
847case AddedData.AddedAs of
848AddNone: // no AddedData to plot; just plot the PlotData
849begin
850z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);
851z := z * ViewData.xyGrid.zScale;
852with PlotData do
853begin
854MaxZ := zMax * ViewData.xyGrid.zScale;
855MinZ := zMin * ViewData.xyGrid.zScale;
856if zCap then
857begin
858if zLim and (z > MaxZ) then
859z := MaxZ;
860if zLim and (z < MinZ) then
861z := MinZ;
862end
863else if zLim and ((z < MinZ) or (z > MaxZ)) then
864z := NaN;
865VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);
866end;
867end;
868
869AddDerivX: // this is for partial derivative wrt x
870begin
871x1 := X - AddedData.xInc;
872x2 := X + AddedData.xInc;
873z1 := ParseEvaluateFxy(x1, Y, SelectedData.fxyStr, e);
874// evaluate z1,x1,y
875z2 := ParseEvaluateFxy(x2, Y, SelectedData.fxyStr, e);
876// evaluate z2,x2,y
877z := (z2 - z1) / (x2 - x1); // z = slope wrt x axis
878z := z * ViewData.xyGrid.zScale;
879with AddedData do
880begin
881MaxZ := zMax * ViewData.xyGrid.zScale;
882MinZ := zMin * ViewData.xyGrid.zScale;
883if zCap then
884begin
885if zLim and (z > MaxZ) then
886z := MaxZ;
887if zLim and (z < MinZ) then
888z := MinZ;
889end
890else if zLim and ((z < MinZ) or (z > MaxZ)) then
891z := NaN;
892VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);
893end;
894end;
895
896AddDerivY: // this is for partial derivative wrt y
897begin
898y1 := Y - AddedData.yInc;
899y2 := Y + AddedData.yInc;
900z1 := ParseEvaluateFxy(X, y1, SelectedData.fxyStr, e);
901// evaluate z1,x,y1
902z2 := ParseEvaluateFxy(X, y2, SelectedData.fxyStr, e);
903// evaluate z2,x,y2
904z := (z2 - z1) / (y2 - y1); // z = slope wrt y axis
905z := z * ViewData.xyGrid.zScale;
906with AddedData do
907begin
908MaxZ := zMax * ViewData.xyGrid.zScale;
909MinZ := zMin * ViewData.xyGrid.zScale;
910if zCap then
911begin
912if zLim and (z > MaxZ) then
913z := MaxZ;
914if zLim and (z < MinZ) then
915z := MinZ;
916end
917else if zLim and ((z < MinZ) or (z > MaxZ)) then
918z := NaN;
919VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);
920end;
921end;
922
923AddVolume: // this is for double integral
924begin
925z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);
926with AddedData do
927begin
928z := z * ViewData.xyGrid.zScale;
929MaxZ := zMax * ViewData.xyGrid.zScale;
930MinZ := zMin * ViewData.xyGrid.zScale;
931if zCap then
932begin
933if zLim and (z > MaxZ) then
934z := MaxZ;
935if zLim and (z < MinZ) then
936z := MinZ;
937end
938else if zLim and ((z < MinZ) or (z > MaxZ)) then
939z := NaN;
940VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);
941
942TGLLines.CreateAsChild(VolumeLines);
943with VolumeLines do
944begin
945with TGLLines(Children[Count - 1]) do
946begin
947LineColor.AsWinColor := AddLineColor;
948LineWidth := AddLineWidth;
949NodesAspect := LnaInvisible;
950
951Nodes.Add;
952Nodes[0].X := X; // start point
953Nodes[0].Y := Y;
954if zLim then
955Nodes[0].z := MinZ
956else
957Nodes[0].z := 0;
958
959Nodes.Add;
960Nodes[1].X := X; // end point
961Nodes[1].Y := Y;
962Nodes[1].z := z;
963end;
964end;
965end;
966end;
967end; // case AddedData.AddedAs of...
968end;
969
970procedure TFormPlotStars.PlotDerivativeField;
971var
972i: Integer;
973FoundSelected: Boolean;
974
975begin
976Screen.Cursor := crHourGlass;
977try
978i := 0;
979if FunctionsForm.CheckListBox.Count > 1 then // find Selected item
980begin
981FoundSelected := False;
982while not FoundSelected and (i < FunctionsForm.CheckListBox.Count) do
983begin
984FoundSelected := FunctionsForm.CheckListBox.Selected[i];
985if not FoundSelected then
986Inc(i);
987end;
988end;
989
990with FunctionsForm.CheckListBox do
991SelectedData := TPlotDataObject(Items.Objects[i]).Data;
992
993with AddedData do
994begin
995with TGLHeightField(AddedField.Children[0]) do
996begin
997with XSamplingScale do
998begin
999Step := xInc;
1000Min := xMin;
1001Max := xMax;
1002end;
1003
1004with YSamplingScale do
1005begin
1006Step := yInc;
1007Min := yMin;
1008Max := yMax;
1009end;
1010
1011case ViewMode of
1012vmAmbient:
1013ColorMode := hfcmAmbient;
1014vmAmbientandDiffuse:
1015ColorMode := hfcmAmbientAndDiffuse;
1016vmDiffuse:
1017ColorMode := hfcmDiffuse;
1018vmEmmision:
1019ColorMode := hfcmEmission;
1020vmNone:
1021ColorMode := hfcmNone;
1022end;
1023
1024case fxyMode of
1025fxyFill:
1026Material.PolygonMode := pmFill;
1027fxyLines:
1028Material.PolygonMode := pmLines;
1029fxyPoints:
1030Material.PolygonMode := pmPoints;
1031end;
1032OnGetHeight := Formulate;
1033end;
1034GLSViewer.Refresh; // needed to display each zField data in list
1035end;
1036finally
1037Screen.Cursor := crDefault;
1038end;
1039end;
1040
1041procedure TFormPlotStars.PlotIntegralField;
1042procedure PlotVolume;
1043begin // PlotVolume
1044with AddedData do
1045begin
1046with TGLHeightField(AddedField.Children[0]) do
1047begin
1048with XSamplingScale do
1049begin
1050Step := xInc;
1051Min := xMin;
1052Max := xMax;
1053end;
1054
1055with YSamplingScale do
1056begin
1057Step := yInc;
1058Min := yMin;
1059Max := yMax;
1060end;
1061
1062case ViewMode of
1063vmAmbient:
1064ColorMode := hfcmAmbient;
1065vmAmbientandDiffuse:
1066ColorMode := hfcmAmbientAndDiffuse;
1067vmDiffuse:
1068ColorMode := hfcmDiffuse;
1069vmEmmision:
1070ColorMode := hfcmEmission;
1071vmNone:
1072ColorMode := hfcmNone;
1073end;
1074
1075case fxyMode of
1076fxyFill:
1077Material.PolygonMode := pmFill;
1078fxyLines:
1079Material.PolygonMode := pmLines;
1080fxyPoints:
1081Material.PolygonMode := pmPoints;
1082end;
1083OnGetHeight := Formulate;
1084end;
1085GLSViewer.Refresh; // needed to display each zField data in list
1086end;
1087end; // PlotVolume
1088
1089procedure CalculateVolume;
1090var
1091e: byte;
1092i, j, iCount, jCount: Integer;
1093X, Y, z, x0, y0, a, VolPos, VolNeg: TGLFloat;
1094
1095begin // CalculateVolume
1096with AddedData do
1097begin
1098a := xInc * yInc; // base area
1099iCount := round((xMax - xMin) / xInc) - 1; // number of x points
1100jCount := round((yMax - yMin) / yInc) - 1; // number of y points
1101VolPos := 0;
1102VolNeg := 0;
1103x0 := xMin + xInc / 2; // base centre x0
1104y0 := yMin + yInc / 2; // base centre y0
1105for j := 0 to jCount do
1106begin
1107Y := y0 + j * yInc; // next column wrt y
1108for i := 0 to iCount do
1109begin
1110X := x0 + i * xInc; // next column wrt x
1111z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);
1112
1113if zLim then // zLimit applied
1114begin
1115if (zMax >= 0) and (zMin <= 0) then // above and below zero
1116begin
1117if z > 0 then
1118begin
1119if z > zMax then
1120VolPos := VolPos + a * zMax
1121else
1122VolPos := VolPos + a * z;
1123end
1124else
1125begin
1126if z < zMin then
1127VolNeg := VolNeg + a * zMin
1128else
1129VolNeg := VolNeg + a * z;
1130end;
1131end
1132else if zMin > 0 then // both above zero
1133begin
1134if z >= zMin then
1135begin
1136if z > zMax then
1137VolPos := VolPos + a * (zMax - zMin)
1138else
1139VolPos := VolPos + a * (z - zMin);
1140end;
1141end
1142else if zMax < 0 then // both below zero
1143begin
1144if z <= zMax then
1145begin
1146if z < zMin then
1147VolNeg := VolNeg + a * (zMax - zMin)
1148else
1149VolNeg := VolNeg + a * (z - zMax);
1150end;
1151end;
1152end
1153else // no zLimit applied
1154begin
1155if z > 0 then
1156VolPos := VolPos + a * z
1157else
1158VolNeg := VolNeg + a * z;
1159end;
1160end;
1161end;
1162end;
1163
1164with DerivativesForm do
1165begin
1166PosVolLabel.Caption := '������������� �����: ' + FloatToStr(VolPos);
1167NegVolLabel.Caption := '������������� �����: ' + FloatToStr(VolNeg);
1168TotalLabel.Caption := '���������� �����: ' + FloatToStr(VolPos - VolNeg);
1169VolumeLabel.Caption := '������ �����: ' + FloatToStr(VolPos + VolNeg);
1170end;
1171end; // CalculateVolume
1172
1173begin // TFormPlotStars.PlotIntegralField
1174Screen.Cursor := crHourGlass;
1175with AddedData do
1176begin
1177PlotVolume;
1178CalculateVolume;
1179end;
1180DerivativesForm.VolumeRB.Checked := False; //
1181Screen.Cursor := crDefault;
1182end; // TFormPlotStars.PlotIntegralField
1183
1184procedure TFormPlotStars.miPlotColoursClick(Sender: TObject);
1185begin
1186PlotColorsForm.Show;
1187end;
1188
1189procedure TFormPlotStars.CreateHeightFields(const n: Integer);
1190var
1191i: Integer;
1192
1193begin
1194while Fields.Count > 0 do
1195TGLHeightField(Fields.Children[0]).Free;
1196for i := 0 to n - 1 do
1197begin
1198TGLHeightField.CreateAsChild(Fields);
1199TGLHeightField(Fields.Children[Fields.Count - 1]).Material.BlendingMode :=
1200bmTransparency;
1201end;
1202end;
1203
1204procedure TFormPlotStars.CreateAddedField;
1205begin
1206ClearAddedField;
1207TGLHeightField.CreateAsChild(AddedField);
1208TGLHeightField(AddedField.Children[0]).Material.BlendingMode :=
1209bmTransparency;
1210end;
1211
1212procedure TFormPlotStars.UpdatePlot;
1213begin
1214CreateHeightFields(FunctionsForm.CheckListBox.Count);
1215PlotFunctions;
1216end;
1217
1218procedure TFormPlotStars.UpdateAdded;
1219begin
1220CreateAddedField;
1221AddXLine.LineColor.AsWinColor := AddedData.AddLineColor;
1222AddYLine.LineColor.AsWinColor := AddedData.AddLineColor;
1223AddZLine.LineColor.AsWinColor := AddedData.AddLineColor;
1224AddXLine.LineWidth := AddedData.AddLineWidth;
1225AddYLine.LineWidth := AddedData.AddLineWidth;
1226AddZLine.LineWidth := AddedData.AddLineWidth;
1227if AddedData.AddedAs = AddVolume then
1228PlotIntegralField
1229else
1230PlotDerivativeField;
1231end;
1232
1233procedure TFormPlotStars.miAboutClick(Sender: TObject);
1234begin
1235with TFormAbout.Create(Self) do
1236try
1237ShowModal;
1238finally
1239Free;
1240end;
1241end;
1242
1243procedure TFormPlotStars.ClearAddedField;
1244begin
1245with TGLHeightField(AddedField) do
1246if Count > 0 then
1247Children[0].Free;
1248end;
1249
1250procedure TFormPlotStars.ClearAddedLines;
1251begin
1252Screen.Cursor := crHourGlass;
1253with TGLLines(VolumeLines) do
1254while Count > 0 do
1255Children[Count - 1].Free;
1256Screen.Cursor := crDefault;
1257end;
1258
1259end.
1260