ArenaZ
1447 строк · 46.2 Кб
1unit uMainForm;
2
3{$mode objfpc}{$H+}
4{$INLINE ON}
5{$MODESWITCH ADVANCEDRECORDS}
6
7interface
8
9uses
10Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
11Menus, StdCtrls, ComCtrls, GLVectorTypes, GLVectorGeometry, GLGeomObjects,
12GLObjects, GLScene, GLLCLViewer, GLMaterial, GLCadencer, GLColor,
13GLBitmapFont, GLWindowsFont, GLHUDObjects, GLGraph, uNavCube, GLZArrayClasses,
14Types;
15
16
17// Simple MOL2 Tag Format description
18Const
19MOL2_MOLECULE_HEADER = '@<TRIPOS>MOLECULE';
20MOL2_ATOM_HEADER = '@<TRIPOS>ATOM';
21MOL2_BOND_HEADER = '@<TRIPOS>BOND';
22MOL2_SUBSTR_HEADER = '@<TRIPOS>SUBSTRUCTURE';
23
24Const
25cAtomBondingTypeStr : array[1..4] of String =
26('diatomic',
27'atomic',
28'metallic',
29'covalent network');
30
31cAtomGroupBlockStr : array[1..11] of string =
32('nonmetal',
33'noble gas',
34'alkali metal',
35'alkaline earth metal',
36'metalloid',
37'halogen',
38'transition metal',
39'metal',
40'lanthanoid',
41'actinoid',
42'post-transition metal');
43
44cAtomStandardStateStr : array[1..3] of String =
45('Gaz',
46'Liquid',
47'Solid'
48);
49type
50// https://github.com/andrejewski/periodic-table/blob/master/data.csv
51// et une plus complète https://gist.githubusercontent.com/GoodmanSciences/c2dd862cd38f21b0ad36b8f96b4bf1ee/raw/1d92663004489a5b6926e944c1b3d9ec5c40900e/Periodic%2520Table%2520of%2520Elements.csv
52TAtomData = Record // Données dans l'ordre de taille des propriétés
53atomicNumber : Byte;
54atomicRadius : Byte;
55standardState : Byte;
56symbol : String[2];
57ionizationEnergy : Integer;
58electronAffinity : Integer;
59meltingPoint : Integer;
60boilingPoint : Integer;
61
62bondingType : Integer;
63electronegativity : Double; // Extend
64vanDelWaalsRadius : Double; // Extend
65density : Double; // Extend
66atomicMass : String; // Extend
67cpkColor : String; //TColorVector;
68name : String;
69electronicConfiguration : String;
70ionRadius : String;
71oxidationStates : String;
72groupBlock : String;
73yearDiscovered : String; //Integer;
74end;
75
76TMoleculeAtomData = record
77AtomNumber: integer;
78Pos: TAffineVector;
79class operator =(Constref A, B : TMoleculeAtomData):Boolean;overload;
80
81procedure Create(ElemNum : Byte; aPos : TAffineVector); overload;
82procedure Create(ElemSym : String; aPos : TAffineVector); overload;
83end;
84
85TMoleculeAtomLinkData = record
86BondingType: integer;
87IdStart, IdEnd: integer;
88class operator =(Constref A, B : TMoleculeAtomLinkData):Boolean;overload;
89
90procedure Create(el1,el2, elType : Integer);
91end;
92
93
94{ TGLAtomDataList }
95generic TGLCustomArray<T> = class(specialize TGLZBaseArray<T>);
96
97TAtomDataList = class(specialize TGLCustomArray<TAtomData>);
98
99TMoleculeAtomDataList = class(specialize TGLCustomArray<TMoleculeAtomData>);
100
101TMoleculeAtomLinkDataList = class(specialize TGLCustomArray<TMoleculeAtomLinkData>); //Links = Bonds = Liaison
102
103//TCPKColorList = class(specialize TGLCustomArray<TColorVector>);
104
105
106{ TGLMolecule }
107
108TGLMolecule = class(TObject)
109private
110FAtoms: TMoleculeAtomDataList;
111FLinks: TMoleculeAtomLinkDataList;
112FDisplayName: string;
113FRootObject : TGLBaseSceneObject;
114FAtomsInfos, FBondsInfos : TStringList;
115//FColorMapCPK : TCPKColorList;
116FViewMode : Byte; // 0 = Atoms+Bonds, 1= Atoms 2 = Bonds
117procedure SetDisplayName(const Value: string);
118procedure SetViewMode(AValue: Byte);
119protected
120DCAtoms, DCLinks : TGLDummyCube;
121//procedure InitCPK;virtual;
122function getAtomColor(anAtom : TAtomData):TColorVector;
123function getLinkColor(Idx:Byte):TColorVector;
124public
125constructor Create;
126destructor Destroy; override;
127procedure Clear;
128
129procedure LoadFromFile(Const FileName : String);
130procedure CreateMolecule(Const RootObj : TGLBaseSceneObject);
131
132function getAtomsInfos :TStringList;
133function getBondsInfos : TStringList;
134
135property Atoms: TMoleculeAtomDataList read FAtoms;
136property Links: TMoleculeAtomLinkDataList read FLinks;
137property DisplayName: string read FDisplayName write SetDisplayName;
138
139property ViewMode : Byte read FViewMode Write SetViewMode;
140//property RootObject : TGLBaseSceneObject read FRootObject;
141end;
142
143// function GetPeriodicTableData : TAtomDataList;
144
145type
146
147{ TMainForm }
148
149TMainForm = class(TForm)
150CheckBox1: TCheckBox;
151CheckBox2: TCheckBox;
152CheckBox3: TCheckBox;
153GLCadencer: TGLCadencer;
154DCWorld: TGLDummyCube;
155DCMoleculeWorld: TGLDummyCube;
156
157GLCamera: TGLCamera;
158DCTarget: TGLDummyCube;
159DCWorldGrid: TGLDummyCube;
160DCGrids: TGLDummyCube;
161DCGridXY: TGLDummyCube;
162DCGridXZ: TGLDummyCube;
163DCGridYZ: TGLDummyCube;
164GLPoints1: TGLPoints;
165GridYZ: TGLXYZGrid;
166GridXZ: TGLXYZGrid;
167GridXY: TGLXYZGrid;
168WorldGrid: TGLXYZGrid;
169MainLightSource1: TGLLightSource;
170DCMolInfos: TGLDummyCube;
171lblMolInfo2: TGLHUDText;
172GLWindowsBitmapFont1: TGLWindowsBitmapFont;
173LblMolInfo: TGLFlatText;
174MainStatusBar: TStatusBar;
175MoleculeAxis: TGLCube;
176DCMolecule: TGLDummyCube;
177GLMatLib: TGLMaterialLibrary;
178GLScene: TGLScene;
179GLViewer: TGLSceneViewer;
180GroupBox1: TGroupBox;
181GroupBox2: TGroupBox;
182Label1: TLabel;
183lblMolName: TLabel;
184MainMenu1: TMainMenu;
185mmoMolAtoms: TMemo;
186MenuItem1: TMenuItem;
187MenuItem2: TMenuItem;
188MenuItem3: TMenuItem;
189MenuItem4: TMenuItem;
190MenuItem5: TMenuItem;
191MenuItem6: TMenuItem;
192MenuItem8: TMenuItem;
193MenuItem9: TMenuItem;
194mmoMolBonds: TMemo;
195OpenDlg: TOpenDialog;
196Panel1: TPanel;
197Panel2: TPanel;
198Panel3: TPanel;
199Panel4: TPanel;
200RadioGroup1: TRadioGroup;
201MainTimer: TTimer;
202procedure CheckBox1Change(Sender: TObject);
203procedure CheckBox2Change(Sender: TObject);
204procedure CheckBox3Change(Sender: TObject);
205procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
206procedure FormCreate(Sender: TObject);
207procedure FormKeyPress(Sender: TObject; var Key: char);
208procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
209procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
210procedure FormShow(Sender: TObject);
211procedure GLCadencerProgress(Sender: TObject; const deltaTime, newTime: Double);
212procedure GLViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
213procedure GLViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
214procedure GLViewerMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
215procedure MainTimerTimer(Sender: TObject);
216procedure MenuItem2Click(Sender: TObject);
217procedure MenuItem4Click(Sender: TObject);
218procedure MenuItem6Click(Sender: TObject);
219procedure MenuItem9Click(Sender: TObject);
220procedure RadioGroup1Click(Sender: TObject);
221private
222oldPick, CurrentPick : TGLCustomSceneObject;
223oldColor : TColorVector;
224
225procedure ShowCameraLocation;
226procedure ShowFocalLength;
227procedure ShowLightLocation;
228procedure ShowTargetLocation;
229
230protected
231MousePoint: TPoint;
232md:Boolean;
233DoMouseMoveObj : Integer;
234
235procedure UpdateAtomInfosForm(anAtom : TAtomData);
236public
237
238Mol: TGLMolecule;
239end;
240
241const
242crLightxz = 1;
243crLightyz = 2;
244crLightxy = 3;
245crSlidexy = 4;
246crSlideyz = 5;
247crSlidexz = 6;
248crRotate = 7;
249crZoom = 8;
250crHandMove = 9;
251crSlidezy = 10;
252
253Const
254cUnknownAtom : TAtomData = (
255atomicNumber : 0;
256atomicRadius : 0;
257standardState : 0;
258symbol : '--';
259ionizationEnergy : 0;
260electronAffinity : 0;
261meltingPoint : 0;
262boilingPoint : 0;
263bondingType : 0;
264electronegativity : 0;
265vanDelWaalsRadius : 0;
266density : 0;
267atomicMass : 'na';
268cpkColor : 'clrBlack';
269name : 'Unknown';
270electronicConfiguration : 'Unknown';
271ionRadius : 'Unknown';
272oxidationStates : 'Unknown';
273groupBlock : 'Unknown';
274yearDiscovered : 'Unknown';
275);
276
277var
278MainForm: TMainForm;
279NavCube: TGLNavCube;
280PeriodicTable : TAtomDataList;
281
282implementation
283
284{$R *.lfm}
285{$R Cursors.res}
286
287uses
288LazFileUtils,
289GLZStringUtils,
290uCPKForm, uHelpCommandsForm, uAtomInfosForm;
291
292Const
293{_GLRatio / _FPColorRatio : rapport Byte/Float d'une couleur }
294_FPColorRatio: single = 1/255;
295
296{%region%=====[ Functions Tools ]==============================================}
297
298function LoadCursorFromRes(CursorName:String):THandle;
299var
300Cur: TCursorImage;
301begin
302Cur := TCursorImage.Create;
303Cur.LoadFromResourceName(HInstance,CursorName);
304result := Cur.ReleaseHandle;
305Cur.Free;
306end;
307
308procedure Split(const Delimiter: Char; Input: string; const Strings: TStrings);
309begin
310Assert(Assigned(Strings)) ;
311Strings.Clear;
312Strings.StrictDelimiter := true;
313Strings.Delimiter := Delimiter;
314Strings.DelimitedText := Input;
315end;
316
317function HexColorToColorVector(const aHexValue : String):TColorVector;
318begin
319
320result.x := (StrToInt('$'+Copy(aHexValue,1,2)))*_FPColorRatio;
321result.y := (StrToInt('$'+Copy(aHexValue,3,2)))*_FPColorRatio;
322result.z := (StrToInt('$'+Copy(aHexValue,5,2)))*_FPColorRatio;
323result.w := 1.0;//AlphaOpaque;
324end;
325
326const
327WhiteSpaces = [#8, #9, #13, #10, #32];
328
329procedure SkipWhiteSpace(var Line: string);
330begin
331while (Length(Line) > 0) and (Line[1] in WhiteSpaces) do
332Delete(Line, 1, 1);
333end;
334
335function ReadString(var Line: string): string;
336begin
337Result := '';
338SkipWhiteSpace(Line);
339while (Length(Line) > 0) and not(Line[1] in WhiteSpaces) do
340begin
341SetLength(Result, Length(Result) + 1);
342Result[Length(Result)] := Line[1];
343Delete(Line, 1, 1);
344end;
345end;
346
347function ReadInt(var Line: string): Integer;
348Var
349i:Integer;
350s : string;
351begin
352result := 0;
353s := ReadString(Line);
354if TryStrToInt(s,i) then result := i; //StrToInt(s);
355end;
356
357function ReadFloat(var Line: string): Double;
358begin
359Result := StrToFloat(ReadString(Line));
360end;
361
362function AtomSymbolToAtomicNum(const symbol: string): byte;
363var s: string;
364begin
365s := LowerCase(symbol);
366if s = 'h' then Result := 1 else
367if s = 'he' then Result := 2 else
368if s = 'li' then Result := 3 else
369if s = 'be' then Result := 4 else
370if s = 'b' then Result := 5 else
371if s = 'c' then Result := 6 else
372if s = 'n' then Result := 7 else
373if s = 'o' then Result := 8 else
374if s = 'f' then Result := 9 else
375if s = 'ne' then Result := 10 else
376if s = 'na' then Result := 11 else
377if s = 'mg' then Result := 12 else
378if s = 'al' then Result := 13 else
379if s = 'si' then Result := 14 else
380if s = 'p' then Result := 15 else
381if s = 's' then Result := 16 else
382if s = 'cl' then Result := 17 else
383if s = 'ar' then Result := 18 else
384if s = 'k' then Result := 19 else
385if s = 'ca' then Result := 20 else
386if s = 'sc' then Result := 21 else
387if s = 'ti' then Result := 22 else
388if s = 'v' then Result := 23 else
389if s = 'cr' then Result := 24 else
390if s = 'mn' then Result := 25 else
391if s = 'fe' then Result := 26 else
392if s = 'co' then Result := 27 else
393if s = 'ni' then Result := 28 else
394if s = 'cu' then Result := 29 else
395if s = 'zn' then Result := 30 else
396if s = 'ga' then Result := 31 else
397if s = 'ge' then Result := 32 else
398if s = 'as' then Result := 33 else
399if s = 'se' then Result := 34 else
400if s = 'br' then Result := 35 else
401if s = 'kr' then Result := 36 else
402if s = 'rb' then Result := 37 else
403if s = 'sr' then Result := 38 else
404if s = 'y' then Result := 39 else
405if s = 'zr' then Result := 40 else
406if s = 'nb' then Result := 41 else
407if s = 'mo' then Result := 42 else
408if s = 'tc' then Result := 43 else
409if s = 'ru' then Result := 44 else
410if s = 'rh' then Result := 45 else
411if s = 'pd' then Result := 46 else
412if s = 'ag' then Result := 47 else
413if s = 'cd' then Result := 48 else
414if s = 'in' then Result := 49 else
415if s = 'sn' then Result := 50 else
416if s = 'sb' then Result := 51 else
417if s = 'te' then Result := 52 else
418if s = 'i' then Result := 53 else
419if s = 'xe' then Result := 54 else
420if s = 'cs' then Result := 55 else
421if s = 'ba' then Result := 56 else
422if s = 'la' then Result := 57 else
423if s = 'ce' then Result := 58 else
424if s = 'pr' then Result := 59 else
425if s = 'nd' then Result := 60 else
426if s = 'pm' then Result := 61 else
427if s = 'sm' then Result := 62 else
428if s = 'eu' then Result := 63 else
429if s = 'gd' then Result := 64 else
430if s = 'tb' then Result := 65 else
431if s = 'dy' then Result := 66 else
432if s = 'ho' then Result := 67 else
433if s = 'er' then Result := 68 else
434if s = 'tm' then Result := 69 else
435if s = 'yb' then Result := 70 else
436if s = 'lu' then Result := 71 else
437if s = 'hf' then Result := 72 else
438if s = 'ta' then Result := 73 else
439if s = 'w' then Result := 74 else
440if s = 're' then Result := 75 else
441if s = 'os' then Result := 76 else
442if s = 'ir' then Result := 77 else
443if s = 'pt' then Result := 78 else
444if s = 'au' then Result := 79 else
445if s = 'hg' then Result := 80 else
446if s = 'tl' then Result := 81 else
447if s = 'pb' then Result := 82 else
448if s = 'bi' then Result := 83 else
449if s = 'po' then Result := 84 else
450if s = 'at' then Result := 85 else
451if s = 'rn' then Result := 86 else
452if s = 'fr' then Result := 87 else
453if s = 'ra' then Result := 88 else
454if s = 'ac' then Result := 89 else
455if s = 'th' then Result := 90 else
456if s = 'pa' then Result := 91 else
457if s = 'u' then Result := 92 else
458if s = 'np' then Result := 93 else
459if s = 'pu' then Result := 94 else
460if s = 'am' then Result := 95 else
461if s = 'cm' then Result := 96 else
462if s = 'bk' then Result := 97 else
463if s = 'cf' then Result := 98 else
464if s = 'es' then Result := 99 else
465if s = 'fm' then Result := 100 else
466if s = 'md' then Result := 101 else
467if s = 'no' then Result := 102 else
468if s = 'lr' then Result := 103 else
469if s = 'rf' then Result := 104 else
470if s = 'db' then Result := 105 else
471if s = 'sg' then Result := 106 else
472if s = 'bh' then Result := 107 else
473if s = 'hs' then Result := 108 else
474if s = 'mt' then Result := 109 else
475if s = 'ds' then Result := 110 else
476if s = 'rg' then Result := 111 else
477if s = 'cn' then Result := 112 else
478if s = 'uut' then Result := 113 else
479if s = 'uuq' then Result := 114 else
480if s = 'uup' then Result := 115 else
481if s = 'uuh' then Result := 116 else
482if s = 'uus' then Result := 117 else
483if s = 'uuo' then Result := 118 else
484Result := 0;
485end;
486
487
488procedure QuaternionRotation(var Obj:TGLBaseSceneObject;Ex,Ey,eZ:Double);
489var
490q : TQuaternion;
491m : TMatrix;
492vFrom, vTo : TAffineVector;
493begin
494q := QuaternionFromRollPitchYaw(eX,eZ,eY);
495//QuaternionToPoints(q, vFrom, vTo);
496m := QuaternionToMatrix(QuaternionConjugate(q));
497Obj.Matrix := MatrixMultiply(Obj.Matrix,m);
498Obj.TransformationChanged;
499end;
500
501{%endregion%}
502
503{%region%=====[ TGLMoleculeAtomDataList ]=======================================}
504
505class operator TMoleculeAtomData.=(Constref A, B: TMoleculeAtomData): Boolean;
506begin
507Result := (A.AtomNumber = B.AtomNumber) And (VectorEquals(A.Pos,B.Pos));
508end;
509
510procedure TMoleculeAtomData.Create(ElemNum : Byte; aPos : TAffineVector);
511begin
512with Self do
513begin
514AtomNumber:=ElemNum; // Numero de l'element de la table periodique
515Pos := aPos;
516end;
517end;
518
519procedure TMoleculeAtomData.Create(ElemSym : String; aPos : TAffineVector);
520begin
521with Self do
522begin
523AtomNumber:=AtomSymbolToAtomicNum(ElemSym); // Numero de l'element de la table periodique
524Pos := aPos;
525end;
526end;
527
528class operator TMoleculeAtomLinkData.=(Constref A, B: TMoleculeAtomLinkData): Boolean;
529begin
530Result := (A.BondingType = B.BondingType) And (A.IdEnd = B.IdEnd) And (A.IdStart = B.IdStart);
531end;
532
533procedure TMoleculeAtomLinkData.Create(el1,el2, elType : Integer);
534begin
535with Self do
536begin
537BondingType:=elType;
538idStart:= el1;
539idEnd := el2;
540end;
541end;
542
543{%endregion%}
544
545{%region%=====[ TGLMolecule ]===================================================}
546
547constructor TGLMolecule.Create;
548begin
549inherited;
550FAtoms := TMoleculeAtomDataList.Create;
551FLinks := TMoleculeAtomLinkDataList.Create;
552FAtomsInfos := TStringList.Create;
553FBondsInfos := TStringList.Create;
554FViewMode := 0;
555//FColorMapCPK := TCPKColorList.Create;
556//InitCPK;
557end;
558
559destructor TGLMolecule.Destroy;
560begin
561//FColorMapCPK.Free;
562FBondsInfos.Free;
563FAtomsInfos.Free;
564FLinks.Free;
565FAtoms.Free;
566inherited;
567end;
568
569procedure TGLMolecule.Clear;
570begin
571FAtoms.Clear;
572FLinks.Clear;
573end;
574
575procedure TGLMolecule.LoadFromFile(const FileName: String);
576var
577ext : String;
578sl : TStringList;
579s : String;
580nba,nbb, i, cnt, linepos : Integer;
581px,py,pz : Double;
582atomSym : String;
583iStart, iEnd, iType, iNum : Integer;
584MolAtomData: TMoleculeAtomData;
585MolLinkData: TMoleculeAtomLinkData;
586begin
587
588// Prise ne charge basique des fichiers au format .MOL et .MOL2
589
590// mol2 file format description : https://fr.scribd.com/document/218351247/mol2
591// https://docs.chemaxon.com/display/docs/MDL+MOLfiles%2C+RGfiles%2C+SDfiles%2C+Rxnfiles%2C+RDfiles+formats
592// http://infochim.u-strasbg.fr/recherche/Download/Fragmentor/MDL_SDF.pdf
593
594ext := lowercase(ExtractFileExt(FileName));
595
596if (ext = '.mol') then
597begin
598// On efface les anciennes données
599FAtoms.Clear;
600FLinks.Clear;
601
602sl := TStringList.Create;
603sl.LoadFromFile(FileName);
604
605// Read Header block
606DisplayName := sl[0];
607
608// Skip comments and other infos header (2 lines)
609s:=sl[3];
610
611// Counts Line
612nba := readInt(s); // nb atoms
613nbb := readInt(s); // nb bonds
614
615// Read Atoms block
616cnt := nba-1;
617linepos := 4;
618for i:= 0 to cnt do
619begin
620s := sl[LinePos];
621px := ReadFloat(s);
622py := ReadFloat(s);
623pz := ReadFloat(s);
624atomSym := ReadString(s);
625
626MolAtomData.Create(AtomSym,AffineVectorMake(px,py,pz));
627FAtoms.Add(MolAtomData);
628inc(LinePos);
629end;
630
631// Read Bonds block
632cnt := nbb -1;
633for i:= 0 to cnt do
634begin
635s := sl[LinePos];
636iStart := ReadInt(s);
637iEnd := ReadInt(s);
638iType := ReadInt(s);
639MolLinkData.Create(iStart,iEnd,iType);
640FLinks.Add(MolLinkData);
641inc(LinePos);
642end;
643// Read properties block
644{@TODO}
645
646sl.Free;
647end
648else if (ext = '.mol2') then
649begin
650sl := TStringList.Create;
651sl.Free;
652end;
653
654end;
655
656procedure TGLMolecule.CreateMolecule(const RootObj: TGLBaseSceneObject);
657var
658i,k: integer;
659sf: double;
660sph: TGLSphere;
661MolAtomData: TMoleculeAtomData;
662MolLinkData: TMoleculeAtomLinkData;
663AtomData : TAtomData;
664pStart, pEnd, pMid, pAngle: TAffineVector;
665cyl: TGLCylinder;
666Lines : TGLLines;
667//aNodeStart,
668//aNodeEnd : TGLLinesNode;
669
670//aZ,aX : Double;
671begin
672FRootObject := RootObj;
673FRootObject.DeleteChildren;
674FAtomsInfos.Clear;
675FBondsInfos.Clear;
676
677DCAtoms := TGLDummyCube.CreateAsChild(FRootObject);
678DCLinks := TGLDummyCube.CreateAsChild(FRootObject);
679for i := 0 to Atoms.Count-1 do
680begin
681MolAtomData := (FAtoms.Items[i]);
682AtomData := PeriodicTable.Items[MolAtomData.AtomNumber];
683sph := TGLSphere.CreateAsChild(DCAtoms);
684//sf := AtomicNrToScale(atomData.AtomKind);
685sf:=1.0;
686With sph do
687begin
688//Material.MaterialOptions:= [moNoLighting];
689Material.FrontProperties.Diffuse.DirectColor := getAtomColor(atomData);
690Radius := 0.5 * (AtomData.atomicRadius*0.01) ;
691Position.AsAffineVector := MolAtomData.Pos;
692FAtomsInfos.Add('Atom : ' + i.ToString +' | ( '+TAtomData(PeriodicTable.Items[MolAtomData.AtomNumber]).symbol
693+' ) [' + sph.Position.AsString + ']');
694Scale.AsAffineVector := AffineVectorMake(sf,sf,sf);
695Tag := MolAtomData.AtomNumber;
696k:=i+1;
697Hint := 'Atom : ' + k.ToString +' | ( '+TAtomData(PeriodicTable.Items[MolAtomData.AtomNumber]).symbol
698+' ) [' + sph.Position.AsString + ']';
699end;
700end;
701
702for i := 0 to Links.Count-1 do
703begin
704MolLinkData := FLinks.Items[i];
705Lines := TGLLines.CreateAsChild(DCLinks);
706With Lines do
707begin
708Antialiased := true;
709LineColor.DirectColor := getLinkColor(MolLinkData.BondingType);
710NodeColor.DirectColor := clrBrightGold;
711NodesAspect := lnaDodecahedron;
712NodeSize := 0.1;
713LineWidth := 2;
714Pickable := True;
715k:=i+1;
716Hint := 'Link : ' + k.ToString + ' | Type : '+ IntToStr((MolLinkData.BondingType))+' [' + MolLinkData.IdStart.ToString + '-->' + MolLinkData.IdEnd.ToString + ']';
717end;
718pStart := Atoms.Items[MolLinkData.IdStart-1].Pos;
719pEnd := Atoms.Items[MolLinkData.IdEnd-1].Pos;
720
721Lines.Nodes.AddNode(pStart);
722Lines.Nodes.AddNode(pEnd);
723
724
725{ C'est, stupide mais je n'arrive pas à visualiser comment calculer
726les bons angles de rotations avec des cylindres.....;(
727
728//if VectorMorethen(pStart,pEnd) then
729//begin
730// pMid := pStart;
731// pStart := pEnd;
732// pEnd :=pMid;
733//end;
734pMid := AffineVectorMake((pStart.X+pEnd.X)*0.5,(pStart.Y+pEnd.Y)*0.5,(pStart.Z+pEnd.Z)*0.5);
735cyl := TGLCylinder.CreateAsChild(DCLinks);
736with cyl do
737begin
738Material.FrontProperties.Diffuse.DirectColor := getLinkColor(MolLinkData.BondingType);
739//Position.AsAffineVector := pMid;
740Height := VectorDistance(pStart,pEnd);
741TopRadius := 0.05;
742BottomRadius:= 0.05;
743Tag := i;
744Hint := 'Link : ' + i.ToString + '| Type : '+ IntToStr((MolLinkData.BondingType))+' [' + MolLinkData.IdStart.ToString + '-->' + MolLinkData.IdEnd.ToString + ']';
745end;
746
747// C'est la dedans que ça foire
748pAngle.X := 180/Pi*ArcTan2(pEnd.X-pStart.X, pEnd.Y-pStart.Y);
749pAngle.Y := 180/Pi*ArcTan2(pEnd.X-pStart.X, pEnd.Z-pStart.Z);
750pAngle.Z := 180/Pi*ArcTan2(pEnd.Z-pStart.Z, pEnd.Y-pStart.Y);
751
752//if pAngle.X<>0 then Cyl.Roll(pAngle.X);
753//if pAngle.Z<>0 then Cyl.Pitch(pAngle.Z);
754//if pAngle.Y<>0 then Cyl.Turn(pAngle.Y);
755//Cyl.RotateAbsolute(pAngle.X,pAngle.Y,pAngle.Z);
756QuaternionRotation(TGLBaseSceneObject(Cyl),pAngle.X,pAngle.Y,pAngle.Z);
757Cyl.Position.AsAffineVector := pMid;
758}
759
760
761FBondsInfos.Add(Lines.Hint);
762end;
763
764end;
765
766function TGLMolecule.getAtomsInfos: TStringList;
767begin
768result:= FAtomsInfos;
769end;
770
771function TGLMolecule.getBondsInfos: TStringList;
772begin
773result := FBondsInfos;
774end;
775
776procedure TGLMolecule.SetDisplayName(const Value: string);
777begin
778FDisplayName := Value;
779end;
780
781procedure TGLMolecule.SetViewMode(AValue: Byte);
782var
783i: integer;
784sph: TGLSphere;
785// cyl: TGLCylinder;
786lines : TGLLines;
787begin
788if FViewMode=AValue then Exit;
789FViewMode:=AValue;
790
791for i := 0 to DCAtoms.Count-1 do
792begin
793sph := TGLSphere(DCAtoms.Children[i]);
794sph.Visible := ((FViewMode = 0) or (FViewMode = 1));
795end;
796
797for i := 0 to DCLinks.Count-1 do
798begin
799Lines := TGLLines(DCLinks.Children[i]);
800Lines.Visible:= ((FViewMode = 0) or (FViewMode = 2));
801//cyl := TGLCylinder(DCLinks.Children[i]);
802//cyl.Visible := ((FViewMode = 0) or (FViewMode = 2));
803end;
804
805end;
806
807//procedure TGLMolecule.InitCPK;
808//begin
809// FColorMapCPK.Capacity:=118;
810// FColorMapCPK.Items[0] := VectorMake(0.96,0.96,0.96); //
811// FColorMapCPK.Items[1] := VectorMake(0.80,0.50,1.00); //
812// FColorMapCPK.Items[2] := VectorMake(0.67,0.36,0.95); //
813// FColorMapCPK.Items[3] := VectorMake(0.56,0.25,0.83); //
814// FColorMapCPK.Items[4] := VectorMake(0.44,0.18,0.69); //
815// FColorMapCPK.Items[5] := VectorMake(0.34,0.09,0.56); //
816// FColorMapCPK.Items[6] := VectorMake(0.40,0.40,0.40); // C
817// FColorMapCPK.Items[7] := VectorMake(1.0,0.0,0.0); //
818//
819// FColorMapCPK.Items[8] := VectorMake(0.96,0.96,0.96); // Be
820// FColorMapCPK.Items[9] := VectorMake(0.96,0.96,0.96); // Mg
821// FColorMapCPK.Items[10] := VectorMake(0.96,0.96,0.96);// Ca
822// FColorMapCPK.Items[11] := VectorMake(0.96,0.96,0.96);// Sr
823// FColorMapCPK.Items[12] := VectorMake(0.96,0.96,0.96);// Ba
824// FColorMapCPK.Items[13] := VectorMake(0.96,0.96,0.96);// Ra
825//
826// FColorMapCPK.Items[14] := VectorMake(0.96,0.96,0.96); // Sc
827// FColorMapCPK.Items[15] := VectorMake(0.96,0.96,0.96); // Y
828// FColorMapCPK.Items[16] := VectorMake(0.96,0.96,0.96); // Lu
829// FColorMapCPK.Items[17] := VectorMake(0.96,0.96,0.96); // Lr
830// FColorMapCPK.Items[18] := VectorMake(0.96,0.96,0.96);
831// FColorMapCPK.Items[19] := VectorMake(0.96,0.96,0.96);
832//
833// FColorMapCPK.Items[20] := VectorMake(0.96,0.96,0.96);
834// FColorMapCPK.Items[21] := VectorMake(0.96,0.96,0.96);
835// FColorMapCPK.Items[22] := VectorMake(0.96,0.96,0.96);
836// FColorMapCPK.Items[23] := VectorMake(0.96,0.96,0.96);
837// FColorMapCPK.Items[24] := VectorMake(0.96,0.96,0.96);
838// FColorMapCPK.Items[25] := VectorMake(0.96,0.96,0.96);
839// FColorMapCPK.Items[26] := VectorMake(0.96,0.96,0.96);
840// FColorMapCPK.Items[27] := VectorMake(0.96,0.96,0.96);
841// FColorMapCPK.Items[28] := VectorMake(0.96,0.96,0.96);
842// FColorMapCPK.Items[29] := VectorMake(0.96,0.96,0.96);
843// FColorMapCPK.Items[30] := VectorMake(0.96,0.96,0.96);
844// FColorMapCPK.Items[31] := VectorMake(0.96,0.96,0.96);
845// FColorMapCPK.Items[32] := VectorMake(0.96,0.96,0.96);
846// FColorMapCPK.Items[33] := VectorMake(0.96,0.96,0.96);
847// FColorMapCPK.Items[34] := VectorMake(0.96,0.96,0.96);
848// FColorMapCPK.Items[35] := VectorMake(0.96,0.96,0.96);
849// FColorMapCPK.Items[36] := VectorMake(0.96,0.96,0.96);
850// FColorMapCPK.Items[37] := VectorMake(0.96,0.96,0.96);
851// FColorMapCPK.Items[38] := VectorMake(0.96,0.96,0.96);
852// FColorMapCPK.Items[39] := VectorMake(0.96,0.96,0.96);
853//
854// FColorMapCPK.Items[40] := VectorMake(0.96,0.96,0.96);
855// FColorMapCPK.Items[41] := VectorMake(0.96,0.96,0.96);
856// FColorMapCPK.Items[42] := VectorMake(0.96,0.96,0.96);
857// FColorMapCPK.Items[43] := VectorMake(0.96,0.96,0.96);
858// FColorMapCPK.Items[44] := VectorMake(0.96,0.96,0.96);
859// FColorMapCPK.Items[45] := VectorMake(0.96,0.96,0.96);
860// FColorMapCPK.Items[46] := VectorMake(0.96,0.96,0.96);
861// FColorMapCPK.Items[47] := VectorMake(0.96,0.96,0.96);
862// FColorMapCPK.Items[48] := VectorMake(0.96,0.96,0.96);
863// FColorMapCPK.Items[49] := VectorMake(0.96,0.96,0.96);
864// FColorMapCPK.Items[50] := VectorMake(0.96,0.96,0.96);
865// FColorMapCPK.Items[51] := VectorMake(0.96,0.96,0.96);
866// FColorMapCPK.Items[52] := VectorMake(0.96,0.96,0.96);
867// FColorMapCPK.Items[53] := VectorMake(0.96,0.96,0.96);
868// FColorMapCPK.Items[54] := VectorMake(0.96,0.96,0.96);
869// FColorMapCPK.Items[55] := VectorMake(0.96,0.96,0.96);
870// FColorMapCPK.Items[56] := VectorMake(0.96,0.96,0.96);
871// FColorMapCPK.Items[57] := VectorMake(0.96,0.96,0.96);
872// FColorMapCPK.Items[58] := VectorMake(0.96,0.96,0.96);
873// FColorMapCPK.Items[59] := VectorMake(0.96,0.96,0.96);
874//
875// FColorMapCPK.Items[60] := VectorMake(0.96,0.96,0.96);
876// FColorMapCPK.Items[61] := VectorMake(0.96,0.96,0.96);
877// FColorMapCPK.Items[62] := VectorMake(0.96,0.96,0.96);
878// FColorMapCPK.Items[63] := VectorMake(0.96,0.96,0.96);
879// FColorMapCPK.Items[64] := VectorMake(0.96,0.96,0.96);
880// FColorMapCPK.Items[65] := VectorMake(0.96,0.96,0.96);
881// FColorMapCPK.Items[66] := VectorMake(0.96,0.96,0.96);
882// FColorMapCPK.Items[67] := VectorMake(0.96,0.96,0.96);
883// FColorMapCPK.Items[68] := VectorMake(0.96,0.96,0.96);
884// FColorMapCPK.Items[69] := VectorMake(0.96,0.96,0.96);
885// FColorMapCPK.Items[70] := VectorMake(0.96,0.96,0.96);
886// FColorMapCPK.Items[71] := VectorMake(0.96,0.96,0.96);
887// FColorMapCPK.Items[72] := VectorMake(0.96,0.96,0.96);
888// FColorMapCPK.Items[73] := VectorMake(0.96,0.96,0.96);
889// FColorMapCPK.Items[74] := VectorMake(0.96,0.96,0.96);
890// FColorMapCPK.Items[75] := VectorMake(0.96,0.96,0.96);
891// FColorMapCPK.Items[76] := VectorMake(0.96,0.96,0.96);
892// FColorMapCPK.Items[77] := VectorMake(0.96,0.96,0.96);
893// FColorMapCPK.Items[78] := VectorMake(0.96,0.96,0.96);
894// FColorMapCPK.Items[79] := VectorMake(0.96,0.96,0.96);
895//
896// FColorMapCPK.Items[80] := VectorMake(0.96,0.96,0.96);
897// FColorMapCPK.Items[81] := VectorMake(0.96,0.96,0.96);
898// FColorMapCPK.Items[82] := VectorMake(0.96,0.96,0.96);
899// FColorMapCPK.Items[83] := VectorMake(0.96,0.96,0.96);
900// FColorMapCPK.Items[84] := VectorMake(0.96,0.96,0.96);
901// FColorMapCPK.Items[85] := VectorMake(0.96,0.96,0.96);
902// FColorMapCPK.Items[86] := VectorMake(0.96,0.96,0.96);
903// FColorMapCPK.Items[87] := VectorMake(0.96,0.96,0.96);
904// FColorMapCPK.Items[88] := VectorMake(0.96,0.96,0.96);
905// FColorMapCPK.Items[89] := VectorMake(0.96,0.96,0.96);
906// FColorMapCPK.Items[90] := VectorMake(0.96,0.96,0.96);
907// FColorMapCPK.Items[91] := VectorMake(0.96,0.96,0.96);
908// FColorMapCPK.Items[92] := VectorMake(0.96,0.96,0.96);
909// FColorMapCPK.Items[93] := VectorMake(0.96,0.96,0.96);
910// FColorMapCPK.Items[94] := VectorMake(0.96,0.96,0.96);
911// FColorMapCPK.Items[95] := VectorMake(0.96,0.96,0.96);
912// FColorMapCPK.Items[96] := VectorMake(0.96,0.96,0.96);
913// FColorMapCPK.Items[97] := VectorMake(0.96,0.96,0.96);
914// FColorMapCPK.Items[98] := VectorMake(0.96,0.96,0.96);
915// FColorMapCPK.Items[99] := VectorMake(0.96,0.96,0.96);
916//
917// FColorMapCPK.Items[100] := VectorMake(0.96,0.96,0.96);
918// FColorMapCPK.Items[101] := VectorMake(0.96,0.96,0.96);
919// FColorMapCPK.Items[102] := VectorMake(0.96,0.96,0.96);
920// FColorMapCPK.Items[103] := VectorMake(0.96,0.96,0.96);
921// FColorMapCPK.Items[104] := VectorMake(0.96,0.96,0.96);
922// FColorMapCPK.Items[105] := VectorMake(0.96,0.96,0.96);
923// FColorMapCPK.Items[106] := VectorMake(0.96,0.96,0.96);
924// FColorMapCPK.Items[107] := VectorMake(0.96,0.96,0.96);
925// FColorMapCPK.Items[108] := VectorMake(0.96,0.96,0.96);
926// FColorMapCPK.Items[109] := VectorMake(0.96,0.96,0.96);
927// FColorMapCPK.Items[110] := VectorMake(0.96,0.96,0.96);
928// FColorMapCPK.Items[111] := VectorMake(0.96,0.96,0.96);
929// FColorMapCPK.Items[112] := VectorMake(0.96,0.96,0.96);
930// FColorMapCPK.Items[113] := VectorMake(0.96,0.96,0.96);
931// FColorMapCPK.Items[114] := VectorMake(0.96,0.96,0.96);
932// FColorMapCPK.Items[115] := VectorMake(0.96,0.96,0.96);
933// FColorMapCPK.Items[116] := VectorMake(0.96,0.96,0.96);
934// FColorMapCPK.Items[117] := VectorMake(0.96,0.96,0.96);
935//
936//end;
937
938function TGLMolecule.getAtomColor(anAtom: TAtomData): TColorVector;
939begin
940Result := HexColorToColorVector(anAtom.cpkColor);
941end;
942
943function TGLMolecule.getLinkColor(Idx: Byte): TColorVector;
944begin
945Case Idx of
9461 : Result := clrYellow;
9472 : Result := clrBlue;
9483 : Result := clrGreen;
9494 : Result := clrFuchsia;
950else Result := clrRed; // Liaison inconnue
951end;
952end;
953
954{%endregion%}
955
956
957{ TMainForm }
958
959procedure TMainForm.FormCreate(Sender: TObject);
960Var
961AnAtomData : TMoleculeAtomData;
962AnAtomLinkData : TMoleculeAtomLinkData;
963
964procedure LoadPeriodicTable;
965var
966sl : TStringList;
967s : String;
968dpt : TStringList;
969i : Integer;
970anAtom : TAtomData;
971begin
972sl := TStringList.Create;
973dpt := TStringList.Create;
974sl.LoadFromFile('periodictable.dat');
975
976PeriodicTable.Add(cUnknownAtom);
977
978for i:=0 to sl.Count-1 do
979begin
980s := sl.Strings[i];
981dpt := StrOps.Explode(s,',');
982
983//showMessage('Out : '+dpt.Strings[0]+' - '+dpt.Strings[1]+' - '+dpt.Strings[2]);
984//ShowMessage('Exploded = '+ dpt.Text);
985with anAtom do
986begin
987atomicNumber := strToInt(dpt[0]);
988atomicRadius := strToInt(dpt[7]);
989standardState := strToInt(dpt[13]); //****
990symbol := dpt[1];
991ionizationEnergy := strToInt(dpt[10]);
992electronAffinity := strToInt(dpt[11]);
993meltingPoint := strToInt(dpt[15]);
994boilingPoint := strToInt(dpt[16]);
995bondingType := strToInt(dpt[14]);
996atomicMass := dpt[3]; //StrToFloat(dpt[3]);
997electronegativity := StrToFloat(dpt[6]);
998vanDelWaalsRadius := StrToFloat(dpt[9]);
999density := StrToFloat(dpt[17]);
1000cpkColor := dpt[4];//clrBlack;
1001name := dpt[2];
1002electronicConfiguration := dpt[5];
1003ionRadius := dpt[8];
1004oxidationStates := dpt[12];
1005groupBlock := dpt[18];
1006yearDiscovered := dpt[19]; //strToInt(dpt[19]);
1007end;
1008PeriodicTable.Add(anAtom);
1009end;
1010dpt.Free;
1011sl.Free;
1012end;
1013
1014begin
1015PeriodicTable := TAtomDataList.Create;
1016LoadPeriodicTable;
1017
1018Screen.Cursors[crLightxy] := LoadCursorFromRes('LIGHTXY');
1019Screen.Cursors[crLightyz] := LoadCursorFromRes('LIGHTYZ');
1020Screen.Cursors[crLightxz] := LoadCursorFromRes('LIGHTXZ');
1021Screen.Cursors[crSlidexy] := LoadCursorFromRes('SLIDEXY');
1022Screen.Cursors[crSlidexz] := LoadCursorFromRes('SLIDEXZ');
1023Screen.Cursors[crSlideyz] := LoadCursorFromRes('SLIDEYZ');
1024Screen.Cursors[crRotate] := LoadCursorFromRes('ROTATE');
1025Screen.Cursors[crZoom] := LoadCursorFromRes('ZOOM');
1026Screen.Cursors[crSlidezy] := LoadCursorFromRes('SLIDEZY');
1027
1028NavCube := TGLNavCube.CreateAsChild(GLScene.Objects);
1029NavCube.SceneViewer := GLViewer;
1030NavCube.Camera:=GLCamera;
1031NavCube.ActiveMouse:=True;
1032NavCube.FPS := 30;
1033DoMouseMoveObj := 0;
1034
1035Mol := TGLMolecule.Create;
1036With Mol do
1037begin
1038DisplayName :='Benzene';
1039With Atoms do
1040begin
1041AnAtomData.Create(6,AffineVectorMake(1.9050,-0.7932,0.0000));
1042Add(AnAtomData);
1043AnAtomData.Create(6,AffineVectorMake(1.9050, -2.1232,0.0000));
1044Add(AnAtomData);
1045AnAtomData.Create(6,AffineVectorMake(0.7531,-0.1282 ,0.0000));
1046Add(AnAtomData);
1047AnAtomData.Create(6,AffineVectorMake(0.7531,-2.7882,0.0000));
1048Add(AnAtomData);
1049AnAtomData.Create(6,AffineVectorMake(-0.3987,-0.7932,0.0000));
1050Add(AnAtomData);
1051AnAtomData.Create(6,AffineVectorMake(-0.3987,-2.1232,0.0000));
1052Add(AnAtomData);
1053end;
1054
1055With Links do
1056begin
1057AnAtomLinkData.Create(2,1,1);
1058Add(AnAtomLinkData);
1059AnAtomLinkData.Create(3,1,2);
1060Add(AnAtomLinkData);
1061AnAtomLinkData.Create(4,2,2);
1062Add(AnAtomLinkData);
1063AnAtomLinkData.Create(5,3,1);
1064Add(AnAtomLinkData);
1065AnAtomLinkData.Create(6,4,1);
1066Add(AnAtomLinkData);
1067AnAtomLinkData.Create(6,5,2);
1068Add(AnAtomLinkData);
1069end;
1070end;
1071end;
1072
1073procedure TMainForm.ShowCameraLocation;
1074begin
1075with GLCamera.Position do
1076MainStatusBar.Panels[0].Text := 'Camera: '+FloatToStrF(X, ffNumber, 5, 2)+', '+
1077FloatToStrF(Y, ffNumber, 5, 2)+', '+FloatToStrF(Z, ffNumber, 5, 2);
1078end;
1079
1080procedure TMainForm.ShowTargetLocation;
1081begin
1082with DCTarget.Position do
1083MainStatusBar.Panels[2].Text := 'Target: '+
1084FloatToStrF(-X, ffNumber, 5, 2)+', '+FloatToStrF(-Y, ffNumber, 5, 2)+', '+
1085FloatToStrF(-Z, ffNumber, 5, 2);
1086end;
1087
1088procedure TMainForm.ShowFocalLength;
1089begin
1090with GLCamera do
1091MainStatusBar.Panels[1].Text := 'Focal: '+FloatToStrF(FocalLength, ffnumber, 5, 2);
1092end;
1093
1094procedure TMainForm.ShowLightLocation;
1095begin
1096with MainLightSource1.Position do
1097MainStatusBar.Panels[3].Text := 'Light: '+
1098FloatToStrF(X, ffNumber, 5, 2)+', '+FloatToStrF(Y, ffNumber, 5, 2)+', '+
1099FloatToStrF(Z, ffNumber, 5, 2);
1100end;
1101
1102procedure TMainForm.FormKeyPress(Sender: TObject; var Key: char);
1103begin
1104if Key = 'x' then DoMouseMoveObj := 1
1105else if Key = 'y' then DoMouseMoveObj := 2
1106else if Key = 'z' then DoMouseMoveObj := 3
1107else DoMouseMoveObj := 0;
1108end;
1109
1110procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
1111begin
1112DoMouseMoveObj := 0;
1113end;
1114
1115procedure TMainForm.CheckBox1Change(Sender: TObject);
1116begin
1117MoleculeAxis.Visible:= not(MoleculeAxis.Visible);
1118end;
1119
1120procedure TMainForm.CheckBox2Change(Sender: TObject);
1121begin
1122DCWorld.ShowAxes:= not(DCWorld.ShowAxes);
1123end;
1124
1125procedure TMainForm.CheckBox3Change(Sender: TObject);
1126begin
1127DCWorldGrid.Visible:= not(DCWorldGrid.Visible);
1128end;
1129
1130procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
1131begin
1132GLCadencer.Enabled:= False;
1133end;
1134
1135procedure TMainForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
1136WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
1137begin
1138//if (MousePoint.X >= GLViewer.Left) and
1139// (MousePoint.X <= GLViewer.Left + GLViewer.Width) and
1140// (MousePoint.Y >= GLViewer.Top) and
1141// (MousePoint.y <= GLViewer.Top + GLViewer.Height) then
1142//begin
1143{ a wheel step = WheelDelta/300; each step adjusts target distance by 2.5%
1144another method to zoom in or out }
1145GLCamera.AdjustDistanceToTarget(Power(1.025, WheelDelta / 300));
1146GLCamera.DepthOfView := 2 * GLCamera.DistanceToTarget + 2 * DCMoleculeWorld.BoundingSphereRadius;
1147// end;
1148Handled := True;
1149
1150end;
1151
1152procedure TMainForm.FormShow(Sender: TObject);
1153begin
1154Mol.CreateMolecule(DCMolecule);
1155mmoMolAtoms.Clear;
1156mmoMolAtoms.Lines := Mol.getAtomsInfos;
1157mmoMolBonds.Clear;
1158mmoMolBonds.Lines := Mol.getBondsInfos;
1159lblMolName.Caption := Mol.DisplayName;
1160
1161ShowCameraLocation;
1162ShowFocalLength;
1163ShowTargetLocation;
1164//ShowLightLocation;
1165
1166GLCadencer.Enabled:= true;
1167
1168end;
1169
1170procedure TMainForm.GLCadencerProgress(Sender: TObject; const deltaTime,newTime: Double);
1171begin
1172// Fait tourner la scene sur elle même sur l'axe des Y
1173if NavCube.InactiveTime > 5 then
1174begin
1175if NavCube.InactiveTime < 8 then
1176GLCamera.TurnAngle := GLCamera.TurnAngle + (NavCube.InactiveTime - 5) * deltaTime * 2
1177else
1178GLCamera.TurnAngle := GLCamera.TurnAngle + deltatime * 6;
1179end;
1180GLViewer.Refresh;
1181if Self.Focused then GLViewer.Invalidate;
1182end;
1183
1184procedure TMainForm.GLViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
1185Var
1186AtomData : TAtomData;
1187begin
1188MousePoint.X := X;
1189MousePoint.Y := Y;
1190if ssCtrl in Shift then
1191begin
1192if ssRight in Shift then Screen.Cursor := crRotate;
1193end
1194else if ssShift in Shift then
1195begin
1196Screen.Cursor := crDrag;
1197end
1198else
1199begin // no Shift, no Ctrl, no Alt
1200if ssleft in Shift then
1201begin
1202if Assigned(CurrentPick) then
1203begin
1204if CurrentPick is TGLSphere then
1205begin
1206if not(AtomInfosForm.Visible) then AtomInfosForm.Show;
1207AtomData := PeriodicTable.Items[CurrentPick.Tag];
1208UpdateAtomInfosForm(AtomData);
1209end;
1210end;
1211if DoMouseMoveObj>0 then
1212begin
1213NavCube.ActiveMouse := False;
1214if (DoMouseMoveObj = 1) then Screen.Cursor := crSlidexy
1215else if (DoMouseMoveObj = 2) then Screen.Cursor := crSlidezy
1216else if (DoMouseMoveObj = 3) then Screen.Cursor := crSlideyz;
1217end
1218else
1219begin
1220Screen.Cursor := crRotate;
1221NavCube.ActiveMouse := True;
1222end;
1223end
1224else if ssRight in Shift then Screen.Cursor := crZoom;
1225end;
1226
1227md:=true;
1228
1229end;
1230
1231procedure TMainForm.GLViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
1232var
1233d: double;
1234begin
1235if md and (Shift <> []) then
1236begin
1237if ssLeft in Shift then
1238begin
1239if ssShift in Shift then
1240begin
1241if ssCtrl in Shift then
1242begin
1243d := 0.01 * (X - MousePoint.x );
1244DCTarget.Translate(d, 0, 0);
1245d := 0.01 * (Y - MousePoint.y );
1246DCTarget.Translate(0, 0, d);
1247end
1248else
1249begin
1250d := 0.01 * (X - MousePoint.x );
1251DCTarget.Translate(d, 0, 0);
1252d := 0.01 * (Y - MousePoint.y );
1253DCTarget.Translate(0, d, 0);
1254end;
1255end
1256else
1257begin
1258if DoMouseMoveObj >0 then // Translate Object
1259begin
1260d := GLCamera.DistanceToTarget * 0.01 * (X - MousePoint.x + Y - MousePoint.y);
1261if (DoMouseMoveObj = 1) then DCMolecule.Translate(d, 0, 0)
1262else if (DoMouseMoveObj = 2) then DCMolecule.Translate(0, d, 0)
1263else if (DoMouseMoveObj = 3) then DCMolecule.Translate(0, 0, d);
1264
1265// Surely not working under *nix system
1266//if IsKeyDown('x') then DCMoleculeWorld.Translate(d, 0, 0)
1267//else if IsKeyDown('y') then DCMoleculeWorld.Translate(0, d, 0)
1268//else if IsKeyDown('z') then DCMoleculeWorld.Translate(0, 0, d)
1269end
1270else
1271begin // Move Around the world, like a Daft punk
1272// NavCube.ActiveMouse:=False;
1273GLCamera.MoveAroundTarget((MousePoint.y - Y) * 0.1, (MousePoint.x - X) * 0.1)
1274end;
1275end;
1276end
1277else if ssRight in Shift then
1278begin
1279if ssShift in Shift then //Adjuste Camera Distance to LookAt Target Object
1280begin
1281with GLCamera do AdjustDistanceToTarget(Power(1.0125, MousePoint.y - Y));
1282end
1283else if(ssCtrl in Shift) then // Rotate Target Object
1284begin
1285if (ssAlt in Shift) then
1286// 1st Solution : Rotate object with a very little step thrue Camera
1287GLCamera.RotateObject(DCMolecule, (MousePoint.y - Y) * 0.1, (MousePoint.x - X) * 0.1)
1288//GLCamera.RotateObject(DCMolecule, MousePoint.y - Y, MousePoint.x - X);
1289else
1290begin
1291// 2nd Solution : Rotate object directly by using Roll, Turn, Pitch functions
1292DCMolecule.Turn(MousePoint.y - Y);
1293DCMolecule.Pitch(MousePoint.x - X);
1294
1295// 3rd Solution : Rotate object thrue RotationAbsolute Functions
1296// DCMolecule.RotateAbsolute(MousePoint.x - X, MousePoint.y - Y,0);
1297
1298// 4rd Solution : Rotate object thrue Rotation propertie
1299// Note the all the follow lines don't work
1300// It's have a bug in the notification scheme of TGLCoordinates object
1301// DCMolecule.Rotation.X := MousePoint.x - X;
1302// DCMolecule.Rotation.Y := MousePoint.y - Y;
1303// or
1304//DCMolecule.Rotation.Rotate(XVector,90);
1305//DCMolecule.Rotation.Rotate(YVector,45);
1306
1307
1308end;
1309end
1310else
1311begin
1312with GLCamera do
1313begin
1314// Change Focal (FOV)
1315FocalLength := FocalLength - (MousePoint.y - Y);
1316if FocalLength > 3000 then FocalLength := 3000; { max focal length }
1317if FocalLength < 10 then FocalLength := 10; { min focal length }
1318end; { display in statusbar palel }
1319end;
1320end
1321end
1322else
1323begin
1324// find what's under the mouse
1325CurrentPick := (GLViewer.Buffer.GetPickedObject(x, y) as TGLCustomSceneObject);
1326// if it has changed since last MouseMove...
1327if (CurrentPick <> oldPick) then
1328begin
1329// ...turn to black previous "hot" object...
1330if Assigned(oldPick) then
1331begin
1332if (oldPick is TGLLines) then
1333TGLLines(oldPick).LineColor.DirectColor := OldColor
1334else
1335oldPick.Material.FrontProperties.Emission.Color := clrBlack;
1336end;
1337// ...and heat up the new selection...
1338if Assigned(CurrentPick ) then
1339begin
1340if CurrentPick is TGLLines then
1341begin
1342OldColor := TGLLines(CurrentPick).LineColor.DirectColor;
1343TGLLines(CurrentPick).LineColor.DirectColor := clrIndian;
1344end
1345else
1346CurrentPick .Material.FrontProperties.Emission.Color := clrIndian;
1347
1348LblMolInfo2.Text:= AnsiToUTF8(CurrentPick.Hint);
1349LblMolInfo2.Visible:=true;
1350end
1351else LblMolInfo2.Visible:=False;
1352
1353// ...and don't forget it !
1354oldPick := CurrentPick ;
1355
1356end;
1357end;
1358
1359
1360
1361MousePoint.X := X; { update mouse position }
1362MousePoint.Y := Y;
1363
1364end;
1365
1366procedure TMainForm.GLViewerMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
1367begin
1368Screen.Cursor := crDefault;
1369md := False;
1370end;
1371
1372procedure TMainForm.MainTimerTimer(Sender: TObject);
1373begin
1374ShowCameraLocation;
1375ShowFocalLength;
1376ShowTargetLocation;
1377// ShowLightLocation;
1378MainStatusBar.Panels[4].Text := Format('%.1f FPS', [GLViewer.FramesPerSecond]);
1379GLViewer.ResetPerformanceMonitor;
1380end;
1381
1382procedure TMainForm.MenuItem2Click(Sender: TObject);
1383begin
1384if OpenDlg.Execute then
1385begin
1386Mol.LoadFromFile(OpenDlg.FileName);
1387Mol.CreateMolecule(DCMolecule);
1388mmoMolAtoms.Clear;
1389mmoMolAtoms.Lines := Mol.getAtomsInfos;
1390mmoMolBonds.Clear;
1391mmoMolBonds.Lines := Mol.getBondsInfos;
1392lblMolName.Caption := Mol.DisplayName;
1393end;
1394end;
1395
1396procedure TMainForm.MenuItem4Click(Sender: TObject);
1397begin
1398Application.Terminate;
1399end;
1400
1401procedure TMainForm.MenuItem6Click(Sender: TObject);
1402begin
1403HelpCommandsForm.ShowModal;
1404end;
1405
1406procedure TMainForm.MenuItem9Click(Sender: TObject);
1407begin
1408CPKForm.Show;
1409end;
1410
1411procedure TMainForm.RadioGroup1Click(Sender: TObject);
1412begin
1413Mol.ViewMode:= RadioGroup1.ItemIndex;
1414GLViewer.Invalidate;
1415end;
1416
1417procedure TMainForm.UpdateAtomInfosForm(anAtom: TAtomData);
1418begin
1419if AtomInfosForm.Visible then
1420begin
1421with AtomInfosForm do
1422begin
1423lblAtomName.Caption := anAtom.name;
1424lblAtomicNum.Caption := IntToStr(anAtom.atomicNumber);
1425lblAtomSym.Caption := anAtom.symbol;
1426lblAtomYear.Caption := anAtom.yearDiscovered;
1427lblAtomBondType.Caption := cAtomBondingTypeStr[anAtom.bondingType];
1428lblIonizationNrj.Caption := IntToStr(anAtom.ionizationEnergy);
1429lblElectronAffinity.Caption := IntToStr(anAtom.electronAffinity);
1430lblElectronNeg.Caption := FloatToStr(anAtom.electronegativity);
1431lblAtomelectronicCfg.Caption := anAtom.electronicConfiguration;
1432lblDelWaalsRadius.Caption := FloatToStr(anAtom.vanDelWaalsRadius);
1433lblAtomicMass.Caption := anAtom.atomicMass;
1434lblonRadius.Caption := anAtom.ionRadius;
1435lblAtomicradius.Caption := IntToStr(anAtom.atomicRadius);
1436lblAtomDensity.Caption := FloatToStr(anAtom.density);
1437lblAtomOxidationState.Caption := anAtom.oxidationStates;
1438lblAtomBoilingPoint.Caption := IntToStr(anAtom.boilingPoint);
1439lblAtomMeltingPoint.Caption := IntToStr(anAtom.meltingPoint);
1440lblAtomStandardState.Caption := cAtomStandardStateStr[anAtom.standardState];
1441lblAtomGroup.Caption := anAtom.groupBlock; //cAtomGroupBlockStr[
1442end;
1443end;
1444end;
1445
1446
1447end.
1448
1449