25 #include "wx/wxprec.h"
32 #include "wx/notebook.h"
33 #include "wx/minifram.h"
35 #include "ObjCryst/wxCryst/wxCrystal.h"
37 #include "wx/colordlg.h"
38 #include "wx/progdlg.h"
39 #include "wx/busyinfo.h"
40 #include "wx/config.h"
42 #include "ObjCryst/Quirks/Chronometer.h"
43 #include "ObjCryst/ObjCryst/Atom.h"
44 #include "ObjCryst/ObjCryst/ZScatterer.h"
45 #include "ObjCryst/ObjCryst/Molecule.h"
46 #include "ObjCryst/ObjCryst/PowderPattern.h"
47 #include "ObjCryst/ObjCryst/ScatteringPowerSphere.h"
48 #include "ObjCryst/ObjCryst/Polyhedron.h"
56 #include <OpenGL/glu.h>
70 #include <GLUT/glut.h>
81 #include "ObjCryst/wxCryst/trackball.h"
102 static int sFontDisplayListBase=0;
105 GLvoid crystGLPrint(
const string &s)
107 glDisable (GL_BLEND);
109 for(
unsigned int l=0;l<s.size();l++)
110 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,*(s.c_str()+l));
117 static int shift = 0;
118 static bool microsoft_opengl_bug_init =
true;
119 if (microsoft_opengl_bug_init)
122 sv << glGetString(GL_VENDOR);
123 sr << glGetString(GL_RENDERER);
124 if((sv.str().find(
"Microsoft Corporation") != std::string::npos) && (sr.str().find(
"GDI Generic") != std::string::npos))
126 microsoft_opengl_bug_init =
false;
129 for (
unsigned int i = 0; i < s.size(); ++i) glCallList(sFontDisplayListBase + (
unsigned int)s.c_str()[i]);
132 glPushAttrib(GL_LIST_BIT);
133 glListBase(sFontDisplayListBase);
134 glCallLists(s.size(), GL_UNSIGNED_BYTE, s.c_str());
142 class UserSelectBoundingBox :
public wxDialog {
144 UserSelectBoundingBox(wxWindow * parent,
const char * title, BBox bbox);
145 ~UserSelectBoundingBox ();
148 void OnOk (wxCommandEvent & WXUNUSED(event));
149 wxTextCtrl * mpXminCtrl, *mpXmaxCtrl;
150 wxTextCtrl * mpYminCtrl, *mpYmaxCtrl;
151 wxTextCtrl * mpZminCtrl, *mpZmaxCtrl;
153 DECLARE_EVENT_TABLE()
157 class UserXYZBox :
public wxDialog {
159 UserXYZBox(wxWindow * parent,
const wxString &title, Triple xyz);
163 void OnOk (wxCommandEvent & WXUNUSED(event));
164 wxTextCtrl * mpXCtrl;
165 wxTextCtrl * mpYCtrl;
166 wxTextCtrl * mpZCtrl;
168 DECLARE_EVENT_TABLE()
176 WXCrystalScrolledGridWindow::WXCrystalScrolledGridWindow(wxWindow* parent, WXCrystal* p,
long id):
177 wxGrid(parent,id),mpWXCrystal(p)
180 WXCrystalScrolledGridWindow::~WXCrystalScrolledGridWindow()
182 if(mpWXCrystal!=0) mpWXCrystal->NotifyDeleteListWin(
this);
190 WXCrystal::RowScattPow::RowScattPow():
192 mBiso(1.0),mFormalCharge(0.0),mR(1.0),mG(1.0),mB(1.0),mMaximumLikelihoodError(0.0),mNbGhostAtoms(0.0),
193 mNeedUpdateUI(true),mIdx(-1)
201 Molecule* Atoms2Molecule(list<Atom *> &vAtom)
203 VFN_DEBUG_ENTRY(
"Atoms2Molecule()",6)
204 Molecule *mol=new Molecule((*vAtom.begin())->GetCrystal(),"Molecule");
205 const
unsigned long nb=vAtom.size();
208 for(list<Atom *>::iterator pos=vAtom.begin();pos!=vAtom.end();++pos)
210 REAL x=(*pos)->GetX();
211 REAL y=(*pos)->GetY();
212 REAL z=(*pos)->GetZ();
213 (*pos)->GetCrystal().FractionalToOrthonormalCoords(x,y,z);
217 mol->AddAtom(x,y,z,&((*pos)->GetScatteringPower()),(*pos)->GetName());
218 mol->GetAtom(i++).SetOccupancy((*pos)->GetOccupancy());
221 CrystVector_REAL x(nb),y(nb),z(nb),radius(nb);
222 vector<pair<const ScatteringPowerAtom *,long> > scattpow(nb);
223 for(
unsigned int i=0;i<nb;++i)
225 x(i)=mol->GetAtom(i).GetX();
226 y(i)=mol->GetAtom(i).GetY();
227 z(i)=mol->GetAtom(i).GetZ();
228 if(mol->GetAtom(i).IsDummy())
235 radius(i)=mol->GetAtom(i).GetScatteringPower().GetRadius();
236 scattpow[i].first=
dynamic_cast<const ScatteringPowerAtom *
>
237 (&(mol->GetAtom(i).GetScatteringPower()));
238 scattpow[i].second=scattpow[i].first->GetAtomicNumber();
241 for(
unsigned int i=0;i<nb;++i)
243 if(scattpow[i].first==0)
continue;
244 const REAL x1=x(i),y1=y(i),z1=z(i);
248 for(
unsigned int j=i+1;j<nb;++j)
250 if(scattpow[j].first==0)
continue;
251 const REAL dist=sqrt(x(j)*x(j)+y(j)*y(j)+z(j)*z(j));
253 if(dist<(1.10*(radius(i)+radius(j))))
255 if((1!=scattpow[i].second)||(1!=scattpow[j].second))
257 mol->AddBond(mol->GetAtom(i),mol->GetAtom(j),dist,.01,.02,
false);
265 mol->BuildConnectivityTable();
266 for(map<MolAtom*,set<MolAtom*> >::const_iterator pos=mol->GetConnectivityTable().begin();
267 pos!=mol->GetConnectivityTable().end();++pos)
269 for(set<MolAtom*>::const_iterator pos1=pos->second.begin();
270 pos1!=pos->second.end();++pos1)
272 for(set<MolAtom*>::const_iterator pos2=pos1;
273 pos2!=pos->second.end();++pos2)
275 if(pos2==pos1)
continue;
276 if(mol->FindBondAngle(**pos1,*(pos->first),**pos2)== mol->GetBondAngleList().end())
277 mol->AddBondAngle(**pos1,*(pos->first),**pos2,
278 GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,
false);
285 mol->GetCrystal().OrthonormalToFractionalCoords(x0,y0,z0);
289 mol->UpdateDisplay();
290 VFN_DEBUG_EXIT(
"ZScatterer2Molecule()",6)
299 static const
long ID_CRYSTAL_MENU_SAVECIF =WXCRYST_ID();
300 static const
long ID_CRYSTAL_MENU_SAVETEXT =WXCRYST_ID();
301 static const
long ID_CRYSTAL_MENU_DISPLAY =WXCRYST_ID();
302 static const
long ID_CRYSTAL_MENU_DISPLAY_3DVIEW =WXCRYST_ID();
303 static const
long ID_CRYSTAL_MENU_SCATT =WXCRYST_ID();
304 static const
long ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS =WXCRYST_ID();
305 static const
long ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES =WXCRYST_ID();
306 static const
long ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW =WXCRYST_ID();
307 static const
long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM =WXCRYST_ID();
308 static const
long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE =WXCRYST_ID();
309 static const
long ID_CRYSTAL_MENU_SCATT_ADDATOM =WXCRYST_ID();
310 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST =WXCRYST_ID();
311 static const
long ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER =WXCRYST_ID();
312 static const
long ID_CRYSTAL_MENU_SCATT_ADDMOLECULE =WXCRYST_ID();
313 static const
long ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE =WXCRYST_ID();
314 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX =WXCRYST_ID();
315 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX =WXCRYST_ID();
316 static const
long ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON =WXCRYST_ID();
317 static const
long ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON =WXCRYST_ID();
318 static const
long ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE =WXCRYST_ID();
319 static const
long ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE =WXCRYST_ID();
320 static const
long ID_CRYSTAL_MENU_SCATT_ADDCUBE =WXCRYST_ID();
321 static const
long ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL =WXCRYST_ID();
322 static const
long ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL =WXCRYST_ID();
323 static const
long ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON =WXCRYST_ID();
324 static const
long ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER =WXCRYST_ID();
325 static const
long ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER =WXCRYST_ID();
326 static const
long ID_CRYSTAL_MENU_ADD_INTERMOLECULARDIST =WXCRYST_ID();
327 static const
long ID_CRYSTAL_MENU_REMOVE_INTERMOLDIST_WIN =WXCRYST_ID();
328 static const
long ID_CRYSTAL_SPACEGROUP =WXCRYST_ID();
329 static const
long ID_GLCRYSTAL_MENU_UPDATE =WXCRYST_ID();
330 static const
long ID_GLCRYSTAL_WINDOW =WXCRYST_ID();
331 static const
long ID_CRYSTAL_WIN_SCATTPOW =WXCRYST_ID();
332 static const
long ID_CRYSTAL_WIN_ANTIBUMP =WXCRYST_ID();
333 static const
long ID_CRYSTAL_WIN_BONDVALENCE =WXCRYST_ID();
334 static const
long ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN =WXCRYST_ID();
335 static const
long ID_CRYSTAL_MENU_SHOW_INTERMOLDIST_WIN =WXCRYST_ID();
336 static const
long ID_CRYSTAL_WIN_INTERMOLDIST_EVENT =WXCRYST_ID();
339 static const
long ID_GLCRYSTAL_FOURIER_ADD= WXCRYST_ID();
340 static const
long ID_GLCRYSTAL_FOURIER_REMOVE= WXCRYST_ID();
341 static const
long ID_GLCRYSTAL_FOURIER_UPDATE= WXCRYST_ID();
342 static const
long ID_GLCRYSTAL_FOURIER_WIREFRAME= WXCRYST_ID();
343 static const
long ID_GLCRYSTAL_FOURIER_SHOW= WXCRYST_ID();
344 static const
long ID_GLCRYSTAL_FOURIER_SHARPEN= WXCRYST_ID();
345 static const
long ID_GLCRYSTAL_FOURIER_LISTMAP= WXCRYST_ID();
346 static const
long ID_GLCRYSTAL_FOURIER_LISTGLMAP= WXCRYST_ID();
347 static const
long ID_GLCRYSTAL_FOURIER_CONTOUR= WXCRYST_ID();
348 static const
long ID_GLCRYSTAL_FOURIER_NEWCONTOUR= WXCRYST_ID();
349 static const
long ID_GLCRYSTAL_FOURIER_COLOURPICKER= WXCRYST_ID();
352 BEGIN_EVENT_TABLE(WXCrystal,wxWindow)
353 EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse)
354 EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave)
355 EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad)
356 EVT_MENU(ID_CRYSTAL_MENU_SAVECIF, WXCrystal::OnMenuSaveCIF)
357 EVT_MENU(ID_CRYSTAL_MENU_SAVETEXT, WXCrystal::OnMenuSaveText)
358 EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
359 EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
360 EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize)
361 EVT_MENU(ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS, WXCrystal::OnMenuSetRelativeXYZLimits)
362 EVT_MENU(ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES, WXCrystal::OnMenuTestRandomMoves)
364 EVT_MENU(ID_CRYSTAL_MENU_DISPLAY_3DVIEW, WXCrystal::OnMenuCrystalGL)
366 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM, WXCrystal::OnMenuAddScattPowAtom)
367 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE, WXCrystal::OnMenuAddScattPowSphere)
368 EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW, WXCrystal::OnMenuRemoveScattPow)
369 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDATOM, WXCrystal::OnMenuAddScatterer)
370 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST, WXCrystal::OnMenuAddScatterer)
371 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER, WXCrystal::OnMenuAddScatterer)
372 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDMOLECULE, WXCrystal::OnMenuAddScatterer)
373 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE, WXCrystal::OnMenuAtoms2Molecule)
374 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX,WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix)
375 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX, WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix)
376 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON, WXCrystal::OnMenuAddScatterer)
377 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON, WXCrystal::OnMenuAddScatterer)
378 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE, WXCrystal::OnMenuAddScatterer)
379 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE, WXCrystal::OnMenuAddScatterer)
380 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDCUBE, WXCrystal::OnMenuAddScatterer)
381 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL,WXCrystal::OnMenuAddScatterer)
382 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL, WXCrystal::OnMenuAddScatterer)
383 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON, WXCrystal::OnMenuAddScatterer)
384 EVT_MENU(ID_CRYSTAL_MENU_ADD_INTERMOLECULARDIST, WXCrystal::OnMenuAddIntermolecularDistRestr)
385 EVT_MENU(ID_CRYSTAL_MENU_REMOVE_INTERMOLDIST_WIN, WXCrystal::OnMenuRemoveIntermolecularDistRestr)
386 EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER, WXCrystal::OnMenuRemoveScatterer)
387 EVT_MENU(ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER, WXCrystal::OnMenuDuplicateScatterer)
388 EVT_MENU(ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN, WXCrystal::OnMenuShowScattPowWindow)
389 EVT_MENU(ID_CRYSTAL_MENU_SHOW_INTERMOLDIST_WIN, WXCrystal::OnMenuShowIntermoDistWindow)
390 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
391 EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_SCATTPOW, WXCrystal::OnEditGridScattPow)
392 EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_ANTIBUMP, WXCrystal::OnEditGridScattPowAntiBump)
393 EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_BONDVALENCE,WXCrystal::OnEditGridScattPowBondValence)
394 EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_INTERMOLDIST_EVENT, WXCrystal::OnEditGridIntermolDistWindow)
398 WXCrystal::WXCrystal(wxWindow* parent, Crystal *obj):
399 WXRefinableObj(parent,(RefinableObj*)obj),mpCrystal(obj),
400 mpScattPowWin(0),mpAntiBumpWin(0),mpBondValenceWin(0),mpIntermolDistWin(0),
401 mIsSelfUpdating(false)
403 ,mCrystalGLDisplayList(0),mCrystalGLNameDisplayList(0),
406 ,mpConditionGLUpdate(0)
409 VFN_DEBUG_ENTRY(
"WXCrystal::WXCrystal()",6)
412 mpWXTitle->SetForegroundColour(wxColour(255,0,0));
414 mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ);
417 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVETEXT,"Save as text");
418 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVECIF,"Save as CIF");
419 mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
420 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
421 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
422 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE,
423 "Randomize Configuration");
424 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS,
425 "Set Relative Limits On All XYZ Parameters");
426 mpMenuBar->GetMenu(ID_REFOBJ_MENU_PAR).AppendSeparator();
427 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES,
428 "Test Random Moves for 30s");
429 mpMenuBar->AddMenu("Scatterers",ID_CRYSTAL_MENU_SCATT);
430 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN,
431 "Show Scattering Powers Parameters Window");
432 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
433 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM,
434 "Add Atomic Scattering Power");
435 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE,
436 "Add Sphere Scattering Power");
437 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW,
438 "Remove Scattering Power");
439 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
440 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDATOM,
442 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST,
443 "Import a List of Atoms");
444 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDMOLECULE,
446 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE,
447 "Convert Atoms to a Molecule");
448 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX,
449 "Import Molecule from Fenske-Hall Z-Matrix");
450 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX,
451 "Import Molecule from a named Z-Matrix");
452 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER,
454 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER,
455 "Duplicate Scatterer");
456 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
457 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON,
459 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON,
461 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE,
462 "Add Triangle Plane");
463 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE,
465 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDCUBE,
467 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,
468 ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL,
469 "Add Antiprism Tetragonal");
470 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL,
471 "Add Prism Trigonal");
472 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON,
474 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
475 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_ADD_INTERMOLECULARDIST,
476 "Add Intermolecular Distance Restraint");
477 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SHOW_INTERMOLDIST_WIN,
478 "Show Intermolecular Distance Restraints");
479 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_REMOVE_INTERMOLDIST_WIN,
480 "Remove Intermolecular Distance Restraints");
483 mpMenuBar->AddMenu("Display",ID_CRYSTAL_MENU_DISPLAY);
484 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_CRYSTAL_MENU_DISPLAY_3DVIEW,
494 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(0).WXGet())->SetToolTip(
495 _T("Use this option ONLY if you want to use\n")
496 _T("a higher symmetry than the one allowed by\n")
497 _T("the spacegroup. This can be useful to search\n")
498 _T("structures derived from higher symmetries.\n\n")
499 _T("This option should almost never be used."));
501 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(1).WXGet())->SetToolTip(
502 _T("This option allows Fox to automatically adjust\n")
503 _T("the occupancy of atoms that are on a special position,\n")
504 _T("or overlapping with another (e.g. two oxygens from\n")
505 _T("two polyhedra).\n\n")
506 _T("Practically you should choose:\n")
507 _T("- Yes for inorganic structures\n")
508 _T("- No for organic structures\n\n")
509 _T("This option increases computing time\n")
510 _T("by up to 50%, so only use when necessary\n\n")
511 _T("In doubt, choose Yes"));
513 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(2).WXGet())->SetToolTip(
514 _T("This option only affects the 3D display,\n")
515 _T("and is used to display the enantiomer\n")
516 _T("of the crystal structure.\n\n")
517 _T("This can be used to compare several\n")
518 _T("crystal structures."));
522 wxBoxSizer* pAntiBumpSizer=new wxBoxSizer(wxHORIZONTAL);
523 WXFieldPar<REAL> *pWXFieldBumpMerge=
524 new WXFieldPar<REAL>(this,"AntiBump",-1,&(mpCrystal->mBumpMergeCost),100);
525 WXFieldPar<REAL> *pAntiBumpScale=
526 new WXFieldPar<REAL>(this,"Scale",-1,&(mpCrystal->mBumpMergeScale));
527 pAntiBumpSizer->Add(pWXFieldBumpMerge);
528 pAntiBumpSizer->Add(pAntiBumpScale);
529 mpSizer->Add(pAntiBumpSizer,0,wxALIGN_LEFT);
530 mList.Add(pWXFieldBumpMerge);
531 mList.Add(pAntiBumpScale);
532 pWXFieldBumpMerge->SetFormat(_T("%8.2f"));
533 pAntiBumpScale->SetFormat(_T("%8.2f"));
534 pWXFieldBumpMerge->SetToolTip(_T("Current anti-bump cost"));
535 pAntiBumpScale->SetToolTip(
536 _T("Scale (multiplier) for the anti-bump cost.\n")
537 _T("If 0, the anti-bump will be ignored and not calculated\n")
538 _T("during optimization (saving time)\n\n")
539 _T("Use a value larger than 1 to increase the importance\n")
540 _T("of the anti-bump relatively to the diffraction data Chi^2\n\n")
541 _T("Note that anti-bump should only be used if the diffraction data\n\n")
542 _T("is not of good enough quality to ensure finding the correct\n\n")
545 wxBoxSizer* pBondValenceSizer=new wxBoxSizer(wxHORIZONTAL);
546 WXFieldPar<REAL> *pWXFieldBondValence=
547 new WXFieldPar<REAL>(this,"Bond Valence Cost",-1,&(mpCrystal->mBondValenceCost),100);
548 WXFieldPar<REAL> *pBondValenceScale=
549 new WXFieldPar<REAL>(this,"Scale",-1,&(mpCrystal->mBondValenceCostScale));
550 pBondValenceSizer->Add(pWXFieldBondValence);
551 pBondValenceSizer->Add(pBondValenceScale);
552 mpSizer->Add(pBondValenceSizer,0,wxALIGN_LEFT);
553 mList.Add(pWXFieldBondValence);
554 mList.Add(pBondValenceScale);
555 pWXFieldBondValence->SetFormat(_T("%8.2f"));
556 pBondValenceScale->SetFormat(_T("%8.2f"));
557 pWXFieldBondValence->SetToolTip(_T("Current bond valence cost"));
558 pBondValenceScale->SetToolTip(
559 _T("Scale (multiplier) for the bond valence cost.\n")
560 _T("If 0, the bond valence will be ignored and not calculated\n")
561 _T("during optimization (saving time)\n\n")
562 _T("Use a value larger than 1 to increase the importance\n")
563 _T("of the bond valence relatively to the diffraction data Chi^2\n\n")
564 _T("Note that bond valence should only be used if the diffraction data\n\n")
565 _T("is not of good enough quality to ensure finding the correct\n\n")
568 wxBoxSizer* pInterMolDistSizer=new wxBoxSizer(wxHORIZONTAL);
569 WXFieldPar<REAL> *pWXFieldInterMoldDistCost=
570 new WXFieldPar<REAL>(this,"Inter-molecular Distance Cost",-1,&(mpCrystal->mInterMolDistCost),100);
571 WXFieldPar<REAL> *pInterMoleDistScale=
572 new WXFieldPar<REAL>(this,"Scale",-1,&(mpCrystal->mInterMolDistCostScale));
573 pInterMolDistSizer->Add(pWXFieldInterMoldDistCost);
574 pInterMolDistSizer->Add(pInterMoleDistScale);
575 mpSizer->Add(pInterMolDistSizer,0,wxALIGN_LEFT);
576 mList.Add(pWXFieldInterMoldDistCost);
577 mList.Add(pInterMoleDistScale);
578 pWXFieldInterMoldDistCost->SetFormat(_T("%8.2f"));
579 pInterMoleDistScale->SetFormat(_T("%8.2f"));
580 pWXFieldInterMoldDistCost->SetToolTip(_T("Current Inter-molecular Distance cost"));
581 pInterMoleDistScale->SetToolTip(
582 _T("Scale (multiplier) for the inter-molecular distance cost.\n")
583 _T("If 0, the user-defined inter-molecular distances will be ignored and not calculated\n")
584 _T("during optimization (saving time)\n\n")
585 _T("Use a value larger than 1 to increase the importance\n")
586 _T("of the bond valence relatively to the diffraction data Chi^2.\n\n"));
589 wxBoxSizer* lattice=new wxBoxSizer(wxHORIZONTAL);
591 WXCrystObjBasic* pFieldLatticeA
592 =mpCrystal->GetPar("a").WXCreate(this);
593 WXCrystObjBasic* pFieldLatticeB
594 =mpCrystal->GetPar("b").WXCreate(this);
595 WXCrystObjBasic* pFieldLatticeC
596 =mpCrystal->GetPar("c").WXCreate(this);
597 WXCrystObjBasic* pFieldLatticeAlpha
598 =mpCrystal->GetPar("alpha").WXCreate(this);
599 WXCrystObjBasic* pFieldLatticeBeta
600 =mpCrystal->GetPar("beta").WXCreate(this);
601 WXCrystObjBasic* pFieldLatticeGamma
602 =mpCrystal->GetPar("gamma").WXCreate(this);
604 lattice->Add(pFieldLatticeA ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
605 lattice->Add(pFieldLatticeB ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
606 lattice->Add(pFieldLatticeC ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
607 lattice->Add(pFieldLatticeAlpha,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
608 lattice->Add(pFieldLatticeBeta ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
609 lattice->Add(pFieldLatticeGamma,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
612 mpSizer->Add(lattice,0,wxALIGN_LEFT);
613 mList.Add(pFieldLatticeA);
614 mList.Add(pFieldLatticeB);
615 mList.Add(pFieldLatticeC);
616 mList.Add(pFieldLatticeAlpha);
617 mList.Add(pFieldLatticeBeta);
618 mList.Add(pFieldLatticeGamma);
620 dynamic_cast<WXFieldRefPar *>(pFieldLatticeA)->SetFormat(_T("%8.4f"));
621 dynamic_cast<WXFieldRefPar *>(pFieldLatticeB)->SetFormat(_T("%8.4f"));
622 dynamic_cast<WXFieldRefPar *>(pFieldLatticeC)->SetFormat(_T("%8.4f"));
623 dynamic_cast<WXFieldRefPar *>(pFieldLatticeAlpha)->SetFormat(_T("%8.3f"));
624 dynamic_cast<WXFieldRefPar *>(pFieldLatticeBeta)->SetFormat(_T("%8.3f"));
625 dynamic_cast<WXFieldRefPar *>(pFieldLatticeGamma)->SetFormat(_T("%8.3f"));
627 pFieldLatticeA->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
628 pFieldLatticeB->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
629 pFieldLatticeC->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
630 pFieldLatticeAlpha->SetToolTip(_T("Lattice angle parameter (in degrees)"));
631 pFieldLatticeBeta->SetToolTip(_T("Lattice angle parameter (in degrees)"));
632 pFieldLatticeGamma->SetToolTip(_T("Lattice angle parameter (in degrees)"));
635 mpFieldSpacegroup=new WXFieldName(this,"SpaceGroup:",this,ID_CRYSTAL_SPACEGROUP,100);
636 mpSizer->Add(mpFieldSpacegroup,0,wxALIGN_LEFT);
637 mList.Add(mpFieldSpacegroup);
639 mpFieldSpacegroup->SetToolTip(_T("Spacegroup Symbol. You can use:\n\n")
640 _T("- spacegroup number: \"1\" \"62\" ... \"227\",\"230\"\n")
641 _T("- Hermann-Mauguin symbol: \"P1\" \"Pnma\" ... \"Fd3m\",\"Ia3d\"\n")
642 _T("- Hall symbol: \"P1\" \"-P 2ac 2n\" ... \"-F 4vw 2vw 3\",\"-I 4bd 2c 3\"\n\n")
643 _T("ORIGIN CHOICE: for some spacegroups there are several\n")
644 _T("possible origins - the default is the one on \n")
645 _T("the center of symmetry (origin 2). You can specify\n")
646 _T(" the origin by writing \"Fd3m:1\" or \"Fd3m:2\"\n\n")
647 _T("CELL CHOICE: to specify a rhomboedral or hexagonal unit cell,\n")
648 _T("append R or H to the symbol:\"R-3:R\"or \"R-3:H\"\n"));
651 mpWXScatteringPowerRegistry=mpCrystal
652 ->GetScatteringPowerRegistry().WXCreate(this);
653 mpSizer->Add(mpWXScatteringPowerRegistry,0,wxALIGN_LEFT);
654 mList.Add(mpWXScatteringPowerRegistry);
657 mpWXScattererRegistry=mpCrystal
658 ->GetScattererRegistry().WXCreate(this);
659 mpSizer->Add(mpWXScattererRegistry,0,wxALIGN_LEFT);
660 mList.Add(mpWXScattererRegistry);
661 this->CrystUpdate(true);
664 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Automatically open crystal 3D view")))
665 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Automatically open crystal 3D view"),
false);
668 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Automatically open crystal 3D view"), &val);
671 (*fpObjCrystInformUser)(
"Automatically opening 3D Crystal view");
672 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_CRYSTAL_MENU_DISPLAY_3DVIEW);
673 wxPostEvent(
this,event);
674 (*fpObjCrystInformUser)(
"Finished opening 3D Crystal view");
678 wxTheApp->GetTopWindow()->PostSizeEvent();
679 VFN_DEBUG_EXIT(
"WXCrystal::WXCrystal()",6)
682 WXCrystal::~WXCrystal()
684 VFN_DEBUG_ENTRY(
"WXCrystal::~WXCrystal()",10)
685 if(0!=mpScattPowWin) mpScattPowWin->GetParent()->Destroy();
686 if(0!=mpIntermolDistWin) mpIntermolDistWin->GetParent()->Destroy();
687 VFN_DEBUG_EXIT("WXCrystal::~WXCrystal()",10)
690 void WXCrystal::CrystUpdate(const
bool uui,const
bool lock)
692 VFN_DEBUG_ENTRY(
"WXCrystal::CrystUpdate()",5)
695 mpCrystal->GetBumpMergeCost();
696 mpCrystal->GetBondValenceCost();
697 mpCrystal->GetInterMolDistCost();
701 if(lock) mMutex.Lock();
702 BBox box=mpCrystalGL->GetCellBBox();
703 const REAL fadeDistance=mpCrystalGL->GetFadeDistance();
704 if(lock) mMutex.Unlock();
705 bool showFullMolecule;
706 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Show full molecules in 3D view"), &showFullMolecule);
708 this->UpdateGL(
false,box.xMin,box.xMax,box.yMin,box.yMax,box.zMin,box.zMax,fadeDistance, showFullMolecule);
711 if(lock) mMutex.Lock();
713 if((
false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() ) this->GetCrystal().InitRefParList();
719 if((
false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() &&(mpScattPowWin!=0)&&(mpAntiBumpWin!=0)&&(mpBondValenceWin!=0))
724 bool needLayout=
false;
726 for(map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();)
727 if(this->GetCrystal().GetScatteringPowerRegistry().Find(pos->second.mName,
"ScatteringPowerAtom",
true)<0)
729 VFN_DEBUG_MESSAGE(
"WXCrystal::CrystUpdate(): Removing scattering power: "<<pos->second.mName,5)
730 mpScattPowWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
731 mpAntiBumpWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
732 mpBondValenceWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
733 mpAntiBumpWin->DeleteCols(mvpRowScattPow.size()-1,1,
false);
734 mpBondValenceWin->DeleteCols(mvpRowScattPow.size()-1,1,
false);
735 mvpRowScattPow.erase(pos++);
740 for(
int i=0;i<this->GetCrystal().GetScatteringPowerRegistry().GetNb();++i)
742 ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i));
746 if(mvpRowScattPow.find(p)==mvpRowScattPow.end())
748 VFN_DEBUG_MESSAGE(
"WXCrystal::CrystUpdate(): Adding scattering power: "<<s->
GetName(),5)
749 mpScattPowWin->AppendRows();
750 mpAntiBumpWin->AppendRows();
751 mpAntiBumpWin->AppendCols();
752 mpBondValenceWin->AppendRows();
753 mpBondValenceWin->AppendCols();
763 for(
int i=0;i<this->GetCrystal().GetScatteringPowerRegistry().GetNb();++i)
765 ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i));
769 if(mvpRowScattPow[p].mIdx!=i-j)
771 mvpRowScattPow[p].mIdx=i-j;
772 mvpRowScattPow[p].mNeedUpdateUI=
true;
780 mpScattPowWin->FitInside();
781 mpAntiBumpWin->FitInside();
782 mpBondValenceWin->FitInside();
787 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
788 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
790 const string name=pos->first->
GetName();
791 const REAL biso=pos->first->GetBiso();
792 const REAL formalCharge=pos->first->GetFormalCharge();
793 const float *pRGB=pos->first->GetColourRGB();
794 const REAL mlerror=pos->first->GetMaximumLikelihoodPositionError();
795 const REAL nbghost=pos->first->GetMaximumLikelihoodNbGhostAtom();
796 if( (name !=pos->second.mName)
797 ||(biso !=pos->second.mBiso)
798 ||(formalCharge!=pos->second.mFormalCharge)
799 ||(pRGB[0]!=pos->second.mR)
800 ||(pRGB[1]!=pos->second.mG)
801 ||(pRGB[2]!=pos->second.mB)
802 ||(mlerror!=pos->second.mMaximumLikelihoodError)
803 ||(nbghost!=pos->second.mNbGhostAtoms)
804 || pos->second.mNeedUpdateUI)
806 pos->second.mName=name;
807 pos->second.mBiso=biso;
808 pos->second.mFormalCharge=formalCharge;
809 pos->second.mR=pRGB[0];
810 pos->second.mG=pRGB[1];
811 pos->second.mB=pRGB[2];
812 pos->second.mMaximumLikelihoodError=mlerror;
813 pos->second.mNbGhostAtoms=nbghost;
814 pos->second.mNeedUpdateUI=
true;
820 map<ScatteringPowerAtom*,RowScattPow>::iterator pos,pos1;
821 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
823 const string name=pos->first->GetName();
825 vector<REAL> dist(mvpRowScattPow.size());
826 for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1)
828 Crystal::VBumpMergePar::const_iterator pos2;
829 if(pos->first<pos1->first) pos2=pMap->find(make_pair(pos->first,pos1->first));
830 else pos2=pMap->find(make_pair(pos1->first,pos->first));
831 if(pos2==pMap->end()) dist[pos1->second.mIdx]=-999;
832 else dist[pos1->second.mIdx]=sqrt(pos2->second.mDist2);
834 if( (name!=pos->second.mName)
835 ||(dist!=pos->second.mvAntiBumpDistance)
836 || pos->second.mNeedUpdateUI)
838 pos->second.mName=name;
839 pos->second.mvAntiBumpDistance=dist;
840 pos->second.mNeedUpdateUI=
true;
846 map<ScatteringPowerAtom*,RowScattPow>::iterator pos,pos1;
847 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
849 const string name=pos->first->GetName();
850 const std::map<pair<const ScatteringPower*,const ScatteringPower*>, REAL> *pMap=&(mpCrystal->GetBondValenceRoList());
851 vector<REAL> ro(mvpRowScattPow.size());
852 for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1)
854 map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>::const_iterator pos2;
855 if(pos->first<pos1->first) pos2=pMap->find(make_pair(pos->first,pos1->first));
856 else pos2=pMap->find(make_pair(pos1->first,pos->first));
857 if(pos2==pMap->end()) ro[pos1->second.mIdx]=-999;
858 else ro[pos1->second.mIdx]=pos2->second;
860 if( (name!=pos->second.mName)
861 ||(ro!=pos->second.mvBondValenceRo)
862 || pos->second.mNeedUpdateUI)
864 pos->second.mName=name;
865 pos->second.mvBondValenceRo=ro;
866 pos->second.mNeedUpdateUI=
true;
871 if(lock) mMutex.Unlock();
873 this->WXRefinableObj::CrystUpdate(uui,lock);
874 VFN_DEBUG_EXIT(
"WXCrystal::CrystUpdate():End",5)
878 void WXCrystal::UpdateGL(
const bool onlyIndependentAtoms,
879 const REAL xMin,
const REAL xMax,
880 const REAL yMin,
const REAL yMax,
881 const REAL zMin,
const REAL zMax,
882 const REAL fadeDistance,
883 const bool fullMoleculeInLimits)
886 VFN_DEBUG_ENTRY(
"WXCrystal::UpdateGL()",8)
887 WXCrystValidateAllUserInput();
890 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():mpCrystalGL",7)
891 if(false==wxThread::IsMain())
893 mpConditionGLUpdate=
new wxCondition(mMutexGLUpdate);
894 bool ok=mpConditionGLUpdate->IsOk();
895 mMutexGLUpdate.Lock();
896 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
897 wxPostEvent(mpCrystalGL,event);
899 wxThread::This()->Yield();
901 while(mpConditionGLUpdate->WaitTimeout(200)!=wxCOND_NO_ERROR)
903 cout<<
"WXCrystal::UpdateGL():timeout waiting for mpConditionGLUpdate release: #"<<++ct<<
":"<<ok<<endl;
907 mMutexGLUpdate.Unlock();
908 delete mpConditionGLUpdate;
909 mpConditionGLUpdate=0;
910 VFN_DEBUG_EXIT(
"WXCrystal::UpdateGL()-Not in main thread :End",8)
913 mpCrystalGL->SetCurrent();
914 if(mCrystalGLDisplayList==0)
916 mCrystalGLDisplayList=glGenLists(1);
917 mCrystalGLNameDisplayList=glGenLists(1);
918 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():created mCrystalGLDisplayList=" << mCrystalGLDisplayList <<
",mCrystalGLNameDisplayList=" << mCrystalGLNameDisplayList, 10)
920 glNewList(mCrystalGLDisplayList,GL_COMPILE);
922 mpCrystal->GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,
false,!(mpCrystalGL->GetShowHydrogens()),fadeDistance,fullMoleculeInLimits);
931 glNewList(mCrystalGLNameDisplayList,GL_COMPILE);
933 mpCrystal->GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,
true,!(mpCrystalGL->GetShowHydrogens()),fadeDistance,fullMoleculeInLimits);
936 mpCrystalGL->CrystUpdate();
937 if(mpConditionGLUpdate!=0)
939 wxMutexLocker lock(mMutexGLUpdate);
940 mpConditionGLUpdate->Signal();
945 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():No mpCrystalGL",7)
947 VFN_DEBUG_EXIT(
"WXCrystal::UpdateGL():End",8)
950 int WXCrystal::GetCrystalGLDisplayList(
const bool atomName)
const
952 VFN_DEBUG_MESSAGE(
"WXCrystal::GetCrystalGLDisplayList()",7)
953 if(atomName) return mCrystalGLNameDisplayList;
954 return mCrystalGLDisplayList;
957 class WXGLCrystalCanvasFrame :public wxFrame
960 WXGLCrystalCanvasFrame(wxWindow *parent, wxWindowID
id,
const wxString& title,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE,
const wxString& name = wxFrameNameStr) :
961 wxFrame(parent, id, title, pos, size, style, name)
963 ~WXGLCrystalCanvasFrame()
965 gvWindowPosition[ID_GLCRYSTAL_WINDOW] = make_pair(this->GetScreenPosition(), this->GetSize());
970 void WXCrystal::OnMenuCrystalGL(wxCommandEvent & WXUNUSED(event))
972 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuCrystalGL()",6)
973 if(mpCrystalGL!=0) return;
975 if (gvWindowPosition.count(ID_GLCRYSTAL_WINDOW))
978 frame =
new WXGLCrystalCanvasFrame(
this, ID_GLCRYSTAL_WINDOW, wxString::Format(
"%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()),
979 gvWindowPosition[ID_GLCRYSTAL_WINDOW].first,
980 gvWindowPosition[ID_GLCRYSTAL_WINDOW].second, wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);
983 frame =
new WXGLCrystalCanvasFrame(
this, ID_GLCRYSTAL_WINDOW, wxString::Format(
"%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()),
984 wxDefaultPosition, wxSize(400, 400), wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);
986 mpCrystalGL=
new WXGLCrystalCanvas(
this,frame,-1);
988 frame->CreateStatusBar(1);
989 frame->SetStatusText(wxString::Format(
"%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()));
996 void WXCrystal::NotifyCrystalGLDelete()
998 VFN_DEBUG_MESSAGE(
"WXCrystal::NotifyCrystalGLDelete()",7)
1001 WXGLCrystalCanvas * WXCrystal::GetCrystalGL()
1003 VFN_DEBUG_MESSAGE(
"WXCrystal::GetCrystalGL()",7)
1008 void WXCrystal::OnMenuSaveCIF(wxCommandEvent & WXUNUSED(event))
1011 wxFileDialog save(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.cif"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1012 if(save.ShowModal() != wxID_OK)
return;
1014 ofstream out(save.GetPath().ToAscii());
1016 mpCrystal->CIFOutput(out);
1020 void WXCrystal::OnMenuSaveText(wxCommandEvent & WXUNUSED(event))
1023 wxFileDialog save(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1024 if(save.ShowModal() != wxID_OK)
return;
1026 ofstream out(save.GetPath().ToAscii());
1028 mpCrystal->Print(out);
1029 mpCrystal->PrintMinDistanceTable(.05,out);
1033 void WXCrystal::OnMenuAddScattPowAtom(wxCommandEvent & WXUNUSED(event))
1035 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScattPowAtom()",6)
1036 WXCrystValidateAllUserInput();
1037 ScatteringPowerAtom *scatt=new ScatteringPowerAtom("Change me","H");
1038 mpCrystal->AddScatteringPower(scatt);
1039 VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScattPowAtom():End",6)
1041 this->CrystUpdate(true,false);
1042 wxTheApp->GetTopWindow()->Layout();
1043 wxTheApp->GetTopWindow()->SendSizeEvent();
1046 void WXCrystal::OnMenuAddScattPowSphere(wxCommandEvent & WXUNUSED(event))
1048 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuAddScattSphere()",6)
1049 WXCrystValidateAllUserInput();
1050 ScatteringPower *scatt= new ScatteringPowerSphere;
1051 mpCrystal->AddScatteringPower(scatt);
1053 this->CrystUpdate(true,false);
1054 VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScattPowSphere()",6)
1055 wxTheApp->GetTopWindow()->Layout();
1056 wxTheApp->GetTopWindow()->SendSizeEvent();
1059 void WXCrystal::OnMenuRemoveScattPow(wxCommandEvent & WXUNUSED(event))
1061 VFN_DEBUG_ENTRY(
"WXCrystal::OnButtonRemoveScattPow()",6)
1062 WXCrystValidateAllUserInput();
1064 ScatteringPower *scatt=
1065 WXDialogChooseFromRegistry(mpCrystal->GetScatteringPowerRegistry(),this,
1066 "Choose Scattering Power to remove:",choice);
1069 VFN_DEBUG_EXIT(
"WXCrystal::OnButtonRemoveScattPow():Cancelled",6)
1072 const ScatteringComponentList *pList=&(mpCrystal->GetScatteringComponentList());
1073 for(
long i=0;i<pList->GetNbComponent();++i)
1074 if((*pList)(i).mpScattPow==scatt)
1076 wxMessageDialog dumbUser(
this,_T(
"This Scattering Power is still used !"),
1077 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
1078 dumbUser.ShowModal();
1079 VFN_DEBUG_EXIT(
"WXCrystal::OnButtonRemoveScattPow()",6)
1082 mpCrystal->RemoveScatteringPower(scatt);
1083 VFN_DEBUG_EXIT("WXCrystal::OnButtonRemoveScattPow()",6)
1085 this->CrystUpdate(true,false);
1086 wxTheApp->GetTopWindow()->Layout();
1087 wxTheApp->GetTopWindow()->SendSizeEvent();
1089 void WXCrystal::OnMenuRemoveIntermolecularDistRestr(wxCommandEvent & event)
1093 wxArrayString choices;
1094 choices.resize(mpCrystal->GetIntermolDistNb());
1095 for(
int i=0;i<choices.size();i++) {
1096 Crystal::InterMolDistPar imdp = mpCrystal->GetIntermolDistPar(i);
1098 for(
int j=0;j<imdp.mAt1.size();j++) {
1099 myline += imdp.mAt1[j] +
" ";
1102 for(
int j=0;j<imdp.mAt2.size();j++) {
1103 myline += imdp.mAt2[j] +
" ";
1106 choices[i] = myline;
1109 wxSingleChoiceDialog dialog(
this,_T(
"Choose restraints you want to delete"),_T(
"Select line"),choices);
1110 if(wxID_OK!=dialog.ShowModal())
return;
1111 int pos = dialog.GetSelection();
1113 mpCrystal->RemoveIntermolDistPar(pos);
1114 wxMessageDialog dialog5(
this, _T(
"The restriction was removed"));
1115 dialog5.ShowModal();
1117 wxTheApp->GetTopWindow()->Layout();
1118 wxTheApp->GetTopWindow()->SendSizeEvent();
1120 void WXCrystal::OnMenuAddIntermolecularDistRestr(wxCommandEvent & event)
1123 VFN_DEBUG_ENTRY(
"WXMolecule::OnMenuAddBond()",6)
1124 WXCrystValidateAllUserInput();
1126 const vector<Crystal::NamedScatteringComponent> pList=mpCrystal->GetNamedScatteringComponentList();
1128 wxArrayString choices;
1129 choices.resize(pList.size());
1130 for(
unsigned int i=0;i<pList.size();i++)
1131 choices[i]= wxString::FromAscii(pList[i].mName.c_str());
1133 wxMultiChoiceDialog dialog(this,_T("Choose name(s) of the first atom(s)"),_T("Select Atom(s)"),choices);
1134 if(wxID_OK!=dialog.ShowModal()) return;
1135 wxArrayInt At1=dialog.GetSelections();
1136 if((At1.size()==0) || (At1.size()>=pList.size())) return;
1138 wxMultiChoiceDialog dialog1(this,_T("Choose name(s) of the second atom(s)"),_T("Select Atom(s)"),choices);
1139 if(wxID_OK!=dialog1.ShowModal()) return;
1140 wxArrayInt At2=dialog1.GetSelections();
1141 if((At2.size()==0) || (At2.size()>=pList.size())) return;
1144 vector<
string> vectAt1;
1145 for(
int i=0;i<At1.size();i++) {
1146 tmpAt1 += choices[At1[i]];
1147 vectAt1.push_back(choices[At1[i]].ToStdString());
1148 if(i<(At1.size()-1)) {
1154 vector<string> vectAt2;
1155 for(
int i=0;i<At2.size();i++) {
1156 tmpAt2 += choices[At2[i]];
1157 vectAt2.push_back(choices[At2[i]].ToStdString());
1158 if(i<(At2.size()-1)) {
1162 string mes =
"Enter bond distance (Angstroems) for "+ tmpAt1 +
" - " + tmpAt2;
1163 wxTextEntryDialog dialog2(
this,wxString::FromAscii(mes.c_str()),
1164 _T(
"Intermolecular bond distance"),
"3.5",wxOK | wxCANCEL);
1165 dialog2.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1166 if(wxID_OK!=dialog2.ShowModal())
return;
1168 dialog2.GetValue().ToDouble(&d);
1170 wxTextEntryDialog dialog3(
this,_T(
"Enter sigma"),
1171 _T(
"Sigma"),
"0.1",wxOK | wxCANCEL);
1172 dialog3.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1173 if(wxID_OK!=dialog3.ShowModal())
return;
1175 dialog3.GetValue().ToDouble(&sigma);
1177 wxTextEntryDialog dialog4(
this,_T(
"Enter Delta"),
1178 _T(
"Delta"),
"0.5",wxOK | wxCANCEL);
1179 dialog4.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1180 if(wxID_OK!=dialog4.ShowModal())
return;
1182 dialog4.GetValue().ToDouble(&delta);
1184 mpCrystal->SetNewInterMolDist(vectAt1, vectAt2, d, sigma, delta);
1186 wxMessageDialog dialog5(
this, _T(
"The restriction was added"));
1187 dialog5.ShowModal();
1189 wxTheApp->GetTopWindow()->Layout();
1190 wxTheApp->GetTopWindow()->SendSizeEvent();
1193 void WXCrystal::OnMenuAddScatterer(wxCommandEvent &event)
1195 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuAddScatterer()",6)
1196 WXCrystValidateAllUserInput();
1198 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDATOM)
1201 ScatteringPower *scattPow=
1203 "Choose an atom type (ScatteringPower):",choice);
1206 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1209 scatt=new Atom(0,0,0,"Change Me!",scattPow);
1211 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST)
1213 wxFileDialog open(
this,_T(
"Choose a file with a list of atoms: Element x y z occup"),_T(
""),_T(
""),_T(
"*"),
1214 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1215 if(open.ShowModal() != wxID_OK)
return;
1216 ifstream fin (open.GetPath().ToAscii());
1219 throw ObjCrystException(
"WXCrystal::OnMenuAddScatterer() : Error opening file for input:"+
string(open.GetPath().ToAscii()));
1229 if(fin.eof())
break;
1230 fin>>x>>y>>z>>occup;
1231 cout<<symbol<<n<<
": "<<x<<
", "<<y<<
", "<<z<<endl;
1232 scattPow=mpCrystal->GetScatteringPowerRegistry().Find(symbol,
"ScatteringPowerAtom",
true);
1235 cout<<
"Scattering power "<<symbol<<
" not found, creating it..."<<endl;
1236 mpCrystal->AddScatteringPower(
new ScatteringPowerAtom(symbol,symbol));
1238 sprintf(buf,
"%d",n++);
1239 mpCrystal->AddScatterer(
new Atom(x,y,z,symbol+(
string)buf,&(mpCrystal->GetScatteringPower(symbol)),occup));
1240 if(fin.eof())
break;
1245 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER)
1247 scatt=
new ZScatterer(
"Change Me!",*mpCrystal);
1249 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDMOLECULE)
1251 scatt=
new Molecule(*mpCrystal,
"Molecule");
1253 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON)
1259 mpCrystal->GetScatteringPowerRegistry(),
1260 this,
"Central atom type (ScatteringPower):",choice);
1263 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1267 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1268 mpCrystal->GetScatteringPowerRegistry(),
1269 this,"Corner atom type (ScatteringPower):",choice);
1272 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1276 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1277 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1278 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1279 if(wxID_OK!=bondLengthDialog.ShowModal())
1281 VFN_DEBUG_EXIT(
"WXZScatterer))OnMenuAddZAtom())Cancelled",6)
1285 bondLengthDialog.GetValue().ToDouble(&bondLength);
1287 Molecule *mol=MakeTetrahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4",
1288 scattPow1,scattPow2,bondLength);
1289 mol->RestraintStatus(cout);
1292 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON)
1297 mpCrystal->GetScatteringPowerRegistry(),
1298 this,
"Central atom type (ScatteringPower):",choice);
1301 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1305 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1306 mpCrystal->GetScatteringPowerRegistry(),
1307 this,"Corner atom type (ScatteringPower))",choice);
1310 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1314 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1315 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1316 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1317 if(wxID_OK!=bondLengthDialog.ShowModal())
1319 VFN_DEBUG_EXIT(
"WXZScatterer))OnMenuAddZAtom())Cancelled",6)
1323 bondLengthDialog.GetValue().ToDouble(&bondLength);
1325 Molecule *mol=MakeOctahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6",
1326 scattPow1,scattPow2,bondLength);
1327 mol->RestraintStatus(cout);
1330 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE)
1332 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScatterer())Add triangle plane",6)
1335 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry(
1336 mpCrystal->GetScatteringPowerRegistry(),
1337 this,"Central atom type (ScatteringPower))",choice);
1340 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1344 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1345 mpCrystal->GetScatteringPowerRegistry(),
1346 this,"Corner atom type (ScatteringPower))",choice);
1349 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1353 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1354 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1355 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1356 if(wxID_OK!=bondLengthDialog.ShowModal())
1358 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1362 bondLengthDialog.GetValue().ToDouble(&bondLength);
1364 Molecule *mol=MakeTriangle(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"3",
1365 scattPow1,scattPow2,bondLength);
1366 mol->RestraintStatus(cout);
1369 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE)
1371 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScatterer():Add square plane",6)
1374 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry(
1375 mpCrystal->GetScatteringPowerRegistry(),
1376 this,"Central atom type (ScatteringPower))",choice);
1379 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1383 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1384 mpCrystal->GetScatteringPowerRegistry(),
1385 this,"Corner atom type (ScatteringPower))",choice);
1388 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1392 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1393 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1394 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1395 if(wxID_OK!=bondLengthDialog.ShowModal())
1397 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1401 bondLengthDialog.GetValue().ToDouble(&bondLength);
1403 Molecule *mol=MakeSquarePlane(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4",
1404 scattPow1,scattPow2,bondLength);
1405 mol->RestraintStatus(cout);
1408 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDCUBE)
1413 mpCrystal->GetScatteringPowerRegistry(),
1414 this,
"Central atom type (ScatteringPower):",choice);
1417 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1421 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1422 mpCrystal->GetScatteringPowerRegistry(),
1423 this,"Corner atom type (ScatteringPower))",choice);
1426 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1430 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1431 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1432 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1433 if(wxID_OK!=bondLengthDialog.ShowModal())
1435 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1439 bondLengthDialog.GetValue().ToDouble(&bondLength);
1441 Molecule *mol=MakeCube(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8",
1442 scattPow1,scattPow2,bondLength);
1443 mol->RestraintStatus(cout);
1446 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL)
1451 mpCrystal->GetScatteringPowerRegistry(),
1452 this,
"Central atom type (ScatteringPower):",choice);
1455 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1459 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1460 mpCrystal->GetScatteringPowerRegistry(),
1461 this,"Corner atom type (ScatteringPower))",choice);
1464 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1468 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1469 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1470 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1471 if(wxID_OK!=bondLengthDialog.ShowModal())
1473 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1477 bondLengthDialog.GetValue().ToDouble(&bondLength);
1479 Molecule *mol=MakeAntiPrismTetragonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8",
1480 scattPow1,scattPow2,bondLength);
1481 mol->RestraintStatus(cout);
1484 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL)
1489 mpCrystal->GetScatteringPowerRegistry(),
1490 this,
"Central atom type (ScatteringPower))",choice);
1493 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1497 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1498 mpCrystal->GetScatteringPowerRegistry(),
1499 this,"Corner atom type (ScatteringPower))",choice);
1502 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1506 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1507 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1508 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1509 if(wxID_OK!=bondLengthDialog.ShowModal())
1511 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom())Cancelled",6)
1515 bondLengthDialog.GetValue().ToDouble(&bondLength);
1517 Molecule *mol=MakePrismTrigonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6",
1518 scattPow1,scattPow2,bondLength);
1519 mol->RestraintStatus(cout);
1522 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON)
1527 mpCrystal->GetScatteringPowerRegistry(),
1528 this,
"Central atom type (ScatteringPower):",choice);
1531 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1535 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry(
1536 mpCrystal->GetScatteringPowerRegistry(),
1537 this,"Corner atom type (ScatteringPower):",choice);
1540 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1544 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1545 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1546 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1547 if(wxID_OK!=bondLengthDialog.ShowModal())
1549 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1553 bondLengthDialog.GetValue().ToDouble(&bondLength);
1555 Molecule *mol=MakeIcosahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"12",
1556 scattPow1,scattPow2,bondLength);
1557 mol->RestraintStatus(cout);
1562 mpCrystal->AddScatterer(scatt);
1563 mpCrystal->UpdateDisplay();
1565 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScatterer():calling Layout()",6)
1568 wxTheApp->GetTopWindow()->Layout();
1569 wxTheApp->GetTopWindow()->SendSizeEvent();
1570 VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer()",6)
1573 void WXCrystal::OnMenuRemoveScatterer(wxCommandEvent & WXUNUSED(event))
1575 VFN_DEBUG_MESSAGE(
"WXCrystal::OnButtonRemoveScatterer()",6)
1576 WXCrystValidateAllUserInput();
1578 Scatterer *scatt=WXDialogChooseFromRegistry(mpCrystal->GetScattererRegistry(),this,
1579 "Select the Scatterer to remove:",choice);
1580 if(0==scatt) return;
1581 mpCrystal->RemoveScatterer(scatt);
1582 VFN_DEBUG_MESSAGE("WXCrystal::OnButtonRemoveScatterer():End",6)
1584 wxTheApp->GetTopWindow()->Layout();
1585 wxTheApp->GetTopWindow()->SendSizeEvent();
1586 this->CrystUpdate(true);
1589 void WXCrystal::OnMenuDuplicateScatterer(wxCommandEvent & WXUNUSED(event))
1591 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuDuplicateScatterer()",6)
1592 WXCrystValidateAllUserInput();
1594 Scatterer *scatt=WXDialogChooseFromRegistry(mpCrystal->GetScattererRegistry(),this,
1595 "Select the Scatterer to duplicate:",choice);
1596 if(0==scatt) return;
1597 Scatterer *copy=scatt->CreateCopy();
1598 scatt->SetName(scatt->GetName()+(
string)"(copy)");
1599 mpCrystal->AddScatterer(copy);
1601 wxTheApp->GetTopWindow()->Layout();
1602 wxTheApp->GetTopWindow()->SendSizeEvent();
1603 VFN_DEBUG_EXIT("WXCrystal::OnMenuDuplicateScatterer():End",6)
1606 Molecule *ZScatterer2Molecule(ZScatterer *scatt);
1608 void WXCrystal::OnMenuAtoms2Molecule(wxCommandEvent &event)
1611 for(
unsigned int i=0; i<mpCrystal->GetScattererRegistry().GetNb();++i)
1613 Atom *pAtom=
dynamic_cast<Atom *
>(&(mpCrystal->GetScattererRegistry().GetObj(i)));
1614 if(pAtom!=0) v.push_back(pAtom);
1616 const unsigned int nb=v.size();
1617 wxString *choices =
new wxString[nb];
1618 for(
unsigned int i=0;i<nb;i++)
1619 choices[i]= wxString::FromAscii((v[i]->GetName()).c_str());
1621 wxMultiChoiceDialog dialog (
this,_T(
"Choose the molecule's atoms"),_T(
"Select Atoms"),nb,choices,wxOK | wxCANCEL);
1622 dialog.SetSize(300,300);
1624 wxMultiChoiceDialog_ListBox dialog(
this,_T(
"Choose the molecule's atoms"),_T(
"Select Atoms"),nb,choices);
1626 if(wxID_OK!=dialog.ShowModal())
return;
1627 wxArrayInt choice=dialog.GetSelections();
1628 if(choice.GetCount()>0)
1630 list<Atom*> vChoice;
1631 for(
unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(v[choice.Item(i)]);
1633 mpCrystal->AddScatterer(Atoms2Molecule(vChoice));
1634 for(
unsigned int i=0;i<choice.GetCount();++i) mpCrystal->RemoveScatterer(v[choice.Item(i)]);
1635 mpCrystal->UpdateDisplay();
1637 wxTheApp->GetTopWindow()->Layout();
1638 wxTheApp->GetTopWindow()->SendSizeEvent();
1641 void WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix(wxCommandEvent &event)
1643 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuImportFenskeHallZMatrix()",6)
1644 WXCrystValidateAllUserInput();
1645 string tmp("Fenske-Hall z-matrix|*.fhz;*.fh");
1646 if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) tmp="Fox z-matrix|*.zmat";
1647 wxFileDialog open(this,_T("Choose a file with a Fenske-Hall Z-matrix"),_T(""),_T(""), wxString::FromAscii(tmp.c_str()),
1648 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1649 if(open.ShowModal() != wxID_OK) return;
1650 ifstream fin ( open.GetPath().ToAscii());
1653 throw ObjCrystException(
"WXCrystal::OnMenuImportFenskeHallZMatrix() : \
1654 Error opening file for input:"+
string(open.GetPath().ToAscii()));
1656 string filename(open.GetPath().ToAscii());
1659 std::string::size_type idx =filename.rfind(
"/");
1660 std::string::size_type idx2=filename.rfind(
"\\");
1661 std::string::size_type idx3=filename.rfind(
":");
1662 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
1663 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
1664 if(idx==string::npos)
1667 shortName=filename.substr(idx+1);
1669 ZScatterer scatt(shortName,*mpCrystal);
1671 if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) named=
true;
1672 scatt.ImportFenskeHallZMatrix(fin,named);
1675 wxTheApp->GetTopWindow()->Layout();
1676 wxTheApp->GetTopWindow()->SendSizeEvent();
1677 this->CrystUpdate(
true);
1678 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuImportFenskeHallZMatrix()",6)
1681 void WXCrystal::OnMenuSetRelativeXYZLimits(wxCommandEvent & WXUNUSED(event))
1683 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6)
1684 WXCrystValidateAllUserInput();
1685 wxTextEntryDialog limitDialog(this,_T("Relative limits"),
1686 _T("Enter relative limits for x,y,z (Angstroems)"),
1687 _T("0.5"),wxOK | wxCANCEL);
1688 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1689 if(wxID_OK!=limitDialog.ShowModal())
1691 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6)
1695 limitDialog.GetValue().ToDouble(&limit);
1698 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslX,
1699 -limit/mpCrystal->GetLatticePar(0),
1700 limit/mpCrystal->GetLatticePar(0));
1701 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslY,
1702 -limit/mpCrystal->GetLatticePar(1),
1703 limit/mpCrystal->GetLatticePar(1));
1704 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslZ,
1705 -limit/mpCrystal->GetLatticePar(2),
1706 limit/mpCrystal->GetLatticePar(2));
1707 VFN_DEBUG_EXIT("WXCrystal::OnMenuSetRelativeXYZLimits()",6)
1711 class TestCrystalThread: public wxThread
1714 TestCrystalThread(Crystal &cryst,
float seconds):
1715 wxThread(wxTHREAD_DETACHED),mpCryst(&cryst),mSeconds(seconds){};
1716 virtual void *Entry()
1718 cout<<endl<<
"Entering refinement thread "<<endl<<endl;
1719 mpCryst->BeginOptimization();
1721 float dt0=chrono.seconds();
1722 while(chrono.seconds()<30)
1724 mpCryst->BeginGlobalOptRandomMove();
1725 mpCryst->GlobalOptRandomMove(0.05,gpRefParTypeObjCryst);
1727 if((chrono.seconds()-dt0)>0.05) {mpCryst->UpdateDisplay();dt0=chrono.seconds();}
1729 mpCryst->EndOptimization();
1732 virtual void OnExit()
1734 cout <<endl<<
"Exiting refinement thread "<<endl<<endl;
1743 void WXCrystal::OnMenuTestRandomMoves(wxCommandEvent &event)
1745 TestCrystalThread *pTest =
new TestCrystalThread(*mpCrystal,30);
1746 if(pTest->Create() != wxTHREAD_NO_ERROR)
1747 wxLogError(_T(
"Can't create test optimization thread"));
1751 bool WXCrystal::OnChangeName(
const int id)
1753 VFN_DEBUG_MESSAGE(
"WXCrystal::OnChangeName()",6)
1754 if(this->WXRefinableObj::OnChangeName(
id)==
true)
return true;
1755 if(
id==ID_CRYSTAL_SPACEGROUP)
1757 VFN_DEBUG_MESSAGE(
"WXCrystal::OnChangeName():Changing SpaceGroup",6)
1758 mpCrystal->Init(mpCrystal->GetLatticePar(0),
1759 mpCrystal->GetLatticePar(1),
1760 mpCrystal->GetLatticePar(2),
1761 mpCrystal->GetLatticePar(3),
1762 mpCrystal->GetLatticePar(4),
1763 mpCrystal->GetLatticePar(5),
1764 mpFieldSpacegroup->GetValue(),
1765 mpCrystal->GetName());
1766 this->CrystUpdate(
true);
1773 void WXCrystal::UpdateUI(
const bool lock)
1775 VFN_DEBUG_ENTRY(
"WXCrystal::UpdateUI()",6)
1776 if(!mpCrystal->IsBeingRefined())
1778 if(lock) mMutex.Lock();
1779 mpFieldSpacegroup->SetValue(mpCrystal->GetSpaceGroup().GetName());
1781 if(0!=mpCrystalGL) mpCrystalGL->GetParent()->SetLabel(wxString::Format(
"%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()));
1783 if(lock) mMutex.Unlock();
1785 if(lock) mMutex.Lock();
1786 if(0!=mpScattPowWin)
1788 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1789 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1791 if(pos->second.mNeedUpdateUI==
true)
1793 mIsSelfUpdating=
true;
1794 mpScattPowWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1796 tmp.Printf(_T(
"%f"),pos->second.mBiso);
1797 mpScattPowWin->SetCellValue(pos->second.mIdx, 0, tmp);
1798 tmp.Printf(_T(
"%f"),pos->second.mFormalCharge);
1799 mpScattPowWin->SetCellValue(pos->second.mIdx, 1, tmp);
1800 tmp.Printf(_T(
"%f"),pos->second.mR);
1801 mpScattPowWin->SetCellValue(pos->second.mIdx, 2, tmp);
1802 tmp.Printf(_T(
"%f"),pos->second.mG);
1803 mpScattPowWin->SetCellValue(pos->second.mIdx, 3, tmp);
1804 tmp.Printf(_T(
"%f"),pos->second.mB);
1805 mpScattPowWin->SetCellValue(pos->second.mIdx, 4, tmp);
1806 tmp.Printf(_T(
"%f"),pos->second.mMaximumLikelihoodError);
1807 mpScattPowWin->SetCellValue(pos->second.mIdx, 5, tmp);
1808 tmp.Printf(_T(
"%f"),pos->second.mNbGhostAtoms);
1809 mpScattPowWin->SetCellValue(pos->second.mIdx, 6, tmp);
1810 mIsSelfUpdating=
false;
1814 if(0!=mpAntiBumpWin)
1816 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1817 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1819 if(pos->second.mNeedUpdateUI==
true)
1821 mIsSelfUpdating=
true;
1822 mpAntiBumpWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1823 mpAntiBumpWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1825 for(
unsigned long j=0;j<pos->second.mvAntiBumpDistance.size();++j)
1827 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateUI():Antibump("<<pos->first->GetName()
1829 <<
")="<<pos->second.mvAntiBumpDistance[j],3);
1830 if(pos->second.mvAntiBumpDistance[j]>-998)
1832 tmp.Printf(_T(
"%f"),pos->second.mvAntiBumpDistance[j]);
1833 mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,tmp);
1834 }
else mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,_T(
""));
1836 mIsSelfUpdating=
false;
1840 if(0!=mpBondValenceWin)
1842 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1843 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1845 if(pos->second.mNeedUpdateUI==
true)
1847 mIsSelfUpdating=
true;
1848 mpBondValenceWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1849 mpBondValenceWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1851 for(
unsigned long j=0;j<pos->second.mvBondValenceRo.size();++j)
1853 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateUI():BondValence("<<pos->first->GetName()
1855 <<
")="<<pos->second.mvBondValenceRo[j],3);
1856 if(pos->second.mvBondValenceRo[j]>-998)
1858 tmp.Printf(_T(
"%f"),pos->second.mvBondValenceRo[j]);
1859 mpBondValenceWin->SetCellValue(pos->second.mIdx,j,tmp);
1860 }
else mpBondValenceWin->SetCellValue(pos->second.mIdx,j,_T(
""));
1862 mIsSelfUpdating=
false;
1866 if(lock) mMutex.Unlock();
1867 this->WXRefinableObj::UpdateUI(lock);
1868 VFN_DEBUG_EXIT(
"WXCrystal::UpdateUI()",6)
1870 Crystal& WXCrystal::GetCrystal(){
return *mpCrystal;}
1871 const Crystal& WXCrystal::GetCrystal()
const{
return *mpCrystal;}
1873 void WXCrystal::OnMenuShowIntermoDistWindow(wxCommandEvent &event)
1875 if(mpIntermolDistWin!=0)
return;
1877 wxFrame *frame=
new wxFrame(
this,-1,_T(
"Intermolecular Distance Restraints"),
1878 wxDefaultPosition,wxSize(800,300));
1880 mpIntermolDistWin =
new WXCrystalScrolledGridWindow(frame,
this,ID_CRYSTAL_WIN_INTERMOLDIST_EVENT);
1884 mpIntermolDistWin->SetColMinimalAcceptableWidth(150);
1885 mpIntermolDistWin->CreateGrid(0,5);
1887 mpIntermolDistWin->SetColLabelValue(0,_T(
"At1"));
1888 mpIntermolDistWin->SetColLabelValue(1,_T(
"At2"));
1889 mpIntermolDistWin->SetColFormatFloat(2,5,3);
1890 mpIntermolDistWin->SetColLabelValue(2,_T(
"Distance"));
1891 mpIntermolDistWin->SetColFormatFloat(3,5,3);
1892 mpIntermolDistWin->SetColLabelValue(3,_T(
"Sigma"));
1893 mpIntermolDistWin->SetColFormatFloat(4,5,3);
1894 mpIntermolDistWin->SetColLabelValue(4,_T(
"Delta"));
1896 mpIntermolDistWin->AutoSizeRows();
1897 mpIntermolDistWin->AutoSizeColumns();
1899 mpIntermolDistWin->AppendRows(mpCrystal->GetIntermolDistNb());
1900 for(
int i=0;i<mpCrystal->GetIntermolDistNb();i++) {
1901 Crystal::InterMolDistPar imdp = mpCrystal->GetIntermolDistPar(i);
1903 for(
int j=0;j<imdp.mAt1.size();j++) {
1904 tmpAt1 += imdp.mAt1[j] +
" ";
1906 mpIntermolDistWin->SetCellValue(i, 0, tmpAt1);
1909 for(
int j=0;j<imdp.mAt2.size();j++) {
1910 tmpAt2 += imdp.mAt2[j] +
" ";
1912 mpIntermolDistWin->SetCellValue(i, 1, tmpAt2);
1913 float d = imdp.mDist2;
1914 if(d>0.0) d=sqrt(d);
1915 mpIntermolDistWin->SetCellValue(i, 2, wxString::Format(wxT(
"%f"), d));
1916 mpIntermolDistWin->SetCellValue(i, 3, wxString::Format(wxT(
"%f"), imdp.mSig));
1917 mpIntermolDistWin->SetCellValue(i, 4, wxString::Format(wxT(
"%f"), imdp.mDelta));
1920 this->CrystUpdate(
true);
1925 void WXCrystal::OnMenuShowScattPowWindow(wxCommandEvent &event)
1927 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuShowScattPowWindow()",10)
1928 if(0!=mpScattPowWin) return;
1929 WXCrystValidateAllUserInput();
1931 wxFrame *frame= new wxFrame(this,-1,_T("Scattering Powers parameters for: ")
1932 + wxString::FromAscii(this->GetCrystal().GetName().c_str()),
1933 wxDefaultPosition,wxSize(800,300));
1935 wxNotebook *notebook = new wxNotebook(frame, -1);
1937 mpScattPowWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_SCATTPOW);
1938 notebook->AddPage(mpScattPowWin, _T(
"Scattering Powers"),
true);
1940 mpScattPowWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1941 mpScattPowWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1942 mpScattPowWin->SetColMinimalAcceptableWidth(150);
1943 mpScattPowWin->CreateGrid(0,7);
1945 mpScattPowWin->SetColLabelValue(0,_T(
"Biso"));
1946 mpScattPowWin->SetColLabelValue(1,_T(
"Charge"));
1947 mpScattPowWin->SetColLabelValue(2,_T(
"Red"));
1948 mpScattPowWin->SetColLabelValue(3,_T(
"Green"));
1949 mpScattPowWin->SetColLabelValue(4,_T(
"Blue"));
1950 mpScattPowWin->SetColLabelValue(5,_T(
"ML Error"));
1951 mpScattPowWin->SetColLabelValue(6,_T(
"#ghost"));
1953 mpScattPowWin->AutoSizeRows();
1954 mpScattPowWin->AutoSizeColumns();
1957 mpAntiBumpWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_ANTIBUMP);
1958 notebook->AddPage(mpAntiBumpWin, _T(
"AntiBump"),
true);
1960 mpAntiBumpWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1961 mpAntiBumpWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1962 mpAntiBumpWin->SetColMinimalAcceptableWidth(150);
1963 mpAntiBumpWin->CreateGrid(0,0);
1965 mpAntiBumpWin->AutoSizeRows();
1966 mpAntiBumpWin->AutoSizeColumns();
1969 mpBondValenceWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_BONDVALENCE);
1970 notebook->AddPage(mpBondValenceWin, _T(
"BondValence"),
true);
1972 mpBondValenceWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1973 mpBondValenceWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1974 mpBondValenceWin->SetColMinimalAcceptableWidth(150);
1975 mpBondValenceWin->CreateGrid(0,0);
1977 mpBondValenceWin->AutoSizeRows();
1978 mpBondValenceWin->AutoSizeColumns();
1980 notebook->SetSelection(0);
1981 this->CrystUpdate(
true);
1985 void WXCrystal::OnEditGridIntermolDistWindow(wxGridEvent &e)
1987 if(mIsSelfUpdating)
return;
1988 if(mpCrystal->GetIntermolDistNb() == 0)
return;
1990 const int r=e.GetRow();
1991 const int c=e.GetCol();
1993 Crystal::InterMolDistPar *imdp = mpCrystal->GetIntermolDistPar_ptr(r);
1996 wxString s=mpIntermolDistWin->GetCellValue(r,c);
2004 stringstream ss(s.ToStdString());
2007 while (ss >> word) {
2008 At1.push_back(word);
2011 for(
int i=0;i<At1.size();i++) {
2012 if(mpCrystal->FindScatterersInComponentList(At1[i]).size()==0) {
2014 wxMessageBox(wxString::Format(
"Atom with %s name does not exist !", At1[i].c_str()), _T(
"Unknown atom"), wxOK | wxICON_INFORMATION,
this);
2022 wxMessageBox(_T(
"The cell is empty, please write there at least one atom name !"), _T(
"Unknown atom"), wxOK | wxICON_INFORMATION,
this);
2030 stringstream ss(s.ToStdString());
2033 while (ss >> word) {
2034 At2.push_back(word);
2037 for(
int i=0;i<At2.size();i++) {
2038 if(mpCrystal->FindScatterersInComponentList(At2[i]).size()==0) {
2040 wxMessageBox(wxString::Format(
"Atom with %s name does not exist !", At2[i].c_str()), _T(
"Unknown atom"), wxOK | wxICON_INFORMATION,
this);
2048 wxMessageBox(_T(
"The cell is empty, please write there at least one atom name !"), _T(
"Unknown atom"), wxOK | wxICON_INFORMATION,
this);
2083 mpCrystal->mInterMolDistListNeedsInit=
true;
2084 this->CrystUpdate();
2087 void WXCrystal::OnEditGridScattPow(wxGridEvent &e)
2089 if(mIsSelfUpdating)
return;
2090 const int r=e.GetRow();
2091 const int c=e.GetCol();
2092 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
2093 while(pos->second.mIdx!=r)++pos;
2094 ScatteringPowerAtom *
const p=pos->first;
2096 wxString s=mpScattPowWin->GetCellValue(r,c);
2115 p->SetFormalCharge(d);
2125 const REAL gg=p->GetColourRGB()[1];
2126 const REAL bb=p->GetColourRGB()[2];
2127 p->SetColour(d,gg,bb);
2137 const REAL rr=p->GetColourRGB()[0];
2138 const REAL bb=p->GetColourRGB()[2];
2139 p->SetColour(rr,d,bb);
2149 const REAL rr=p->GetColourRGB()[0];
2150 const REAL gg=p->GetColourRGB()[1];
2151 p->SetColour(rr,gg,d);
2161 p->SetMaximumLikelihoodPositionError(d);
2171 p->SetMaximumLikelihoodNbGhostAtom(d);
2176 this->CrystUpdate();
2179 void WXCrystal::OnEditGridScattPowAntiBump(wxGridEvent &e)
2181 if(mIsSelfUpdating)
return;
2182 const int r=e.GetRow();
2183 const int c=e.GetCol();
2185 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
2186 while(pos->second.mIdx!=r)++pos;
2187 const ScatteringPowerAtom *
const p1=pos->first;
2189 pos=mvpRowScattPow.begin();
2190 while(pos->second.mIdx!=c)++pos;
2191 const ScatteringPowerAtom *
const p2=pos->first;
2193 wxString s=mpAntiBumpWin->GetCellValue(r,c);
2196 if(d>0.01) mpCrystal->SetBumpMergeDistance(*p1,*p2,d);
2197 else mpCrystal->RemoveBumpMergeDistance(*p1,*p2);
2198 this->CrystUpdate(
true,
false);
2201 void WXCrystal::OnEditGridScattPowBondValence(wxGridEvent &e)
2203 if(mIsSelfUpdating)
return;
2204 const int r=e.GetRow();
2205 const int c=e.GetCol();
2207 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
2208 while(pos->second.mIdx!=r)++pos;
2209 const ScatteringPowerAtom *
const p1=pos->first;
2211 pos=mvpRowScattPow.begin();
2212 while(pos->second.mIdx!=c)++pos;
2213 const ScatteringPowerAtom *
const p2=pos->first;
2215 wxString s=mpBondValenceWin->GetCellValue(r,c);
2218 if(d>0.01) mpCrystal->AddBondValenceRo(*p1,*p2,d);
2219 else mpCrystal->RemoveBondValenceRo(*p1,*p2);
2220 this->CrystUpdate(
true,
false);
2223 void WXCrystal::NotifyDeleteListWin(WXCrystalScrolledGridWindow *win)
2225 if(win==mpScattPowWin) mpScattPowWin=0;
2226 if(win==mpAntiBumpWin) mpAntiBumpWin=0;
2227 if(win==mpBondValenceWin) mpBondValenceWin=0;
2228 if(win==mpIntermolDistWin) mpIntermolDistWin=0;
2230 if((mpScattPowWin==0)&&(mpAntiBumpWin==0)&&(mpBondValenceWin==0)) mvpRowScattPow.clear();
2272 bool WXCrystal::Enable(
bool e)
2274 if(0!=mpScattPowWin) mpScattPowWin ->Enable(e);
2275 if(0!=mpAntiBumpWin) mpAntiBumpWin ->Enable(e);
2276 if(0!=mpBondValenceWin) mpBondValenceWin->Enable(e);
2277 if(0!=mpIntermolDistWin) mpIntermolDistWin->Enable(e);
2278 return this->::wxWindow::Enable(e);
2287 UnitCellMap::UnitCellMap(
const Crystal&crystal):
2290 UnitCellMap::~UnitCellMap(){}
2291 void UnitCellMap::GLInitDisplayList(
const float minValue,
2292 WXGLCrystalCanvas * parentCrystal)
const
2294 VFN_DEBUG_ENTRY(
"UnitCellMap::GLInitDisplayList()",10)
2297 VFN_DEBUG_MESSAGE("UnitCellMap::GLInitDisplayList(): Generate Triangles",7)
2299 const
int nx=mPoints.cols();
2300 const
int ny=mPoints.rows();
2301 const
int nz=mPoints.depth();
2303 step[0]=1/(
float)nx;
2304 step[1]=1/(
float)ny;
2305 step[2]=1/(
float)nz;
2306 int nxMin, nxMax, nyMin, nyMax, nzMin, nzMax;
2307 BBox mapbbox = parentCrystal->GetMapBBox();
2309 if (mapbbox.xMin == mapbbox.xMax) mapbbox = parentCrystal->GetCellBBox();
2310 nxMin = (
int)(mapbbox.xMin * nx);
2311 nxMax = (
int)(mapbbox.xMax * nx);
2312 nyMin = (
int)(mapbbox.yMin * ny);
2313 nyMax = (
int)(mapbbox.yMax * ny);
2314 nzMin = (
int)(mapbbox.zMin * nz);
2315 nzMax = (
int)(mapbbox.zMax * nz);
2316 const
int snx = nxMax-nxMin+1, sny = nyMax-nyMin+1, snz = nzMax-nzMin+1;
2317 const
unsigned int sny_snz = sny*snz;
2319 unsigned int ni, nj, si, sj, sk, sni, snj, sind;
2324 for(i=nxMin, si=0; i <= nxMax; i++, si++)
2326 ni = ((nx + i % nx) % nx);
2328 for(j=nyMin, sj=0; j <= nyMax; j++, sj++)
2330 nj = ((ny + j % ny) % ny);
2332 for(k=nzMin, sk=0; k <= nzMax; k++, sk++)
2334 sind = sni + snj + sk;
2335 x = i*step[0]; y = j*step[1]; z = k*step[2];
2336 mpCrystal->FractionalToOrthonormalCoords(x, y, z);
2337 subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z;
2339 subPoints[sind].val = mPoints((nz+ k % nz)% nz,nj,ni);
2344 VFN_DEBUG_MESSAGE(
"UnitCellMap::GLInitDisplayList(): MC, Min Value="<<minValue,10)
2345 const
TRIANGLE *pTriangles= MC(snx-1, sny-1, snz-1, step[0], step[1], step[2], minValue, subPoints, numOfTriangles);
2347 VFN_DEBUG_MESSAGE("UnitCellMap::GLInitDisplayList(): OpenGL instructions",7)
2348 glBegin(GL_TRIANGLES);
2349 float normx,normy,normz;
2350 for(
int i=0; i < numOfTriangles; i++)
2353 for(
int j=0; j < 3; j++)
2357 normx=pTriangles[i].norm[j].x;
2358 normy=pTriangles[i].norm[j].y;
2359 normz=pTriangles[i].norm[j].z;
2362 glNormal3f(normx, normy, normz);
2363 glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z);
2366 for(
int j=2; j >=0; j--)
2370 normx=-pTriangles[i].norm[j].x;
2371 normy=-pTriangles[i].norm[j].y;
2372 normz=-pTriangles[i].norm[j].z;
2375 glNormal3f(normx, normy, normz);
2376 glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z);
2381 delete [] subPoints;
2382 delete [] pTriangles;
2383 VFN_DEBUG_EXIT(
"UnitCellMap::GLInitDisplayList():nb triangles="<<numOfTriangles,10)
2386 void UnitCellMap::POVRayDescription(ostream &os,
const float minValue,
2387 const CrystalPOVRayOptions &options)
const
2389 VFN_DEBUG_ENTRY(
"UnitCellMap::POVRayDescription()",7)
2391 VFN_DEBUG_MESSAGE("UnitCellMap::POVRayDescription(): Generate Triangles",7)
2393 const
int nx=mPoints.cols();
2394 const
int ny=mPoints.rows();
2395 const
int nz=mPoints.depth();
2397 step[0]=1/(
float)nx;
2398 step[1]=1/(
float)ny;
2399 step[2]=1/(
float)nz;
2400 int nxMin, nxMax, nyMin, nyMax, nzMin, nzMax;
2401 nxMin = (
int)(options.mXmin * nx);
2402 nxMax = (
int)(options.mXmax * nx);
2403 nyMin = (
int)(options.mYmin * ny);
2404 nyMax = (
int)(options.mYmax * ny);
2405 nzMin = (
int)(options.mZmin * nz);
2406 nzMax = (
int)(options.mZmax * nz);
2407 const
int snx = nxMax-nxMin+1, sny = nyMax-nyMin+1, snz = nzMax-nzMin+1;
2408 const
unsigned int sny_snz = sny*snz;
2410 unsigned int ni, nj, si, sj, sk, sni, snj, sind;
2415 for(i=nxMin, si=0; i <= nxMax; i++, si++)
2417 ni = ((nx + i % nx) % nx);
2419 for(j=nyMin, sj=0; j <= nyMax; j++, sj++)
2421 nj = ((ny + j % ny) % ny);
2423 for(k=nzMin, sk=0; k <= nzMax; k++, sk++)
2425 sind = sni + snj + sk;
2426 x = i*step[0]; y = j*step[1]; z = k*step[2];
2427 mpCrystal->FractionalToOrthonormalCoords(x, y, z);
2428 subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z;
2430 subPoints[sind].val = mPoints((nz+ k % nz)% nz,nj,ni);
2435 VFN_DEBUG_MESSAGE(
"UnitCellMap::POVRayDescription(): MC, Min Value="<<minValue,10)
2436 const
TRIANGLE *pTriangles= MC(snx-1, sny-1, snz-1, step[0], step[1], step[2], minValue, subPoints, numOfTriangles);
2438 VFN_DEBUG_MESSAGE("UnitCellMap::POVRayDescription(): POVRay instructions",7)
2439 float normx,normy,normz;
2440 for(
int i=0; i < numOfTriangles; i++)
2442 const float x1=pTriangles[i].p[0].x;
2443 const float x2=pTriangles[i].p[1].x;
2444 const float x3=pTriangles[i].p[2].x;
2445 const float y1=pTriangles[i].p[0].y;
2446 const float y2=pTriangles[i].p[1].y;
2447 const float y3=pTriangles[i].p[2].y;
2448 const float z1=pTriangles[i].p[0].z;
2449 const float z2=pTriangles[i].p[1].z;
2450 const float z3=pTriangles[i].p[2].z;
2453 const float d12=abs(x1-x2)+abs(y1-y2)+abs(z1-z2);
2454 const float d13=abs(x1-x3)+abs(y1-y3)+abs(z1-z3);
2455 const float d23=abs(x2-x3)+abs(y2-y3)+abs(z2-z3);
2456 if((d12<0.05)||(d13<0.05)||(d23<0.05))
continue;
2459 normx=pTriangles[i].norm[j].x;
2460 normy=pTriangles[i].norm[j].y;
2461 normz=pTriangles[i].norm[j].z;
2464 os<<
" ObjCrystMeshTriangle("
2465 <<x1<<
","<<y1<<
","<<z1<<
","
2466 <<x2<<
","<<y2<<
","<<z2<<
","
2467 <<x3<<
","<<y3<<
","<<z3<<
","
2468 <<normx<<
","<<normy<<
","<<normz<<
","
2469 <<normx<<
","<<normy<<
","<<normz<<
","
2470 <<normx<<
","<<normy<<
","<<normz<<
")"
2474 delete [] subPoints;
2475 delete [] pTriangles;
2476 VFN_DEBUG_EXIT(
"UnitCellMap::GLInitDisplayList()",7)
2479 int UnitCellMap::ImportGRD(
const string&filename)
2481 VFN_DEBUG_ENTRY(
"UnitCellMap::ImportGRD()",7)
2482 ifstream ffile(filename.c_str());
2483 if(!ffile.is_open())
2485 VFN_DEBUG_MESSAGE(
"UnitCellMap::ImportGRD() error opening "<<filename.c_str(),10)
2486 (*fpObjCrystInformUser)(
"Error opening file: "+filename);
2491 ffile.getline(buff, 100);
2492 float a, b, c, alpha, beta, gamma;
2493 ffile >>a >>b >>c >>alpha >>beta >>gamma;
2494 if(!ffile.good()) { (*fpObjCrystInformUser)(
"Error reading file: "+filename);
return 0; }
2523 ffile >>nx >>ny >>nz;
2524 if(!ffile.good()) { (*fpObjCrystInformUser)(
"Error reading file: "+filename);
return 0; }
2525 mPoints.resize(nz,ny,nx);
2526 for(
int i=0; i < nx; i++) {
2527 for(
int j=0; j < ny; j++) {
2528 for(
int k=0; k < nz; k++) {
2529 ffile >>mPoints(k,j,i);
2535 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2539 mStandardDeviation=0.0;
2540 const REAL *tmp=mPoints.data();
2541 for(
long i=0;i<mPoints.numElements();i++)
2543 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2546 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2555 std::string::size_type idx =filename.rfind(
"/");
2556 std::string::size_type idx2=filename.rfind(
"\\");
2557 std::string::size_type idx3=filename.rfind(
":");
2558 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
2559 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
2560 if(idx==string::npos)
2564 cout<<
"name="<<filename.substr(idx+1)<<endl;
2565 mName=filename.substr(idx+1);
2569 VFN_DEBUG_EXIT(
"UnitCellMap::ImportGRD()",7)
2574 void swap2(
void *data,
unsigned int nb)
2576 char * dataptr = (
char *)data;
2579 for (
unsigned int i=0; i<(nb-1); i+=2)
2582 dataptr[i] = dataptr[i+1];
2587 int UnitCellMap::ImportDSN6(
const string&filename)
2589 VFN_DEBUG_ENTRY(
"UnitCellMap::ImportDSN6()",7)
2590 FILE *pfile=fopen(filename.c_str(),"rb");
2593 VFN_DEBUG_MESSAGE(
"UnitCellMap::ImportDSN6() error opening "<<filename.c_str(),10)
2594 (*fpObjCrystInformUser)(
"Error opening file: "+filename);
2599 fread(header,
sizeof(
short), 256, pfile);
2600 bool needswap=
false;
2601 if (header[18] == 25600) needswap=
true;
2602 if(needswap) swap2(header, 19*
sizeof(
short));
2604 const long xstart=header[0];
2605 const long ystart=header[1];
2606 const long zstart=header[2];
2607 const long xextent=header[3];
2608 const long yextent=header[4];
2609 const long zextent=header[5];
2610 const unsigned long xsamplingrate=header[6];
2611 const unsigned long ysamplingrate=header[7];
2612 const unsigned long zsamplingrate=header[8];
2613 const float celledgea=(float)header[ 9]/(
float)header[17];
2614 const float celledgeb=(float)header[10]/(
float)header[17];
2615 const float celledgec=(float)header[11]/(
float)header[17];
2616 const float alpha=(float)header[12]/(
float)header[17];
2617 const float beta=(float)header[13]/(
float)header[17];
2618 const float gamma=(float)header[14]/(
float)header[17];
2619 const float rhoscale=(float)header[15]/(
float)header[18];
2620 const float rhozero =(float)header[16];
2621 cout <<
"xstart="<<xstart<<endl
2622 <<
"ystart="<<ystart<<endl
2623 <<
"zstart="<<zstart<<endl
2624 <<
"xextent="<<xextent<<endl
2625 <<
"yextent="<<yextent<<endl
2626 <<
"zextent="<<zextent<<endl
2627 <<
"xsamplingrate="<<xsamplingrate<<endl
2628 <<
"ysamplingrate="<<ysamplingrate<<endl
2629 <<
"zsamplingrate="<<zsamplingrate<<endl
2630 <<
"celledgea="<<celledgea<<endl
2631 <<
"celledgeb="<<celledgeb<<endl
2632 <<
"celledgec="<<celledgec<<endl
2633 <<
"alpha="<<alpha<<endl
2634 <<
"beta="<<beta<<endl
2635 <<
"gamma="<<gamma<<endl
2636 <<
"rhoscale="<<rhoscale<<endl
2637 <<
"rhozero="<<rhozero<<endl;
2639 #define BRICKSIZE 512
2642 unsigned char Points[BRICKSIZE];
2646 mPoints.resize(xsamplingrate,ysamplingrate,zsamplingrate);
2649 const unsigned int nxbrick=((xextent)/BRICKEDGE)+(xextent%8 ? 1 : 0);
2650 const unsigned int nybrick=((yextent)/BRICKEDGE)+(zextent%8 ? 1 : 0);
2651 const unsigned int nzbrick=((zextent)/BRICKEDGE)+(zextent%8 ? 1 : 0);
2653 for(
unsigned int zbrick=0;zbrick<nzbrick;zbrick++)
2654 for(
unsigned int ybrick=0;ybrick<nybrick;ybrick++)
2655 for(
unsigned int xbrick=0;xbrick<nxbrick;xbrick++)
2657 fread(&Points,
sizeof(
unsigned char), BRICKSIZE, pfile);
2660 if(needswap) swap2((
void *)&Points, BRICKSIZE);
2661 const unsigned char* pPoint=&Points[0];
2662 for(
unsigned int z=0;z<BRICKEDGE;z++)
2663 for(
unsigned int y=0;y<BRICKEDGE;y++)
2664 for(
unsigned int x=0;x<BRICKEDGE;x++)
2666 if( ((xbrick*BRICKEDGE+x)<xsamplingrate)
2667 &&((ybrick*BRICKEDGE+y)<ysamplingrate)
2668 &&((zbrick*BRICKEDGE+z)<zsamplingrate))
2669 mPoints(zbrick*BRICKEDGE+z,ybrick*BRICKEDGE+y,xbrick*BRICKEDGE+x)
2670 = ((float) *pPoint - rhozero)/ rhoscale ;
2676 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2680 mStandardDeviation=0.0;
2681 const REAL *tmp=mPoints.data();
2682 for(
long i=0;i<mPoints.numElements();i++)
2684 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2687 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2696 std::string::size_type idx =filename.rfind(
"/");
2697 std::string::size_type idx2=filename.rfind(
"\\");
2698 std::string::size_type idx3=filename.rfind(
":");
2699 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
2700 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
2701 if(idx==string::npos)
2706 mName=filename.substr(idx+1);
2709 VFN_DEBUG_EXIT(
"UnitCellMap::ImportDSN6()",7)
2719 unsigned int closest235(
unsigned int v)
2721 unsigned int n2=0,n3=0,n5=0;
2722 unsigned int v2,v3,v5=1;
2723 unsigned int bestdiff=10000;
2724 unsigned int best=0;
2725 for(
unsigned int i5=1;;)
2728 for(
unsigned int i3=1;;)
2731 for(
unsigned int i2=1;;)
2733 const unsigned int n=v2*v3*v5;
2743 if(best==v)
return best;
2750 if((v3*v5)>(v+bestdiff))
break;
2753 if(v5>(v+bestdiff))
break;
2758 int UnitCellMap::CalcFourierMap(
const ScatteringData& data,
unsigned int type0,
const bool normalized_sf)
2761 const float resolution=0.3;
2763 const unsigned long sizex=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(0)/resolution+.5)) ;
2764 const unsigned long sizey=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(1)/resolution+.5)) ;
2765 const unsigned long sizez=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(2)/resolution+.5)) ;
2767 fftwf_complex *in= (fftwf_complex*) fftwf_malloc(
sizeof(fftwf_complex) * sizex*sizey*sizez);
2768 fftwf_plan plan=fftwf_plan_dft_3d(sizez, sizey, sizex,in, in,FFTW_FORWARD, FFTW_ESTIMATE);
2770 float *p=(
float*)in;
2771 for(
unsigned long i=0;i<sizex*sizey*sizez*2;i++) *p++=0;
2773 const long nb=data.GetNbReflBelowMaxSinThetaOvLambda();
2776 if(data.GetFhklObsSq().numElements()==0) mType=1;
2778 CrystVector_REAL norm_sf;
2781 CrystVector_REAL tmp;
2782 norm_sf.resize(data.GetFhklCalcReal().numElements());
2784 const map<const ScatteringPower*,CrystVector_REAL> *pSF=&(data.GetScatteringFactor());
2785 const ScatteringComponentList *pComp =&(mpCrystal->GetScatteringComponentList());
2787 for(
unsigned int i=0;i<pComp->GetNbComponent();i++)
2789 tmp=pSF->find((*pComp)(i).mpScattPow)->second;
2791 tmp*= (*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr;
2793 const REAL sf0=(*pComp)(i).mpScattPow->GetForwardScatteringFactor(data.GetRadiationType ());
2794 norm0+=(*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr *sf0*sf0;
2798 REAL *p=norm_sf.data();
2800 for(
unsigned int i=norm_sf.numElements();i>0;i--) {*p=sqrt(*p * norm0);p++;}
2804 REAL scale_fobs=1.0;
2809 for(
long i=0;i<nb;++i) {scale_fobs+=data.GetFhklCalcSq()(i); tmp+=data.GetFhklObsSq()(i);}
2810 scale_fobs=sqrt(scale_fobs/(tmp+1e-10));
2814 const REAL v=1/mpCrystal->GetVolume();
2815 for(
long i=0;i<nb;++i)
2817 CrystMatrix_REAL m=mpCrystal->GetSpaceGroup().GetAllEquivRefl (data.GetH()(i),data.GetK()(i),data.GetL()(i),
2818 false, data.IsIgnoringImagScattFact(),
2819 data.GetFhklCalcReal()(i),data.GetFhklCalcImag()(i));
2821 if(normalized_sf) norm=1/norm_sf(i);
2822 for(
int j=0;j<m.rows();j++)
2824 int h=int(m(j,0)),k=int(m(j,1)),l=int(m(j,2));
2825 if((abs(h*2)>sizex)||(abs(k*2)>sizey)||(abs(l*2)>sizez))
continue;
2836 const REAL fobs=scale_fobs*sqrt(fabs(data.GetFhklObsSq()(i)));
2837 const REAL rec=m(j,3),imc=m(j,4),fcalc=sqrt(fabs(data.GetFhklCalcSq()(i)));
2838 in[h+sizex*k+sizex*sizey*l][0]=v*rec*(fobs-fcalc)/sqrt(rec*rec+imc*imc)*norm;
2839 in[h+sizex*k+sizex*sizey*l][1]=v*imc*(fobs-fcalc)/sqrt(rec*rec+imc*imc)*norm;
2843 in[h+sizex*k+sizex*sizey*l][0]=v*m(j,3)*norm;
2844 in[h+sizex*k+sizex*sizey*l][1]=v*m(j,4)*norm;
2848 const REAL iobs=scale_fobs*sqrt(fabs(data.GetFhklObsSq()(i)));
2849 const REAL rec=m(j,3),imc=m(j,4),icalc=sqrt(fabs(data.GetFhklCalcSq()(i)));
2850 in[h+sizex*k+sizex*sizey*l][0]=v*rec*iobs/icalc*norm;
2851 in[h+sizex*k+sizex*sizey*l][1]=v*imc*iobs/icalc*norm;
2859 const int nbSymmetrics=mpCrystal->GetSpaceGroup().GetNbSymmetrics(
false,
false);
2860 const ScatteringComponentList *pScattCompList=&(mpCrystal->GetScatteringComponentList());
2861 const long nbComp=pScattCompList->GetNbComponent();
2862 for(
long i=0;i<nbComp;i++)
2865 in[0][0]+= (*pScattCompList)(i).mpScattPow->GetForwardScatteringFactor(data.GetRadiationType())
2866 *(*pScattCompList)(i).mOccupancy
2867 *(*pScattCompList)(i).mDynPopCorr
2872 fftwf_execute(plan);
2873 mPoints.resize(sizez,sizey,sizex);
2874 REAL *p1=mPoints.data();
2875 for(
unsigned int i=0;i<sizex*sizey*sizez;i++) *p1++ =in[i][0] ;
2882 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2886 mStandardDeviation=0.0;
2887 const REAL *tmp=mPoints.data();
2888 for(
long i=0;i<mPoints.numElements();i++)
2890 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2893 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2901 fftwf_destroy_plan(plan);
2904 mName=data.GetClassName()+
":";
2905 if(data.GetName()==
"") mName+=
"?";
2906 else mName+=data.GetName();
2907 if(data.GetClassName()==
"PowderPatternDiffraction")
2910 if(data.GetRadiationType()==RAD_XRAY) mName+=
"Xray:";
2911 if(data.GetRadiationType()==RAD_NEUTRON) mName+=
"Neut:";
2912 if(data.GetRadiationType()==RAD_ELECTRON) mName+=
"Elec:";
2915 if(data.GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mName+=
"TOF:";
2918 sprintf(buf,
"%6.3fA:",data.GetWavelength()(0));
2921 const PowderPatternDiffraction* diff=
dynamic_cast<const PowderPatternDiffraction *
>(&data);
2922 if(diff!=0) mName+=diff->GetParentPowderPattern().GetName();
2924 if(data.GetClassName()==
"DiffractionDataSingleCrystal")
2927 if(data.GetRadiationType()==RAD_XRAY) mName+=
"Xray:";
2928 if(data.GetRadiationType()==RAD_NEUTRON) mName+=
"Neut:";
2929 if(data.GetRadiationType()==RAD_ELECTRON) mName+=
"Elec:";
2932 if(data.GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mName+=
"TOF:";
2935 sprintf(buf,
"%6.3fA:",data.GetWavelength()(0));
2938 mName+=data.GetName();
2941 if(mType==0) mName=
"(Fo)"+mName;
2942 if(mType==1) mName=
"(Fc)"+mName;
2943 if(mType==2) mName=
"(Fo-Fc)"+mName;
2948 const string & UnitCellMap::GetName()
const
2953 REAL UnitCellMap::GetValue(
const REAL x,
const REAL y,
const REAL z)
const
2955 const int nx=mPoints.cols();
2956 const int ny=mPoints.rows();
2957 const int nz=mPoints.depth();
2958 long ix=((long)floor(x*nx+.5))%nx;
2959 long iy=((long)floor(y*ny+.5))%ny;
2960 long iz=((long)floor(z*nz+.5))%nz;
2964 return mPoints(iz,iy,ix);
2966 REAL UnitCellMap::Max()
const{
return mMax;}
2967 REAL UnitCellMap::Min()
const{
return mMin;}
2968 REAL UnitCellMap::Mean()
const{
return mMean;}
2969 REAL UnitCellMap::StandardDeviation()
const{
return mStandardDeviation;}
2970 int UnitCellMap::GetType()
const{
return mType;}
2971 const Crystal &UnitCellMap::GetCrystal()
const{
return *mpCrystal;}
2972 const ScatteringData *UnitCellMap::GetData()
const{
return mpData;}
2979 UnitCellMapGLList::UnitCellMapGLList(
const UnitCellMap &ucmap,WXGLCrystalCanvas * parent,
2980 const bool showWire,
float contour,
2981 const float r,
const float g,
const float b,
const float t):
2982 mGLDisplayList(0),mShowWire(showWire),mShow(true),mContour(contour),mpUCMap(&ucmap),mpParent(parent)
2984 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::UnitCellMapGLList()",10)
2985 this->SetColour(r,g,b,t);
2988 UnitCellMapGLList::~UnitCellMapGLList()
2990 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::~UnitCellMapGLList()",10)
2991 if(0!=mGLDisplayList) glDeleteLists(mGLDisplayList,1);
2993 void UnitCellMapGLList::GenList()
2995 VFN_DEBUG_ENTRY(
"UnitCellMapGLList::GenList()",7)
2996 if(0==mGLDisplayList) mGLDisplayList=glGenLists(1);
2997 glNewList(mGLDisplayList,GL_COMPILE);
2999 mpUCMap->GLInitDisplayList(mContour, mpParent);
3002 VFN_DEBUG_EXIT("UnitCellMapGLList::GenList()",7)
3005 void UnitCellMapGLList::SetColour(const
float r,const
float g,const
float b,
3014 const float* UnitCellMapGLList::GetColour()
const
3019 void UnitCellMapGLList::ToggleShowWire()
3021 mShowWire =! mShowWire;
3024 bool UnitCellMapGLList::ShowWire()
const
3029 void UnitCellMapGLList::Draw()
const
3031 if(0==mGLDisplayList)
3033 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::Draw():No Display list generated !",7)
3037 if(mShowWire) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3038 else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3040 glMaterialfv(GL_FRONT, GL_AMBIENT, mColour);
3041 glMaterialfv(GL_FRONT, GL_DIFFUSE, mColour);
3042 glMaterialfv(GL_FRONT, GL_SPECULAR, mColour);
3043 const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f};
3044 glMaterialfv(GL_FRONT, GL_EMISSION, colour0);
3048 glMaterialf( GL_FRONT, GL_SHININESS, 0.0);
3050 const GLfloat colorBack [] = {mColour[0]/3.0f, mColour[1]/3.0f, mColour[2]/3.0f, mColour[3]};
3051 glMaterialfv(GL_BACK, GL_AMBIENT, colorBack);
3052 glMaterialfv(GL_BACK, GL_DIFFUSE, colorBack);
3053 glMaterialfv(GL_BACK, GL_SPECULAR, colorBack);
3054 glMaterialf( GL_BACK, GL_SHININESS, 0.0);
3057 glCallList(mGLDisplayList);
3059 VFN_DEBUG_EXIT(
"UnitCellMapGLList::Draw()",7)
3062 void UnitCellMapGLList::SetName(
const string &name)
3066 const string &UnitCellMapGLList::GetName()
const
3070 void UnitCellMapGLList::SetShow(
bool show) {mShow=show;}
3071 bool UnitCellMapGLList::Show()
const {
return mShow;}
3072 void UnitCellMapGLList::SetContour(
float contour) {mContour=contour;}
3073 float UnitCellMapGLList::GetContour()
const {
return mContour;}
3074 const UnitCellMap & UnitCellMapGLList::GetMap()
const {
return *mpUCMap;}
3081 WXGLCrystalCanvas::WXFourierMapList::WXFourierMapList(WXGLCrystalCanvas *pGLCrystalCanvas,wxWindow *parent):
3082 wxWindow(parent,-1),mpGLCrystalCanvas(pGLCrystalCanvas),mIsUpdating(false)
3084 this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
3085 wxBoxSizer* pSizer=
new wxBoxSizer(wxVERTICAL);
3087 wxBoxSizer* pSizerButtons=
new wxBoxSizer(wxHORIZONTAL);
3088 wxButton *pButtonUpdate=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_UPDATE,_T(
"Update 3D View"));
3089 mpWireFrame=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_WIREFRAME,_T(
"Wireframe"));
3090 mpShowFourier=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_SHOW,_T(
"Show Fourier"));
3091 mpSharpenMap=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_SHARPEN,_T(
"Sharpen maps"));
3092 pSizerButtons->Add(pButtonUpdate,0,wxALIGN_CENTER);
3093 pSizerButtons->Add(mpWireFrame,0,wxALIGN_CENTER);
3094 pSizerButtons->Add(mpShowFourier,0,wxALIGN_CENTER);
3095 pSizerButtons->Add(mpSharpenMap,0,wxALIGN_CENTER);
3096 pSizer->Add(pSizerButtons,0,wxALIGN_CENTER);
3099 wxBoxSizer* pSizerMaps=
new wxBoxSizer(wxHORIZONTAL);
3102 wxBoxSizer* pSizerLeft=
new wxBoxSizer(wxVERTICAL);
3103 pSizerMaps->Add(pSizerLeft,0,wxALIGN_TOP);
3105 wxStaticText *mpLabel0=
new wxStaticText(
this,-1,_T(
"Available Maps"));
3106 pSizerLeft->Add(mpLabel0,0,wxALIGN_CENTER);
3107 mpAvailableMapList=
new wxListBox(
this,ID_GLCRYSTAL_FOURIER_LISTMAP,wxDefaultPosition,wxSize(400,150));
3108 pSizerLeft->Add(mpAvailableMapList,0,wxALIGN_CENTER);
3110 mpMapInfo=
new wxStaticText(
this,-1,_T(
"min=+00.00 max=+00.00 sigma=00.00"));
3111 pSizerLeft->Add(mpMapInfo,0,wxALIGN_CENTER);
3113 wxBoxSizer* pSizerLeft2=
new wxBoxSizer(wxHORIZONTAL);
3114 pSizerLeft->Add(pSizerLeft2,0,wxALIGN_CENTER);
3115 wxStaticText *mpLabel2=
new wxStaticText(
this,-1,_T(
"New Contour:"));
3116 mpNewContourValue=
new wxTextCtrl(
this,ID_GLCRYSTAL_FOURIER_NEWCONTOUR,_T(
""),wxDefaultPosition,wxDefaultSize,
3117 wxTE_PROCESS_ENTER,wxTextValidator(wxFILTER_NUMERIC));
3118 pSizerLeft2->Add(mpLabel2,0,wxALIGN_CENTER);
3119 pSizerLeft2->Add(mpNewContourValue,0,wxALIGN_CENTER);
3121 wxButton *pButtonAdd=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_ADD,_T(
"Add"));
3122 pSizerLeft->Add(pButtonAdd,0,wxALIGN_CENTER);
3124 pSizerMaps->AddSpacer(5);
3126 wxBoxSizer* pSizerRight=
new wxBoxSizer(wxVERTICAL);
3127 pSizerMaps->Add(pSizerRight,0,wxALIGN_TOP);
3129 wxStaticText *mpLabel0r=
new wxStaticText(
this,-1,_T(
"Displayed Maps"));
3130 pSizerRight->Add(mpLabel0r,0,wxALIGN_CENTER);
3131 mpDisplayedMapList=
new wxListBox(
this,ID_GLCRYSTAL_FOURIER_LISTGLMAP,wxDefaultPosition,wxSize(400,150));
3132 pSizerRight->Add(mpDisplayedMapList,0,wxALIGN_CENTER);
3134 wxBoxSizer* pSizerRight1=
new wxBoxSizer(wxHORIZONTAL);
3135 pSizerRight->Add(pSizerRight1,0,wxALIGN_CENTER);
3136 wxStaticText *mpLabel3=
new wxStaticText(
this,-1,_T(
"Contour:"));
3137 mpContourValue=
new wxTextCtrl(
this,ID_GLCRYSTAL_FOURIER_CONTOUR,_T(
""),wxDefaultPosition,wxDefaultSize,
3138 wxTE_PROCESS_ENTER,wxTextValidator(wxFILTER_NUMERIC));
3139 pSizerRight1->Add(mpLabel3,0,wxALIGN_CENTER);
3140 pSizerRight1->Add(mpContourValue,0,wxALIGN_CENTER);
3142 mpColourPicker=
new wxColourPickerCtrl(
this, ID_GLCRYSTAL_FOURIER_COLOURPICKER, *wxRED, wxDefaultPosition, wxDefaultSize,wxCLRP_USE_TEXTCTRL);
3143 wxButton *pButtonRemove=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_REMOVE,_T(
"Remove"));
3144 pSizerRight->Add(mpColourPicker,0,wxALIGN_CENTER);
3145 pSizerRight->Add(pButtonRemove,0,wxALIGN_CENTER);
3146 pSizer->Add(pSizerMaps,0,wxALIGN_CENTER);
3147 this->SetSizer(pSizer);
3148 this->SetAutoLayout(
true);
3149 pSizer->SetSizeHints(
this);
3150 pSizer->SetSizeHints(parent);
3153 WXGLCrystalCanvas::WXFourierMapList::~WXFourierMapList()
3155 mpGLCrystalCanvas->NotifyDeleteFourierWin();
3158 struct GLCrystalConfig
3160 GLCrystalConfig(
const bool saved=
false);
3173 GLCrystalConfig::GLCrystalConfig(
const bool saved)
3178 static GLCrystalConfig sGLCrystalConfig;
3185 static const long ID_GLCRYSTAL_MENU_SHOWATOMLABEL= WXCRYST_ID();
3186 static const long ID_GLCRYSTAL_MENU_SHOWHYDROGENS= WXCRYST_ID();
3187 static const long ID_GLCRYSTAL_MENU_SHOWCURSOR= WXCRYST_ID();
3188 static const long ID_GLCRYSTAL_MENU_SETCURSOR= WXCRYST_ID();
3189 static const long ID_GLCRYSTAL_UPDATEUI= WXCRYST_ID();
3190 static const long ID_GLCRYSTAL_MENU_CHANGELIMITS= WXCRYST_ID();
3191 static const long ID_GLCRYSTAL_MENU_LIMITS_FULLCELL= WXCRYST_ID();
3192 static const long ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL= WXCRYST_ID();
3193 static const long ID_GLCRYSTAL_MENU_SHOWCRYSTAL= WXCRYST_ID();
3194 static const long ID_GLCRYSTAL_MENU_FOURIER= WXCRYST_ID();
3195 static const long ID_GLCRYSTAL_MENU_LOADFOURIERGRD= WXCRYST_ID();
3196 static const long ID_GLCRYSTAL_MENU_LOADFOURIERDSN6= WXCRYST_ID();
3198 static const long ID_GLCRYSTAL_MENU_POVRAY= WXCRYST_ID();
3199 static const long ID_GLCRYSTAL_MENU_SHOWHELP= WXCRYST_ID();
3202 BEGIN_EVENT_TABLE(WXGLCrystalCanvas, wxGLCanvas)
3203 EVT_PAINT (WXGLCrystalCanvas::OnPaint)
3204 EVT_ERASE_BACKGROUND (WXGLCrystalCanvas::OnEraseBackground)
3205 EVT_MOUSE_EVENTS (WXGLCrystalCanvas::OnMouse)
3206 EVT_MENU (ID_GLCRYSTAL_MENU_UPDATE, WXGLCrystalCanvas::OnUpdate)
3207 EVT_MENU (ID_GLCRYSTAL_MENU_CHANGELIMITS, WXGLCrystalCanvas::OnChangeLimits)
3208 EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, WXGLCrystalCanvas::OnChangeLimits)
3209 EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, WXGLCrystalCanvas::OnChangeLimits)
3210 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCRYSTAL, WXGLCrystalCanvas::OnShowCrystal)
3211 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWATOMLABEL, WXGLCrystalCanvas::OnShowAtomLabel)
3212 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWHYDROGENS, WXGLCrystalCanvas::OnShowHydrogens)
3213 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCURSOR, WXGLCrystalCanvas::OnShowCursor)
3214 EVT_MENU (ID_GLCRYSTAL_MENU_SETCURSOR, WXGLCrystalCanvas::OnSetCursor)
3215 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWHELP, WXGLCrystalCanvas::OnShowHelp)
3216 EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERGRD, WXGLCrystalCanvas::OnLoadFourierGRD)
3217 EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERDSN6, WXGLCrystalCanvas::OnLoadFourierDSN6)
3219 EVT_MENU (ID_GLCRYSTAL_MENU_POVRAY, WXGLCrystalCanvas::OnPOVRay)
3220 EVT_MENU (ID_GLCRYSTAL_MENU_FOURIER, WXGLCrystalCanvas::OnFourier)
3221 EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTGLMAP, WXGLCrystalCanvas::OnFourier)
3222 EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTMAP, WXGLCrystalCanvas::OnFourier)
3223 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_ADD, WXGLCrystalCanvas::OnFourier)
3224 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_REMOVE, WXGLCrystalCanvas::OnFourier)
3225 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_UPDATE, WXGLCrystalCanvas::OnFourier)
3226 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_WIREFRAME, WXGLCrystalCanvas::OnFourier)
3227 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHOW, WXGLCrystalCanvas::OnFourier)
3228 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHARPEN, WXGLCrystalCanvas::OnFourier)
3229 EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_NEWCONTOUR, WXGLCrystalCanvas::OnFourier)
3230 EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_CONTOUR, WXGLCrystalCanvas::OnFourier)
3231 EVT_COLOURPICKER_CHANGED(ID_GLCRYSTAL_FOURIER_COLOURPICKER, WXGLCrystalCanvas::OnFourierChangeColour)
3232 EVT_CHAR (WXGLCrystalCanvas::OnKeyDown)
3233 EVT_KEY_DOWN (WXGLCrystalCanvas::OnKeyDown)
3234 EVT_KEY_UP (WXGLCrystalCanvas::OnKeyUp)
3235 EVT_UPDATE_UI(ID_GLCRYSTAL_UPDATEUI,WXGLCrystalCanvas::OnUpdateUI)
3238 int AttribList [] = {WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16,0};
3240 WXGLCrystalCanvas::WXGLCrystalCanvas(WXCrystal *wxcryst,
3241 wxFrame *parent, wxWindowID
id,
3243 const wxSize &size):
3244 wxGLCanvas(parent, id,AttribList,pos,size,wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE,_T(
"GLCanvas"),wxNullPalette),
3246 mpParentFrame(parent),
3247 mpWXCrystal(wxcryst),mIsGLInit(false),mDist(60),mX0(0),mY0(0),mZ0(0),mViewAngle(15),
3248 mShowFourier(true),mShowCrystal(true),mShowAtomName(true),mShowHydrogens(true),
3249 mShowCursor(false),mSharpenMap(true),mShowHelp(false),mShowFullMolecule(false), mWhiteBackground(false),
3250 mIsGLFontBuilt(false),mGLFontDisplayListBase(0),mpFourierMapListWin(0),mFadeDistance(0)
3252 mpwxGLContext=
new wxGLContext(
this);
3253 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::WXGLCrystalCanvas()",3)
3254 if(sGLCrystalConfig.mSaved)
3256 mDist=sGLCrystalConfig.mDist;
3257 mX0=sGLCrystalConfig.mX0;
3258 mY0=sGLCrystalConfig.mY0;
3259 mZ0=sGLCrystalConfig.mZ0;
3260 mViewAngle=sGLCrystalConfig.mViewAngle;
3261 for(
int i=0;i<4;++i) mQuat[i]=sGLCrystalConfig.mQuat[i];
3262 mShowAtomName=sGLCrystalConfig.mShowAtomName;
3263 mShowCursor=sGLCrystalConfig.mShowCursor;
3265 mcellbbox.xMin=sGLCrystalConfig.mcellbbox.xMin;
3266 mcellbbox.xMax=sGLCrystalConfig.mcellbbox.xMax;
3267 mcellbbox.yMin=sGLCrystalConfig.mcellbbox.yMin;
3268 mcellbbox.yMax=sGLCrystalConfig.mcellbbox.yMax;
3269 mcellbbox.zMin=sGLCrystalConfig.mcellbbox.zMin;
3270 mcellbbox.zMax=sGLCrystalConfig.mcellbbox.zMax;
3272 mmapbbox.xMin=sGLCrystalConfig.mmapbbox.xMin;
3273 mmapbbox.xMax=sGLCrystalConfig.mmapbbox.xMax;
3274 mmapbbox.yMin=sGLCrystalConfig.mmapbbox.yMin;
3275 mmapbbox.yMax=sGLCrystalConfig.mmapbbox.yMax;
3276 mmapbbox.zMin=sGLCrystalConfig.mmapbbox.zMin;
3277 mmapbbox.zMax=sGLCrystalConfig.mmapbbox.zMax;
3279 mViewCntr.x=sGLCrystalConfig.mViewCntr.x;
3280 mViewCntr.y=sGLCrystalConfig.mViewCntr.y;
3281 mViewCntr.z=sGLCrystalConfig.mViewCntr.z;
3285 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
3286 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
3287 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
3288 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
3289 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
3290 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
3294 mmapbbox.xMin = mmapbbox.xMax = mmapbbox.yMin = mmapbbox.zMin = 0.;
3295 mmapbbox.yMax = mmapbbox.zMax = 1.;
3296 mpPopUpMenu=
new wxMenu(_T(
"Crystal"));
3297 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_UPDATE, _T(
"&Update"));
3298 mpPopUpMenu->AppendSeparator();
3299 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_CHANGELIMITS, _T(
"Change display &Limits"));
3300 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, _T(
"Show Full Unit Cell"));
3301 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, _T(
"Show Asymmetric Unit Cell"));
3302 mpPopUpMenu->AppendSeparator();
3303 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Hide Crystal"));
3304 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
3305 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Hide Hydrogens"));
3306 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Show Cursor"));
3307 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SETCURSOR, _T(
"Set view cntr and cursor pos."));
3308 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_POVRAY, _T(
"Create POVRay file"));
3309 mpPopUpMenu->AppendSeparator();
3310 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_FOURIER, _T(
"Fourier Maps"));
3311 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERGRD, _T(
"Load GRD Fourier Map"));
3312 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,_T(
"Load DSN6 Fourier Map"));
3313 mpPopUpMenu->AppendSeparator();
3314 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWHELP, _T(
"Show &Help"));
3319 if(sGLCrystalConfig.mSaved==
false)
3321 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view")))
3322 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"),
true);
3326 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"), &val);
3329 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
3330 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
3331 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
3332 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
3333 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
3334 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
3346 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Default-display atom names in 3D view")))
3347 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Default-display atom names in 3D view"), mShowAtomName);
3350 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Default-display atom names in 3D view"), &mShowAtomName);
3354 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/REAL/3D fade distance")))
3355 wxConfigBase::Get()->Write(_T(
"Crystal/REAL/3D fade distance"), 4);
3357 wxConfigBase::Get()->Read(_T(
"Crystal/REAL/3D fade distance"), &mFadeDistance);
3360 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Show full molecules in 3D view")))
3361 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Show full molecules in 3D view"), mShowFullMolecule);
3363 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Show full molecules in 3D view"), &mShowFullMolecule);
3365 if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
3366 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Show Atom Labels"));
3369 WXGLCrystalCanvas::~WXGLCrystalCanvas()
3371 mpWXCrystal->NotifyCrystalGLDelete();
3373 this->DeleteGLFont();
3376 sGLCrystalConfig.mDist = mDist;
3377 sGLCrystalConfig.mX0=mX0;
3378 sGLCrystalConfig.mY0=mY0;
3379 sGLCrystalConfig.mZ0=mZ0;
3380 sGLCrystalConfig.mViewAngle=mViewAngle;
3381 for(
int i=0;i<4;++i) sGLCrystalConfig.mQuat[i]=mQuat[i];
3382 sGLCrystalConfig.mShowAtomName=mShowAtomName;
3383 sGLCrystalConfig.mShowCursor=mShowCursor;
3385 sGLCrystalConfig.mcellbbox.xMin=mcellbbox.xMin;
3386 sGLCrystalConfig.mcellbbox.xMax=mcellbbox.xMax;
3387 sGLCrystalConfig.mcellbbox.yMin=mcellbbox.yMin;
3388 sGLCrystalConfig.mcellbbox.yMax=mcellbbox.yMax;
3389 sGLCrystalConfig.mcellbbox.zMin=mcellbbox.zMin;
3390 sGLCrystalConfig.mcellbbox.zMax=mcellbbox.zMax;
3392 sGLCrystalConfig.mmapbbox.xMin=mmapbbox.xMin;
3393 sGLCrystalConfig.mmapbbox.xMax=mmapbbox.xMax;
3394 sGLCrystalConfig.mmapbbox.yMin=mmapbbox.yMin;
3395 sGLCrystalConfig.mmapbbox.yMax=mmapbbox.yMax;
3396 sGLCrystalConfig.mmapbbox.zMin=mmapbbox.zMin;
3397 sGLCrystalConfig.mmapbbox.zMax=mmapbbox.zMax;
3399 sGLCrystalConfig.mViewCntr.x=mViewCntr.x;
3400 sGLCrystalConfig.mViewCntr.y=mViewCntr.y;
3401 sGLCrystalConfig.mViewCntr.z=mViewCntr.z;
3402 sGLCrystalConfig.mSaved=
true;
3403 delete mpwxGLContext;
3406 void WXGLCrystalCanvas::OnExit(wxCommandEvent &event)
3411 void WXGLCrystalCanvas::OnPaint(wxPaintEvent &event)
3413 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnPaint()",7)
3416 if(false==mIsGLInit)
3424 GetClientSize(& width, & height);
3427 glViewport(0, 0, width, height);
3428 glMatrixMode(GL_PROJECTION);
3430 if( (width>0)&&(height>0))
3431 gluPerspective(mViewAngle,(
float)width/(
float)height,1.f,2.*mDist);
3434 glMatrixMode( GL_MODELVIEW );
3437 if(mWhiteBackground) glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
3438 else glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3439 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
3444 glTranslatef( 0, 0, -mDist );
3445 build_rotmatrix( m,mQuat);
3446 glMultMatrixf( &m[0][0] );
3447 glTranslatef( mX0, mY0, mZ0 );
3450 for(
unsigned int passnum = 0; passnum<2; passnum++)
3454 glDepthMask(GL_TRUE);
3455 glAlphaFunc(GL_GREATER,0.99);
3459 glDepthMask(GL_FALSE);
3460 glAlphaFunc(GL_LEQUAL,0.99);
3465 if(mWhiteBackground) glColor3f(0.0,0.0,0.0);
3466 else glColor3f(1.0,1.0,1.0);
3467 glTranslatef(0, 0, -mDist);
3468 glMultMatrixf(&m[0][0]);
3469 glTranslatef(mX0, mY0, mZ0);
3470 glCallList(mpWXCrystal->GetCrystalGLDisplayList());
3474 if(mWhiteBackground) glColor3f(0.0,0.0,0.0);
3475 else glColor3f(1.0,1.0,1.0);
3476 glTranslatef( -0.3, 0, -mDist+1. );
3477 glMultMatrixf( &m[0][0] );
3478 glTranslatef( mX0, mY0, mZ0 );
3479 glCallList(mpWXCrystal->GetCrystalGLDisplayList(
true));
3485 GetClientSize(& w, & h);
3486 GLfloat colour2 [] = {1.00, 1.00, 1.00, 0.3};
3487 if(mWhiteBackground)
3488 for(
unsigned int i=0;i<3;i++) colour2[i] = 0.0;
3490 for(
unsigned int i=0;i<3;i++) colour2[i] = 1.0;
3492 glMaterialfv(GL_FRONT, GL_EMISSION, colour2);
3495 glMatrixMode(GL_PROJECTION);
3498 gluOrtho2D(0,w,0,h);
3499 if(mWhiteBackground) glColor3f(0.0,0.0,0.0);
3500 else glColor3f(1.0,1.0,1.0);
3502 glRasterPos2i(2,h-12*i);
3504 sprintf(c,
"%5.3f<x<%5.3f\n",mcellbbox.xMin,mcellbbox.xMax);
3508 glRasterPos2i(2, h-12*i);
3509 sprintf(c,
"%5.3f<y<%5.3f\n",mcellbbox.yMin,mcellbbox.yMax);
3513 glRasterPos2i(2, h-12*i);
3514 sprintf(c,
"%5.3f<z<%5.3f\n",mcellbbox.zMin,mcellbbox.zMax);
3520 glRasterPos2i(2, h-12*i);
3524 glRasterPos2i(2, h-12*i);
3525 sprintf(c,
" left-click & drag: change orientation");
3528 glRasterPos2i(2, h-12*i);
3529 sprintf(c,
" middle-click & drag: zoom (vert) change depth perception (horiz)");
3532 glRasterPos2i(2, h-12*i);
3533 sprintf(c,
" wheel: rotate");
3537 glRasterPos2i(2, h-12*i);
3538 sprintf(c,
"Trackpad");
3541 glRasterPos2i(2, h-12*i);
3542 sprintf(c,
" two-finger drag: change orientation");
3546 glRasterPos2i(2, h-12*i);
3547 sprintf(c,
"Keyboard (all lowercase)");
3550 glRasterPos2i(2, h-12*i);
3551 sprintf(c,
" +,-: change zoom");
3554 glRasterPos2i(2, h-12*i);
3555 sprintf(c,
" 2,4,6,8,D,C,F,R: rotate");
3558 glRasterPos2i(2, h-12*i);
3559 sprintf(c,
" F1,F2,F3,F4,F5,F6: increase/decrease display area");
3562 glRasterPos2i(2, h-12*i);
3563 sprintf(c,
" shift+F1,F2,F3,F4,F5,F6: shift display area");
3566 glRasterPos2i(2, h-12*i);
3567 sprintf(c,
" F7,F8: increase/decrease fade distance");
3570 glRasterPos2i(2, h-12*i);
3571 sprintf(c,
" F9,F10: display area=asymmetric or full unit cell");
3574 glRasterPos2i(2, h-12*i);
3575 sprintf(c,
" H: toggle help display");
3578 glRasterPos2i(2, h-12*i);
3579 sprintf(c,
" L: toggle atom labels");
3582 glRasterPos2i(2, h-12*i);
3583 sprintf(c,
" M: toggle full molecules");
3586 glRasterPos2i(2, h-12*i);
3587 sprintf(c,
" Y: toggle hydrogens");
3590 glRasterPos2i(2, h-12*i);
3591 sprintf(c,
" B: toggle white/black background");
3596 glMatrixMode( GL_MODELVIEW );
3602 glTranslatef( 0, 0, -mDist);
3603 glMultMatrixf( &m[0][0] );
3604 const GLfloat colour0 [] = {0.00, 0.00, 0.00, 0.00};
3605 const GLfloat colour1 [] = {1.0f, 1.0f, 1.0f, 1.00};
3606 glMaterialfv(GL_FRONT, GL_AMBIENT, colour1);
3607 glMaterialfv(GL_FRONT, GL_DIFFUSE, colour1);
3608 glMaterialfv(GL_FRONT, GL_SPECULAR, colour0);
3609 glMaterialfv(GL_FRONT, GL_EMISSION, colour1);
3610 glMaterialfv(GL_FRONT, GL_SHININESS, colour1);
3612 glVertex3f(-1.0f, 0.0f, 0.0f);
3613 glVertex3f( 1.0f, 0.0f, 0.0f);
3615 glVertex3f( 0.0f,-1.0f, 0.0f);
3616 glVertex3f( 0.0f, 1.0f, 0.0f);
3618 glVertex3f( 0.0f, 0.0f,-1.0f);
3619 glVertex3f( 0.0f, 0.0f, 1.0f);
3624 wxString statusText;
3628 mpWXCrystal->GetCrystal().OrthonormalToFractionalCoords(x,y,z);
3629 x=(mcellbbox.xMax+mcellbbox.xMin)/2.-x;
3630 y=(mcellbbox.yMax+mcellbbox.yMin)/2.-y;
3631 z=(mcellbbox.zMax+mcellbbox.zMin)/2.-z;
3632 statusText.Printf(_T(
"Center@(%5.3f,%5.3f,%5.3f)"),x,y,z);
3633 for(
unsigned int i=0;i<mvpUnitCellMap.size();++i)
3635 statusText+=_T(
", map(") + wxString::FromAscii(mvpUnitCellMap[i]->GetName().c_str())
3636 +wxString::Format(_T(
")=%5.2fe"),mvpUnitCellMap[i]->GetValue(x,y,z));
3638 mpParentFrame->SetStatusText(statusText);
3640 if (mShowFourier && (passnum==0))
3642 glAlphaFunc(GL_ALWAYS,1);
3644 glTranslatef( 0, 0, -mDist );
3645 build_rotmatrix( m,mQuat);
3646 glMultMatrixf( &m[0][0] );
3647 glTranslatef( mX0, mY0, mZ0 );
3650 BBox cellbbox = this->GetCellBBox();
3651 REAL xc=(cellbbox.xMin+cellbbox.xMax)/2.;
3652 REAL yc=(cellbbox.yMin+cellbbox.yMax)/2.;
3653 REAL zc=(cellbbox.zMin+cellbbox.zMax)/2.;
3654 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(xc, yc, zc);
3655 glTranslatef(-xc, -yc, -zc);
3657 vector<boost::shared_ptr<UnitCellMapGLList> >::const_iterator pos;
3658 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos)
3659 if((*pos)->Show()) (*pos)->Draw();
3663 glDepthMask(GL_TRUE);
3664 glAlphaFunc(GL_ALWAYS,1);
3667 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::OnPaint():End",7)
3670 void WXGLCrystalCanvas::OnEraseBackground(wxEraseEvent& event)
3674 void WXGLCrystalCanvas::OnKeyDown(wxKeyEvent& event)
3676 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():"<<event.GetKeyCode(),2)
3677 switch(event.GetKeyCode())
3681 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():Bigger",2)
3683 GetClientSize(& width, & height);
3686 glMatrixMode(GL_PROJECTION);
3688 if( (width>0)&&(height>0))
3689 gluPerspective(mViewAngle,(
float)width/(
float)height,
3690 (mDist>100)?(mDist-100):1.,mDist+100);
3696 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():Smaller",2)
3698 GetClientSize(& width, & height);
3701 glMatrixMode(GL_PROJECTION);
3703 if( (width>0)&&(height>0))
3704 gluPerspective(mViewAngle,(
float)width/(
float)height,
3705 (mDist>100)?(mDist-100):1.,mDist+100);
3709 case(WXK_INSERT): mY0 += 0.1; Refresh(FALSE); break;
3710 case(WXK_DELETE): mY0 -= 0.1; Refresh(FALSE); break;
3711 case(WXK_HOME): mX0 -= 0.1; Refresh(FALSE); break;
3712 case(WXK_END): mX0 += 0.1; Refresh(FALSE); break;
3713 case(WXK_PAGEUP): mZ0 -= 0.1; Refresh(FALSE); break;
3714 case(WXK_PAGEDOWN): mZ0 += 0.1; Refresh(FALSE); break;
3717 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate left",2)
3719 trackball(spin_quat,0,0,-.05,0);
3720 add_quats( spin_quat, mQuat, mQuat );
3726 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate right",2)
3728 trackball(spin_quat,0,0,.05,0);
3729 add_quats( spin_quat, mQuat, mQuat );
3735 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate down",2)
3737 trackball(spin_quat,0,0,0,-.05);
3738 add_quats( spin_quat, mQuat, mQuat );
3744 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate up",2)
3746 trackball(spin_quat,0,0,0,.05);
3747 add_quats( spin_quat, mQuat, mQuat );
3753 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate left",2)
3755 trackball(spin_quat,0,0,-.05,0);
3756 add_quats( spin_quat, mQuat, mQuat );
3762 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate right",2)
3764 trackball(spin_quat,0,0,.05,0);
3765 add_quats( spin_quat, mQuat, mQuat );
3771 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate down",2)
3773 trackball(spin_quat,0,0,0,-.05);
3774 add_quats( spin_quat, mQuat, mQuat );
3780 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():toggle black/white background",2)
3781 mWhiteBackground = !mWhiteBackground;
3787 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate up",2)
3789 trackball(spin_quat,0,0,0,.05);
3790 add_quats( spin_quat, mQuat, mQuat );
3796 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():toggle help",2)
3797 mShowHelp = !mShowHelp;
3803 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():toggle atom labels",2)
3804 mShowAtomName = !mShowAtomName;
3810 mShowFullMolecule = !mShowFullMolecule;
3811 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Show full molecules in 3D view"), mShowFullMolecule);
3812 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():toggle showing full molecules: "<<mShowFullMolecule,2)
3815 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3816 mpWXCrystal->UpdateGL(false,
3817 mcellbbox.xMin,mcellbbox.xMax,
3818 mcellbbox.yMin,mcellbbox.yMax,
3819 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
3824 mShowHydrogens = !mShowHydrogens;
3826 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3827 mpWXCrystal->UpdateGL(
false,
3828 mcellbbox.xMin,mcellbbox.xMax,
3829 mcellbbox.yMin,mcellbbox.yMax,
3830 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
3835 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F1",2)
3836 if(event.ShiftDown())
3838 mcellbbox.xMin -= 0.05;
3839 mcellbbox.xMax -= 0.05;
3843 if((mcellbbox.xMax-mcellbbox.xMin)>0.1)
3845 mcellbbox.xMin += 0.05;
3846 mcellbbox.xMax -= 0.05;
3853 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F2",2)
3854 if(event.ShiftDown())
3856 mcellbbox.xMin += 0.05;
3857 mcellbbox.xMax += 0.05;
3861 mcellbbox.xMin -= 0.05;
3862 mcellbbox.xMax += 0.05;
3868 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F3",2)
3869 if(event.ShiftDown())
3871 mcellbbox.yMin -= 0.05;
3872 mcellbbox.yMax -= 0.05;
3876 if((mcellbbox.yMax-mcellbbox.yMin)>0.1)
3878 mcellbbox.yMin += 0.05;
3879 mcellbbox.yMax -= 0.05;
3886 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F4",2)
3887 if(event.ShiftDown())
3889 mcellbbox.yMin += 0.05;
3890 mcellbbox.yMax += 0.05;
3894 mcellbbox.yMin -= 0.05;
3895 mcellbbox.yMax += 0.05;
3901 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F5",2)
3902 if(event.ShiftDown())
3904 mcellbbox.zMin -= 0.05;
3905 mcellbbox.zMax -= 0.05;
3909 if((mcellbbox.zMax-mcellbbox.zMin)>0.1)
3911 mcellbbox.zMin += 0.05;
3912 mcellbbox.zMax -= 0.05;
3919 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F6",2)
3920 if(event.ShiftDown())
3922 mcellbbox.zMin += 0.05;
3923 mcellbbox.zMax += 0.05;
3927 mcellbbox.zMin -= 0.05;
3928 mcellbbox.zMax += 0.05;
3934 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F5",2)
3935 mFadeDistance -=0.5;
3944 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F6",2)
3950 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F9",2)
3951 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
3952 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
3953 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
3954 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
3955 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
3956 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
3961 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():F10",2)
3972 cout<<
"WXGLCrystalCanvas::OnKeyDown(): Unknown KeyCode: "<<
event.GetKeyCode()<<endl;
3976 if( (event.GetKeyCode()==WXK_F1)||(event.GetKeyCode()==WXK_F2)||(event.GetKeyCode()==WXK_F3)||(event.GetKeyCode()==WXK_F4)
3977 ||(event.GetKeyCode()==WXK_F5)||(event.GetKeyCode()==WXK_F6)||(event.GetKeyCode()==WXK_F7)||(event.GetKeyCode()==WXK_F8)
3978 ||(event.GetKeyCode()==WXK_F9)||(event.GetKeyCode()==WXK_F10))
3980 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3981 mpWXCrystal->UpdateGL(
false,
3982 mcellbbox.xMin,mcellbbox.xMax,
3983 mcellbbox.yMin,mcellbbox.yMax,
3984 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
3988 void WXGLCrystalCanvas::OnKeyUp(wxKeyEvent& event)
3990 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyUp():"<<event.GetKeyCode(),2)
3993 void WXGLCrystalCanvas::OnEnterWindow( wxMouseEvent& event )
3995 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnEnterWindow()",5)
3998 void WXGLCrystalCanvas::OnMouse( wxMouseEvent& event )
4000 if(event.Leaving())
return;
4001 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse()"
4002 <<endl<<
"IsButton():"<<event.IsButton()
4003 <<endl<<
"ButtonDown():"<<event.ButtonDown()
4004 <<endl<<
"Dragging():"<<event.Dragging()
4005 <<endl<<
"Entering():"<<event.Entering()
4006 <<endl<<
"Leaving():"<<event.Leaving()
4007 <<endl<<
"GetButton()"<<event.GetButton()
4008 <<endl<<
"GetWheelAxis():"<<event.GetWheelAxis()
4009 <<endl<<
"GetWheelDelta():"<<event.GetWheelDelta()
4010 <<endl<<
"GetWheelRotation():"<<event.GetWheelRotation()
4011 <<endl<<
"Moving():"<<event.Moving()
4013 if (event.Dragging())
4016 GetClientSize(& width, & height);
4017 if(event.LeftIsDown())
4019 if(event.ShiftDown())
4021 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Left Button",2)
4023 REAL vx1=mTrackBallLastX,vy1=mTrackBallLastY,vz1,
4024 vx2=event.GetX(), vy2=event.GetY(), vz2;
4026 this->UnProject(vx1,vy1,vz1);
4027 this->UnProject(vx2,vy2,vz2);
4033 VFN_DEBUG_MESSAGE("Origin (ortho) = "<<mX0<<", "<<mY0<<", "<<mZ0,2)
4038 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Left Button",2)
4041 trackball(spin_quat,
4042 (2.0*mTrackBallLastX - width) / (width+.001),
4043 ( height - 2.0*mTrackBallLastY) / (height+.001),
4044 ( 2.0*event.GetX() - width) / (width+.001),
4045 ( height - 2.0*event.GetY()) / (height+.001));
4047 add_quats( spin_quat, mQuat, mQuat );
4051 if(event.MiddleIsDown())
4053 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Middle Button",2)
4054 const
float v= (mTrackBallLastY-event.GetY())/(
float)height;
4055 const
float h= (mTrackBallLastX-event.GetX())/(
float)width;
4057 mDist *= (1.+v)/(1.+h);
4058 mViewAngle *=(1.+h);
4060 glMatrixMode(GL_PROJECTION);
4062 if( (width>0)&&(height>0))
4063 gluPerspective(mViewAngle,(
float)width/(
float)height,
4064 (mDist>101)?(mDist-100):1.,mDist+100);
4066 VFN_DEBUG_MESSAGE(mViewAngle <<" "<<mDist,2)
4070 else if(event.RightIsDown())
4072 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Right Button",2)
4073 if(mpWXCrystal->GetCrystal().IsBeingRefined())
4075 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE,
false);
4076 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY,
false);
4077 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD,
false);
4078 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,
false);
4082 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE,
true);
4083 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY,
true);
4084 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD,
true);
4085 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,
true);
4088 this->PopupMenu(mpPopUpMenu, event.GetX(), event.GetY() );
4090 else if (event.GetWheelDelta()>0)
4092 if(event.ControlDown())
4094 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse(): Mouse Wheel / double touch + control (OSX: command)",2)
4097 GetClientSize(& width, & height);
4098 const
int delta=event.GetWheelDelta();
4099 const
int rotation=event.GetWheelRotation();
4101 if(event.GetWheelAxis()==0) mDist *= (1.+
float(rotation)/100.);
4104 mDist /= (1.+float(rotation)/100.);
4105 mViewAngle *=(1.+float(rotation)/100.);
4108 glMatrixMode(GL_PROJECTION);
4110 if( (width>0)&&(height>0))
4111 gluPerspective(mViewAngle,(
float)width/(
float)height,
4112 (mDist>101)?(mDist-100):1.,mDist+100);
4114 VFN_DEBUG_MESSAGE(mViewAngle <<
" "<<mDist,2)
4118 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse(): Mouse Wheel / double touch",2)
4121 GetClientSize(& width, & height);
4122 const
int delta=event.GetWheelDelta();
4124 if(event.GetWheelAxis()==1) dx=-event.GetWheelRotation();
4125 else dy=event.GetWheelRotation();
4127 trackball(spin_quat,
4128 (2.0*mTrackBallLastX - width) / (width+.001),
4129 ( height - 2.0*mTrackBallLastY) / (height+.001),
4130 (2.0*(mTrackBallLastX+dx) - width) / (width+.001),
4131 ( height - 2.0*(mTrackBallLastY+dy)) / (height+.001));
4133 add_quats( spin_quat, mQuat, mQuat );
4138 mTrackBallLastX = event.GetX();
4139 mTrackBallLastY = event.GetY();
4143 void WXGLCrystalCanvas::OnUpdate(wxCommandEvent & WXUNUSED(event))
4145 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnUpdate()",4)
4146 mpWXCrystal->UpdateGL(false,
4147 mcellbbox.xMin,mcellbbox.xMax,
4148 mcellbbox.yMin,mcellbbox.yMax,
4149 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
4150 VFN_DEBUG_EXIT("WXGLCrystalCanvas::OnUpdate()",4)
4153 void WXGLCrystalCanvas::CrystUpdate()
4156 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::CrystUpdate():"<<wxThread::IsMain(),10)
4158 if(mpFourierMapListWin!=0) mpFourierMapListWin->mMutex.Lock();
4160 for(vector<boost::shared_ptr<UnitCellMap> >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();)
4163 if((*pos)->GetType()==3) keep=
true;
4164 if(((*pos)->GetType()==0)||((*pos)->GetType()==2))
4171 if(mpWXCrystal->GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0)
4172 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
4173 if((*pos)->GetData()->GetFhklObsSq().numElements()>0)
4176 if((*pos)->GetType()==1)
4178 if(mpWXCrystal->GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0)
4179 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
4182 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::CrystUpdate()"<<(*pos)->GetName()<<(*pos)->GetType()<<
": keep="<<keep,8)
4186 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
4187 posgl=mvpUnitCellMapGLList.begin();posgl!=mvpUnitCellMapGLList.end();)
4189 if(&(**pos)==&((*posgl)->GetMap()))
4191 VFN_DEBUG_MESSAGE(
"Erasing GL map:"<<(*posgl)->GetName(),8)
4192 posgl=mvpUnitCellMapGLList.erase(posgl);
4195 pos=mvpUnitCellMap.erase(pos);
4199 if((*pos)->GetType()!=3)
4203 if( (mvpUnitCellMapGLList.size()>0)
4204 ||(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
4205 ||(mpFourierMapListWin!=0))
4206 (*pos)->CalcFourierMap(*((*pos)->GetData()),(*pos)->GetType(),mSharpenMap);
4214 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
4215 for(
int i=0;i<mpWXCrystal->GetCrystal().GetClientRegistry().GetNb();++i)
4217 ScatteringData* data=
dynamic_cast<ScatteringData *
>(&(mpWXCrystal->GetCrystal().GetClientRegistry().GetObj(i)));
4222 bool addCalcMap=
true,addObsDiffMaps=
true;
4223 for(vector<boost::shared_ptr<UnitCellMap> >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos)
4224 if((*pos)->GetData()==data)
4226 if((*pos)->GetType()==1) addCalcMap=
false;
4227 if((*pos)->GetType()==0) addObsDiffMaps=
false;
4231 if(addCalcMap&&(data->GetNbRefl()>0))
4233 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(
new UnitCellMap(mpWXCrystal->GetCrystal())));
4234 mvpUnitCellMap.back()->CalcFourierMap(*data,1);
4235 VFN_DEBUG_MESSAGE(
"Added GL map:"<<mvpUnitCellMap.back()->GetName(),8)
4237 if(addObsDiffMaps && (data->GetFhklObsSq().numElements()>0) )
4239 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(
new UnitCellMap(mpWXCrystal->GetCrystal())));
4240 mvpUnitCellMap.back()->CalcFourierMap(*data,0);
4241 VFN_DEBUG_MESSAGE(
"Added GL map:"<<mvpUnitCellMap.back()->GetName()<<
":"<<data->GetFhklObsSq().numElements(),8)
4242 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(new UnitCellMap(mpWXCrystal->GetCrystal())));
4243 mvpUnitCellMap.back()->CalcFourierMap(*data,2);
4244 VFN_DEBUG_MESSAGE("Added GL map:"<<mvpUnitCellMap.back()->GetName()<<":"<<data->GetFhklObsSq().numElements(),8)
4250 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
4251 pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos)
4256 if(mpFourierMapListWin!=0) mpFourierMapListWin->mMutex.Unlock();
4257 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::CrystUpdate()",10)
4259 wxUpdateUIEvent event(ID_GLCRYSTAL_UPDATEUI);
4260 wxPostEvent(this,event);
4273 void WXGLCrystalCanvas::OnUpdateUI(wxUpdateUIEvent&event)
4275 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnUpdateUI()",5)
4276 if(mpFourierMapListWin!=0)
4278 mpFourierMapListWin->mIsUpdating=
true;
4279 mpFourierMapListWin->mMutex.Lock();
4282 for(vector<boost::shared_ptr<UnitCellMap> >::iterator
4283 pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos)
4284 maps.Add( wxString::FromAscii((*pos)->GetName().c_str()));
4285 if(mpFourierMapListWin->mpAvailableMapList->GetStrings()!=maps)
4286 mpFourierMapListWin->mpAvailableMapList->Set(maps);
4288 wxArrayString glmaps;
4289 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
4290 pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos)
4291 glmaps.Add( wxString::FromAscii((*pos)->GetName().c_str()));
4292 if(mpFourierMapListWin->mpDisplayedMapList->GetStrings()!=glmaps)
4293 mpFourierMapListWin->mpDisplayedMapList->Set(glmaps);
4295 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0)
4297 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
4298 mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T(
"min=%5.2f max=%5.2f sigma=%5.2f"),
4299 pMap->Min(),pMap->Max(),pMap->StandardDeviation()));
4301 mpFourierMapListWin->mMutex.Unlock();
4302 mpFourierMapListWin->mIsUpdating=
false;
4304 this->Refresh(
false);
4306 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::OnUpdateUI()",5)
4309 void WXGLCrystalCanvas::SetCurrent()
4311 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::SetCurrent()",4)
4312 this->wxGLCanvas::SetCurrent(*mpwxGLContext);
4314 this->BuildGLFont();
4315 sFontDisplayListBase=mGLFontDisplayListBase;
4317 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::SetCurrent()",4)
4320 void WXGLCrystalCanvas::NotifyDeleteFourierWin()
4322 mpFourierMapListWin=0;
4325 void WXGLCrystalCanvas::InitGL()
4328 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
4329 wxPostEvent(
this,event);
4331 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::InitGL()",8)
4334 static bool needglutinit=
true;
4339 char **argv=
new char*;
4341 glutInit(&argc,argv);
4346 GetClientSize(& width, & height);
4347 glViewport(0, 0, width, height);
4349 glEnable(GL_DEPTH_TEST);
4350 glEnable(GL_ALPHA_TEST);
4351 glEnable(GL_LIGHTING);
4352 glEnable (GL_BLEND);
4353 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4355 const GLfloat colour_Ambient [] = {0.4, 0.4, 0.4, 1.00};
4356 const GLfloat colour_Diffuse [] = {0.6, 0.6, 0.6, 1.00};
4357 const GLfloat colour_Specular[] = {0.2, 0.2, 0.2, 1.00};
4359 glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
4361 const GLfloat LightPosition[]= { -10.0f, 10.0f, 10.0f, 0.0f };
4362 glLightfv(GL_LIGHT1, GL_AMBIENT, colour_Ambient);
4363 glLightfv(GL_LIGHT1, GL_DIFFUSE, colour_Diffuse);
4364 glLightfv(GL_LIGHT1, GL_SPECULAR, colour_Specular);
4365 glLightfv(GL_LIGHT1, GL_SHININESS,colour_Specular);
4366 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
4367 glEnable(GL_LIGHT1);
4369 glEnable(GL_NORMALIZE);
4370 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
4371 glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
4373 if(sGLCrystalConfig.mSaved==
false)
4376 trackball(mQuat,0.,0.,0.,0.);
4379 wxPostEvent(
this,ev);
4382 this->CrystUpdate();
4383 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::InitGL()",8)
4385 void WXGLCrystalCanvas::OnChangeLimits(wxCommandEvent &event)
4387 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits()",10)
4388 if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_FULLCELL)
4396 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
4397 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
4399 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4403 if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL)
4405 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
4406 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
4407 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
4408 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
4409 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
4410 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
4411 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
4412 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
4414 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4418 if(event.GetId()==ID_GLCRYSTAL_MENU_CHANGELIMITS)
4420 UserSelectBoundingBox *BoxDlg =
new UserSelectBoundingBox(
this,
4421 "Set bounding box for display of\natoms (fractional coordinates)",
4423 if (BoxDlg->ShowModal() == wxID_OK )
4425 mcellbbox = BoxDlg->GetBBox();
4426 mpWXCrystal->UpdateGL(
false,
4427 mcellbbox.xMin,mcellbbox.xMax,
4428 mcellbbox.yMin,mcellbbox.yMax,
4429 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
4430 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
4431 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
4433 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4436 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits (X: " <<
4437 mcellbbox.xMin <<
", " << mcellbbox.xMax <<
4439 mcellbbox.yMin <<
", " << mcellbbox.yMax <<
4441 mcellbbox.zMin <<
", " << mcellbbox.zMax <<
4446 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
4447 mpWXCrystal->UpdateGL(
false,
4448 mcellbbox.xMin,mcellbbox.xMax,
4449 mcellbbox.yMin,mcellbbox.yMax,
4450 mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule);
4452 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits():UserSelectBoundingBox done",10)
4455 void WXGLCrystalCanvas::OnShowCrystal( wxCommandEvent & WXUNUSED(event))
4457 if(mShowCrystal) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Show Crystal"));
4458 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Hide Crystal"));
4459 mShowCrystal = !mShowCrystal;
4460 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4463 void WXGLCrystalCanvas::OnShowAtomLabel( wxCommandEvent & WXUNUSED(event))
4465 if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Show Atom Labels"));
4466 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
4467 mShowAtomName= !mShowAtomName;
4468 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4471 void WXGLCrystalCanvas::OnShowHydrogens( wxCommandEvent & WXUNUSED(event))
4473 if(mShowHydrogens) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Show Hydrogens"));
4474 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Hide Hydrogens"));
4475 mShowHydrogens= !mShowHydrogens;
4476 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
4478 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
4479 wxPostEvent(
this,event);
4483 bool WXGLCrystalCanvas::GetShowHydrogens()
const {
return mShowHydrogens;}
4485 void WXGLCrystalCanvas::OnShowCursor( wxCommandEvent & WXUNUSED(event))
4487 if(mShowCursor) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Show Cursor"));
4488 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Hide Cursor"));
4489 mShowCursor= !mShowCursor;
4490 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4493 void WXGLCrystalCanvas::OnSetCursor( wxCommandEvent & WXUNUSED(event))
4495 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnSetCursor",1)
4499 mpWXCrystal->GetCrystal().OrthonormalToFractionalCoords(x,y,z);
4501 mViewCntr.x = (mcellbbox.xMax+mcellbbox.xMin)/2. - x;
4502 mViewCntr.y = (mcellbbox.yMax+mcellbbox.yMin)/2. - y;
4503 mViewCntr.z = (mcellbbox.zMax+mcellbbox.zMin)/2. - z;
4504 UserXYZBox *BoxDlg = new UserXYZBox(this,
4505 wxString("Set fractional coordinates for view\ncenter and cursor position"),
4507 if (BoxDlg->ShowModal() == wxID_OK ) {
4508 mViewCntr = BoxDlg->GetXYZ();
4509 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnSetCursor (frac) = " <<
4510 mViewCntr.x <<
"," << mViewCntr.y <<
"," << mViewCntr.z,1)
4511 mX0 = (mcellbbox.xMax+mcellbbox.xMin)/2. - mViewCntr.x;
4512 mY0 = (mcellbbox.yMax+mcellbbox.yMin)/2. - mViewCntr.y;
4513 mZ0 = (mcellbbox.zMax+mcellbbox.zMin)/2. - mViewCntr.z;
4514 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(mX0, mY0, mZ0);
4515 VFN_DEBUG_MESSAGE("...ortho" << mX0 << "," << mY0 << "," << mZ0,1)
4520 void WXGLCrystalCanvas::OnShowHelp(wxCommandEvent &event)
4522 if(mShowHelp) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHELP, _T(
"Show Help"));
4523 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Hide Help"));
4524 mShowHelp= !mShowHelp;
4525 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4528 void WXGLCrystalCanvas::OnFourier(wxCommandEvent &event)
4530 if(event.GetId()==ID_GLCRYSTAL_MENU_FOURIER)
4532 if(mpFourierMapListWin!=0)
return;
4533 if(mpWXCrystal->GetCrystal().IsBeingRefined())
4535 wxMessageBox(_T(
"The Fourier maps dialog \ncannot be opened during an optimization"), _T(
"Error"), wxOK,
this);
4538 wxFrame *frame=
new wxMiniFrame(
this,-1, wxString::FromAscii((
"Available Fourier maps for "+mpWXCrystal->GetCrystal().GetName()).c_str()),
4539 wxDefaultPosition,wxSize(500,500),wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU);
4540 mpFourierMapListWin=
new WXFourierMapList(
this,frame);
4541 mpFourierMapListWin->mpWireFrame->SetValue(
true);
4542 mpFourierMapListWin->mpShowFourier->SetValue(mShowFourier);
4543 mpFourierMapListWin->mpSharpenMap->SetValue(mSharpenMap);
4545 mpWXCrystal->GetCrystal().UpdateDisplay();
4548 if(mpFourierMapListWin==0)
return;
4549 if(mpFourierMapListWin->mIsUpdating)
return;
4550 if( (event.GetId()==ID_GLCRYSTAL_FOURIER_UPDATE)
4551 ||(event.GetId()==ID_GLCRYSTAL_FOURIER_CONTOUR))
4553 mpFourierMapListWin->mMutex.Lock();
4555 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
4556 if(wxNOT_FOUND!=choice)
4559 mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour);
4560 wxColour col(mpFourierMapListWin->mpColourPicker->GetColour());
4561 if(abs((
float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001)
4563 mvpUnitCellMapGLList[choice]->SetContour((
float)contour);
4564 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
4566 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4567 mvpUnitCellMapGLList[choice]->GenList();
4570 mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5);
4572 mpFourierMapListWin->mMutex.Unlock();
4575 if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTMAP)
4577 mpFourierMapListWin->mMutex.Lock();
4578 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0)
4580 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
4581 mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T(
"min=%5.2f max=%5.2f sigma=%5.2f"),
4582 pMap->Min(),pMap->Max(),pMap->StandardDeviation()));
4584 mpFourierMapListWin->mMutex.Unlock();
4586 if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTGLMAP)
4588 mpFourierMapListWin->mMutex.Lock();
4589 if(mpFourierMapListWin->mpDisplayedMapList->GetSelection()>=0)
4591 boost::shared_ptr<UnitCellMapGLList> pMap=mvpUnitCellMapGLList[mpFourierMapListWin->mpDisplayedMapList->GetSelection()];
4592 mpFourierMapListWin->mpContourValue->SetValue(wxString::Format(_T(
"%5.2f"),pMap->GetContour()));
4593 mpFourierMapListWin->mpColourPicker->SetColour(wxColour(pMap->GetColour()[0]*255,pMap->GetColour()[1]*255,
4594 pMap->GetColour()[2]*255,pMap->GetColour()[3]*255));
4596 mpFourierMapListWin->mMutex.Unlock();
4598 if((event.GetId()==ID_GLCRYSTAL_FOURIER_ADD)||(event.GetId()==ID_GLCRYSTAL_FOURIER_NEWCONTOUR))
4600 mpFourierMapListWin->mMutex.Lock();
4601 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()!=wxNOT_FOUND)
4603 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
4605 wxString scontour=mpFourierMapListWin->mpNewContourValue->GetValue();
4606 if(scontour==_T(
"")) contour=pMap->Min()+pMap->StandardDeviation()*3;
4607 else scontour.ToDouble(&contour);
4608 wxColor ncolor(255,0,0);
4609 ncolor = wxGetColourFromUser((wxWindow*)
this, ncolor);
4611 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4612 mvpUnitCellMapGLList.push_back(boost::shared_ptr<UnitCellMapGLList>(
new UnitCellMapGLList(*pMap,
this,
true,(
float)contour)));
4613 mvpUnitCellMapGLList.back()->SetName(pMap->GetName());
4614 mvpUnitCellMapGLList.back()->SetColour(ncolor.Red()/255.0,ncolor.Green()/255.0,ncolor.Blue()/255.0,0.5);
4615 mpFourierMapListWin->mMutex.Unlock();
4616 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
4619 mvpUnitCellMapGLList.back()->GenList();
4623 if(event.GetId()==ID_GLCRYSTAL_FOURIER_REMOVE)
4625 mpFourierMapListWin->mMutex.Lock();
4626 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
4627 if(wxNOT_FOUND!=choice)
4628 mvpUnitCellMapGLList.erase(mvpUnitCellMapGLList.begin()+choice);
4629 mpFourierMapListWin->mMutex.Unlock();
4631 if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHOW)
4633 mpFourierMapListWin->mMutex.Lock();
4634 mShowFourier=mpFourierMapListWin->mpShowFourier->GetValue();
4635 mpFourierMapListWin->mMutex.Unlock();
4637 if(event.GetId()==ID_GLCRYSTAL_FOURIER_WIREFRAME)
4639 mpFourierMapListWin->mMutex.Lock();
4640 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
4641 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
4642 (*pos)->ToggleShowWire();
4643 mpFourierMapListWin->mMutex.Unlock();
4646 if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHARPEN)
4648 mpFourierMapListWin->mMutex.Lock();
4649 mSharpenMap=mpFourierMapListWin->mpSharpenMap->GetValue();
4650 mpFourierMapListWin->mMutex.Unlock();
4654 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
4655 this->CrystUpdate();
4658 void WXGLCrystalCanvas::OnLoadFourierGRD( wxCommandEvent & WXUNUSED(event))
4660 wxFileDialog fd((wxWindow*)
this, _T(
"Choose a file containing a Fourier Map"),
4661 _T(
""), _T(
""), _T(
"Fourier Map files (*.grd)|*.grd"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
4663 if(fd.ShowModal() == wxID_OK)
4665 const string filename(fd.GetPath().ToAscii());
4666 UnitCellMap *pMap=
new UnitCellMap(mpWXCrystal->GetCrystal());
4667 if (pMap->ImportGRD(filename) == 0)
4669 string tmp=
"Error reading Fourier file:"+filename;
4670 wxMessageBox( wxString::FromAscii(tmp.c_str()), _T(
"File error"), wxOK,
this);
4673 this->AddFourier(pMap);
4677 void WXGLCrystalCanvas::OnLoadFourierDSN6( wxCommandEvent & WXUNUSED(event))
4679 wxFileDialog fd((wxWindow*)
this, _T(
"Choose a file containing a Fourier Map"),
4680 _T(
""), _T(
""), _T(
"Fourier Map files (*.DN6)|*.DN6"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
4682 if(fd.ShowModal() == wxID_OK)
4684 const string filename(fd.GetPath().ToAscii());
4685 UnitCellMap *pMap=
new UnitCellMap(mpWXCrystal->GetCrystal());
4686 if (pMap->ImportDSN6(filename) == 0)
4688 string tmp=
"Error reading Fourier file:"+filename;
4689 wxMessageBox( wxString::FromAscii(tmp.c_str()), _T(
"File error"), wxOK,
this);
4692 this->AddFourier(pMap);
4696 void WXGLCrystalCanvas::AddFourier(UnitCellMap *map)
4698 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(map));
4699 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4701 float contour=map->Mean()+2*map->StandardDeviation();
4702 if(contour>map->Max()) contour=map->Mean()+0.75*(map->Max()-map->Mean());
4703 mvpUnitCellMapGLList.push_back(boost::shared_ptr<UnitCellMapGLList>(
new UnitCellMapGLList(*map,
this)));
4704 switch(mvpUnitCellMapGLList.size())
4706 case 1: mvpUnitCellMapGLList.back()->SetColour(1.,0.,0.,.5);
break;
4707 case 2: mvpUnitCellMapGLList.back()->SetColour(0.,0.,1.,.5);
break;
4708 default:mvpUnitCellMapGLList.back()->SetColour(0.,1.,0.,.5);
break;
4711 mvpUnitCellMapGLList.back()->GenList();
4712 mvpUnitCellMapGLList.back()->SetName(map->GetName());
4714 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4718 void WXGLCrystalCanvas::OnFourierChangeColour(wxColourPickerEvent &event)
4720 mpFourierMapListWin->mMutex.Lock();
4722 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
4723 if(wxNOT_FOUND!=choice)
4726 mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour);
4727 wxColour col(mpFourierMapListWin->mpColourPicker->GetColour());
4728 if(abs((
float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001)
4730 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4731 mvpUnitCellMapGLList[choice]->SetContour((
float)contour);
4732 mvpUnitCellMapGLList[choice]->GenList();
4734 mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5);
4736 mpFourierMapListWin->mMutex.Unlock();
4737 mpWXCrystal->GetCrystal().UpdateDisplay();
4766 void WXGLCrystalCanvas::OnPOVRay( wxCommandEvent & WXUNUSED(event))
4769 wxFileDialog save(
this,_T(
"Choose filename"),_T(
""),_T(
""),_T(
"*.pov"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
4770 if(save.ShowModal() != wxID_OK)
return;
4771 this->POVRayOutput(
string(save.GetPath().char_str()));
4774 void WXGLCrystalCanvas::POVRayOutput(
const std::string &filename)
4776 ofstream os(filename.c_str());
4778 os <<
"#version 3.6 ;"<<endl
4779 <<
"// This File was created by FOX/ObjCryst++ (http://objcryst.sf.net)"<<endl
4781 <<
"// You can produce a ray-traced image using POV-Ray, freely available"<<endl
4782 <<
"//from http://www.povray.org"<<endl
4784 <<
"// Example command line to produce an anti-aliase 640x480 image: "<<endl
4785 <<
"// povray +Ifile.pov +.pov +W640 +H480 +A +Q11"<<endl
4786 <<
"// You can add '+UA' at the end to have a transparent background"<<endl
4787 <<
"// You can add '+kff10' to generate 10 rotated images for an animation"<<endl
4788 <<
"// (see the 'clock' in the 'OrientPitch' definition below)"<<endl
4790 <<
"// Notes:"<<endl
4791 <<
"// - This POVRay file is written to produce a 4/3 image, e.g. 640x480"<<endl
4792 <<
"// If your image in the FOX 3D view was not 4/3, some parts may be cut"<<endl
4793 <<
"// You can then get the full structure by increasing the 'angle' "<<endl
4794 <<
"// (viewing angle) in the camera settings below."<<endl
4795 <<
"// You can change the aspect ratio (e.g. to produce a square image)"<<endl
4796 <<
"// by changing the 'right <-1.33,0,0>' statement in the camera definition"<<endl
4797 <<
"// - You can change the orientation of the view by changing the"<<endl
4798 <<
"// OrientRoll, OrientPitch and OrientYaw angles just below (in degrees)"<<endl
4799 <<
"// - You can change the aspects of atoms by altering the macros below."<<endl
4800 <<
"// The radius of atoms is by default 1/3 of their tabulated atomic radius,"<<endl
4801 <<
"// i.e. as in the FOX/ObjCryst++ 3D Crystal view. To modify this you can"<<endl
4802 <<
"// change the second line of the 'ObjCrystAtom' macro to (e.g. for full radius):"<<endl
4803 <<
"// '{ <atomx,atomy,atomz>,atomr*1.0'"<<endl
4804 <<
"// - The colour of atoms, bonds (free and non-free torsions) can be changed"<<endl
4805 <<
"// in the 'GLOBAL DECLARATIONS FOR ATOMS & BONDS' section"<<endl
4806 <<
"// - Just for fun, you can try getting *very close* to one of the atoms,"<<endl
4807 <<
"// and, in the 'ObjCrystAtom' macro at the end of the 'finish'"<<endl
4808 <<
"// statement, change the 'reflection' value to 1.0, "<<endl
4809 <<
"// to get a mirror effect on the atoms..."<<endl
4811 <<
"// See http://povray.org/documentation/ for more options"<<endl
4812 <<
"//"<<endl<<endl;
4814 os <<
"// Description of Crystal :" << mpWXCrystal->GetCrystal().GetName() <<endl;
4815 os <<
"global_settings { assumed_gamma 2.2 ambient_light rgb <1,1,1>}"<<endl;
4817 REAL xcam=0,ycam=0,zcam=mDist;
4818 build_rotmatrix( m,mQuat);
4820 REAL x=(mcellbbox.xMin+mcellbbox.xMax)/2.;
4821 REAL y=(mcellbbox.yMin+mcellbbox.yMax)/2.;
4822 REAL z=(mcellbbox.zMin+mcellbbox.zMax)/2.;
4823 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(x,y,z);
4828 const REAL q1=mQuat[0];
const REAL q2=mQuat[1];
4829 const REAL q3=mQuat[2];
const REAL q4=mQuat[3];
4831 REAL yaw =(q4*q4 + q1*q1 - q2*q2 - q3*q3);
4832 if(abs(yaw)>1e-6) yaw =atan( 2*(q1*q2+q4*q3) /yaw )*RAD2DEG;
4833 else {
if((q1*q2+q4*q3)>0) yaw =90.;
else yaw =-90;}
4835 const REAL pitch=asin(-2*(q1*q3-q4*q2))*RAD2DEG;
4837 REAL roll=(q4*q4 - q1*q1 - q2*q2 + q3*q3);
4838 if(abs(roll)>1e-6) roll =atan( 2*(q4*q1+q2*q3) /roll)*RAD2DEG;
4839 else {
if((q4*q1+q2*q3)>0) roll=90.;
else roll=-90;}
4841 if((q4*q4 + q1*q1 - q2*q2 - q3*q3)<0) yaw +=180;
4842 if((q4*q4 - q1*q1 - q2*q2 + q3*q3)<0) roll +=180;
4845 os <<
"#declare OrientRoll="<<roll<<
";"<<endl;
4846 os <<
"#declare OrientPitch="<<pitch<<
"+360*clock;"<<endl;
4847 os <<
"#declare OrientYaw="<<yaw<<
";"<<endl<<endl;
4850 os <<
"camera" <<endl;
4852 os <<
" location <"<<xcam+x<<
","<<ycam+y<<
","<<zcam+z<<
">"<<endl
4853 <<
" look_at <" << x <<
"," << y <<
"," << z <<
">"<<endl
4854 <<
" angle "<< mViewAngle*1.2 <<endl
4855 <<
" right <-1.33,0,0> //change handedness as in OpenGL, aspect ratio=4/3"<<endl
4856 <<
" translate <" <<-x <<
"," <<-y <<
"," <<-z <<
">"<<endl
4857 <<
" rotate <OrientRoll,0,0>" <<endl
4858 <<
" rotate <0,OrientPitch,0>" <<endl
4859 <<
" rotate <0,0,OrientYaw>" <<endl
4860 <<
" translate <" << x <<
"," << y <<
"," << z <<
">"<<endl
4863 REAL xlight=-1000,ylight=1000,zlight=1000;
4864 os <<
"light_source"<<endl;
4866 <<
" <"<<xlight<<
","<<ylight<<
","<<zlight<<
">"<<endl
4867 <<
" colour rgb <1.0,1.0,1.0>" <<endl
4868 <<
" //shadowless" <<endl
4869 <<
" translate <" <<-x <<
"," <<-y <<
"," <<-z <<
">"<<endl
4870 <<
" rotate <OrientRoll,0,0>" <<endl
4871 <<
" rotate <0,OrientPitch,0>" <<endl
4872 <<
" rotate <0,0,OrientYaw>" <<endl
4873 <<
" translate <" << x <<
"," << y <<
"," << z <<
">"<<endl
4874 <<
"}" <<endl<<endl;
4876 os <<
"background { colour rgb <0.0, 0.0, 0.0> }"<<endl<<endl;
4878 CrystalPOVRayOptions options;
4879 options.mXmin=mcellbbox.xMin;
4880 options.mXmax=mcellbbox.xMax;
4881 options.mYmin=mcellbbox.yMin;
4882 options.mYmax=mcellbbox.yMax;
4883 options.mZmin=mcellbbox.zMin;
4884 options.mZmax=mcellbbox.zMax;
4885 options.mShowLabel=mShowAtomName;
4886 options.mShowHydrogens=mShowHydrogens;
4889 mpWXCrystal->GetCrystal().POVRayDescription(os,options);
4893 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4895 if (mmapbbox.xMin != mmapbbox.xMax)
4897 options.mXmin=mmapbbox.xMin;
4898 options.mXmax=mmapbbox.xMax;
4899 options.mYmin=mmapbbox.yMin;
4900 options.mYmax=mmapbbox.yMax;
4901 options.mZmin=mmapbbox.zMin;
4902 options.mZmax=mmapbbox.zMax;
4905 os<<
"/////////////////// FOURIER MAPS///////////////////////////"<<endl;
4906 vector<boost::shared_ptr<UnitCellMapGLList> >::const_iterator pos;
4907 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos)
4909 const float *prgbf=(*pos)->GetColour();
4910 if((*pos)->ShowWire())
4912 os <<
"#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3,"
4913 <<
"nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<<endl
4914 <<
" cylinder"<<endl
4915 <<
" { <x1,y1,z1>,"<<endl
4916 <<
" <x2,y2,z2>,"<<endl
4918 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4919 <<
" pigment { colour rgb<"
4920 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4921 <<
" no_shadow"<<endl
4923 <<
" cylinder"<<endl
4924 <<
" { <x2,y2,z2>,"<<endl
4925 <<
" <x3,y3,z3>,"<<endl
4927 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4928 <<
" pigment { colour rgb<"
4929 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4930 <<
" no_shadow"<<endl
4932 <<
" cylinder"<<endl
4933 <<
" { <x1,y1,z1>,"<<endl
4934 <<
" <x3,y3,z3>,"<<endl
4936 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4937 <<
" pigment { colour rgb<"
4938 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4939 <<
" no_shadow"<<endl
4941 <<
"#end"<<endl<<endl;
4942 (*pos)->GetMap().POVRayDescription(os,(*pos)->GetContour(),options);
4946 os <<
"#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3,"
4947 <<
"nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<<endl
4948 <<
" smooth_triangle"<<endl
4949 <<
" {<x1,y1,z1>,<nx1,ny1,nz1>"<<endl
4950 <<
" <x2,y2,z2>,<nx2,ny2,nz2>"<<endl
4951 <<
" <x3,y3,z3>,<nx3,ny3,nz3>}"<<endl
4952 <<
"#end"<<endl<<endl;
4955 (*pos)->GetMap().POVRayDescription(os,(*pos)->GetContour(),options);
4956 os <<
" texture"<<endl
4958 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4959 <<
" pigment { colour rgb<"
4962 os <<*prgbf++<<
">}"<<endl
4964 <<
" no_shadow"<<endl
4974 BBox WXGLCrystalCanvas::GetCellBBox() {
4978 BBox WXGLCrystalCanvas::GetMapBBox() {
4982 REAL WXGLCrystalCanvas::GetFadeDistance()
4984 return mFadeDistance;
4987 void WXGLCrystalCanvas::UnProject(REAL &x, REAL &y, REAL &z)
4989 GLdouble vx,vy,vz,junk;
4991 GLdouble modelMatrix[16];
4992 GLdouble projMatrix[16];
4996 glMatrixMode( GL_MODELVIEW );
4998 glTranslatef( 0, 0, -mDist );
5000 glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
5001 glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
5002 glGetIntegerv(GL_VIEWPORT,viewport);
5005 gluProject(0, 0, 0 ,modelMatrix,projMatrix,viewport,&junk,&junk,&z0);
5007 gluUnProject(x,y,z0,modelMatrix,projMatrix,viewport,&vx,&vy,&vz);
5011 build_rotmatrix( m,mQuat);
5013 x= m[0][0]* vx + m[0][1]*vy + m[0][2]*vz -mX0;
5014 y= m[1][0]* vx + m[1][1]*vy + m[1][2]*vz -mY0;
5015 z= m[2][0]* vx + m[2][1]*vy + m[2][2]*vz -mZ0;
5016 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::UnProject():X Y Z = "<<x<<
" , "<<y<<
" , "<<z,5)
5019 void WXGLCrystalCanvas::BuildGLFont()
5021 if(mIsGLFontBuilt)
return;
5022 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::BuildGLFont()-gldisplay",6)
5025 XFontStruct *fontInfo=NULL;
5027 mGLFontDisplayListBase = glGenLists(96);
5029 dpy = XOpenDisplay(NULL);
5031 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-bold-*-r-*-10-*-*-*-*-*-*-*");
5032 if (fontInfo == NULL)
5033 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-bold-*-*-*-10-*-*-*-*-*-*-*");
5034 if (fontInfo == NULL)
5035 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-bold-*-r-*-10-*-*-*-*-*-*-*");
5036 if (fontInfo == NULL)
5037 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-medium-*-*-*-12-*-*-*-*-*-*-*");
5038 if (fontInfo == NULL)
5039 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-medium-*-*-*-12-*-*-*-*-*-*-*");
5040 if (fontInfo == NULL)
5041 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-*-*-*-*-12-*-*-*-*-*-*-*");
5042 if (fontInfo == NULL)
5043 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-*-*-*-*-12-*-*-*-*-*-*-*");
5044 if (fontInfo == NULL)
5045 fontInfo = XLoadQueryFont(dpy,
"fixed");
5046 if (fontInfo == NULL) cout <<
"no X font available..."<<endl;
5048 glXUseXFont(fontInfo->fid, 32, 96, mGLFontDisplayListBase);
5049 XFreeFont(dpy, fontInfo);
5056 HDC hDC = (HDC)dc.GetHDC();
5058 wxSize s = dc.GetPPI();
5059 int height = int(round(3 * (s.GetHeight() + s.GetWidth()) / 2 / 25.4));
5060 mGLFontDisplayListBase = 100;
5061 font = CreateFont(-height,
5071 CLIP_DEFAULT_PRECIS,
5072 ANTIALIASED_QUALITY,
5073 FF_DONTCARE|DEFAULT_PITCH,
5076 oldfont = (HFONT)SelectObject(hDC, font);
5077 wglUseFontBitmaps(hDC, 0, 128, mGLFontDisplayListBase);
5078 SelectObject(hDC, oldfont);
5081 mIsGLFontBuilt=
true;
5082 sFontDisplayListBase=mGLFontDisplayListBase;
5083 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::BuildGLFont()",6)
5086 void WXGLCrystalCanvas::DeleteGLFont()
const
5088 if(!mIsGLFontBuilt)
return;
5089 glDeleteLists(mGLFontDisplayListBase, 96);
5090 mIsGLFontBuilt=
false;
5091 mGLFontDisplayListBase=0;
5101 BEGIN_EVENT_TABLE(UserSelectBoundingBox, wxDialog)
5102 EVT_BUTTON(wxID_OK, UserSelectBoundingBox::OnOk)
5105 UserSelectBoundingBox::UserSelectBoundingBox (wxWindow *parent, const
char * title,
5107 : wxDialog((wxWindow *)parent, -1, _T("Set bounding box"), wxDefaultPosition,
5108 wxSize(250, 250), wxDEFAULT_DIALOG_STYLE)
5110 wxBoxSizer *dialogSizer =
new wxBoxSizer(wxVERTICAL);
5111 wxFlexGridSizer *inputSizer =
new wxFlexGridSizer(4, 3, 10, 10);
5113 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"")), 0, wxALIGN_CENTRE_VERTICAL);
5114 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"minimum")), 0, wxALIGN_CENTER);
5115 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"maximum")), 0, wxALIGN_CENTER);
5117 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"a")), 0, wxALIGN_CENTRE_VERTICAL);
5118 inputSizer->Add(mpXminCtrl =
new wxTextCtrl(
this, -1,
5119 wxString::Format(_T(
"%f"),bbox.xMin), wxDefaultPosition,
5120 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5121 0, wxALIGN_CENTRE_VERTICAL);
5122 inputSizer->Add(mpXmaxCtrl =
new wxTextCtrl(
this, -1,
5123 wxString::Format(_T(
"%f"),bbox.xMax), wxDefaultPosition,
5124 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5125 0, wxALIGN_CENTRE_VERTICAL);
5127 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"b")), 0, wxALIGN_CENTRE_VERTICAL);
5128 inputSizer->Add(mpYminCtrl =
new wxTextCtrl(
this, -1,
5129 wxString::Format(_T(
"%f"),bbox.yMin), wxDefaultPosition,
5130 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5131 0, wxALIGN_CENTRE_VERTICAL);
5132 inputSizer->Add(mpYmaxCtrl =
new wxTextCtrl(
this, -1,
5133 wxString::Format(_T(
"%f"),bbox.yMax), wxDefaultPosition,
5134 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5135 0, wxALIGN_CENTRE_VERTICAL);
5137 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"c")), 0, wxALIGN_CENTRE_VERTICAL);
5138 inputSizer->Add(mpZminCtrl =
new wxTextCtrl(
this, -1,
5139 wxString::Format(_T(
"%f"),bbox.zMin), wxDefaultPosition,
5140 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5141 0, wxALIGN_CENTRE_VERTICAL);
5142 inputSizer->Add(mpZmaxCtrl =
new wxTextCtrl(
this, -1,
5143 wxString::Format(_T(
"%f"),bbox.zMax), wxDefaultPosition,
5144 wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)),
5145 0, wxALIGN_CENTRE_VERTICAL);
5147 wxFlexGridSizer *buttonSizer =
new wxFlexGridSizer(1, 2, 10, 10);
5148 buttonSizer->Add(
new wxButton(
this, wxID_OK, _T(
"OK")),
5149 0, wxALIGN_CENTRE_VERTICAL);
5150 buttonSizer->Add(
new wxButton(
this, wxID_CANCEL, _T(
"Cancel")),
5151 0, wxALIGN_CENTRE_VERTICAL);
5153 dialogSizer->Add(10, 10);
5154 dialogSizer->Add(
new wxStaticText(
this, -1, wxString::FromAscii(title)), 0,
5156 dialogSizer->Add(10, 10);
5157 dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER);
5158 dialogSizer->Add(20, 20);
5159 dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
5161 SetSizer(dialogSizer);
5162 SetAutoLayout(TRUE);
5166 UserSelectBoundingBox::~UserSelectBoundingBox () {
5173 void UserSelectBoundingBox::OnOk (wxCommandEvent & WXUNUSED(event)) {
5176 mpXminCtrl->GetValue().ToDouble(&val);
5178 mpXmaxCtrl->GetValue().ToDouble(&val);
5180 if (mbbox.xMin == mbbox.xMax) {wxMessageBox(_T(
"Sorry, Xmin must be less than Xmax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
5181 if (mbbox.xMin > mbbox.xMax) {
5182 float tmp = mbbox.xMax;
5183 mbbox.xMax = mbbox.xMin;
5186 VFN_DEBUG_MESSAGE(
"Xmin " << mbbox.xMin <<
" Xmax " << mbbox.xMax,1)
5188 mpYminCtrl->GetValue().ToDouble(&val);
5190 mpYmaxCtrl->GetValue().ToDouble(&val);
5192 if (mbbox.yMin == mbbox.yMax) {wxMessageBox(_T(
"Sorry, Ymin must be less than Ymax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
5193 if (mbbox.yMin > mbbox.yMax) {
5194 float tmp = mbbox.yMax;
5195 mbbox.yMax = mbbox.yMin;
5198 VFN_DEBUG_MESSAGE(
"Ymin " << mbbox.yMin <<
" Ymax " << mbbox.yMax,1)
5200 mpZminCtrl->GetValue().ToDouble(&val);
5202 mpZmaxCtrl->GetValue().ToDouble(&val);
5204 if (mbbox.zMin == mbbox.zMax) {wxMessageBox(_T(
"Sorry, Zmin must be less than Zmax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
5205 if (mbbox.zMin > mbbox.zMax) {
5206 float tmp = mbbox.zMax;
5207 mbbox.zMax = mbbox.zMin;
5210 VFN_DEBUG_MESSAGE(
"Zmin " << mbbox.zMin <<
" Zmax " << mbbox.zMax,1)
5216 BBox UserSelectBoundingBox::GetBBox () {
5226 BEGIN_EVENT_TABLE(UserXYZBox, wxDialog)
5227 EVT_BUTTON(wxID_OK, UserXYZBox::OnOk)
5230 UserXYZBox::UserXYZBox (wxWindow *parent, const wxString &title,
5232 : wxDialog((wxWindow *)parent, -1, _T("Set position"), wxDefaultPosition,
5233 wxSize(250, 250), wxDEFAULT_DIALOG_STYLE)
5235 wxBoxSizer *dialogSizer =
new wxBoxSizer(wxVERTICAL);
5236 wxFlexGridSizer *inputSizer =
new wxFlexGridSizer(3, 2, 10, 10);
5238 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"x")), 0, wxALIGN_CENTRE_VERTICAL);
5239 inputSizer->Add(mpXCtrl =
new wxTextCtrl(
this, -1,
5240 wxString::Format(_T(
"%.3f"),xyz.x), wxDefaultPosition, wxDefaultSize,
5241 wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)),
5242 0, wxALIGN_CENTRE_VERTICAL);
5244 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"y")), 0, wxALIGN_CENTRE_VERTICAL);
5245 inputSizer->Add(mpYCtrl =
new wxTextCtrl(
this, -1,
5246 wxString::Format(_T(
"%.3f"),xyz.y), wxDefaultPosition, wxDefaultSize,
5247 wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)),
5248 0, wxALIGN_CENTRE_VERTICAL);
5250 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"z")), 0, wxALIGN_CENTRE_VERTICAL);
5251 inputSizer->Add(mpZCtrl =
new wxTextCtrl(
this, -1,
5252 wxString::Format(_T(
"%.3f"),xyz.z), wxDefaultPosition, wxDefaultSize,
5253 wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)),
5254 0, wxALIGN_CENTRE_VERTICAL);
5256 wxFlexGridSizer *buttonSizer =
new wxFlexGridSizer(1, 2, 10, 10);
5257 buttonSizer->Add(
new wxButton(
this, wxID_OK, _T(
"OK")),
5258 0, wxALIGN_CENTRE_VERTICAL);
5259 buttonSizer->Add(
new wxButton(
this, wxID_CANCEL, _T(
"Cancel")),
5260 0, wxALIGN_CENTRE_VERTICAL);
5262 dialogSizer->Add(10, 10);
5263 dialogSizer->Add(
new wxStaticText(
this, -1, title), 0,
5265 dialogSizer->Add(10, 10);
5266 dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER);
5267 dialogSizer->Add(20, 20);
5268 dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
5270 SetSizer(dialogSizer);
5271 SetAutoLayout(TRUE);
5275 UserXYZBox::~UserXYZBox () {
5278 void UserXYZBox::OnOk (wxCommandEvent & WXUNUSED(event))
5281 mpXCtrl->GetValue().ToDouble(&tmp);
5284 mpYCtrl->GetValue().ToDouble(&tmp);
5287 mpZCtrl->GetValue().ToDouble(&tmp);
5294 Triple UserXYZBox::GetXYZ () {
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be.
Molecule * ZScatterer2Molecule(ZScatterer *scatt)
Converter from ZScatterer to a Molecule object.
std::map< wxWindowID, std::pair< wxPoint, wxSize > > gvWindowPosition
Used to remember window positions.
REAL GetBondAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3)
Get The Bond Angle of 3 atoms.
T * WXDialogChooseFromRegistry(ObjRegistry< T > ®, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
Crystal class: Unit cell, spacegroup, scatterers.
std::map< pair< const ScatteringPower *, const ScatteringPower * >, Crystal::BumpMergePar > VBumpMergePar
Anti-bump parameters.
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
The Scattering Power for an Atom.
virtual const string & GetName() const
Name of the object.
Simple chronometer class, with microsecond precision.
wxCryst class for Crystals
Structure to store the scattering power parameters.