MathgeomGLS
1253 строки · 33.5 Кб
1unit fPlot2D;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
43uGlobal,44uParser,45fEvaluate,46fGridColors,47fAddPlotColors,48fCoordOptions,49fGridOptions,50fDerivativeOptions,51fPlotColors,52fAbout;53
54type
55TFormPlot2D = class(TForm)56GLSViewer: TGLSceneViewer;57GLScene: TGLScene;58GLLight: TGLLightSource;59CameraCube: TGLDummyCube;60Camera: TGLCamera;61GLxyGrid: TGLXYZGrid;62Fields: TGLDummyCube;63GLWinBmpFont: TGLWindowsBitmapFont;64StatusBar: TStatusBar;65MainMenu: TMainMenu;66File1: TMenuItem;67New1: TMenuItem;68Options1: TMenuItem;69DefaultLayout1: TMenuItem;70OpenFile: TMenuItem;71Save1: TMenuItem;72Saveas1: TMenuItem;73Exit1: TMenuItem;74Grid1: TMenuItem;75GridColours1: TMenuItem;76Evaluate1: TMenuItem;77GLxzGrid: TGLXYZGrid;78GLyzGrid: TGLXYZGrid;79TargetCube: TGLDummyCube;80xCoordLine: TGLLines;81yCoordLine: TGLLines;82zCoordLine: TGLLines;83BoxLine1: TGLLines;84BoxLine2: TGLLines;85BoxLine3: TGLLines;86BoxLine4: TGLLines;87CoordText1: TMenuItem;88YCoordsCube: TGLDummyCube;89XCoordsCube: TGLDummyCube;90ZCoordsCube: TGLDummyCube;91xArrow: TGLArrowLine;92yArrow: TGLArrowLine;93Recent1: TMenuItem;94DerivativeOps: TMenuItem;95AddedField: TGLDummyCube;96AddXLine: TGLLines;97AddYLine: TGLLines;98AddZLine: TGLLines;99PlotColours1: TMenuItem;100DerivativePlotColours1: TMenuItem;101VolumeLines: TGLDummyCube;102N2: TMenuItem;103N3: TMenuItem;104N4: TMenuItem;105Help1: TMenuItem;106About1: TMenuItem;107procedure FormCreate(Sender: TObject);108procedure FormShow(Sender: TObject);109procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);110procedure GLSViewerMouseDown(Sender: TObject; Button: TMouseButton;111Shift: TShiftState; X, Y: Integer);112procedure GLSViewerMouseMove(Sender: TObject; Shift: TShiftState;113X, Y: Integer);114procedure GLSViewerMouseUp(Sender: TObject; Button: TMouseButton;115Shift: TShiftState; X, Y: Integer);116procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;117WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);118procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);119procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);120procedure DefaultLayout1Click(Sender: TObject);121procedure Exit1Click(Sender: TObject);122procedure Grid1Click(Sender: TObject);123procedure GridColours1Click(Sender: TObject);124procedure Evaluate1Click(Sender: TObject);125procedure New1Click(Sender: TObject);126procedure OpenFileClick(Sender: TObject);127procedure Save1Click(Sender: TObject);128procedure Saveas1Click(Sender: TObject);129procedure FormDestroy(Sender: TObject);130procedure FormActivate(Sender: TObject);131procedure CoordText1Click(Sender: TObject);132procedure RecentFilesClick(Sender: TObject);133procedure FormClose(Sender: TObject; var Action: TCloseAction);134procedure DerivativeOpsClick(Sender: TObject);135procedure PlotColours1Click(Sender: TObject);136procedure DerivativePlotColours1Click(Sender: TObject);137procedure About1Click(Sender: TObject);138private139AtStart: Boolean;140SelectedData: TPlotData; // data used to evaluate dz/dx or dz/dy141procedure ShowCameraLocation;142procedure ShowFocalLength;143procedure ShowLightLocation;144procedure DefaultView;145procedure DefaultLayout;146procedure Formulate(const X, Y: Single; var z: Single;147var Color: TGLColorVector; var texPoint: TTexPoint);148procedure CreateHeightFields(const n: Integer);149procedure PlotFunctions;150procedure CreateAddedField;151procedure PlotDerivativeField;152procedure PlotIntegralField;153public154MousePoint: TPoint;155procedure ShowDisplacement;156procedure UpdatePlot;157procedure UpdateAdded;158procedure ClearAddedField;159procedure ClearAddedLines;160end;161
162const
163crLightxz = 1;164crLightyz = 2;165crLightxy = 3;166crSlidexy = 4;167crSlideyz = 5;168crSlidexz = 6;169crRotate = 7;170crZoom = 8;171crHandMove = 9;172crSlidezy = 10;173
174var
175FormPlot2D: TFormPlot2D;176
177// =====================================================================
178implementation
179// =====================================================================
180
181{$R *.dfm}
182{$R CURSORS.RES}
183
184uses
185fFunctions;186
187procedure TFormPlot2D.FormCreate(Sender: TObject);188begin
189BinPath := ExtractFilePath(ParamStr(0));190BinPath := IncludeTrailingPathDelimiter(BinPath);191// PlotPath := BinPath;
192// Delete(PlotPath, Length(PlotPath) - 4, 4);
193DataPath := BinPath + 'Examples\'; // PlotPath194SetCurrentDir(DataPath);195ImagePath := BinPath + 'Images\';196LayoutFName := BinPath + 'Layout.lay';197RecentFName := BinPath + 'Recent.ini';198
199Screen.Cursors[crLightxy] := LoadCursor(HInstance, 'LIGHTXY');200Screen.Cursors[crLightyz] := LoadCursor(HInstance, 'LIGHTYZ');201Screen.Cursors[crLightxz] := LoadCursor(HInstance, 'LIGHTXZ');202Screen.Cursors[crSlidexy] := LoadCursor(HInstance, 'SLIDEXY');203Screen.Cursors[crSlidexz] := LoadCursor(HInstance, 'SLIDEXZ');204Screen.Cursors[crSlideyz] := LoadCursor(HInstance, 'SLIDEYZ');205Screen.Cursors[crRotate] := LoadCursor(HInstance, 'ROTATE');206Screen.Cursors[crZoom] := LoadCursor(HInstance, 'ZOOM');207Screen.Cursors[crSlidezy] := LoadCursor(HInstance, 'SLIDEZY');208AtStart := True;209end;210
211procedure TFormPlot2D.FormShow(Sender: TObject);212var
213LayFile: File of TLayout;214ini: TIniFile;215i, c: Integer;216s: string;217
218begin
219if FileExists(LayoutFName) then220begin221try222AssignFile(LayFile, LayoutFName);223try224Reset(LayFile);225Read(LayFile, Layout);226finally227CloseFile(LayFile);228end;229with Layout do230begin231if IsMaximize then232WindowState := wsMaximized233else234begin235WindowState := wsNormal;236Left := MainLeft;237Top := MainTop;238Width := MainWidth;239Height := MainHeight;240end;241GraphFName := CurrentGraphFName;242DataPath := CurrentDataPath;243ImagePath := CurrentImagePath;244// FormFunctions245FormFunctions.Left := FuncLeft;246FormFunctions.Top := FuncTop;247FormFunctions.Width := FuncWidth;248FormFunctions.Height := FuncHeight;249// GridOptionsForm250if GridsVisible then251FormGridOptions.Show;252FormGridOptions.Left := GridsLeft;253FormGridOptions.Top := GridsTop;254// FormGridColors255FormGridColors.Left := GridColorsLeft;256FormGridColors.Top := GridColorsTop;257// FormPlotColors258FormPlotColors.Left := PlotColorsLeft;259FormPlotColors.Top := PlotColorsTop;260// FormEvaluate261if EvaluateVisible then262FormEvaluate.Show;263FormEvaluate.Left := EvaluateLeft;264FormEvaluate.Top := EvaluateTop;265// FormCoords266if CoordVisible then267FormCoords.Show;268FormCoords.Left := CoordLeft;269FormCoords.Top := CoordTop;270// FormDerivatives271FormDerivatives.Left := DerivLeft;272FormDerivatives.Top := DerivTop;273// FormAddPlotColors274FormAddPlotColors.Left := AddColorsLeft;275FormAddPlotColors.Top := AddColorsTop;276end;277FormFunctions.EditMinX.SetFocus;278except279MessageDlg('File Error! An Error has occurred when attempting to read' +280#13#10'"' + LayoutFName + '".' +281#13#10'The default layout will be used.', mtError, [mbOK], 0);282DefaultLayout;283end;284end285else286DefaultLayout;287
288ShowCameraLocation;289// focallength: right mouse drag up/down290ShowFocalLength;291(* displace origin: x axis: ctrl/left mouse drag left/right292y axis: alt/left mouse drag up/down
293z axis: ctrl/left mouse drag up/down *)
294ShowDisplacement;295(* move light: x axis: ctrl right mouse drag left/right296y axis: alt right mouse drag up/down
297z axis: ctrl right mouse drag up/down *)
298ShowLightLocation;299
300FormFunctions.ReadAndShowInitialData;301Caption := GraphFName;302Altered := False;303CreateHeightFields(FormFunctions.CheckListBox.Count);304
305ini := TIniFile.Create(RecentFName);306with ini do307try308c := ReadInteger(Name, 'RecentCount', 0);309for i := 0 to c - 1 do310begin311Recent1.Add(TMenuItem.Create(Self));312Recent1.Items[i].Caption := ReadString(Name, IntToStr(i), '');313Recent1.Items[i].OnClick := RecentFilesClick;314end;315finally316Free;317end;318end;319
320procedure TFormPlot2D.FormActivate(Sender: TObject);321begin
322if AtStart then323begin324PlotFunctions;325if FormGridColors.Visible then326FormGridColors.ShowGridColorData;327if FormPlotColors.Visible then328FormPlotColors.ShowPlotColorData;329AtStart := False;330end;331end;332
333procedure TFormPlot2D.FormClose(Sender: TObject; var Action: TCloseAction);334var
335ini: TIniFile;336i: Integer;337begin
338ini := TIniFile.Create(RecentFName);339try340ini.WriteInteger(Name, 'RecentCount', Recent1.Count);341for i := 0 to Recent1.Count - 1 do342ini.WriteString(Name, IntToStr(i), Recent1.Items[i].Caption);343finally344ini.Free;345end;346end;347
348procedure TFormPlot2D.FormDestroy(Sender: TObject);349begin
350while Fields.Count > 0 do351TGLHeightField(Fields.Children[0]).Free;352ClearAddedField;353ClearAddedLines;354end;355
356procedure TFormPlot2D.FormCloseQuery(Sender: TObject; var CanClose: Boolean);357var
358f: File of TLayout;359
360begin
361with Layout do362begin363IsMaximize := (Width >= Screen.Width) and (Height >= Screen.Height);364MainLeft := Left;365MainTop := Top;366MainWidth := Width;367MainHeight := Height;368if GraphFName = '' then369GraphFName := NewFName;370CurrentGraphFName := GraphFName;371CurrentDataPath := DataPath;372CurrentImagePath := ImagePath;373
374// FormFunctions375FuncLeft := FormFunctions.Left;376FuncTop := FormFunctions.Top;377FuncWidth := FormFunctions.Width;378FuncHeight := FormFunctions.Height;379
380// FormGridOptions381GridsVisible := FormGridOptions.Visible;382GridsLeft := FormGridOptions.Left;383GridsTop := FormGridOptions.Top;384
385// FormGridColors386GridColorsLeft := FormGridColors.Left;387GridColorsTop := FormGridColors.Top;388
389// FormPlotColors390PlotColorsLeft := FormPlotColors.Left;391PlotColorsTop := FormPlotColors.Top;392
393// FormEvaluate394EvaluateVisible := FormEvaluate.Visible;395EvaluateLeft := FormEvaluate.Left;396EvaluateTop := FormEvaluate.Top;397
398// FormCoords399CoordVisible := FormCoords.Visible;400CoordLeft := FormCoords.Left;401CoordTop := FormCoords.Top;402
403// FormDerivatives404DerivLeft := FormDerivatives.Left;405DerivTop := FormDerivatives.Top;406if FormDerivatives.Visible then407FormDerivatives.Close;408
409// FormAddPlotColors410AddColorsLeft := FormAddPlotColors.Left;411AddColorsTop := FormAddPlotColors.Top;412if FormAddPlotColors.Visible then413FormAddPlotColors.Close;414end;415
416try417AssignFile(f, LayoutFName);418try419Rewrite(f);420write(f, Layout);421finally422CloseFile(f);423end;424except425MessageDlg('File Error! An Error has occurred' +426#13#10'when attempting to write to "' + LayoutFName + '".', mtError,427[mbOK], 0);428end;429
430if Altered or GridColorsAltered or DerivativeAltered then431begin432case MessageDlg('The current graph''s data has been altered.' +433#13#10'Do you wish to save the alterations ?', mtConfirmation,434[mbYes, mbNo, mbCancel], 0) of435mrYes:436FormFunctions.SaveClick(Sender);437mrCancel:438begin439CanClose := False;440Exit;441end;442end;443end;444end;445
446procedure TFormPlot2D.FormKeyDown(Sender: TObject; var Key: Word;447Shift: TShiftState);448var
449d: Integer;450begin
451d := 0;452case Key of453VK_ADD:454d := -1; // zoom in455VK_SUBTRACT:456d := 1; // zoom out457end;458if Key in [VK_ADD, VK_SUBTRACT] then459begin460Screen.Cursor := crZoom;461GLSViewer.SetFocus;462// each step adjusts target distance by 2.5% another method to zoom in or out463Camera.AdjustDistanceToTarget(Power(1.025, d));464ShowCameraLocation;465end466else467case Key of468VK_HOME, VK_NUMPAD7, 72:469DefaultView; // 'H'/'h' key470(* -> = 39471<- = 37
472^ = 38
473| = 40
474-> and ^ = 33
475<- and | = 35 *)
476end;477Key := 0;478end;479
480procedure TFormPlot2D.FormKeyUp(Sender: TObject; var Key: Word;481Shift: TShiftState);482begin
483Screen.Cursor := crDefault;484end;485
486procedure TFormPlot2D.FormMouseWheel(Sender: TObject; Shift: TShiftState;487WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);488begin
489if (MousePoint.X >= GLSViewer.Left) and490(MousePoint.X <= GLSViewer.Left + GLSViewer.Width) and491(MousePoint.Y >= GLSViewer.Top) and492(MousePoint.Y <= GLSViewer.Top + GLSViewer.Height) then493begin494(*495a wheel step = WheelDelta/300; each step adjusts target distance by 2.5%
496another method to zoom in or out
497*)
498GLSViewer.SetFocus;499Camera.AdjustDistanceToTarget(Power(1.025, WheelDelta / 300));500ShowCameraLocation;501end;502end;503
504procedure TFormPlot2D.GLSViewerMouseDown(Sender: TObject; Button: TMouseButton;505Shift: TShiftState; X, Y: Integer);506begin
507MousePoint.X := X;508MousePoint.Y := Y;509if ssShift in Shift then // Shift key down510begin511if ssLeft in Shift then512Screen.Cursor := crZoom;513end514else if ssCtrl in Shift then // Ctrl key down515begin516if ssLeft in Shift then517Screen.Cursor := crSlidexz518else if ssRight in Shift then519Screen.Cursor := crLightxz;520end521else if ssAlt in Shift then // Alt key down522begin523if ssLeft in Shift then524Screen.Cursor := crSlidezy525else if ssRight in Shift then526Screen.Cursor := crLightxy;527end528else // no shift, ctrl or alt key529begin530if Shift = [ssLeft] then531Screen.Cursor := crRotate532else if Shift = [ssRight] then533Screen.Cursor := crZoom;534end;535end;536
537procedure TFormPlot2D.GLSViewerMouseMove(Sender: TObject; Shift: TShiftState;538X, Y: Integer);539var
540dx, dy: Integer;541
542begin // refer GLScene\Demos\interface\camera\Camera.dpr543if MousePoint.X = MaxInt then // FileOpenDialog is visible544begin545MousePoint.X := X;546Exit;547end;548
549dx := MousePoint.X - X;550dy := MousePoint.Y - Y;551
552if ssShift in Shift then // shift key down553begin554if ssLeft in Shift then // shift - left mouse button555begin556(* dy = a step which adjusts target distance by 1.25%; zoom in or out *)557Camera.AdjustDistanceToTarget(Power(1.0125, dy));558ShowCameraLocation;559end;560end561else if ssCtrl in Shift then // Ctrl key down562begin563if ssLeft in Shift then // Ctrl - left mouse button564begin565TargetCube.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 button572begin573GLLight.Position.z := GLLight.Position.z + dy / 10;574GLLight.Position.X := GLLight.Position.X + dx / 10;575ShowLightLocation;576end;577end578else if ssAlt in Shift then // Alt key down579begin580if ssRight in Shift then // Alt - right mouse button581begin582GLLight.Position.X := GLLight.Position.X + dx / 10;583GLLight.Position.Y := GLLight.Position.Y + dy / 10;584ShowLightLocation;585end586else if ssLeft in Shift then // Alt - left mouse button587begin588TargetCube.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;594end595else // no shift key596begin597if Shift = [ssLeft] then598(* Left mouse button changes camera angle by moving around target *)599begin600Camera.MoveAroundTarget(dy, dx);601ShowCameraLocation;602end;603if Shift = [ssRight] then604begin605(*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 then611Camera.FocalLength := 3000; // max focal length612if Camera.FocalLength < 10 then613Camera.FocalLength := 10; // min focal length614
615ShowFocalLength; // display in statusbar palel616end;617end;618MousePoint.X := X; // update mouse position619MousePoint.Y := Y;620end;621
622procedure TFormPlot2D.GLSViewerMouseUp(Sender: TObject; Button: TMouseButton;623Shift: TShiftState; X, Y: Integer);624begin
625Screen.Cursor := crDefault;626end;627
628procedure TFormPlot2D.New1Click(Sender: TObject);629begin
630FormFunctions.New1Click(Sender);631end;632
633procedure TFormPlot2D.OpenFileClick(Sender: TObject);634begin
635FormFunctions.OpenFileClick(Sender);636end;637
638procedure TFormPlot2D.Save1Click(Sender: TObject);639begin
640FormFunctions.SaveClick(Sender);641end;642
643procedure TFormPlot2D.Saveas1Click(Sender: TObject);644begin
645FormFunctions.SaveAsClick(Sender);646end;647
648procedure TFormPlot2D.ShowCameraLocation;649begin
650StatusBar.Panels[0].Text := 'Camera: ' +651FloatToStrF(Camera.Position.X, ffNumber, 5, 2) + ', ' +652FloatToStrF(Camera.Position.Y, ffNumber, 5, 2) + ', ' +653FloatToStrF(Camera.Position.Z, ffNumber, 5, 2);654end;655
656procedure TFormPlot2D.GridColours1Click(Sender: TObject);657begin
658FormGridColors.Show;659end;660
661procedure TFormPlot2D.CoordText1Click(Sender: TObject);662begin
663FormCoords.Show;664end;665
666procedure TFormPlot2D.ShowFocalLength;667begin
668StatusBar.Panels[1].Text := 'f = ' + FloatToStrF(Camera.FocalLength,669ffNumber, 5, 2);670end;671
672procedure TFormPlot2D.ShowDisplacement;673begin
674StatusBar.Panels[2].Text := 'Displaced: ' +675FloatToStrF(-TargetCube.Position.X, ffNumber, 5, 2) + ', ' +676FloatToStrF(-TargetCube.Position.Y, ffNumber, 5, 2) + ', ' +677FloatToStrF(-TargetCube.Position.Z, ffNumber, 5, 2);678end;679
680procedure TFormPlot2D.Evaluate1Click(Sender: TObject);681begin
682FormEvaluate.Show;683end;684
685procedure TFormPlot2D.ShowLightLocation;686begin
687StatusBar.Panels[3].Text := 'Light: ' +688FloatToStrF(GLLight.Position.X, ffNumber, 5, 2) + ', ' +689FloatToStrF(GLLight.Position.Y, ffNumber, 5, 2) + ', ' +690FloatToStrF(GLLight.Position.Z, ffNumber, 5, 2);691end;692
693procedure TFormPlot2D.Grid1Click(Sender: TObject);694begin
695FormGridOptions.Show;696end;697
698procedure TFormPlot2D.DefaultLayout1Click(Sender: TObject);699begin
700DefaultLayout;701end;702
703procedure TFormPlot2D.DefaultView;704begin
705CameraCube.Position.SetPoint(0, 0, 0);706ShowDisplacement;707Camera.FocalLength := 200;708ShowFocalLength;709Camera.Position.SetPoint(50, 50, 30);710Camera.DepthOfView := 1000;711ShowCameraLocation;712GLLight.Position.SetPoint(50, 50, 50);713ShowLightLocation;714TargetCube.Position.SetPoint(0, 0, 0);715end;716
717procedure TFormPlot2D.RecentFilesClick(Sender: TObject);718begin
719FormFunctions.OpenRecentFile(TMenuItem(Sender).Caption);720end;721
722procedure TFormPlot2D.Exit1Click(Sender: TObject);723begin
724Close;725end;726
727procedure TFormPlot2D.DefaultLayout;728begin
729WindowState := wsNormal;730FormPlot2D.Left := 0;731FormPlot2D.Top := 0;732FormFunctions.Width := 335;733FormFunctions.Height := 387;734FormPlot2D.Width := Screen.Width - FormFunctions.Width + 18;735FormPlot2D.Height := Screen.Height - 40;736FormFunctions.Left := FormPlot2D.Left + FormPlot2D.Width - 14;737FormFunctions.Top := FormPlot2D.Top;738FormGridOptions.Left := FormFunctions.Left + 5;739FormGridOptions.Top := FormFunctions.Top + FormFunctions.Height - 6;740FormEvaluate.Left := FormGridOptions.Left;741FormEvaluate.Top := FormGridOptions.Top + FormGridOptions.Height - 3;742FormEvaluate.Show;743FormGridOptions.Show;744FormGridColors.Left := 20;745FormGridColors.Top := 80;746FormPlotColors.Left := 30;747FormPlotColors.Top := 100;748FormAddPlotColors.Left := 40;749FormAddPlotColors.Top := 120;750FormFunctions.EditMinX.SetFocus;751end;752
753procedure TFormPlot2D.DerivativeOpsClick(Sender: TObject);754begin
755if FormPlotColors.Visible then756FormPlotColors.Close;757PlotColours1.Enabled := False;758DerivativePlotColours1.Enabled := True;759FormDerivatives.Show;760end;761
762procedure TFormPlot2D.DerivativePlotColours1Click(Sender: TObject);763begin
764if FormPlotColors.Visible then765FormPlotColors.Close;766PlotColours1.Enabled := False;767FormAddPlotColors.Show;768end;769
770procedure TFormPlot2D.PlotFunctions;771
772procedure PlotFunction(i: Integer);773begin774with PlotData do775begin776with TGLHeightField(Fields.Children[i]) do777begin778XSamplingScale.Step := xInc;779XSamplingScale.Min := xMin;780XSamplingScale.Max := xMax;781
782YSamplingScale.Step := yInc;783YSamplingScale.Min := yMin;784YSamplingScale.Max := yMax;785
786case ViewMode of787vmAmbient:788ColorMode := hfcmAmbient;789vmAmbientandDiffuse:790ColorMode := hfcmAmbientAndDiffuse;791vmDiffuse:792ColorMode := hfcmDiffuse;793vmEmmision:794ColorMode := hfcmEmission;795vmNone:796ColorMode := hfcmNone;797end;798
799case fxyMode of800fxyFill:801Material.PolygonMode := pmFill;802fxyLines:803Material.PolygonMode := pmLines;804fxyPoints:805Material.PolygonMode := pmPoints;806end;807OnGetHeight := Formulate;808end;809GLSViewer.Refresh; // needed to display each zField data in list810end;811end;812
813var
814i: Integer;815fxyParser: TfxyParser;816PD: TPlotData; // save the current PlotData of selected function817
818begin // PlotFunctions819Screen.Cursor := crHourGlass;820PD := PlotData;821fxyParser := TfxyParser.Create(0, 0);822try823with FormFunctions.CheckListBox do824for i := 0 to Items.Count - 1 do825if Checked[i] then826begin827// an item is checked; get the plot data828PlotData := TPlotDataObject(Items.Objects[i]).Data;829PlotFunction(i);830end;831finally832Screen.Cursor := crDefault;833fxyParser.Destroy;834PlotData := PD; // restor the current PlotData835end;836end;837
838procedure TFormPlot2D.Formulate(const X, Y: Single; var z: Single;839var Color: TGLColorVector; var texPoint: TTexPoint);840var
841e: byte;842MaxZ, MinZ: TGLFloat;843x1, x2, y1, y2, z1, z2: extended;844
845begin
846case AddedData.AddedAs of847AddNone: // no AddedData to plot; just plot the PlotData848begin849z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);850z := z * ViewData.xyGrid.zScale;851with PlotData do852begin853MaxZ := zMax * ViewData.xyGrid.zScale;854MinZ := zMin * ViewData.xyGrid.zScale;855if zCap then856begin857if zLim and (z > MaxZ) then858z := MaxZ;859if zLim and (z < MinZ) then860z := MinZ;861end862else if zLim and ((z < MinZ) or (z > MaxZ)) then863z := NaN;864VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);865end;866end;867
868AddDerivX: // this is for partial derivative wrt x869begin870x1 := X - AddedData.xInc;871x2 := X + AddedData.xInc;872z1 := ParseEvaluateFxy(x1, Y, SelectedData.fxyStr, e);873// evaluate z1,x1,y874z2 := ParseEvaluateFxy(x2, Y, SelectedData.fxyStr, e);875// evaluate z2,x2,y876z := (z2 - z1) / (x2 - x1); // z = slope wrt x axis877z := z * ViewData.xyGrid.zScale;878with AddedData do879begin880MaxZ := zMax * ViewData.xyGrid.zScale;881MinZ := zMin * ViewData.xyGrid.zScale;882if zCap then883begin884if zLim and (z > MaxZ) then885z := MaxZ;886if zLim and (z < MinZ) then887z := MinZ;888end889else if zLim and ((z < MinZ) or (z > MaxZ)) then890z := NaN;891VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);892end;893end;894
895AddDerivY: // this is for partial derivative wrt y896begin897y1 := Y - AddedData.yInc;898y2 := Y + AddedData.yInc;899z1 := ParseEvaluateFxy(X, y1, SelectedData.fxyStr, e);900// evaluate z1,x,y1901z2 := ParseEvaluateFxy(X, y2, SelectedData.fxyStr, e);902// evaluate z2,x,y2903z := (z2 - z1) / (y2 - y1); // z = slope wrt y axis904z := z * ViewData.xyGrid.zScale;905with AddedData do906begin907MaxZ := zMax * ViewData.xyGrid.zScale;908MinZ := zMin * ViewData.xyGrid.zScale;909if zCap then910begin911if zLim and (z > MaxZ) then912z := MaxZ;913if zLim and (z < MinZ) then914z := MinZ;915end916else if zLim and ((z < MinZ) or (z > MaxZ)) then917z := NaN;918VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);919end;920end;921
922AddVolume: // this is for double integral923begin924z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);925with AddedData do926begin927z := z * ViewData.xyGrid.zScale;928MaxZ := zMax * ViewData.xyGrid.zScale;929MinZ := zMin * ViewData.xyGrid.zScale;930if zCap then931begin932if zLim and (z > MaxZ) then933z := MaxZ;934if zLim and (z < MinZ) then935z := MinZ;936end937else if zLim and ((z < MinZ) or (z > MaxZ)) then938z := NaN;939VectorLerp(LowerColor, UpperColor, z * ColorBlend - ColorMove, Color);940
941TGLLines.CreateAsChild(VolumeLines);942with VolumeLines do943begin944with TGLLines(Children[Count - 1]) do945begin946LineColor.AsWinColor := AddLineColor;947LineWidth := AddLineWidth;948NodesAspect := LnaInvisible;949
950Nodes.Add;951Nodes[0].X := X; // start point952Nodes[0].Y := Y;953if zLim then954Nodes[0].z := MinZ955else956Nodes[0].z := 0;957
958Nodes.Add;959Nodes[1].X := X; // end point960Nodes[1].Y := Y;961Nodes[1].z := z;962end;963end;964end;965end;966end; // case AddedData.AddedAs of...967end;968
969procedure TFormPlot2D.PlotDerivativeField;970var
971i: Integer;972FoundSelected: Boolean;973
974begin
975Screen.Cursor := crHourGlass;976try977i := 0;978if FormFunctions.CheckListBox.Count > 1 then // find Selected item979begin980FoundSelected := False;981while not FoundSelected and (i < FormFunctions.CheckListBox.Count) do982begin983FoundSelected := FormFunctions.CheckListBox.Selected[i];984if not FoundSelected then985Inc(i);986end;987end;988
989with FormFunctions.CheckListBox do990SelectedData := TPlotDataObject(Items.Objects[i]).Data;991
992with AddedData do993begin994with TGLHeightField(AddedField.Children[0]) do995begin996with XSamplingScale do997begin998Step := xInc;999Min := xMin;1000Max := xMax;1001end;1002
1003with YSamplingScale do1004begin1005Step := yInc;1006Min := yMin;1007Max := yMax;1008end;1009
1010case ViewMode of1011vmAmbient:1012ColorMode := hfcmAmbient;1013vmAmbientandDiffuse:1014ColorMode := hfcmAmbientAndDiffuse;1015vmDiffuse:1016ColorMode := hfcmDiffuse;1017vmEmmision:1018ColorMode := hfcmEmission;1019vmNone:1020ColorMode := hfcmNone;1021end;1022
1023case fxyMode of1024fxyFill:1025Material.PolygonMode := pmFill;1026fxyLines:1027Material.PolygonMode := pmLines;1028fxyPoints:1029Material.PolygonMode := pmPoints;1030end;1031OnGetHeight := Formulate;1032end;1033GLSViewer.Refresh; // needed to display each zField data in list1034end;1035finally1036Screen.Cursor := crDefault;1037end;1038end;1039
1040procedure TFormPlot2D.PlotIntegralField;1041procedure PlotVolume;1042begin // PlotVolume1043with AddedData do1044begin1045with TGLHeightField(AddedField.Children[0]) do1046begin1047with XSamplingScale do1048begin1049Step := xInc;1050Min := xMin;1051Max := xMax;1052end;1053
1054with YSamplingScale do1055begin1056Step := yInc;1057Min := yMin;1058Max := yMax;1059end;1060
1061case ViewMode of1062vmAmbient:1063ColorMode := hfcmAmbient;1064vmAmbientandDiffuse:1065ColorMode := hfcmAmbientAndDiffuse;1066vmDiffuse:1067ColorMode := hfcmDiffuse;1068vmEmmision:1069ColorMode := hfcmEmission;1070vmNone:1071ColorMode := hfcmNone;1072end;1073
1074case fxyMode of1075fxyFill:1076Material.PolygonMode := pmFill;1077fxyLines:1078Material.PolygonMode := pmLines;1079fxyPoints:1080Material.PolygonMode := pmPoints;1081end;1082OnGetHeight := Formulate;1083end;1084GLSViewer.Refresh; // needed to display each zField data in list1085end;1086end; // PlotVolume1087
1088procedure CalculateVolume;1089var1090e: byte;1091i, j, iCount, jCount: Integer;1092X, Y, z, x0, y0, a, VolPos, VolNeg: TGLFloat;1093
1094begin // CalculateVolume1095with AddedData do1096begin1097a := xInc * yInc; // base area1098iCount := round((xMax - xMin) / xInc) - 1; // number of x points1099jCount := round((yMax - yMin) / yInc) - 1; // number of y points1100VolPos := 0;1101VolNeg := 0;1102x0 := xMin + xInc / 2; // base centre x01103y0 := yMin + yInc / 2; // base centre y01104for j := 0 to jCount do1105begin1106Y := y0 + j * yInc; // next column wrt y1107for i := 0 to iCount do1108begin1109X := x0 + i * xInc; // next column wrt x1110z := ParseEvaluateFxy(X, Y, PlotData.fxyStr, e);1111
1112if zLim then // zLimit applied1113begin1114if (zMax >= 0) and (zMin <= 0) then // above and below zero1115begin1116if z > 0 then1117begin1118if z > zMax then1119VolPos := VolPos + a * zMax1120else1121VolPos := VolPos + a * z;1122end1123else1124begin1125if z < zMin then1126VolNeg := VolNeg + a * zMin1127else1128VolNeg := VolNeg + a * z;1129end;1130end1131else if zMin > 0 then // both above zero1132begin1133if z >= zMin then1134begin1135if z > zMax then1136VolPos := VolPos + a * (zMax - zMin)1137else1138VolPos := VolPos + a * (z - zMin);1139end;1140end1141else if zMax < 0 then // both below zero1142begin1143if z <= zMax then1144begin1145if z < zMin then1146VolNeg := VolNeg + a * (zMax - zMin)1147else1148VolNeg := VolNeg + a * (z - zMax);1149end;1150end;1151end1152else // no zLimit applied1153begin1154if z > 0 then1155VolPos := VolPos + a * z1156else1157VolNeg := VolNeg + a * z;1158end;1159end;1160end;1161end;1162
1163with FormDerivatives do1164begin1165PosVolLabel.Caption := 'Positive Volume: ' + FloatToStr(VolPos);1166NegVolLabel.Caption := 'Negative Volume: ' + FloatToStr(VolNeg);1167TotalLabel.Caption := 'Absolute Volume: ' + FloatToStr(VolPos - VolNeg);1168VolumeLabel.Caption := 'Total Volume: ' + FloatToStr(VolPos + VolNeg);1169end;1170end; // CalculateVolume1171
1172begin // TFormPlot2D.PlotIntegralField1173Screen.Cursor := crHourGlass;1174with AddedData do1175begin1176PlotVolume;1177CalculateVolume;1178end;1179FormDerivatives.VolumeRB.Checked := False; //1180Screen.Cursor := crDefault;1181end; // TFormPlot2D.PlotIntegralField1182
1183procedure TFormPlot2D.PlotColours1Click(Sender: TObject);1184begin
1185FormPlotColors.Show;1186end;1187
1188procedure TFormPlot2D.CreateHeightFields(const n: Integer);1189var
1190i: Integer;1191
1192begin
1193while Fields.Count > 0 do1194TGLHeightField(Fields.Children[0]).Free;1195for i := 0 to n - 1 do1196begin1197TGLHeightField.CreateAsChild(Fields);1198TGLHeightField(Fields.Children[Fields.Count - 1]).Material.BlendingMode :=1199bmTransparency;1200end;1201end;1202
1203procedure TFormPlot2D.CreateAddedField;1204begin
1205ClearAddedField;1206TGLHeightField.CreateAsChild(AddedField);1207TGLHeightField(AddedField.Children[0]).Material.BlendingMode :=1208bmTransparency;1209end;1210
1211procedure TFormPlot2D.UpdatePlot;1212begin
1213CreateHeightFields(FormFunctions.CheckListBox.Count);1214PlotFunctions;1215end;1216
1217procedure TFormPlot2D.UpdateAdded;1218begin
1219CreateAddedField;1220AddXLine.LineColor.AsWinColor := AddedData.AddLineColor;1221AddYLine.LineColor.AsWinColor := AddedData.AddLineColor;1222AddZLine.LineColor.AsWinColor := AddedData.AddLineColor;1223AddXLine.LineWidth := AddedData.AddLineWidth;1224AddYLine.LineWidth := AddedData.AddLineWidth;1225AddZLine.LineWidth := AddedData.AddLineWidth;1226if AddedData.AddedAs = AddVolume then1227PlotIntegralField
1228else1229PlotDerivativeField;1230end;1231
1232procedure TFormPlot2D.About1Click(Sender: TObject);1233begin
1234FormAbout.Show;1235end;1236
1237procedure TFormPlot2D.ClearAddedField;1238begin
1239with TGLHeightField(AddedField) do1240if Count > 0 then1241Children[0].Free;1242end;1243
1244procedure TFormPlot2D.ClearAddedLines;1245begin
1246Screen.Cursor := crHourGlass;1247with TGLLines(VolumeLines) do1248while Count > 0 do1249Children[Count - 1].Free;1250Screen.Cursor := crDefault;1251end;1252
1253end.1254