MathgeomGLS
265 строк · 6.7 Кб
1unit FMain;
2
3interface
4
5uses
6Winapi.OpenGL,
7Winapi.Windows,
8Winapi.Messages,
9System.Math,
10System.SysUtils,
11System.UITypes,
12System.Variants,
13System.Classes,
14Vcl.Graphics,
15Vcl.Controls,
16Vcl.Forms,
17Vcl.Dialogs,
18Vcl.StdCtrls,
19Vcl.ExtCtrls,
20Vcl.Menus,
21
22GLS.PersistentClasses,
23GLS.VectorTypes,
24GLS.Scene,
25GLS.State,
26GLS.VectorTypesExt,
27GLS.SceneViewer,
28GLS.Objects,
29GLS.VectorFileObjects,
30GLS.VectorGeometry,
31GLS.Coordinates,
32
33GLS.BaseClasses,
34GLS.IsosurFace,
35GLS.Spline,
36Vcl.Mask;
37
38type
39TFrmMain = class(TForm)
40GLSceneViewer: TGLSceneViewer;
41GLScene: TGLScene;
42OpenDialog: TOpenDialog;
43Camera: TGLCamera;
44dcBox: TGLDummyCube;
45PUSerInterface: TPanel;
46ffCube: TGLFreeForm;
47Label1: TLabel;
48Label2: TLabel;
49lblVertices: TLabel;
50lblTriangles: TLabel;
51LEXDim: TLabeledEdit;
52LEYDim: TLabeledEdit;
53LEZDim: TLabeledEdit;
54LEIsoVal: TLabeledEdit;
55rbgAlgorithm: TRadioGroup;
56MainMenu: TMainMenu;
57File1: TMenuItem;
58miFileOpen: TMenuItem;
59miFileExit: TMenuItem;
60N3: TMenuItem;
61Light: TGLLightSource;
62rbgSurface: TRadioGroup;
63procedure FormCreate(Sender: TObject);
64procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
65WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
66procedure GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton;
67Shift: TShiftState; X, Y: Integer);
68procedure GLSceneViewerMouseMove(Sender: TObject; Shift: TShiftState;
69X, Y: Integer);
70procedure miFileOpenClick(Sender: TObject);
71procedure miFileExitClick(Sender: TObject);
72procedure rbgAlgorithmClick(Sender: TObject);
73procedure rbgSurfaceClick(Sender: TObject);
74private
75ExtractedVertices: TVertexArray; // array of TVertex
76ExtractedTriangles: TIntegerArray; // array of Integer
77Dimensions: array ['x' .. 'z'] of Word;
78
79ExtendedData: TArray3DExt; // array of array of array of Single
80mdx, mdy: Integer;
81
82// Load Data from file
83function LoadCharData(AFileName: String; out ADataout: TArray3DExt;
84var Dims: array of word): Integer;
85public
86{ Public-Deklarationen }
87end;
88
89var
90FrmMain: TFrmMain;
91
92implementation
93
94{$R *.dfm}
95
96procedure TFrmMain.FormCreate(Sender: TObject);
97begin
98ExtendedData := nil;
99end;
100
101function TFrmMain.LoadCharData(AFileName: String; out ADataout: TArray3DExt;
102var Dims: array of word): Integer;
103var
104DataFile: File of Byte;
105i, j, k: Integer;
106DataPoint: Byte;
107Counter: Integer;
108begin
109AssignFile(DataFile, AFileName);
110Reset(DataFile);
111
112SetLength(ADataout, Dims[0], Dims[1], Dims[2]);
113
114i := 0;
115j := 0;
116k := 0;
117Counter := 0;
118try
119repeat
120Read(DataFile, DataPoint);
121ADataout[i, j, k] := DataPoint;
122inc(i);
123if (i = Dims[0]) then
124begin
125i := 0;
126inc(j);
127end;
128if (j = Dims[1]) then
129begin
130j := 0;
131inc(k);
132end;
133inc(Counter);
134until Eof(DataFile);
135finally
136Closefile(DataFile);
137end;
138Result := Counter;
139end;
140
141procedure TFrmMain.miFileOpenClick(Sender: TObject);
142var
143DataAmount: cardinal;
144begin
145Dimensions['x'] := StrToInt(LEXDim.Text);
146Dimensions['y'] := StrToInt(LEYDim.Text);
147Dimensions['z'] := StrToInt(LEZDim.Text);
148OpenDialog.InitialDir := ExtractFilePath(ParamStr(0));
149OpenDialog.Filter := 'Volumes|*.vol';
150if OpenDialog.Execute() then
151begin
152DataAmount := LoadCharData(OpenDialog.FileName, ExtendedData, Dimensions);
153MessageDlg(format('%d read. %dx%dx%d', [DataAmount, Dimensions['x'],
154Dimensions['y'], Dimensions['z']]), mtInformation, [mbOK], -1);
155LEXDim.Text := Format('%d', [Dimensions['x']]);
156LEYDim.Text := Format('%d', [Dimensions['y']]);
157LEZDim.Text := Format('%d', [Dimensions['z']]);
158end;
159rbgAlgorithmClick(Self);
160rbgSurfaceClick(Self);
161end;
162
163procedure TFrmMain.rbgAlgorithmClick(Sender: TObject);
164var
165IsoSurfaceEx: TGLIsoSurfaceExtractor;
166i: Integer;
167mo: TGLMeshObject;
168
169begin
170// Create IsoSurfaceExtractor
171IsoSurfaceEx := TGLIsoSurfaceExtractor.Create(Dimensions['x'], Dimensions['y'],
172Dimensions['z'], ExtendedData);
173// Launch Calculation
174case rbgAlgorithm.ItemIndex of
1750:
176IsoSurfaceEx.MarchingTetrahedra(StrToFloat(LEIsoVal.Text), ExtractedVertices,
177ExtractedTriangles, False);
1781:
179IsoSurfaceEx.MarchingCubes(StrToFloat(LEIsoVal.Text), ExtractedVertices,
180ExtractedTriangles, False);
181end;
182
183lblVertices.Caption := Format('%d', [Length(ExtractedVertices)]);
184lblTriangles.Caption := Format('%d', [Length(ExtractedTriangles) div 3]);
185IsoSurfaceEx.Free();
186
187ffCube.MeshObjects.Clear();
188mo := TGLMeshObject.CreateOwned(ffCube.MeshObjects);
189for i := 0 to Length(ExtractedTriangles) - 1 do
190mo.Vertices.Add(AffineVectorMake(ExtractedVertices[ExtractedTriangles[i]].X
191- Dimensions['x'] / 2, ExtractedVertices[ExtractedTriangles[i]].Y -
192Dimensions['y'] / 2, ExtractedVertices[ExtractedTriangles[i]].Z -
193Dimensions['z'] / 2));
194ffCube.StructureChanged();
195
196GLSceneViewer.Invalidate();
197end;
198
199procedure TFrmMain.rbgSurfaceClick(Sender: TObject);
200begin
201if rbgSurface.ItemIndex = 0 then
202ffCube.Material.PolygonMode := pmFill
203else
204ffCube.Material.PolygonMode := pmLines;
205GLSceneViewer.Invalidate();
206end;
207
208procedure TFrmMain.miFileExitClick(Sender: TObject);
209begin
210SetLength(ExtendedData, 0, 0, 0);
211Application.Terminate();
212end;
213
214procedure TFrmMain.FormMouseWheel(Sender: TObject; Shift: TShiftState;
215WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
216begin
217Camera.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
218end;
219
220procedure TFrmMain.GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton;
221Shift: TShiftState; X, Y: Integer);
222begin
223mdx := X;
224mdy := Y;
225end;
226
227procedure TFrmMain.GLSceneViewerMouseMove(Sender: TObject; Shift: TShiftState;
228X, Y: Integer);
229
230var
231dx, dy: Integer;
232v: TGLVector;
233begin
234// calculate delta since last move or last mousedown
235dx := mdx - X;
236dy := mdy - Y;
237mdx := X;
238mdy := Y;
239if ssLeft in Shift then
240begin
241if ssShift in Shift then
242begin
243// right button with shift rotates the teapot
244// (rotation happens around camera's axis)
245Camera.RotateObject(dcBox, dy, dx);
246end
247else
248begin
249// right button without shift changes camera angle
250// (we're moving around the parent and target dummycube)
251Camera.MoveAroundTarget(dy, dx)
252end;
253end
254else if Shift = [ssRight] then
255begin
256// left button moves our target and parent dummycube
257v := Camera.ScreenDeltaToVectorXY(dx, -dy,
2580.12 * Camera.DistanceToTarget / Camera.FocalLength);
259dcBox.Position.Translate(v);
260// notify camera that its position/target has been changed
261Camera.TransformationChanged;
262end;
263end;
264
265end.
266