MathgeomGLS
428 строк · 10.4 Кб
1unit fdGraphVol;
2
3interface
4
5uses
6Winapi.OpenGL,
7System.SysUtils,
8System.Variants,
9System.Classes,
10System.Types,
11System.Math,
12Vcl.Graphics,
13Vcl.Controls,
14Vcl.Forms,
15Vcl.Dialogs,
16Vcl.StdCtrls,
17Vcl.ComCtrls,
18Vcl.ToolWin,
19Vcl.ExtCtrls,
20
21GLS.Scene,
22GLS.Objects,
23GLS.Coordinates,
24GLS.VectorLists,
25GLS.SceneViewer,
26GLS.Nodes,
27GLS.BaseClasses,
28GLS.HUDObjects,
29GLS.BitmapFont,
30GLS.WindowsFont,
31GLS.RenderContextInfo,
32GLS.VectorGeometry,
33GLS.VectorTypes,
34GLS.Cadencer,
35GLS.Color,
36GLS.FileTGA,
37GLS.Graph;
38
39type
40// ñòðàííàÿ òî÷êà ãðàôà, áåç Y
41T_Point = record
42X, Z: single;
43id: Integer;
44sub: array [0 .. 9] of single;
45end;
46
47type
48TFormGrafvol = class(TForm)
49Memo1: TMemo;
50GLScene: TGLScene;
51GLSceneViewer: TGLSceneViewer;
52cam: TGLCamera;
53dcWorld: TGLDummyCube;
54dogl: TGLDirectOpenGL;
55sprite: TGLHUDSprite;
56txt1: TGLHUDText;
57GLWinBitFont: TGLWindowsBitmapFont;
58GLCadencer: TGLCadencer;
59Lines1: TGLLines;
60Lines2: TGLLines;
61Panel1: TPanel;
62Button1: TButton;
63Button2: TButton;
64Button3: TButton;
65Button4: TButton;
66grid1: TGLXYZGrid;
67grid2: TGLXYZGrid;
68txt2: TGLHUDText;
69pts: TGLPoints;
70cam_XY: TGLCamera;
71cam_XZ: TGLCamera;
72cam_YZ: TGLCamera;
73procedure FormCreate(Sender: TObject);
74procedure doglRender(Sender: TObject; var rci: TGLRenderContextInfo);
75procedure GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton;
76Shift: TShiftState; X, Y: Integer);
77procedure GLSceneViewerMouseUp(Sender: TObject; Button: TMouseButton;
78Shift: TShiftState; X, Y: Integer);
79procedure GLCadencerProgress(Sender: TObject;
80const deltaTime, newTime: Double);
81procedure Button1Click(Sender: TObject);
82procedure Button2Click(Sender: TObject);
83procedure Button3Click(Sender: TObject);
84procedure Button4Click(Sender: TObject);
85public
86procedure LoadData(aFileName: TFileName);
87private
88f, len: single;
89fs: TFormatSettings;
90p_cnt: Integer;
91m_turn: boolean; // = false;
92m_pos: TPoint;
93mx, my: Integer;
94points: array of T_Point; // âåðøèíû 3d ãðàôà
95PointFs: array of TPointF; // ìàññèâ âåðøèí 3d ãðàôà, â ïåðñïåêòèâå
96function _Getpid(s: string): TPoint;
97end;
98
99var
100FormGrafvol: TFormGrafvol;
101
102implementation // -------------------------------------------------------------
103
104{$R *.dfm}
105
106//
107// FormCreate
108//
109procedure TFormGrafvol.FormCreate;
110begin
111LoadData('data\datas');
112end;
113
114//
115// Îïðåäåëåíèå òî÷êè âåðøèíû â ìàññèâå äàííûõ
116//
117function TFormGrafvol._Getpid(s: string): TPoint;
118var
119f: single;
120Point: TPoint;
121begin
122f := StrToFloat(s, fs);
123Point.X := Round(f) - 1;
124Point.Y := Round((f - Round(f)) * 100);
125Result := Point;
126end;
127
128//
129// Çàãðóçêà äàííûõ
130//
131procedure TFormGrafvol.LoadData(aFileName: TFileName);
132const
133c: array [1 .. 4] of cardinal = ($222222, $FF2222, $0000FF, $00FF00);
134var
135s, t, u: TStringList;
136pi, li, pc, i, j, k: Integer;
137p1, p2, p3: TPoint;
138v1, v2, v3: TVector3f;
139begin
140if not fileexists(aFileName) then
141exit;
142s := TStringList.Create;
143s.LoadFromFile(aFileName);
144pi := s.IndexOf('[points]');
145li := s.IndexOf('[links]');
146if (pi < 0) or (li < 0) then
147begin
148s.Free;
149exit;
150end;
151t := TStringList.Create;
152u := TStringList.Create;
153fs.DecimalSeparator := '.'; // ðàçäåëèòåëü òî÷êà
154// ïàðñèíã âåðøèí
155pc := 0;
156for i := pi + 1 to li - 1 do
157if Length(s[i]) > 7 then
158inc(pc);
159SetLength(points, pc);
160SetLength(PointFs, pc); // ïîêà íå èñïîëüçóåòñÿ
161p_cnt := 0;
162for i := 0 to pc - 1 do
163begin
164// ïîäãîòîâêà ìàññèâà
165for j := 0 to high(points[i].sub) do
166if j = 0 then
167points[i].sub[j] := 0
168else
169points[i].sub[j] := 9999;
170(*
171for j := 0 to high(PointFs[i].sub) do
172if j = 0 then
173PointFs[i].sub[j] := 0
174else
175PointFs[i].sub[j] := 9999;
176*)
177t.Text := stringReplace(s[i + pi + 1], ' ', #13#10, [rfReplaceAll]);
178// ïðèñâîåíèå çíà÷åíèé âåðøèíàì
179for j := 0 to t.Count - 1 do
180begin
181u.Text := stringReplace(t[j], ',', #13#10, [rfReplaceAll]);
182if u.Count = 3 then
183begin
184points[i].id := _Getpid(u[0]).X;
185points[i].X := StrToFloat(u[1], fs);
186points[i].Z := StrToFloat(u[2], fs);
187inc(p_cnt);
188end
189else
190begin
191points[i].sub[_Getpid(u[0]).Y] := StrToFloat(u[1], fs);
192inc(p_cnt);
193end;
194end;
195end;
196
197// óñòàíîâëåíèå ñâÿçè ñ ëèíèÿìè
198Lines1.Nodes.Clear;
199Lines2.Nodes.Clear;
200pts.Positions.Clear;
201pts.Colors.Clear;
202f := 0.11;
203for i := li + 1 to min(s.Count - 1, li + 5) do
204begin
205t.Text := stringReplace(s[i], ' ', #13#10, [rfReplaceAll]);
206for j := 0 to t.Count - 1 do
207if Length(t[j]) = 9 then
208begin
209u.Text := stringReplace(t[j], ':', #13#10, [rfReplaceAll]);
210p1 := _Getpid(u[0]);
211p2 := _Getpid(u[1]);
212if (points[p1.X].sub[p1.Y] = 9999) or (points[p2.X].sub[p2.Y] = 9999)
213then
214Continue;
215if points[p2.X].sub[p2.Y] > points[p1.X].sub[p1.Y] then
216begin
217p3 := p2;
218p2 := p1;
219p1 := p3;
220end;
221SetVector(v1, points[p1.X].X, points[p1.X].sub[p1.Y], points[p1.X].Z);
222// âåðøèíû âûøå è íèæå
223if (points[p2.X].sub[p2.Y] < 0) and (points[p1.X].sub[p1.Y] >= 0) then
224begin
225SetVector(v3, points[p2.X].X, points[p2.X].sub[p2.Y], points[p2.X].Z);
226// intersection with zero plane
227v2 := VectorLerp(v1, v3, -v1.Y / (v3.Y - v1.Y));
228pts.Positions.Add(v2);
229pts.Colors.Add(ConvertWinColor(c[i - li - 1]));
230
231len := vectorDistance(v2, v3);
232Lines2.Nodes.AddNode(v2);
233TGLLinesNode(Lines2.Nodes.Last).Color.AsWinColor := c[i - li - 1];
234Lines2.Nodes.AddNode(VectorLerp(v2, v3, 1 - f / len));
235TGLLinesNode(Lines2.Nodes.Last).Color.AsWinColor := c[i - li - 1];
236
237len := vectorDistance(v1, v2);
238Lines1.Nodes.AddNode(VectorLerp(v1, v2, f / len));
239TGLLinesNode(Lines1.Nodes.Last).Color.AsWinColor := c[i - li - 1];
240Lines1.Nodes.AddNode(v2);
241TGLLinesNode(Lines1.Nodes.Last).Color.AsWinColor := c[i - li - 1];
242end
243else
244begin
245SetVector(v2, points[p2.X].X, points[p2.X].sub[p2.Y], points[p2.X].Z);
246// îáå âåðøèíû íèæå
247if (points[p2.X].sub[p2.Y] < 0) and (points[p1.X].sub[p1.Y] < 0) then
248begin
249len := vectorDistance(v1, v2);
250Lines2.Nodes.AddNode(VectorLerp(v1, v2, f / len));
251TGLLinesNode(Lines2.Nodes.Last).Color.AsWinColor := c[i - li - 1];
252
253Lines2.Nodes.AddNode(VectorLerp(v1, v2, 1 - f / len));
254TGLLinesNode(Lines2.Nodes.Last).Color.AsWinColor := c[i - li - 1];
255end
256// îáå âåðøèíû âûøå
257else
258begin
259len := vectorDistance(v1, v2);
260Lines1.Nodes.AddNode(VectorLerp(v1, v2, f / len));
261TGLLinesNode(Lines1.Nodes.Last).Color.AsWinColor := c[i - li - 1];
262Lines1.Nodes.AddNode(VectorLerp(v1, v2, 1 - f / len));
263TGLLinesNode(Lines1.Nodes.Last).Color.AsWinColor := c[i - li - 1];
264end;
265end;
266end;
267end;
268s.Free;
269t.Free;
270u.Free;
271end;
272
273//
274// vpMouseDown
275//
276procedure TFormGrafvol.GLSceneViewerMouseDown;
277begin
278if Shift = [ssleft] then
279begin
280m_turn := True;
281m_pos := mouse.CursorPos;
282end;
283end;
284
285//
286// vpMouseUp
287//
288procedure TFormGrafvol.GLSceneViewerMouseUp;
289begin
290m_turn := False;
291end;
292
293//
294// cadProgress
295//
296procedure TFormGrafvol.GLCadencerProgress;
297begin
298if m_turn and (GLSceneViewer.Camera = cam) then
299begin
300with mouse.CursorPos do
301cam.MoveAroundTarget(m_pos.Y - Y, m_pos.X - X);
302
303m_pos := mouse.CursorPos;
304end;
305pts.Visible := GLSceneViewer.Camera = cam;
306
307Lines1.Visible := pts.Visible;
308Lines2.Visible := pts.Visible;
309grid1.Visible := pts.Visible;
310grid2.Visible := pts.Visible;
311end;
312
313//
314// doglRender
315//
316procedure TFormGrafvol.doglRender;
317var
318i, j, k: Integer;
319v: TGLVector;
320a1: array of record id, sub: Integer;
321sx, sy, depth: single;
322end;
323
324(* sub *) procedure shellSort;
325var
326i, j, k, n: Integer;
327f: single;
328begin
329k := high(a1) div 2;
330while k > 0 do
331begin
332for i := 0 to high(a1) - k do
333begin
334j := i;
335while (j >= 0) and (a1[j].depth < a1[j + k].depth) do
336begin
337n := a1[j].id;
338a1[j].id := a1[j + k].id;
339a1[j + k].id := n;
340n := a1[j].sub;
341a1[j].sub := a1[j + k].sub;
342a1[j + k].sub := n;
343f := a1[j].sx;
344a1[j].sx := a1[j + k].sx;
345a1[j + k].sx := f;
346f := a1[j].sy;
347a1[j].sy := a1[j + k].sy;
348a1[j + k].sy := f;
349f := a1[j].depth;
350a1[j].depth := a1[j + k].depth;
351a1[j + k].depth := f;
352if j > k then
353Dec(j, k)
354else
355j := 0;
356end;
357end;
358k := k div 2
359end;
360end;
361
362begin
363SetLength(a1, p_cnt);
364k := 0;
365for i := 0 to High(points) do
366for j := 0 to High(points[i].sub) do
367begin
368if points[i].sub[j] = 9999 then
369Continue;
370
371a1[k].id := points[i].id + 1;
372a1[k].sub := j;
373
374// ïîëîæåíèå è ðàññòîÿíèå äî êàìåðû
375with points[i] do
376SetVector(v, X, sub[j], Z);
377a1[k].depth := vectorNorm(vectorSubtract(v, cam.AbsolutePosition));
378
379// ïîçèöèÿ âåðøèíû â ýêðàííûõ êîîðäèíàòàõ
380v := GLSceneViewer.Buffer.WorldToScreen(v);
381a1[k].sx := v.X;
382a1[k].sy := GLSceneViewer.Height - v.Y;
383inc(k);
384end;
385
386// ñîðòèðîâêà ðàññòîÿíèé äî êàìåðû
387shellSort;
388for i := 0 to p_cnt - 1 do
389with a1[i] do
390begin
391sprite.Position.SetPoint(sx, sy, 0);
392sprite.Render(rci);
393txt1.Position.SetPoint(sx - 2, sy, 0);
394txt1.Text := IntToStr(id);
395txt1.Render(rci);
396
397if sub > 0 then
398begin
399txt2.Position.SetPoint(sx + GLWinBitFont.TextWidth(txt1.Text) / 2 + 1,
400sy - GLWinBitFont.CharHeight / 2 + 7, 0);
401txt2.Text := IntToStr(sub);
402txt2.Render(rci);
403end;
404end;
405end;
406
407// --------------------------------------------------------------------
408procedure TFormGrafvol.Button1Click(Sender: TObject);
409begin
410GLSceneViewer.Camera := cam_XY;
411end;
412
413procedure TFormGrafvol.Button2Click(Sender: TObject);
414begin
415GLSceneViewer.Camera := cam_XZ
416end;
417
418procedure TFormGrafvol.Button3Click(Sender: TObject);
419begin
420GLSceneViewer.Camera := cam_YZ;
421end;
422
423procedure TFormGrafvol.Button4Click(Sender: TObject);
424begin
425GLSceneViewer.Camera := cam;
426end;
427
428end.
429