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"
55 #ifdef __WXMAC__ // For the wxMac version of wxWindows, i.e. with the "Aqua" look
56 #include <OpenGL/glu.h>
69 #ifdef __WXMAC__ // For the wxMac version of wxWindows, i.e. with the "Aqua" look
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());
145 class UserSelectBoundingBox :
public wxDialog {
147 UserSelectBoundingBox(wxWindow * parent,
const char * title, BBox bbox);
148 ~UserSelectBoundingBox ();
151 void OnOk (wxCommandEvent & WXUNUSED(event));
152 wxTextCtrl * mpXminCtrl, *mpXmaxCtrl;
153 wxTextCtrl * mpYminCtrl, *mpYmaxCtrl;
154 wxTextCtrl * mpZminCtrl, *mpZmaxCtrl;
156 DECLARE_EVENT_TABLE()
160 class UserXYZBox :
public wxDialog {
162 UserXYZBox(wxWindow * parent,
const wxString &title, Triple xyz);
166 void OnOk (wxCommandEvent & WXUNUSED(event));
167 wxTextCtrl * mpXCtrl;
168 wxTextCtrl * mpYCtrl;
169 wxTextCtrl * mpZCtrl;
171 DECLARE_EVENT_TABLE()
179 WXCrystalScrolledGridWindow::WXCrystalScrolledGridWindow(wxWindow* parent, WXCrystal* p,
long id):
180 wxGrid(parent,id),mpWXCrystal(p)
183 WXCrystalScrolledGridWindow::~WXCrystalScrolledGridWindow()
193 WXCrystal::RowScattPow::RowScattPow():
195 mBiso(1.0),mFormalCharge(0.0),mR(1.0),mG(1.0),mB(1.0),mMaximumLikelihoodError(0.0),mNbGhostAtoms(0.0),
196 mNeedUpdateUI(true),mIdx(-1)
204 Molecule* Atoms2Molecule(list<Atom *> &vAtom)
206 VFN_DEBUG_ENTRY(
"Atoms2Molecule()",6)
207 Molecule *mol=new Molecule((*vAtom.begin())->GetCrystal(),"Molecule");
208 const
unsigned long nb=vAtom.size();
211 for(list<Atom *>::iterator pos=vAtom.begin();pos!=vAtom.end();++pos)
213 REAL x=(*pos)->GetX();
214 REAL y=(*pos)->GetY();
215 REAL z=(*pos)->GetZ();
216 (*pos)->GetCrystal().FractionalToOrthonormalCoords(x,y,z);
220 mol->AddAtom(x,y,z,&((*pos)->GetScatteringPower()),(*pos)->GetName());
221 mol->GetAtom(i++).SetOccupancy((*pos)->GetOccupancy());
224 CrystVector_REAL x(nb),y(nb),z(nb),radius(nb);
225 vector<pair<const ScatteringPowerAtom *,long> > scattpow(nb);
226 for(
unsigned int i=0;i<nb;++i)
228 x(i)=mol->GetAtom(i).GetX();
229 y(i)=mol->GetAtom(i).GetY();
230 z(i)=mol->GetAtom(i).GetZ();
231 if(mol->GetAtom(i).IsDummy())
238 radius(i)=mol->GetAtom(i).GetScatteringPower().GetRadius();
239 scattpow[i].first=
dynamic_cast<const ScatteringPowerAtom *
>
240 (&(mol->GetAtom(i).GetScatteringPower()));
241 scattpow[i].second=scattpow[i].first->GetAtomicNumber();
244 for(
unsigned int i=0;i<nb;++i)
246 if(scattpow[i].first==0)
continue;
247 const REAL x1=x(i),y1=y(i),z1=z(i);
251 for(
unsigned int j=i+1;j<nb;++j)
253 if(scattpow[j].first==0)
continue;
254 const REAL dist=sqrt(x(j)*x(j)+y(j)*y(j)+z(j)*z(j));
256 if(dist<(1.10*(radius(i)+radius(j))))
258 if((1!=scattpow[i].second)||(1!=scattpow[j].second))
260 mol->AddBond(mol->GetAtom(i),mol->GetAtom(j),dist,.01,.02,
false);
268 mol->BuildConnectivityTable();
269 for(map<MolAtom*,set<MolAtom*> >::const_iterator pos=mol->GetConnectivityTable().begin();
270 pos!=mol->GetConnectivityTable().end();++pos)
272 for(set<MolAtom*>::const_iterator pos1=pos->second.begin();
273 pos1!=pos->second.end();++pos1)
275 for(set<MolAtom*>::const_iterator pos2=pos1;
276 pos2!=pos->second.end();++pos2)
278 if(pos2==pos1)
continue;
279 if(mol->FindBondAngle(**pos1,*(pos->first),**pos2)== mol->GetBondAngleList().end())
280 mol->AddBondAngle(**pos1,*(pos->first),**pos2,
281 GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,
false);
288 mol->GetCrystal().OrthonormalToFractionalCoords(x0,y0,z0);
292 mol->UpdateDisplay();
293 VFN_DEBUG_EXIT(
"ZScatterer2Molecule()",6)
302 static const
long ID_CRYSTAL_MENU_SAVECIF =WXCRYST_ID();
303 static const
long ID_CRYSTAL_MENU_SAVETEXT =WXCRYST_ID();
304 static const
long ID_CRYSTAL_MENU_DISPLAY =WXCRYST_ID();
305 static const
long ID_CRYSTAL_MENU_DISPLAY_3DVIEW =WXCRYST_ID();
306 static const
long ID_CRYSTAL_MENU_SCATT =WXCRYST_ID();
307 static const
long ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS =WXCRYST_ID();
308 static const
long ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES =WXCRYST_ID();
309 static const
long ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW =WXCRYST_ID();
310 static const
long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM =WXCRYST_ID();
311 static const
long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE =WXCRYST_ID();
312 static const
long ID_CRYSTAL_MENU_SCATT_ADDATOM =WXCRYST_ID();
313 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST =WXCRYST_ID();
314 static const
long ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER =WXCRYST_ID();
315 static const
long ID_CRYSTAL_MENU_SCATT_ADDMOLECULE =WXCRYST_ID();
316 static const
long ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE =WXCRYST_ID();
317 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX =WXCRYST_ID();
318 static const
long ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX =WXCRYST_ID();
319 static const
long ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON =WXCRYST_ID();
320 static const
long ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON =WXCRYST_ID();
321 static const
long ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE =WXCRYST_ID();
322 static const
long ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE =WXCRYST_ID();
323 static const
long ID_CRYSTAL_MENU_SCATT_ADDCUBE =WXCRYST_ID();
324 static const
long ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL =WXCRYST_ID();
325 static const
long ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL =WXCRYST_ID();
326 static const
long ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON =WXCRYST_ID();
327 static const
long ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER =WXCRYST_ID();
328 static const
long ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER =WXCRYST_ID();
329 static const
long ID_CRYSTAL_SPACEGROUP =WXCRYST_ID();
330 static const
long ID_GLCRYSTAL_MENU_UPDATE =WXCRYST_ID();
331 static const
long ID_GLCRYSTAL_WINDOW =WXCRYST_ID();
332 static const
long ID_CRYSTAL_WIN_SCATTPOW =WXCRYST_ID();
333 static const
long ID_CRYSTAL_WIN_ANTIBUMP =WXCRYST_ID();
334 static const
long ID_CRYSTAL_WIN_BONDVALENCE =WXCRYST_ID();
335 static const
long ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN =WXCRYST_ID();
338 static const
long ID_GLCRYSTAL_FOURIER_ADD= WXCRYST_ID();
339 static const
long ID_GLCRYSTAL_FOURIER_REMOVE= WXCRYST_ID();
340 static const
long ID_GLCRYSTAL_FOURIER_UPDATE= WXCRYST_ID();
341 static const
long ID_GLCRYSTAL_FOURIER_WIREFRAME= WXCRYST_ID();
342 static const
long ID_GLCRYSTAL_FOURIER_SHOW= WXCRYST_ID();
343 static const
long ID_GLCRYSTAL_FOURIER_SHARPEN= WXCRYST_ID();
344 static const
long ID_GLCRYSTAL_FOURIER_LISTMAP= WXCRYST_ID();
345 static const
long ID_GLCRYSTAL_FOURIER_LISTGLMAP= WXCRYST_ID();
346 static const
long ID_GLCRYSTAL_FOURIER_CONTOUR= WXCRYST_ID();
347 static const
long ID_GLCRYSTAL_FOURIER_NEWCONTOUR= WXCRYST_ID();
348 static const
long ID_GLCRYSTAL_FOURIER_COLOURPICKER= WXCRYST_ID();
351 BEGIN_EVENT_TABLE(WXCrystal,wxWindow)
352 EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse)
353 EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave)
354 EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad)
355 EVT_MENU(ID_CRYSTAL_MENU_SAVECIF, WXCrystal::OnMenuSaveCIF)
356 EVT_MENU(ID_CRYSTAL_MENU_SAVETEXT, WXCrystal::OnMenuSaveText)
357 EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
358 EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
359 EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize)
360 EVT_MENU(ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS, WXCrystal::OnMenuSetRelativeXYZLimits)
361 EVT_MENU(ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES, WXCrystal::OnMenuTestRandomMoves)
363 EVT_MENU(ID_CRYSTAL_MENU_DISPLAY_3DVIEW, WXCrystal::OnMenuCrystalGL)
365 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM, WXCrystal::OnMenuAddScattPowAtom)
366 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE, WXCrystal::OnMenuAddScattPowSphere)
367 EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW, WXCrystal::OnMenuRemoveScattPow)
368 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDATOM, WXCrystal::OnMenuAddScatterer)
369 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST, WXCrystal::OnMenuAddScatterer)
370 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER, WXCrystal::OnMenuAddScatterer)
371 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDMOLECULE, WXCrystal::OnMenuAddScatterer)
372 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE, WXCrystal::OnMenuAtoms2Molecule)
373 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX,WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix)
374 EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX, WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix)
375 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON, WXCrystal::OnMenuAddScatterer)
376 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON, WXCrystal::OnMenuAddScatterer)
377 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE, WXCrystal::OnMenuAddScatterer)
378 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE, WXCrystal::OnMenuAddScatterer)
379 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDCUBE, WXCrystal::OnMenuAddScatterer)
380 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL,WXCrystal::OnMenuAddScatterer)
381 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL, WXCrystal::OnMenuAddScatterer)
382 EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON, WXCrystal::OnMenuAddScatterer)
383 EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER, WXCrystal::OnMenuRemoveScatterer)
384 EVT_MENU(ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER, WXCrystal::OnMenuDuplicateScatterer)
385 EVT_MENU(ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN, WXCrystal::OnMenuShowScattPowWindow)
386 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
387 EVT_GRID_CMD_CELL_CHANGE(ID_CRYSTAL_WIN_SCATTPOW, WXCrystal::OnEditGridScattPow)
388 EVT_GRID_CMD_CELL_CHANGE(ID_CRYSTAL_WIN_ANTIBUMP, WXCrystal::OnEditGridScattPowAntiBump)
389 EVT_GRID_CMD_CELL_CHANGE(ID_CRYSTAL_WIN_BONDVALENCE,WXCrystal::OnEditGridScattPowBondValence)
393 WXCrystal::WXCrystal(wxWindow* parent, Crystal *obj):
394 WXRefinableObj(parent,(RefinableObj*)obj),mpCrystal(obj),
395 mpScattPowWin(0),mpAntiBumpWin(0),mpBondValenceWin(0),
396 mIsSelfUpdating(false)
398 ,mCrystalGLDisplayList(0),mCrystalGLNameDisplayList(0),
401 ,mpConditionGLUpdate(0)
404 VFN_DEBUG_ENTRY(
"WXCrystal::WXCrystal()",6)
407 mpWXTitle->SetForegroundColour(wxColour(255,0,0));
409 mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ);
412 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVETEXT,"Save as text");
413 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVECIF,"Save as CIF");
414 mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
415 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
416 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
417 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE,
418 "Randomize Configuration");
419 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS,
420 "Set Relative Limits On All XYZ Parameters");
421 mpMenuBar->GetMenu(ID_REFOBJ_MENU_PAR).AppendSeparator();
422 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES,
423 "Test Random Moves for 30s");
424 mpMenuBar->AddMenu("Scatterers",ID_CRYSTAL_MENU_SCATT);
425 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN,
426 "Show Scattering Powers Parameters Window");
427 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
428 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM,
429 "Add Atomic Scattering Power");
430 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE,
431 "Add Sphere Scattering Power");
432 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW,
433 "Remove Scattering Power");
434 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
435 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDATOM,
437 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST,
438 "Import a List of Atoms");
439 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDMOLECULE,
441 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE,
442 "Convert Atoms to a Molecule");
443 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX,
444 "Import Molecule from Fenske-Hall Z-Matrix");
445 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX,
446 "Import Molecule from a named Z-Matrix");
447 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER,
449 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER,
450 "Duplicate Scatterer");
451 mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator();
452 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON,
454 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON,
456 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE,
457 "Add Triangle Plane");
458 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE,
460 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDCUBE,
462 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,
463 ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL,
464 "Add Antiprism Tetragonal");
465 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL,
466 "Add Prism Trigonal");
467 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON,
469 mpMenuBar->AddMenu("Display",ID_CRYSTAL_MENU_DISPLAY);
470 mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_CRYSTAL_MENU_DISPLAY_3DVIEW,
480 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(0).WXGet())->SetToolTip(
481 _T("Use this option ONLY if you want to use\n")
482 _T("a higher symmetry than the one allowed by\n")
483 _T("the spacegroup. This can be useful to search\n")
484 _T("structures derived from higher symmetries.\n\n")
485 _T("This option should almost never be used."));
487 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(1).WXGet())->SetToolTip(
488 _T("This option allows Fox to automatically adjust\n")
489 _T("the occupancy of atoms that are on a special position,\n")
490 _T("or overlapping with another (e.g. two oxygens from\n")
491 _T("two polyhedra).\n\n")
492 _T("Practically you should choose:\n")
493 _T("- Yes for inorganic structures\n")
494 _T("- No for organic structures\n\n")
495 _T("This option increases computing time\n")
496 _T("by up to 50%, so only use when necessary\n\n")
497 _T("In doubt, choose Yes"));
499 dynamic_cast<WXFieldOption *>(mpCrystal->GetOption(2).WXGet())->SetToolTip(
500 _T("This option only affects the 3D display,\n")
501 _T("and is used to display the enantiomer\n")
502 _T("of the crystal structure.\n\n")
503 _T("This can be used to compare several\n")
504 _T("crystal structures."));
508 wxBoxSizer* pAntiBumpSizer=new wxBoxSizer(wxHORIZONTAL);
509 WXFieldPar<REAL> *pWXFieldBumpMerge=
510 new WXFieldPar<REAL>(this,"AntiBump",-1,&(mpCrystal->mBumpMergeCost),100);
511 WXFieldPar<REAL> *pAntiBumpScale=
512 new WXFieldPar<REAL>(this,"Scale",-1,&(mpCrystal->mBumpMergeScale));
513 pAntiBumpSizer->Add(pWXFieldBumpMerge);
514 pAntiBumpSizer->Add(pAntiBumpScale);
515 mpSizer->Add(pAntiBumpSizer,0,wxALIGN_LEFT);
516 mList.Add(pWXFieldBumpMerge);
517 mList.Add(pAntiBumpScale);
518 pWXFieldBumpMerge->SetFormat(_T("%8.2f"));
519 pAntiBumpScale->SetFormat(_T("%8.2f"));
520 pWXFieldBumpMerge->SetToolTip(_T("Current anti-bump cost"));
521 pAntiBumpScale->SetToolTip(
522 _T("Scale (multiplier) for the anti-bump cost.\n")
523 _T("If 0, the anti-bump will be ignored and not calculated\n")
524 _T("during optimization (saving time)\n\n")
525 _T("Use a value larger than 1 to increase the importance\n")
526 _T("of the anti-bump relatively to the diffraction data Chi^2\n\n")
527 _T("Note that anti-bump should only be used if the diffraction data\n\n")
528 _T("is not of good enough quality to ensure finding the correct\n\n")
531 wxBoxSizer* pBondValenceSizer=new wxBoxSizer(wxHORIZONTAL);
532 WXFieldPar<REAL> *pWXFieldBondValence=
533 new WXFieldPar<REAL>(this,"Bond Valence Cost",-1,&(mpCrystal->mBondValenceCost),100);
534 WXFieldPar<REAL> *pBondValenceScale=
535 new WXFieldPar<REAL>(this,"Scale",-1,&(mpCrystal->mBondValenceCostScale));
536 pBondValenceSizer->Add(pWXFieldBondValence);
537 pBondValenceSizer->Add(pBondValenceScale);
538 mpSizer->Add(pBondValenceSizer,0,wxALIGN_LEFT);
539 mList.Add(pWXFieldBondValence);
540 mList.Add(pBondValenceScale);
541 pWXFieldBondValence->SetFormat(_T("%8.2f"));
542 pBondValenceScale->SetFormat(_T("%8.2f"));
543 pWXFieldBondValence->SetToolTip(_T("Current bond valence cost"));
544 pBondValenceScale->SetToolTip(
545 _T("Scale (multiplier) for the bond valence cost.\n")
546 _T("If 0, the bond valence will be ignored and not calculated\n")
547 _T("during optimization (saving time)\n\n")
548 _T("Use a value larger than 1 to increase the importance\n")
549 _T("of the bond valence relatively to the diffraction data Chi^2\n\n")
550 _T("Note that bond valence should only be used if the diffraction data\n\n")
551 _T("is not of good enough quality to ensure finding the correct\n\n")
554 wxBoxSizer* lattice=new wxBoxSizer(wxHORIZONTAL);
556 WXCrystObjBasic* pFieldLatticeA
557 =mpCrystal->GetPar("a").WXCreate(this);
558 WXCrystObjBasic* pFieldLatticeB
559 =mpCrystal->GetPar("b").WXCreate(this);
560 WXCrystObjBasic* pFieldLatticeC
561 =mpCrystal->GetPar("c").WXCreate(this);
562 WXCrystObjBasic* pFieldLatticeAlpha
563 =mpCrystal->GetPar("alpha").WXCreate(this);
564 WXCrystObjBasic* pFieldLatticeBeta
565 =mpCrystal->GetPar("beta").WXCreate(this);
566 WXCrystObjBasic* pFieldLatticeGamma
567 =mpCrystal->GetPar("gamma").WXCreate(this);
569 lattice->Add(pFieldLatticeA ,0,wxALIGN_CENTER);
570 lattice->Add(pFieldLatticeB ,0,wxALIGN_CENTER);
571 lattice->Add(pFieldLatticeC ,0,wxALIGN_CENTER);
572 lattice->Add(pFieldLatticeAlpha,0,wxALIGN_CENTER);
573 lattice->Add(pFieldLatticeBeta ,0,wxALIGN_CENTER);
574 lattice->Add(pFieldLatticeGamma,0,wxALIGN_CENTER);
577 mpSizer->Add(lattice,0,wxALIGN_LEFT);
578 mList.Add(pFieldLatticeA);
579 mList.Add(pFieldLatticeB);
580 mList.Add(pFieldLatticeC);
581 mList.Add(pFieldLatticeAlpha);
582 mList.Add(pFieldLatticeBeta);
583 mList.Add(pFieldLatticeGamma);
585 dynamic_cast<WXFieldRefPar *>(pFieldLatticeA)->SetFormat(_T("%8.4f"));
586 dynamic_cast<WXFieldRefPar *>(pFieldLatticeB)->SetFormat(_T("%8.4f"));
587 dynamic_cast<WXFieldRefPar *>(pFieldLatticeC)->SetFormat(_T("%8.4f"));
588 dynamic_cast<WXFieldRefPar *>(pFieldLatticeAlpha)->SetFormat(_T("%8.3f"));
589 dynamic_cast<WXFieldRefPar *>(pFieldLatticeBeta)->SetFormat(_T("%8.3f"));
590 dynamic_cast<WXFieldRefPar *>(pFieldLatticeGamma)->SetFormat(_T("%8.3f"));
592 pFieldLatticeA->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
593 pFieldLatticeB->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
594 pFieldLatticeC->SetToolTip(_T("Lattice length parameter (in Angstroems)"));
595 pFieldLatticeAlpha->SetToolTip(_T("Lattice angle parameter (in degrees)"));
596 pFieldLatticeBeta->SetToolTip(_T("Lattice angle parameter (in degrees)"));
597 pFieldLatticeGamma->SetToolTip(_T("Lattice angle parameter (in degrees)"));
600 mpFieldSpacegroup=new WXFieldName(this,"SpaceGroup:",this,ID_CRYSTAL_SPACEGROUP,100);
601 mpSizer->Add(mpFieldSpacegroup,0,wxALIGN_LEFT);
602 mList.Add(mpFieldSpacegroup);
604 mpFieldSpacegroup->SetToolTip(_T("Spacegroup Symbol. You can use:\n\n")
605 _T("- spacegroup number: \"1\" \"62\" ... \"227\",\"230\"\n")
606 _T("- Hermann-Mauguin symbol: \"P1\" \"Pnma\" ... \"Fd3m\",\"Ia3d\"\n")
607 _T("- Hall symbol: \"P1\" \"-P 2ac 2n\" ... \"-F 4vw 2vw 3\",\"-I 4bd 2c 3\"\n\n")
608 _T("ORIGIN CHOICE: for some spacegroups there are several\n")
609 _T("possible origins - the default is the one on \n")
610 _T("the center of symmetry (origin 2). You can specify\n")
611 _T(" the origin by writing \"Fd3m:1\" or \"Fd3m:2\"\n\n")
612 _T("CELL CHOICE: to specify a rhomboedral or hexagonal unit cell,\n")
613 _T("append R or H to the symbol:\"R-3:R\"or \"R-3:H\"\n"));
616 mpWXScatteringPowerRegistry=mpCrystal
617 ->GetScatteringPowerRegistry().WXCreate(this);
618 mpSizer->Add(mpWXScatteringPowerRegistry,0,wxALIGN_LEFT);
619 mList.Add(mpWXScatteringPowerRegistry);
622 mpWXScattererRegistry=mpCrystal
623 ->GetScattererRegistry().WXCreate(this);
624 mpSizer->Add(mpWXScattererRegistry,0,wxALIGN_LEFT);
625 mList.Add(mpWXScattererRegistry);
626 this->CrystUpdate(true);
629 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Automatically open crystal 3D view")))
630 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Automatically open crystal 3D view"),
false);
633 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Automatically open crystal 3D view"), &val);
636 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_CRYSTAL_MENU_DISPLAY_3DVIEW);
637 wxPostEvent(
this,event);
641 wxTheApp->GetTopWindow()->PostSizeEvent();
642 VFN_DEBUG_EXIT(
"WXCrystal::WXCrystal()",6)
645 WXCrystal::~WXCrystal()
647 VFN_DEBUG_ENTRY(
"WXCrystal::~WXCrystal()",10)
648 if(0!=mpScattPowWin) mpScattPowWin->GetParent()->Destroy();
649 VFN_DEBUG_EXIT("WXCrystal::~WXCrystal()",10)
654 VFN_DEBUG_ENTRY(
"WXCrystal::CrystUpdate()",5)
664 BBox box=mpCrystalGL->GetCellBBox();
666 this->UpdateGL(
false,box.xMin,box.xMax,box.yMin,box.yMax,box.zMin,box.zMax);
671 if((
false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() ) this->GetCrystal().InitRefParList();
673 if((
false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() &&(mpScattPowWin!=0)&&(mpAntiBumpWin!=0)&&(mpBondValenceWin!=0))
678 bool needLayout=
false;
680 for(map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();)
681 if(this->GetCrystal().GetScatteringPowerRegistry().Find(pos->second.mName,
"ScatteringPowerAtom",
true)<0)
683 VFN_DEBUG_MESSAGE(
"WXCrystal::CrystUpdate(): Removing scattering power: "<<pos->second.mName,5)
684 mpScattPowWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
685 mpAntiBumpWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
686 mpBondValenceWin->DeleteRows(mvpRowScattPow.size()-1,1,
false);
687 mpAntiBumpWin->DeleteCols(mvpRowScattPow.size()-1,1,
false);
688 mpBondValenceWin->DeleteCols(mvpRowScattPow.size()-1,1,
false);
689 mvpRowScattPow.erase(pos++);
694 for(
int i=0;i<this->GetCrystal().GetScatteringPowerRegistry().GetNb();++i)
696 ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i));
700 if(mvpRowScattPow.find(p)==mvpRowScattPow.end())
702 VFN_DEBUG_MESSAGE(
"WXCrystal::CrystUpdate(): Adding scattering power: "<<s->
GetName(),5)
703 mpScattPowWin->AppendRows();
704 mpAntiBumpWin->AppendRows();
705 mpAntiBumpWin->AppendCols();
706 mpBondValenceWin->AppendRows();
707 mpBondValenceWin->AppendCols();
717 for(
int i=0;i<this->GetCrystal().GetScatteringPowerRegistry().GetNb();++i)
719 ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i));
723 if(mvpRowScattPow[p].mIdx!=i-j)
725 mvpRowScattPow[p].mIdx=i-j;
726 mvpRowScattPow[p].mNeedUpdateUI=
true;
734 mpScattPowWin->FitInside();
735 mpAntiBumpWin->FitInside();
736 mpBondValenceWin->FitInside();
741 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
742 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
744 const string name=pos->first->GetName();
745 const REAL biso=pos->first->GetBiso();
746 const REAL formalCharge=pos->first->GetFormalCharge();
747 const float *pRGB=pos->first->GetColourRGB();
748 const REAL mlerror=pos->first->GetMaximumLikelihoodPositionError();
749 const REAL nbghost=pos->first->GetMaximumLikelihoodNbGhostAtom();
750 if( (name !=pos->second.mName)
751 ||(biso !=pos->second.mBiso)
752 ||(formalCharge!=pos->second.mFormalCharge)
753 ||(pRGB[0]!=pos->second.mR)
754 ||(pRGB[1]!=pos->second.mG)
755 ||(pRGB[2]!=pos->second.mB)
756 ||(mlerror!=pos->second.mMaximumLikelihoodError)
757 ||(nbghost!=pos->second.mNbGhostAtoms)
758 || pos->second.mNeedUpdateUI)
760 pos->second.mName=name;
761 pos->second.mBiso=biso;
762 pos->second.mFormalCharge=formalCharge;
763 pos->second.mR=pRGB[0];
764 pos->second.mG=pRGB[1];
765 pos->second.mB=pRGB[2];
766 pos->second.mMaximumLikelihoodError=mlerror;
767 pos->second.mNbGhostAtoms=nbghost;
768 pos->second.mNeedUpdateUI=
true;
774 map<ScatteringPowerAtom*,RowScattPow>::iterator pos,pos1;
775 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
777 const string name=pos->first->GetName();
779 vector<REAL> dist(mvpRowScattPow.size());
780 for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1)
782 Crystal::VBumpMergePar::const_iterator pos2;
783 if(pos->first<pos1->first) pos2=pMap->find(make_pair(pos->first,pos1->first));
784 else pos2=pMap->find(make_pair(pos1->first,pos->first));
785 if(pos2==pMap->end()) dist[pos1->second.mIdx]=-999;
786 else dist[pos1->second.mIdx]=sqrt(pos2->second.mDist2);
788 if( (name!=pos->second.mName)
789 ||(dist!=pos->second.mvAntiBumpDistance)
790 || pos->second.mNeedUpdateUI)
792 pos->second.mName=name;
793 pos->second.mvAntiBumpDistance=dist;
794 pos->second.mNeedUpdateUI=
true;
800 map<ScatteringPowerAtom*,RowScattPow>::iterator pos,pos1;
801 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
803 const string name=pos->first->GetName();
804 const std::map<pair<const ScatteringPower*,const ScatteringPower*>, REAL> *pMap=&(mpCrystal->GetBondValenceRoList());
805 vector<REAL> ro(mvpRowScattPow.size());
806 for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1)
808 map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>::const_iterator pos2;
809 if(pos->first<pos1->first) pos2=pMap->find(make_pair(pos->first,pos1->first));
810 else pos2=pMap->find(make_pair(pos1->first,pos->first));
811 if(pos2==pMap->end()) ro[pos1->second.mIdx]=-999;
812 else ro[pos1->second.mIdx]=pos2->second;
814 if( (name!=pos->second.mName)
815 ||(ro!=pos->second.mvBondValenceRo)
816 || pos->second.mNeedUpdateUI)
818 pos->second.mName=name;
819 pos->second.mvBondValenceRo=ro;
820 pos->second.mNeedUpdateUI=
true;
828 VFN_DEBUG_EXIT(
"WXCrystal::CrystUpdate():End",5)
832 void WXCrystal::UpdateGL(
const bool onlyIndependentAtoms,
833 const REAL xMin,
const REAL xMax,
834 const REAL yMin,
const REAL yMax,
835 const REAL zMin,
const REAL zMax)
838 VFN_DEBUG_ENTRY(
"WXCrystal::UpdateGL()",8)
842 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():mpCrystalGL",7)
843 if(false==wxThread::IsMain())
848 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
849 wxPostEvent(mpCrystalGL,event);
851 wxThread::This()->Yield();
856 cout<<
"WXCrystal::UpdateGL():timeout waiting for mpConditionGLUpdate release: #"<<++ct<<
":"<<ok<<endl;
866 VFN_DEBUG_EXIT(
"WXCrystal::UpdateGL()-Not in main thread :End",8)
869 mpCrystalGL->SetCurrent();
870 if(mCrystalGLDisplayList==0)
872 mCrystalGLDisplayList=glGenLists(1);
873 mCrystalGLNameDisplayList=glGenLists(1);
874 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():created mCrystalGLDisplayList=" << mCrystalGLDisplayList <<
",mCrystalGLNameDisplayList=" << mCrystalGLNameDisplayList, 10)
876 glNewList(mCrystalGLDisplayList,GL_COMPILE);
878 mpCrystal->
GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,
false,!(mpCrystalGL->GetShowHydrogens()));
887 glNewList(mCrystalGLNameDisplayList,GL_COMPILE);
889 mpCrystal->
GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,
true,!(mpCrystalGL->GetShowHydrogens()));
892 mpCrystalGL->CrystUpdate();
901 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateGL():No mpCrystalGL",7)
903 VFN_DEBUG_EXIT(
"WXCrystal::UpdateGL():End",8)
906 int WXCrystal::GetCrystalGLDisplayList(
const bool atomName)
const
908 VFN_DEBUG_MESSAGE(
"WXCrystal::GetCrystalGLDisplayList()",7)
909 if(atomName) return mCrystalGLNameDisplayList;
910 return mCrystalGLDisplayList;
913 class WXGLCrystalCanvasFrame :public wxFrame
916 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) :
917 wxFrame(parent, id, title, pos, size, style, name)
919 ~WXGLCrystalCanvasFrame()
921 gvWindowPosition[ID_GLCRYSTAL_WINDOW] = make_pair(this->GetScreenPosition(), this->GetSize());
926 void WXCrystal::OnMenuCrystalGL(wxCommandEvent & WXUNUSED(event))
928 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuCrystalGL()",6)
929 if(mpCrystalGL!=0) return;
934 frame =
new WXGLCrystalCanvasFrame(
this, ID_GLCRYSTAL_WINDOW, wxString::FromAscii(mpCrystal->
GetName().c_str()),
936 gvWindowPosition[ID_GLCRYSTAL_WINDOW].second, wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION);
939 frame =
new WXGLCrystalCanvasFrame(
this, ID_GLCRYSTAL_WINDOW, wxString::FromAscii(mpCrystal->
GetName().c_str()),
940 wxDefaultPosition,wxSize(400,400),wxCLOSE_BOX|wxRESIZE_BORDER|wxCAPTION);
942 mpCrystalGL=
new WXGLCrystalCanvas(
this,frame,-1);
944 frame->CreateStatusBar(1);
945 frame->SetStatusText( wxString::FromAscii(mpCrystal->
GetName().c_str()));
952 void WXCrystal::NotifyCrystalGLDelete()
954 VFN_DEBUG_MESSAGE(
"WXCrystal::NotifyCrystalGLDelete()",7)
957 WXGLCrystalCanvas * WXCrystal::GetCrystalGL()
959 VFN_DEBUG_MESSAGE(
"WXCrystal::GetCrystalGL()",7)
964 void WXCrystal::OnMenuSaveCIF(wxCommandEvent & WXUNUSED(event))
967 wxFileDialog save(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.cif"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
968 if(save.ShowModal() != wxID_OK)
return;
970 ofstream out(save.GetPath().ToAscii());
976 void WXCrystal::OnMenuSaveText(wxCommandEvent & WXUNUSED(event))
979 wxFileDialog save(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
980 if(save.ShowModal() != wxID_OK)
return;
982 ofstream out(save.GetPath().ToAscii());
984 mpCrystal->
Print(out);
989 void WXCrystal::OnMenuAddScattPowAtom(wxCommandEvent & WXUNUSED(event))
991 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScattPowAtom()",6)
993 ScatteringPowerAtom *scatt=new ScatteringPowerAtom("Change me","H");
994 mpCrystal->AddScatteringPower(scatt);
995 VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScattPowAtom():End",6)
998 wxTheApp->GetTopWindow()->Layout();
999 wxTheApp->GetTopWindow()->SendSizeEvent();
1002 void WXCrystal::OnMenuAddScattPowSphere(wxCommandEvent & WXUNUSED(event))
1004 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuAddScattSphere()",6)
1006 ScatteringPower *scatt= new ScatteringPowerSphere;
1007 mpCrystal->AddScatteringPower(scatt);
1010 VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScattPowSphere()",6)
1011 wxTheApp->GetTopWindow()->Layout();
1012 wxTheApp->GetTopWindow()->SendSizeEvent();
1015 void WXCrystal::OnMenuRemoveScattPow(wxCommandEvent & WXUNUSED(event))
1017 VFN_DEBUG_ENTRY(
"WXCrystal::OnButtonRemoveScattPow()",6)
1020 ScatteringPower *scatt=
1022 "Choose Scattering Power to remove:",choice);
1025 VFN_DEBUG_EXIT(
"WXCrystal::OnButtonRemoveScattPow():Cancelled",6)
1028 const ScatteringComponentList *pList=&(mpCrystal->GetScatteringComponentList());
1029 for(
long i=0;i<pList->GetNbComponent();++i)
1030 if((*pList)(i).mpScattPow==scatt)
1032 wxMessageDialog dumbUser(
this,_T(
"This Scattering Power is still used !"),
1033 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
1034 dumbUser.ShowModal();
1035 VFN_DEBUG_EXIT(
"WXCrystal::OnButtonRemoveScattPow()",6)
1038 mpCrystal->RemoveScatteringPower(scatt);
1039 VFN_DEBUG_EXIT("WXCrystal::OnButtonRemoveScattPow()",6)
1042 wxTheApp->GetTopWindow()->Layout();
1043 wxTheApp->GetTopWindow()->SendSizeEvent();
1046 void WXCrystal::OnMenuAddScatterer(wxCommandEvent &event)
1048 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuAddScatterer()",6)
1051 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDATOM)
1054 ScatteringPower *scattPow=
1056 "Choose an atom type (ScatteringPower):",choice);
1059 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1062 scatt=new Atom(0,0,0,"Change Me!",scattPow);
1064 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST)
1066 wxFileDialog open(
this,_T(
"Choose a file with a list of atoms: Element x y z occup"),_T(
""),_T(
""),_T(
"*"),
1067 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1068 if(open.ShowModal() != wxID_OK)
return;
1069 ifstream fin (open.GetPath().ToAscii());
1072 throw ObjCrystException(
"WXCrystal::OnMenuAddScatterer() : Error opening file for input:"+
string(open.GetPath().ToAscii()));
1082 if(fin.eof())
break;
1083 fin>>x>>y>>z>>occup;
1084 cout<<symbol<<n<<
": "<<x<<
", "<<y<<
", "<<z<<endl;
1088 cout<<
"Scattering power "<<symbol<<
" not found, creating it..."<<endl;
1091 sprintf(buf,
"%d",n++);
1093 if(fin.eof())
break;
1098 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER)
1100 scatt=
new ZScatterer(
"Change Me!",*mpCrystal);
1102 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDMOLECULE)
1104 scatt=
new Molecule(*mpCrystal,
"Molecule");
1106 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON)
1113 this,
"Central atom type (ScatteringPower):",choice);
1116 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1121 mpCrystal->GetScatteringPowerRegistry(),
1122 this,"Corner atom type (ScatteringPower):",choice);
1125 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1129 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1130 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1131 if(wxID_OK!=bondLengthDialog.ShowModal())
1133 VFN_DEBUG_EXIT(
"WXZScatterer))OnMenuAddZAtom())Cancelled",6)
1137 bondLengthDialog.GetValue().ToDouble(&bondLength);
1139 Molecule *mol=MakeTetrahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4",
1140 scattPow1,scattPow2,bondLength);
1141 mol->RestraintStatus(cout);
1144 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON)
1149 mpCrystal->GetScatteringPowerRegistry(),
1150 this,
"Central atom type (ScatteringPower):",choice);
1153 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1158 mpCrystal->GetScatteringPowerRegistry(),
1159 this,"Corner atom type (ScatteringPower))",choice);
1162 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1166 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1167 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1168 if(wxID_OK!=bondLengthDialog.ShowModal())
1170 VFN_DEBUG_EXIT(
"WXZScatterer))OnMenuAddZAtom())Cancelled",6)
1174 bondLengthDialog.GetValue().ToDouble(&bondLength);
1176 Molecule *mol=MakeOctahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6",
1177 scattPow1,scattPow2,bondLength);
1178 mol->RestraintStatus(cout);
1181 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE)
1183 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScatterer())Add triangle plane",6)
1187 mpCrystal->GetScatteringPowerRegistry(),
1188 this,"Central atom type (ScatteringPower))",choice);
1191 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1196 mpCrystal->GetScatteringPowerRegistry(),
1197 this,"Corner atom type (ScatteringPower))",choice);
1200 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1204 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1205 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1206 if(wxID_OK!=bondLengthDialog.ShowModal())
1208 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1212 bondLengthDialog.GetValue().ToDouble(&bondLength);
1214 Molecule *mol=MakeTriangle(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"3",
1215 scattPow1,scattPow2,bondLength);
1216 mol->RestraintStatus(cout);
1219 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE)
1221 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuAddScatterer():Add square plane",6)
1225 mpCrystal->GetScatteringPowerRegistry(),
1226 this,"Central atom type (ScatteringPower))",choice);
1229 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1234 mpCrystal->GetScatteringPowerRegistry(),
1235 this,"Corner atom type (ScatteringPower))",choice);
1238 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1242 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1243 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1244 if(wxID_OK!=bondLengthDialog.ShowModal())
1246 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1250 bondLengthDialog.GetValue().ToDouble(&bondLength);
1252 Molecule *mol=MakeSquarePlane(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4",
1253 scattPow1,scattPow2,bondLength);
1254 mol->RestraintStatus(cout);
1257 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDCUBE)
1262 mpCrystal->GetScatteringPowerRegistry(),
1263 this,
"Central atom type (ScatteringPower):",choice);
1266 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1271 mpCrystal->GetScatteringPowerRegistry(),
1272 this,"Corner atom type (ScatteringPower))",choice);
1275 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1279 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1280 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1281 if(wxID_OK!=bondLengthDialog.ShowModal())
1283 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1287 bondLengthDialog.GetValue().ToDouble(&bondLength);
1289 Molecule *mol=MakeCube(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8",
1290 scattPow1,scattPow2,bondLength);
1291 mol->RestraintStatus(cout);
1294 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL)
1299 mpCrystal->GetScatteringPowerRegistry(),
1300 this,
"Central atom type (ScatteringPower):",choice);
1303 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1308 mpCrystal->GetScatteringPowerRegistry(),
1309 this,"Corner atom type (ScatteringPower))",choice);
1312 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1316 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1317 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1318 if(wxID_OK!=bondLengthDialog.ShowModal())
1320 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1324 bondLengthDialog.GetValue().ToDouble(&bondLength);
1326 Molecule *mol=MakeAntiPrismTetragonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8",
1327 scattPow1,scattPow2,bondLength);
1328 mol->RestraintStatus(cout);
1331 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL)
1336 mpCrystal->GetScatteringPowerRegistry(),
1337 this,
"Central atom type (ScatteringPower))",choice);
1340 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
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 if(wxID_OK!=bondLengthDialog.ShowModal())
1357 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom())Cancelled",6)
1361 bondLengthDialog.GetValue().ToDouble(&bondLength);
1363 Molecule *mol=MakePrismTrigonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6",
1364 scattPow1,scattPow2,bondLength);
1365 mol->RestraintStatus(cout);
1368 if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON)
1373 mpCrystal->GetScatteringPowerRegistry(),
1374 this,
"Central atom type (ScatteringPower):",choice);
1377 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1382 mpCrystal->GetScatteringPowerRegistry(),
1383 this,"Corner atom type (ScatteringPower):",choice);
1386 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuAddScatterer():Canceled",6)
1390 wxTextEntryDialog bondLengthDialog(this,_T("Bond length"),
1391 _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL);
1392 if(wxID_OK!=bondLengthDialog.ShowModal())
1394 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
1398 bondLengthDialog.GetValue().ToDouble(&bondLength);
1400 Molecule *mol=MakeIcosahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"12",
1401 scattPow1,scattPow2,bondLength);
1402 mol->RestraintStatus(cout);
1405 if(scatt!=0) mpCrystal->AddScatterer(scatt);
1406 VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScatterer():calling Layout()",6)
1409 wxTheApp->GetTopWindow()->Layout();
1410 wxTheApp->GetTopWindow()->SendSizeEvent();
1411 VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer()",6)
1414 void WXCrystal::OnMenuRemoveScatterer(wxCommandEvent & WXUNUSED(event))
1416 VFN_DEBUG_MESSAGE(
"WXCrystal::OnButtonRemoveScatterer()",6)
1420 "Select the Scatterer to remove:",choice);
1421 if(0==scatt) return;
1422 mpCrystal->RemoveScatterer(scatt);
1423 VFN_DEBUG_MESSAGE("WXCrystal::OnButtonRemoveScatterer():End",6)
1425 wxTheApp->GetTopWindow()->Layout();
1426 wxTheApp->GetTopWindow()->SendSizeEvent();
1430 void WXCrystal::OnMenuDuplicateScatterer(wxCommandEvent & WXUNUSED(event))
1432 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuDuplicateScatterer()",6)
1436 "Select the Scatterer to duplicate:",choice);
1437 if(0==scatt) return;
1438 Scatterer *copy=scatt->CreateCopy();
1439 scatt->SetName(scatt->GetName()+(
string)"(copy)");
1440 mpCrystal->AddScatterer(copy);
1442 wxTheApp->GetTopWindow()->Layout();
1443 wxTheApp->GetTopWindow()->SendSizeEvent();
1444 VFN_DEBUG_EXIT("WXCrystal::OnMenuDuplicateScatterer():End",6)
1449 void WXCrystal::OnMenuAtoms2Molecule(wxCommandEvent &event)
1452 for(
unsigned int i=0; i<mpCrystal->GetScattererRegistry().GetNb();++i)
1454 Atom *pAtom=
dynamic_cast<Atom *
>(&(mpCrystal->GetScattererRegistry().GetObj(i)));
1455 if(pAtom!=0) v.push_back(pAtom);
1457 const unsigned int nb=v.size();
1458 wxString *choices =
new wxString[nb];
1459 for(
unsigned int i=0;i<nb;i++)
1460 choices[i]= wxString::FromAscii((v[i]->GetName()).c_str());
1462 wxMultiChoiceDialog dialog (
this,_T(
"Choose the molecule's atoms"),_T(
"Select Atoms"),nb,choices,wxOK | wxCANCEL);
1463 dialog.SetSize(300,300);
1465 wxMultiChoiceDialog_ListBox dialog(
this,_T(
"Choose the molecule's atoms"),_T(
"Select Atoms"),nb,choices);
1467 if(wxID_OK!=dialog.ShowModal())
return;
1468 wxArrayInt choice=dialog.GetSelections();
1469 if(choice.GetCount()>0)
1471 list<Atom*> vChoice;
1472 for(
unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(v[choice.Item(i)]);
1474 mpCrystal->AddScatterer(Atoms2Molecule(vChoice));
1475 for(
unsigned int i=0;i<choice.GetCount();++i) mpCrystal->RemoveScatterer(v[choice.Item(i)]);
1476 mpCrystal->UpdateDisplay();
1478 wxTheApp->GetTopWindow()->Layout();
1479 wxTheApp->GetTopWindow()->SendSizeEvent();
1482 void WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix(wxCommandEvent &event)
1484 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuImportFenskeHallZMatrix()",6)
1486 string tmp("Fenske-Hall z-matrix|*.fhz;*.fh");
1487 if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) tmp="Fox z-matrix|*.zmat";
1488 wxFileDialog open(this,_T("Choose a file with a Fenske-Hall Z-matrix"),_T(""),_T(""), wxString::FromAscii(tmp.c_str()),
1489 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1490 if(open.ShowModal() != wxID_OK) return;
1491 ifstream fin ( open.GetPath().ToAscii());
1494 throw ObjCrystException(
"WXCrystal::OnMenuImportFenskeHallZMatrix() : \
1495 Error opening file for input:"+
string(open.GetPath().ToAscii()));
1497 string filename(open.GetPath().ToAscii());
1500 std::string::size_type idx =filename.rfind(
"/");
1501 std::string::size_type idx2=filename.rfind(
"\\");
1502 std::string::size_type idx3=filename.rfind(
":");
1503 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
1504 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
1505 if(idx==string::npos)
1508 shortName=filename.substr(idx+1);
1510 ZScatterer scatt(shortName,*mpCrystal);
1512 if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) named=
true;
1513 scatt.ImportFenskeHallZMatrix(fin,named);
1516 wxTheApp->GetTopWindow()->Layout();
1517 wxTheApp->GetTopWindow()->SendSizeEvent();
1519 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuImportFenskeHallZMatrix()",6)
1522 void WXCrystal::OnMenuSetRelativeXYZLimits(wxCommandEvent & WXUNUSED(event))
1524 VFN_DEBUG_ENTRY(
"WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6)
1526 wxTextEntryDialog limitDialog(this,_T("Relative limits"),
1527 _T("Enter relative limits for x,y,z (Angstroems)"),
1528 _T("0.5"),wxOK | wxCANCEL);
1529 if(wxID_OK!=limitDialog.ShowModal())
1531 VFN_DEBUG_EXIT(
"WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6)
1535 limitDialog.GetValue().ToDouble(&limit);
1538 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslX,
1539 -limit/mpCrystal->GetLatticePar(0),
1540 limit/mpCrystal->GetLatticePar(0));
1541 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslY,
1542 -limit/mpCrystal->GetLatticePar(1),
1543 limit/mpCrystal->GetLatticePar(1));
1544 mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslZ,
1545 -limit/mpCrystal->GetLatticePar(2),
1546 limit/mpCrystal->GetLatticePar(2));
1547 VFN_DEBUG_EXIT("WXCrystal::OnMenuSetRelativeXYZLimits()",6)
1551 class TestCrystalThread: public wxThread
1554 TestCrystalThread(Crystal &cryst,
float seconds):
1555 wxThread(wxTHREAD_DETACHED),mpCryst(&cryst),mSeconds(seconds){};
1556 virtual void *Entry()
1558 cout<<endl<<
"Entering refinement thread "<<endl<<endl;
1559 mpCryst->BeginOptimization();
1561 float dt0=chrono.seconds();
1562 while(chrono.seconds()<30)
1564 mpCryst->BeginGlobalOptRandomMove();
1567 if((chrono.seconds()-dt0)>0.05) {mpCryst->UpdateDisplay();dt0=chrono.seconds();}
1569 mpCryst->EndOptimization();
1572 virtual void OnExit()
1574 cout <<endl<<
"Exiting refinement thread "<<endl<<endl;
1583 void WXCrystal::OnMenuTestRandomMoves(wxCommandEvent &event)
1585 TestCrystalThread *pTest =
new TestCrystalThread(*mpCrystal,30);
1586 if(pTest->Create() != wxTHREAD_NO_ERROR)
1587 wxLogError(_T(
"Can't create test optimization thread"));
1593 VFN_DEBUG_MESSAGE(
"WXCrystal::OnChangeName()",6)
1595 if(
id==ID_CRYSTAL_SPACEGROUP)
1597 VFN_DEBUG_MESSAGE(
"WXCrystal::OnChangeName():Changing SpaceGroup",6)
1598 mpCrystal->Init(mpCrystal->GetLatticePar(0),
1599 mpCrystal->GetLatticePar(1),
1600 mpCrystal->GetLatticePar(2),
1601 mpCrystal->GetLatticePar(3),
1602 mpCrystal->GetLatticePar(4),
1603 mpCrystal->GetLatticePar(5),
1604 mpFieldSpacegroup->GetValue(),
1605 mpCrystal->GetName());
1615 VFN_DEBUG_ENTRY(
"WXCrystal::UpdateUI()",6)
1616 if(!mpCrystal->IsBeingRefined())
1619 mpFieldSpacegroup->SetValue(mpCrystal->GetSpaceGroup().GetName());
1621 if(0!=mpCrystalGL) mpCrystalGL->GetParent()->SetLabel( wxString::FromAscii(mpCrystal->GetName().c_str()));
1623 if(lock)
mMutex.Unlock();
1626 if(0!=mpScattPowWin)
1628 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1629 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1631 if(pos->second.mNeedUpdateUI==
true)
1634 mpScattPowWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1636 tmp.Printf(_T(
"%f"),pos->second.mBiso);
1637 mpScattPowWin->SetCellValue(pos->second.mIdx, 0, tmp);
1638 tmp.Printf(_T(
"%f"),pos->second.mFormalCharge);
1639 mpScattPowWin->SetCellValue(pos->second.mIdx, 1, tmp);
1640 tmp.Printf(_T(
"%f"),pos->second.mR);
1641 mpScattPowWin->SetCellValue(pos->second.mIdx, 2, tmp);
1642 tmp.Printf(_T(
"%f"),pos->second.mG);
1643 mpScattPowWin->SetCellValue(pos->second.mIdx, 3, tmp);
1644 tmp.Printf(_T(
"%f"),pos->second.mB);
1645 mpScattPowWin->SetCellValue(pos->second.mIdx, 4, tmp);
1646 tmp.Printf(_T(
"%f"),pos->second.mMaximumLikelihoodError);
1647 mpScattPowWin->SetCellValue(pos->second.mIdx, 5, tmp);
1648 tmp.Printf(_T(
"%f"),pos->second.mNbGhostAtoms);
1649 mpScattPowWin->SetCellValue(pos->second.mIdx, 6, tmp);
1654 if(0!=mpAntiBumpWin)
1656 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1657 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1659 if(pos->second.mNeedUpdateUI==
true)
1662 mpAntiBumpWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1663 mpAntiBumpWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1665 for(
unsigned long j=0;j<pos->second.mvAntiBumpDistance.size();++j)
1667 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateUI():Antibump("<<pos->first->GetName()
1669 <<
")="<<pos->second.mvAntiBumpDistance[j],3);
1670 if(pos->second.mvAntiBumpDistance[j]>-998)
1672 tmp.Printf(_T(
"%f"),pos->second.mvAntiBumpDistance[j]);
1673 mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,tmp);
1674 }
else mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,_T(
""));
1680 if(0!=mpBondValenceWin)
1682 map<ScatteringPowerAtom*,RowScattPow>::iterator pos;
1683 for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos)
1685 if(pos->second.mNeedUpdateUI==
true)
1688 mpBondValenceWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1689 mpBondValenceWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str()));
1691 for(
unsigned long j=0;j<pos->second.mvBondValenceRo.size();++j)
1693 VFN_DEBUG_MESSAGE(
"WXCrystal::UpdateUI():BondValence("<<pos->first->GetName()
1695 <<
")="<<pos->second.mvBondValenceRo[j],3);
1696 if(pos->second.mvBondValenceRo[j]>-998)
1698 tmp.Printf(_T(
"%f"),pos->second.mvBondValenceRo[j]);
1699 mpBondValenceWin->SetCellValue(pos->second.mIdx,j,tmp);
1700 }
else mpBondValenceWin->SetCellValue(pos->second.mIdx,j,_T(
""));
1706 if(lock)
mMutex.Unlock();
1708 VFN_DEBUG_EXIT(
"WXCrystal::UpdateUI()",6)
1710 Crystal& WXCrystal::GetCrystal(){
return *mpCrystal;}
1711 const Crystal& WXCrystal::GetCrystal()
const{
return *mpCrystal;}
1713 void WXCrystal::OnMenuShowScattPowWindow(wxCommandEvent &event)
1715 VFN_DEBUG_MESSAGE(
"WXCrystal::OnMenuShowScattPowWindow()",10)
1716 if(0!=mpScattPowWin) return;
1719 wxFrame *frame= new wxFrame(this,-1,_T("Scattering Powers parameters for: ")
1720 + wxString::FromAscii(this->GetCrystal().GetName().c_str()),
1721 wxDefaultPosition,wxSize(800,300));
1723 wxNotebook *notebook = new wxNotebook(frame, -1);
1725 mpScattPowWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_SCATTPOW);
1726 notebook->AddPage(mpScattPowWin, _T(
"Scattering Powers"),
true);
1728 mpScattPowWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1729 mpScattPowWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1730 mpScattPowWin->SetColMinimalAcceptableWidth(150);
1731 mpScattPowWin->CreateGrid(0,7);
1733 mpScattPowWin->SetColLabelValue(0,_T(
"Biso"));
1734 mpScattPowWin->SetColLabelValue(1,_T(
"Charge"));
1735 mpScattPowWin->SetColLabelValue(2,_T(
"Red"));
1736 mpScattPowWin->SetColLabelValue(3,_T(
"Green"));
1737 mpScattPowWin->SetColLabelValue(4,_T(
"Blue"));
1738 mpScattPowWin->SetColLabelValue(5,_T(
"ML Error"));
1739 mpScattPowWin->SetColLabelValue(6,_T(
"#ghost"));
1741 mpScattPowWin->AutoSizeRows();
1742 mpScattPowWin->AutoSizeColumns();
1745 mpAntiBumpWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_ANTIBUMP);
1746 notebook->AddPage(mpAntiBumpWin, _T(
"AntiBump"),
true);
1748 mpAntiBumpWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1749 mpAntiBumpWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1750 mpAntiBumpWin->SetColMinimalAcceptableWidth(150);
1751 mpAntiBumpWin->CreateGrid(0,0);
1753 mpAntiBumpWin->AutoSizeRows();
1754 mpAntiBumpWin->AutoSizeColumns();
1757 mpBondValenceWin =
new WXCrystalScrolledGridWindow(notebook,
this,ID_CRYSTAL_WIN_BONDVALENCE);
1758 notebook->AddPage(mpBondValenceWin, _T(
"BondValence"),
true);
1760 mpBondValenceWin->SetDefaultRenderer(
new wxGridCellFloatRenderer(5,3));
1761 mpBondValenceWin->SetDefaultEditor(
new wxGridCellFloatEditor(5,3));
1762 mpBondValenceWin->SetColMinimalAcceptableWidth(150);
1763 mpBondValenceWin->CreateGrid(0,0);
1765 mpBondValenceWin->AutoSizeRows();
1766 mpBondValenceWin->AutoSizeColumns();
1768 notebook->SetSelection(0);
1774 void WXCrystal::OnEditGridScattPow(wxGridEvent &e)
1777 const int r=e.GetRow();
1778 const int c=e.GetCol();
1779 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
1780 while(pos->second.mIdx!=r)++pos;
1781 ScatteringPowerAtom *
const p=pos->first;
1783 wxString s=mpScattPowWin->GetCellValue(r,c);
1802 p->SetFormalCharge(d);
1812 const REAL gg=p->GetColourRGB()[1];
1813 const REAL bb=p->GetColourRGB()[2];
1814 p->SetColour(d,gg,bb);
1824 const REAL rr=p->GetColourRGB()[0];
1825 const REAL bb=p->GetColourRGB()[2];
1826 p->SetColour(rr,d,bb);
1836 const REAL rr=p->GetColourRGB()[0];
1837 const REAL gg=p->GetColourRGB()[1];
1838 p->SetColour(rr,gg,d);
1848 p->SetMaximumLikelihoodPositionError(d);
1858 p->SetMaximumLikelihoodNbGhostAtom(d);
1866 void WXCrystal::OnEditGridScattPowAntiBump(wxGridEvent &e)
1869 const int r=e.GetRow();
1870 const int c=e.GetCol();
1872 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
1873 while(pos->second.mIdx!=r)++pos;
1874 const ScatteringPowerAtom *
const p1=pos->first;
1876 pos=mvpRowScattPow.begin();
1877 while(pos->second.mIdx!=c)++pos;
1878 const ScatteringPowerAtom *
const p2=pos->first;
1880 wxString s=mpAntiBumpWin->GetCellValue(r,c);
1883 if(d>0.01) mpCrystal->SetBumpMergeDistance(*p1,*p2,d);
1884 else mpCrystal->RemoveBumpMergeDistance(*p1,*p2);
1888 void WXCrystal::OnEditGridScattPowBondValence(wxGridEvent &e)
1891 const int r=e.GetRow();
1892 const int c=e.GetCol();
1894 map<ScatteringPowerAtom*,RowScattPow>::iterator pos=mvpRowScattPow.begin();
1895 while(pos->second.mIdx!=r)++pos;
1896 const ScatteringPowerAtom *
const p1=pos->first;
1898 pos=mvpRowScattPow.begin();
1899 while(pos->second.mIdx!=c)++pos;
1900 const ScatteringPowerAtom *
const p2=pos->first;
1902 wxString s=mpBondValenceWin->GetCellValue(r,c);
1905 if(d>0.01) mpCrystal->AddBondValenceRo(*p1,*p2,d);
1906 else mpCrystal->RemoveBondValenceRo(*p1,*p2);
1910 void WXCrystal::NotifyDeleteListWin(WXCrystalScrolledGridWindow *win)
1912 if(win==mpScattPowWin) mpScattPowWin=0;
1913 if(win==mpAntiBumpWin) mpAntiBumpWin=0;
1914 if(win==mpBondValenceWin) mpBondValenceWin=0;
1916 if((mpScattPowWin==0)&&(mpAntiBumpWin==0)&&(mpBondValenceWin==0)) mvpRowScattPow.clear();
1958 bool WXCrystal::Enable(
bool e)
1960 if(0!=mpScattPowWin) mpScattPowWin ->Enable(e);
1961 if(0!=mpAntiBumpWin) mpAntiBumpWin ->Enable(e);
1962 if(0!=mpBondValenceWin) mpBondValenceWin->Enable(e);
1963 return this->::wxWindow::Enable(e);
1972 UnitCellMap::UnitCellMap(
const Crystal&crystal):
1975 UnitCellMap::~UnitCellMap(){}
1976 void UnitCellMap::GLInitDisplayList(
const float minValue,
1977 WXGLCrystalCanvas * parentCrystal)
const
1979 VFN_DEBUG_ENTRY(
"UnitCellMap::GLInitDisplayList()",10)
1982 VFN_DEBUG_MESSAGE("UnitCellMap::GLInitDisplayList(): Generate Triangles",7)
1984 const
int nx=mPoints.cols();
1985 const
int ny=mPoints.rows();
1986 const
int nz=mPoints.depth();
1988 step[0]=1/(
float)nx;
1989 step[1]=1/(
float)ny;
1990 step[2]=1/(
float)nz;
1991 int nxMin, nxMax, nyMin, nyMax, nzMin, nzMax;
1992 BBox mapbbox = parentCrystal->GetMapBBox();
1994 if (mapbbox.xMin == mapbbox.xMax) mapbbox = parentCrystal->GetCellBBox();
1995 nxMin = (
int)(mapbbox.xMin * nx);
1996 nxMax = (
int)(mapbbox.xMax * nx);
1997 nyMin = (
int)(mapbbox.yMin * ny);
1998 nyMax = (
int)(mapbbox.yMax * ny);
1999 nzMin = (
int)(mapbbox.zMin * nz);
2000 nzMax = (
int)(mapbbox.zMax * nz);
2001 const
int snx = nxMax-nxMin+1, sny = nyMax-nyMin+1, snz = nzMax-nzMin+1;
2002 const
unsigned int sny_snz = sny*snz;
2004 unsigned int ni, nj, si, sj, sk, sni, snj, sind;
2009 for(i=nxMin, si=0; i <= nxMax; i++, si++)
2011 ni = ((nx + i % nx) % nx);
2013 for(j=nyMin, sj=0; j <= nyMax; j++, sj++)
2015 nj = ((ny + j % ny) % ny);
2017 for(k=nzMin, sk=0; k <= nzMax; k++, sk++)
2019 sind = sni + snj + sk;
2020 x = i*step[0]; y = j*step[1]; z = k*step[2];
2021 mpCrystal->FractionalToOrthonormalCoords(x, y, z);
2022 subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z;
2024 subPoints[sind].val = mPoints((nz+ k % nz)% nz,nj,ni);
2029 VFN_DEBUG_MESSAGE(
"UnitCellMap::GLInitDisplayList(): MC, Min Value="<<minValue,10)
2030 const
TRIANGLE *pTriangles= MC(snx-1, sny-1, snz-1, step[0], step[1], step[2], minValue, subPoints, numOfTriangles);
2032 VFN_DEBUG_MESSAGE("UnitCellMap::GLInitDisplayList(): OpenGL instructions",7)
2033 glBegin(GL_TRIANGLES);
2034 float normx,normy,normz;
2035 for(
int i=0; i < numOfTriangles; i++)
2038 for(
int j=0; j < 3; j++)
2042 normx=pTriangles[i].norm[j].x;
2043 normy=pTriangles[i].norm[j].y;
2044 normz=pTriangles[i].norm[j].z;
2047 glNormal3f(normx, normy, normz);
2048 glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z);
2051 for(
int j=2; j >=0; j--)
2055 normx=-pTriangles[i].norm[j].x;
2056 normy=-pTriangles[i].norm[j].y;
2057 normz=-pTriangles[i].norm[j].z;
2060 glNormal3f(normx, normy, normz);
2061 glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z);
2066 delete [] subPoints;
2067 delete [] pTriangles;
2068 VFN_DEBUG_EXIT(
"UnitCellMap::GLInitDisplayList():nb triangles="<<numOfTriangles,10)
2071 void UnitCellMap::POVRayDescription(ostream &os,
const float minValue,
2072 const CrystalPOVRayOptions &options)
const
2074 VFN_DEBUG_ENTRY(
"UnitCellMap::POVRayDescription()",7)
2076 VFN_DEBUG_MESSAGE("UnitCellMap::POVRayDescription(): Generate Triangles",7)
2078 const
int nx=mPoints.cols();
2079 const
int ny=mPoints.rows();
2080 const
int nz=mPoints.depth();
2082 step[0]=1/(
float)nx;
2083 step[1]=1/(
float)ny;
2084 step[2]=1/(
float)nz;
2085 int nxMin, nxMax, nyMin, nyMax, nzMin, nzMax;
2086 nxMin = (
int)(options.mXmin * nx);
2087 nxMax = (
int)(options.mXmax * nx);
2088 nyMin = (
int)(options.mYmin * ny);
2089 nyMax = (
int)(options.mYmax * ny);
2090 nzMin = (
int)(options.mZmin * nz);
2091 nzMax = (
int)(options.mZmax * nz);
2092 const
int snx = nxMax-nxMin+1, sny = nyMax-nyMin+1, snz = nzMax-nzMin+1;
2093 const
unsigned int sny_snz = sny*snz;
2095 unsigned int ni, nj, si, sj, sk, sni, snj, sind;
2100 for(i=nxMin, si=0; i <= nxMax; i++, si++)
2102 ni = ((nx + i % nx) % nx);
2104 for(j=nyMin, sj=0; j <= nyMax; j++, sj++)
2106 nj = ((ny + j % ny) % ny);
2108 for(k=nzMin, sk=0; k <= nzMax; k++, sk++)
2110 sind = sni + snj + sk;
2111 x = i*step[0]; y = j*step[1]; z = k*step[2];
2112 mpCrystal->FractionalToOrthonormalCoords(x, y, z);
2113 subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z;
2115 subPoints[sind].val = mPoints((nz+ k % nz)% nz,nj,ni);
2120 VFN_DEBUG_MESSAGE(
"UnitCellMap::POVRayDescription(): MC, Min Value="<<minValue,10)
2121 const
TRIANGLE *pTriangles= MC(snx-1, sny-1, snz-1, step[0], step[1], step[2], minValue, subPoints, numOfTriangles);
2123 VFN_DEBUG_MESSAGE("UnitCellMap::POVRayDescription(): POVRay instructions",7)
2124 float normx,normy,normz;
2125 for(
int i=0; i < numOfTriangles; i++)
2127 const float x1=pTriangles[i].p[0].x;
2128 const float x2=pTriangles[i].p[1].x;
2129 const float x3=pTriangles[i].p[2].x;
2130 const float y1=pTriangles[i].p[0].y;
2131 const float y2=pTriangles[i].p[1].y;
2132 const float y3=pTriangles[i].p[2].y;
2133 const float z1=pTriangles[i].p[0].z;
2134 const float z2=pTriangles[i].p[1].z;
2135 const float z3=pTriangles[i].p[2].z;
2138 const float d12=abs(x1-x2)+abs(y1-y2)+abs(z1-z2);
2139 const float d13=abs(x1-x3)+abs(y1-y3)+abs(z1-z3);
2140 const float d23=abs(x2-x3)+abs(y2-y3)+abs(z2-z3);
2141 if((d12<0.05)||(d13<0.05)||(d23<0.05))
continue;
2144 normx=pTriangles[i].norm[j].x;
2145 normy=pTriangles[i].norm[j].y;
2146 normz=pTriangles[i].norm[j].z;
2149 os<<
" ObjCrystMeshTriangle("
2150 <<x1<<
","<<y1<<
","<<z1<<
","
2151 <<x2<<
","<<y2<<
","<<z2<<
","
2152 <<x3<<
","<<y3<<
","<<z3<<
","
2153 <<normx<<
","<<normy<<
","<<normz<<
","
2154 <<normx<<
","<<normy<<
","<<normz<<
","
2155 <<normx<<
","<<normy<<
","<<normz<<
")"
2159 delete [] subPoints;
2160 delete [] pTriangles;
2161 VFN_DEBUG_EXIT(
"UnitCellMap::GLInitDisplayList()",7)
2164 int UnitCellMap::ImportGRD(
const string&filename)
2166 VFN_DEBUG_ENTRY(
"UnitCellMap::ImportGRD()",7)
2167 ifstream ffile(filename.c_str());
2168 if(!ffile.is_open())
2170 VFN_DEBUG_MESSAGE(
"UnitCellMap::ImportGRD() error opening "<<filename.c_str(),10)
2176 ffile.getline(buff, 100);
2177 float a, b, c, alpha, beta, gamma;
2178 ffile >>a >>b >>c >>alpha >>beta >>gamma;
2179 if(!ffile.good()) { (*fpObjCrystInformUser)(
"Error reading file: "+filename);
return 0; }
2208 ffile >>nx >>ny >>nz;
2209 if(!ffile.good()) { (*fpObjCrystInformUser)(
"Error reading file: "+filename);
return 0; }
2210 mPoints.resize(nz,ny,nx);
2211 for(
int i=0; i < nx; i++) {
2212 for(
int j=0; j < ny; j++) {
2213 for(
int k=0; k < nz; k++) {
2214 ffile >>mPoints(k,j,i);
2220 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2224 mStandardDeviation=0.0;
2225 const REAL *tmp=mPoints.data();
2226 for(
long i=0;i<mPoints.numElements();i++)
2228 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2231 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2240 std::string::size_type idx =filename.rfind(
"/");
2241 std::string::size_type idx2=filename.rfind(
"\\");
2242 std::string::size_type idx3=filename.rfind(
":");
2243 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
2244 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
2245 if(idx==string::npos)
2249 cout<<
"name="<<filename.substr(idx+1)<<endl;
2250 mName=filename.substr(idx+1);
2254 VFN_DEBUG_EXIT(
"UnitCellMap::ImportGRD()",7)
2259 void swap2(
void *data,
unsigned int nb)
2261 char * dataptr = (
char *)data;
2264 for (
unsigned int i=0; i<(nb-1); i+=2)
2267 dataptr[i] = dataptr[i+1];
2272 int UnitCellMap::ImportDSN6(
const string&filename)
2274 VFN_DEBUG_ENTRY(
"UnitCellMap::ImportDSN6()",7)
2275 FILE *pfile=fopen(filename.c_str(),"rb");
2278 VFN_DEBUG_MESSAGE(
"UnitCellMap::ImportDSN6() error opening "<<filename.c_str(),10)
2284 fread(header,
sizeof(
short), 256, pfile);
2285 bool needswap=
false;
2286 if (header[18] == 25600) needswap=
true;
2287 if(needswap) swap2(header, 19*
sizeof(
short));
2289 const long xstart=header[0];
2290 const long ystart=header[1];
2291 const long zstart=header[2];
2292 const long xextent=header[3];
2293 const long yextent=header[4];
2294 const long zextent=header[5];
2295 const unsigned long xsamplingrate=header[6];
2296 const unsigned long ysamplingrate=header[7];
2297 const unsigned long zsamplingrate=header[8];
2298 const float celledgea=(float)header[ 9]/(
float)header[17];
2299 const float celledgeb=(float)header[10]/(
float)header[17];
2300 const float celledgec=(float)header[11]/(
float)header[17];
2301 const float alpha=(float)header[12]/(
float)header[17];
2302 const float beta=(float)header[13]/(
float)header[17];
2303 const float gamma=(float)header[14]/(
float)header[17];
2304 const float rhoscale=(float)header[15]/(
float)header[18];
2305 const float rhozero =(float)header[16];
2306 cout <<
"xstart="<<xstart<<endl
2307 <<
"ystart="<<ystart<<endl
2308 <<
"zstart="<<zstart<<endl
2309 <<
"xextent="<<xextent<<endl
2310 <<
"yextent="<<yextent<<endl
2311 <<
"zextent="<<zextent<<endl
2312 <<
"xsamplingrate="<<xsamplingrate<<endl
2313 <<
"ysamplingrate="<<ysamplingrate<<endl
2314 <<
"zsamplingrate="<<zsamplingrate<<endl
2315 <<
"celledgea="<<celledgea<<endl
2316 <<
"celledgeb="<<celledgeb<<endl
2317 <<
"celledgec="<<celledgec<<endl
2318 <<
"alpha="<<alpha<<endl
2319 <<
"beta="<<beta<<endl
2320 <<
"gamma="<<gamma<<endl
2321 <<
"rhoscale="<<rhoscale<<endl
2322 <<
"rhozero="<<rhozero<<endl;
2324 #define BRICKSIZE 512
2327 unsigned char Points[BRICKSIZE];
2331 mPoints.resize(xsamplingrate,ysamplingrate,zsamplingrate);
2334 const unsigned int nxbrick=((xextent)/BRICKEDGE)+(xextent%8 ? 1 : 0);
2335 const unsigned int nybrick=((yextent)/BRICKEDGE)+(zextent%8 ? 1 : 0);
2336 const unsigned int nzbrick=((zextent)/BRICKEDGE)+(zextent%8 ? 1 : 0);
2338 for(
unsigned int zbrick=0;zbrick<nzbrick;zbrick++)
2339 for(
unsigned int ybrick=0;ybrick<nybrick;ybrick++)
2340 for(
unsigned int xbrick=0;xbrick<nxbrick;xbrick++)
2342 fread(&Points,
sizeof(
unsigned char), BRICKSIZE, pfile);
2345 if(needswap) swap2((
void *)&Points, BRICKSIZE);
2346 const unsigned char* pPoint=&Points[0];
2347 for(
unsigned int z=0;z<BRICKEDGE;z++)
2348 for(
unsigned int y=0;y<BRICKEDGE;y++)
2349 for(
unsigned int x=0;x<BRICKEDGE;x++)
2351 if( ((xbrick*BRICKEDGE+x)<xsamplingrate)
2352 &&((ybrick*BRICKEDGE+y)<ysamplingrate)
2353 &&((zbrick*BRICKEDGE+z)<zsamplingrate))
2354 mPoints(zbrick*BRICKEDGE+z,ybrick*BRICKEDGE+y,xbrick*BRICKEDGE+x)
2355 = ((float) *pPoint - rhozero)/ rhoscale ;
2361 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2365 mStandardDeviation=0.0;
2366 const REAL *tmp=mPoints.data();
2367 for(
long i=0;i<mPoints.numElements();i++)
2369 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2372 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2381 std::string::size_type idx =filename.rfind(
"/");
2382 std::string::size_type idx2=filename.rfind(
"\\");
2383 std::string::size_type idx3=filename.rfind(
":");
2384 if(((
long)idx2!=(
long)string::npos)&&((
long)idx2>(
long)idx))idx=idx2;
2385 if(((
long)idx3!=(
long)string::npos)&&((
long)idx3>(
long)idx))idx=idx3;
2386 if(idx==string::npos)
2391 mName=filename.substr(idx+1);
2394 VFN_DEBUG_EXIT(
"UnitCellMap::ImportDSN6()",7)
2404 unsigned int closest235(
unsigned int v)
2406 unsigned int n2=0,n3=0,n5=0;
2407 unsigned int v2,v3,v5=1;
2408 unsigned int bestdiff=10000;
2409 unsigned int best=0;
2410 for(
unsigned int i5=1;;)
2413 for(
unsigned int i3=1;;)
2416 for(
unsigned int i2=1;;)
2418 const unsigned int n=v2*v3*v5;
2428 if(best==v)
return best;
2435 if((v3*v5)>(v+bestdiff))
break;
2438 if(v5>(v+bestdiff))
break;
2443 int UnitCellMap::CalcFourierMap(
const ScatteringData& data,
unsigned int type0,
const bool normalized_sf)
2446 const float resolution=0.3;
2448 const unsigned long sizex=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(0)/resolution+.5)) ;
2449 const unsigned long sizey=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(1)/resolution+.5)) ;
2450 const unsigned long sizez=closest235((
unsigned int)floor(mpCrystal->GetLatticePar(2)/resolution+.5)) ;
2452 fftwf_complex *in= (fftwf_complex*) fftwf_malloc(
sizeof(fftwf_complex) * sizex*sizey*sizez);
2453 fftwf_plan plan=fftwf_plan_dft_3d(sizez, sizey, sizex,in, in,FFTW_FORWARD, FFTW_ESTIMATE);
2455 float *p=(
float*)in;
2456 for(
unsigned long i=0;i<sizex*sizey*sizez*2;i++) *p++=0;
2458 const long nb=data.GetNbReflBelowMaxSinThetaOvLambda();
2461 if(data.GetFhklObsSq().numElements()==0) mType=1;
2463 CrystVector_REAL norm_sf;
2466 CrystVector_REAL tmp;
2467 norm_sf.resize(data.GetFhklCalcReal().numElements());
2469 const map<const ScatteringPower*,CrystVector_REAL> *pSF=&(data.GetScatteringFactor());
2470 const ScatteringComponentList *pComp =&(mpCrystal->GetScatteringComponentList());
2472 for(
unsigned int i=0;i<pComp->GetNbComponent();i++)
2474 tmp=pSF->find((*pComp)(i).mpScattPow)->second;
2476 tmp*= (*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr;
2478 const REAL sf0=(*pComp)(i).mpScattPow->GetForwardScatteringFactor(data.GetRadiationType ());
2479 norm0+=(*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr *sf0*sf0;
2483 REAL *p=norm_sf.data();
2485 for(
unsigned int i=norm_sf.numElements();i>0;i--) {*p=sqrt(*p * norm0);p++;}
2489 REAL scale_fobs=1.0;
2494 for(
long i=0;i<nb;++i) {scale_fobs+=data.GetFhklCalcSq()(i); tmp+=data.GetFhklObsSq()(i);}
2495 scale_fobs=sqrt(scale_fobs/(tmp+1e-10));
2499 const REAL v=1/mpCrystal->GetVolume();
2500 for(
long i=0;i<nb;++i)
2502 CrystMatrix_REAL m=mpCrystal->GetSpaceGroup().GetAllEquivRefl (data.GetH()(i),data.GetK()(i),data.GetL()(i),
2503 false, data.IsIgnoringImagScattFact(),
2504 data.GetFhklCalcReal()(i),data.GetFhklCalcImag()(i));
2506 if(normalized_sf) norm=1/norm_sf(i);
2507 for(
int j=0;j<m.rows();j++)
2509 int h=int(m(j,0)),k=int(m(j,1)),l=int(m(j,2));
2510 if((abs(h*2)>sizex)||(abs(k*2)>sizey)||(abs(l*2)>sizez))
continue;
2521 const REAL fobs=scale_fobs*sqrt(fabs(data.GetFhklObsSq()(i)));
2522 const REAL rec=m(j,3),imc=m(j,4),fcalc=sqrt(fabs(data.GetFhklCalcSq()(i)));
2523 in[h+sizex*k+sizex*sizey*l][0]=v*rec*(fobs-fcalc)/sqrt(rec*rec+imc*imc)*norm;
2524 in[h+sizex*k+sizex*sizey*l][1]=v*imc*(fobs-fcalc)/sqrt(rec*rec+imc*imc)*norm;
2528 in[h+sizex*k+sizex*sizey*l][0]=v*m(j,3)*norm;
2529 in[h+sizex*k+sizex*sizey*l][1]=v*m(j,4)*norm;
2533 const REAL iobs=scale_fobs*sqrt(fabs(data.GetFhklObsSq()(i)));
2534 const REAL rec=m(j,3),imc=m(j,4),icalc=sqrt(fabs(data.GetFhklCalcSq()(i)));
2535 in[h+sizex*k+sizex*sizey*l][0]=v*rec*iobs/icalc*norm;
2536 in[h+sizex*k+sizex*sizey*l][1]=v*imc*iobs/icalc*norm;
2544 const int nbSymmetrics=mpCrystal->GetSpaceGroup().GetNbSymmetrics(
false,
false);
2545 const ScatteringComponentList *pScattCompList=&(mpCrystal->GetScatteringComponentList());
2546 const long nbComp=pScattCompList->GetNbComponent();
2547 for(
long i=0;i<nbComp;i++)
2550 in[0][0]+= (*pScattCompList)(i).mpScattPow->GetForwardScatteringFactor(data.GetRadiationType())
2551 *(*pScattCompList)(i).mOccupancy
2552 *(*pScattCompList)(i).mDynPopCorr
2557 fftwf_execute(plan);
2558 mPoints.resize(sizez,sizey,sizex);
2559 REAL *p1=mPoints.data();
2560 for(
unsigned int i=0;i<sizex*sizey*sizez;i++) *p1++ =in[i][0] ;
2567 mMean=mPoints.sum()/(REAL)(mPoints.numElements());
2571 mStandardDeviation=0.0;
2572 const REAL *tmp=mPoints.data();
2573 for(
long i=0;i<mPoints.numElements();i++)
2575 mStandardDeviation += (*tmp-mMean) * (*tmp-mMean);
2578 mStandardDeviation = sqrt(mStandardDeviation/(REAL)(mPoints.numElements()));
2586 fftwf_destroy_plan(plan);
2589 mName=data.GetClassName()+
":";
2590 if(data.GetName()==
"") mName+=
"?";
2591 else mName+=data.GetName();
2592 if(data.GetClassName()==
"PowderPatternDiffraction")
2595 if(data.GetRadiationType()==RAD_XRAY) mName+=
"Xray:";
2596 if(data.GetRadiationType()==RAD_NEUTRON) mName+=
"Neut:";
2597 if(data.GetRadiationType()==RAD_ELECTRON) mName+=
"Elec:";
2600 if(data.GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mName+=
"TOF:";
2603 sprintf(buf,
"%6.3fA:",data.GetWavelength()(0));
2606 const PowderPatternDiffraction* diff=
dynamic_cast<const PowderPatternDiffraction *
>(&data);
2607 if(diff!=0) mName+=diff->GetParentPowderPattern().GetName();
2609 if(data.GetClassName()==
"DiffractionDataSingleCrystal")
2612 if(data.GetRadiationType()==RAD_XRAY) mName+=
"Xray:";
2613 if(data.GetRadiationType()==RAD_NEUTRON) mName+=
"Neut:";
2614 if(data.GetRadiationType()==RAD_ELECTRON) mName+=
"Elec:";
2617 if(data.GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mName+=
"TOF:";
2620 sprintf(buf,
"%6.3fA:",data.GetWavelength()(0));
2623 mName+=data.GetName();
2626 if(mType==0) mName=
"(Fo)"+mName;
2627 if(mType==1) mName=
"(Fc)"+mName;
2628 if(mType==2) mName=
"(Fo-Fc)"+mName;
2633 const string & UnitCellMap::GetName()
const
2638 REAL UnitCellMap::GetValue(
const REAL x,
const REAL y,
const REAL z)
const
2640 const int nx=mPoints.cols();
2641 const int ny=mPoints.rows();
2642 const int nz=mPoints.depth();
2643 long ix=((long)floor(x*nx+.5))%nx;
2644 long iy=((long)floor(y*ny+.5))%ny;
2645 long iz=((long)floor(z*nz+.5))%nz;
2649 return mPoints(iz,iy,ix);
2651 REAL UnitCellMap::Max()
const{
return mMax;}
2652 REAL UnitCellMap::Min()
const{
return mMin;}
2653 REAL UnitCellMap::Mean()
const{
return mMean;}
2654 REAL UnitCellMap::StandardDeviation()
const{
return mStandardDeviation;}
2655 int UnitCellMap::GetType()
const{
return mType;}
2656 const Crystal &UnitCellMap::GetCrystal()
const{
return *mpCrystal;}
2657 const ScatteringData *UnitCellMap::GetData()
const{
return mpData;}
2664 UnitCellMapGLList::UnitCellMapGLList(
const UnitCellMap &ucmap,WXGLCrystalCanvas * parent,
2665 const bool showWire,
float contour,
2666 const float r,
const float g,
const float b,
const float t):
2667 mGLDisplayList(0),mShowWire(showWire),mShow(true),mContour(contour),mpUCMap(&ucmap),mpParent(parent)
2669 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::UnitCellMapGLList()",10)
2670 this->SetColour(r,g,b,t);
2673 UnitCellMapGLList::~UnitCellMapGLList()
2675 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::~UnitCellMapGLList()",10)
2676 if(0!=mGLDisplayList) glDeleteLists(mGLDisplayList,1);
2678 void UnitCellMapGLList::GenList()
2680 VFN_DEBUG_ENTRY(
"UnitCellMapGLList::GenList()",7)
2681 if(0==mGLDisplayList) mGLDisplayList=glGenLists(1);
2682 glNewList(mGLDisplayList,GL_COMPILE);
2684 mpUCMap->GLInitDisplayList(mContour, mpParent);
2687 VFN_DEBUG_EXIT("UnitCellMapGLList::GenList()",7)
2690 void UnitCellMapGLList::SetColour(const
float r,const
float g,const
float b,
2699 const float* UnitCellMapGLList::GetColour()
const
2704 void UnitCellMapGLList::ToggleShowWire()
2706 mShowWire =! mShowWire;
2709 bool UnitCellMapGLList::ShowWire()
const
2714 void UnitCellMapGLList::Draw()
const
2716 if(0==mGLDisplayList)
2718 VFN_DEBUG_MESSAGE(
"UnitCellMapGLList::Draw():No Display list generated !",7)
2722 if(mShowWire) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2723 else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2725 glMaterialfv(GL_FRONT, GL_AMBIENT, mColour);
2726 glMaterialfv(GL_FRONT, GL_DIFFUSE, mColour);
2727 glMaterialfv(GL_FRONT, GL_SPECULAR, mColour);
2728 const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f};
2729 glMaterialfv(GL_FRONT, GL_EMISSION, colour0);
2733 glMaterialf( GL_FRONT, GL_SHININESS, 0.0);
2735 const GLfloat colorBack [] = {mColour[0]/3., mColour[1]/3., mColour[2]/3., mColour[3]};
2736 glMaterialfv(GL_BACK, GL_AMBIENT, colorBack);
2737 glMaterialfv(GL_BACK, GL_DIFFUSE, colorBack);
2738 glMaterialfv(GL_BACK, GL_SPECULAR, colorBack);
2739 glMaterialf( GL_BACK, GL_SHININESS, 0.0);
2742 glCallList(mGLDisplayList);
2744 VFN_DEBUG_EXIT(
"UnitCellMapGLList::Draw()",7)
2747 void UnitCellMapGLList::SetName(
const string &name)
2751 const string &UnitCellMapGLList::GetName()
const
2755 void UnitCellMapGLList::SetShow(
bool show) {mShow=show;}
2756 bool UnitCellMapGLList::Show()
const {
return mShow;}
2757 void UnitCellMapGLList::SetContour(
float contour) {mContour=contour;}
2758 float UnitCellMapGLList::GetContour()
const {
return mContour;}
2759 const UnitCellMap & UnitCellMapGLList::GetMap()
const {
return *mpUCMap;}
2766 WXGLCrystalCanvas::WXFourierMapList::WXFourierMapList(WXGLCrystalCanvas *pGLCrystalCanvas,wxWindow *parent):
2767 wxWindow(parent,-1),mpGLCrystalCanvas(pGLCrystalCanvas),mIsUpdating(false)
2769 this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2770 wxBoxSizer* pSizer=
new wxBoxSizer(wxVERTICAL);
2772 wxBoxSizer* pSizerButtons=
new wxBoxSizer(wxHORIZONTAL);
2773 wxButton *pButtonUpdate=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_UPDATE,_T(
"Update 3D View"));
2774 mpWireFrame=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_WIREFRAME,_T(
"Wireframe"));
2775 mpShowFourier=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_SHOW,_T(
"Show Fourier"));
2776 mpSharpenMap=
new wxCheckBox(
this,ID_GLCRYSTAL_FOURIER_SHARPEN,_T(
"Sharpen maps"));
2777 pSizerButtons->Add(pButtonUpdate,0,wxALIGN_CENTER);
2778 pSizerButtons->Add(mpWireFrame,0,wxALIGN_CENTER);
2779 pSizerButtons->Add(mpShowFourier,0,wxALIGN_CENTER);
2780 pSizerButtons->Add(mpSharpenMap,0,wxALIGN_CENTER);
2781 pSizer->Add(pSizerButtons,0,wxALIGN_CENTER);
2784 wxBoxSizer* pSizerMaps=
new wxBoxSizer(wxHORIZONTAL);
2787 wxBoxSizer* pSizerLeft=
new wxBoxSizer(wxVERTICAL);
2788 pSizerMaps->Add(pSizerLeft,0,wxALIGN_TOP);
2790 wxStaticText *mpLabel0=
new wxStaticText(
this,-1,_T(
"Available Maps"));
2791 pSizerLeft->Add(mpLabel0,0,wxALIGN_CENTER);
2792 mpAvailableMapList=
new wxListBox(
this,ID_GLCRYSTAL_FOURIER_LISTMAP,wxDefaultPosition,wxSize(400,150));
2793 pSizerLeft->Add(mpAvailableMapList,0,wxALIGN_CENTER);
2795 mpMapInfo=
new wxStaticText(
this,-1,_T(
"min=+00.00 max=+00.00 sigma=00.00"));
2796 pSizerLeft->Add(mpMapInfo,0,wxALIGN_CENTER);
2798 wxBoxSizer* pSizerLeft2=
new wxBoxSizer(wxHORIZONTAL);
2799 pSizerLeft->Add(pSizerLeft2,0,wxALIGN_CENTER);
2800 wxStaticText *mpLabel2=
new wxStaticText(
this,-1,_T(
"New Contour:"));
2801 mpNewContourValue=
new wxTextCtrl(
this,ID_GLCRYSTAL_FOURIER_NEWCONTOUR,_T(
""),wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
2802 pSizerLeft2->Add(mpLabel2,0,wxALIGN_CENTER);
2803 pSizerLeft2->Add(mpNewContourValue,0,wxALIGN_CENTER);
2805 wxButton *pButtonAdd=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_ADD,_T(
"Add"));
2806 pSizerLeft->Add(pButtonAdd,0,wxALIGN_CENTER);
2808 pSizerMaps->AddSpacer(5);
2810 wxBoxSizer* pSizerRight=
new wxBoxSizer(wxVERTICAL);
2811 pSizerMaps->Add(pSizerRight,0,wxALIGN_TOP);
2813 wxStaticText *mpLabel0r=
new wxStaticText(
this,-1,_T(
"Displayed Maps"));
2814 pSizerRight->Add(mpLabel0r,0,wxALIGN_CENTER);
2815 mpDisplayedMapList=
new wxListBox(
this,ID_GLCRYSTAL_FOURIER_LISTGLMAP,wxDefaultPosition,wxSize(400,150));
2816 pSizerRight->Add(mpDisplayedMapList,0,wxALIGN_CENTER);
2818 wxBoxSizer* pSizerRight1=
new wxBoxSizer(wxHORIZONTAL);
2819 pSizerRight->Add(pSizerRight1,0,wxALIGN_CENTER);
2820 wxStaticText *mpLabel3=
new wxStaticText(
this,-1,_T(
"Contour:"));
2821 mpContourValue=
new wxTextCtrl(
this,ID_GLCRYSTAL_FOURIER_CONTOUR,_T(
""),wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
2822 pSizerRight1->Add(mpLabel3,0,wxALIGN_CENTER);
2823 pSizerRight1->Add(mpContourValue,0,wxALIGN_CENTER);
2825 mpColourPicker=
new wxColourPickerCtrl(
this, ID_GLCRYSTAL_FOURIER_COLOURPICKER, *wxRED, wxDefaultPosition, wxDefaultSize,wxCLRP_USE_TEXTCTRL);
2826 wxButton *pButtonRemove=
new wxButton(
this,ID_GLCRYSTAL_FOURIER_REMOVE,_T(
"Remove"));
2827 pSizerRight->Add(mpColourPicker,0,wxALIGN_CENTER);
2828 pSizerRight->Add(pButtonRemove,0,wxALIGN_CENTER);
2829 pSizer->Add(pSizerMaps,0,wxALIGN_CENTER);
2830 this->SetSizer(pSizer);
2831 this->SetAutoLayout(
true);
2832 pSizer->SetSizeHints(
this);
2833 pSizer->SetSizeHints(parent);
2836 WXGLCrystalCanvas::WXFourierMapList::~WXFourierMapList()
2838 mpGLCrystalCanvas->NotifyDeleteFourierWin();
2841 struct GLCrystalConfig
2843 GLCrystalConfig(
const bool saved=
false);
2856 GLCrystalConfig::GLCrystalConfig(
const bool saved)
2861 static GLCrystalConfig sGLCrystalConfig;
2868 static const long ID_GLCRYSTAL_MENU_SHOWATOMLABEL= WXCRYST_ID();
2869 static const long ID_GLCRYSTAL_MENU_SHOWHYDROGENS= WXCRYST_ID();
2870 static const long ID_GLCRYSTAL_MENU_SHOWCURSOR= WXCRYST_ID();
2871 static const long ID_GLCRYSTAL_MENU_SETCURSOR= WXCRYST_ID();
2872 static const long ID_GLCRYSTAL_UPDATEUI= WXCRYST_ID();
2873 static const long ID_GLCRYSTAL_MENU_CHANGELIMITS= WXCRYST_ID();
2874 static const long ID_GLCRYSTAL_MENU_LIMITS_FULLCELL= WXCRYST_ID();
2875 static const long ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL= WXCRYST_ID();
2876 static const long ID_GLCRYSTAL_MENU_SHOWCRYSTAL= WXCRYST_ID();
2877 static const long ID_GLCRYSTAL_MENU_FOURIER= WXCRYST_ID();
2878 static const long ID_GLCRYSTAL_MENU_LOADFOURIERGRD= WXCRYST_ID();
2879 static const long ID_GLCRYSTAL_MENU_LOADFOURIERDSN6= WXCRYST_ID();
2881 static const long ID_GLCRYSTAL_MENU_POVRAY= WXCRYST_ID();
2884 BEGIN_EVENT_TABLE(WXGLCrystalCanvas, wxGLCanvas)
2885 EVT_PAINT (WXGLCrystalCanvas::OnPaint)
2886 EVT_ERASE_BACKGROUND (WXGLCrystalCanvas::OnEraseBackground)
2887 EVT_MOUSE_EVENTS (WXGLCrystalCanvas::OnMouse)
2888 EVT_MENU (ID_GLCRYSTAL_MENU_UPDATE, WXGLCrystalCanvas::OnUpdate)
2889 EVT_MENU (ID_GLCRYSTAL_MENU_CHANGELIMITS, WXGLCrystalCanvas::OnChangeLimits)
2890 EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, WXGLCrystalCanvas::OnChangeLimits)
2891 EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, WXGLCrystalCanvas::OnChangeLimits)
2892 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCRYSTAL, WXGLCrystalCanvas::OnShowCrystal)
2893 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWATOMLABEL, WXGLCrystalCanvas::OnShowAtomLabel)
2894 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWHYDROGENS, WXGLCrystalCanvas::OnShowHydrogens)
2895 EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCURSOR, WXGLCrystalCanvas::OnShowCursor)
2896 EVT_MENU (ID_GLCRYSTAL_MENU_SETCURSOR, WXGLCrystalCanvas::OnSetCursor)
2897 EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERGRD, WXGLCrystalCanvas::OnLoadFourierGRD)
2898 EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERDSN6, WXGLCrystalCanvas::OnLoadFourierDSN6)
2900 EVT_MENU (ID_GLCRYSTAL_MENU_POVRAY, WXGLCrystalCanvas::OnPOVRay)
2901 EVT_MENU (ID_GLCRYSTAL_MENU_FOURIER, WXGLCrystalCanvas::OnFourier)
2902 EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTGLMAP, WXGLCrystalCanvas::OnFourier)
2903 EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTMAP, WXGLCrystalCanvas::OnFourier)
2904 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_ADD, WXGLCrystalCanvas::OnFourier)
2905 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_REMOVE, WXGLCrystalCanvas::OnFourier)
2906 EVT_BUTTON (ID_GLCRYSTAL_FOURIER_UPDATE, WXGLCrystalCanvas::OnFourier)
2907 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_WIREFRAME, WXGLCrystalCanvas::OnFourier)
2908 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHOW, WXGLCrystalCanvas::OnFourier)
2909 EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHARPEN, WXGLCrystalCanvas::OnFourier)
2910 EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_NEWCONTOUR, WXGLCrystalCanvas::OnFourier)
2911 EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_CONTOUR, WXGLCrystalCanvas::OnFourier)
2912 EVT_COLOURPICKER_CHANGED(ID_GLCRYSTAL_FOURIER_COLOURPICKER, WXGLCrystalCanvas::OnFourierChangeColour)
2913 EVT_CHAR (WXGLCrystalCanvas::OnKeyDown)
2914 EVT_KEY_DOWN (WXGLCrystalCanvas::OnKeyDown)
2915 EVT_KEY_UP (WXGLCrystalCanvas::OnKeyUp)
2916 EVT_UPDATE_UI(ID_GLCRYSTAL_UPDATEUI,WXGLCrystalCanvas::OnUpdateUI)
2919 int AttribList [] = {WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16,0};
2921 WXGLCrystalCanvas::WXGLCrystalCanvas(WXCrystal *wxcryst,
2922 wxFrame *parent, wxWindowID
id,
2924 const wxSize &size):
2925 wxGLCanvas(parent, id,AttribList,pos,size,wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE,_T(
"GLCanvas"),wxNullPalette),
2927 mpParentFrame(parent),
2928 mpWXCrystal(wxcryst),mIsGLInit(false),mDist(60),mX0(0),mY0(0),mZ0(0),mViewAngle(15),
2929 mShowFourier(true),mShowCrystal(true),mShowAtomName(true),mShowHydrogens(true),mShowCursor(false),mSharpenMap(true),
2930 mIsGLFontBuilt(false),mGLFontDisplayListBase(0),mpFourierMapListWin(0)
2932 mpwxGLContext=
new wxGLContext(
this);
2933 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::WXGLCrystalCanvas()",3)
2934 if(sGLCrystalConfig.mSaved)
2936 mDist=sGLCrystalConfig.mDist;
2937 mX0=sGLCrystalConfig.mX0;
2938 mY0=sGLCrystalConfig.mY0;
2939 mZ0=sGLCrystalConfig.mZ0;
2940 mViewAngle=sGLCrystalConfig.mViewAngle;
2941 for(
int i=0;i<4;++i) mQuat[i]=sGLCrystalConfig.mQuat[i];
2942 mShowAtomName=sGLCrystalConfig.mShowAtomName;
2943 mShowCursor=sGLCrystalConfig.mShowCursor;
2945 mcellbbox.xMin=sGLCrystalConfig.mcellbbox.xMin;
2946 mcellbbox.xMax=sGLCrystalConfig.mcellbbox.xMax;
2947 mcellbbox.yMin=sGLCrystalConfig.mcellbbox.yMin;
2948 mcellbbox.yMax=sGLCrystalConfig.mcellbbox.yMax;
2949 mcellbbox.zMin=sGLCrystalConfig.mcellbbox.zMin;
2950 mcellbbox.zMax=sGLCrystalConfig.mcellbbox.zMax;
2952 mmapbbox.xMin=sGLCrystalConfig.mmapbbox.xMin;
2953 mmapbbox.xMax=sGLCrystalConfig.mmapbbox.xMax;
2954 mmapbbox.yMin=sGLCrystalConfig.mmapbbox.yMin;
2955 mmapbbox.yMax=sGLCrystalConfig.mmapbbox.yMax;
2956 mmapbbox.zMin=sGLCrystalConfig.mmapbbox.zMin;
2957 mmapbbox.zMax=sGLCrystalConfig.mmapbbox.zMax;
2959 mViewCntr.x=sGLCrystalConfig.mViewCntr.x;
2960 mViewCntr.y=sGLCrystalConfig.mViewCntr.y;
2961 mViewCntr.z=sGLCrystalConfig.mViewCntr.z;
2965 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
2966 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
2967 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
2968 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
2969 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
2970 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
2974 mmapbbox.xMin = mmapbbox.xMax = mmapbbox.yMin = mmapbbox.zMin = 0.;
2975 mmapbbox.yMax = mmapbbox.zMax = 1.;
2976 mpPopUpMenu=
new wxMenu(_T(
"Crystal"));
2977 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_UPDATE, _T(
"&Update"));
2978 mpPopUpMenu->AppendSeparator();
2979 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_CHANGELIMITS, _T(
"Change display &Limits"));
2980 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, _T(
"Show Full Unit Cell"));
2981 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, _T(
"Show Asymmetric Unit Cell"));
2982 mpPopUpMenu->AppendSeparator();
2983 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Hide Crystal"));
2984 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
2985 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Hide Hydrogens"));
2986 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Show Cursor"));
2987 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SETCURSOR, _T(
"Set view cntr and cursor pos."));
2988 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_POVRAY, _T(
"Create POVRay file"));
2989 mpPopUpMenu->AppendSeparator();
2990 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_FOURIER, _T(
"Fourier Maps"));
2991 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERGRD, _T(
"Load GRD Fourier Map"));
2992 mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,_T(
"Load DSN6 Fourier Map"));
2997 if(sGLCrystalConfig.mSaved==
false)
2999 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view")))
3000 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"),
true);
3004 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"), &val);
3007 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
3008 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
3009 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
3010 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
3011 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
3012 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
3024 if(!wxConfigBase::Get()->HasEntry(_T(
"Crystal/BOOL/Default-display atom names in 3D view")))
3025 wxConfigBase::Get()->Write(_T(
"Crystal/BOOL/Default-display atom names in 3D view"), mShowAtomName);
3028 wxConfigBase::Get()->Read(_T(
"Crystal/BOOL/Default-display atom names in 3D view"), &mShowAtomName);
3031 if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
3032 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Show Atom Labels"));
3035 WXGLCrystalCanvas::~WXGLCrystalCanvas()
3037 mpWXCrystal->NotifyCrystalGLDelete();
3039 this->DeleteGLFont();
3042 sGLCrystalConfig.mDist = mDist;
3043 sGLCrystalConfig.mX0=mX0;
3044 sGLCrystalConfig.mY0=mY0;
3045 sGLCrystalConfig.mZ0=mZ0;
3046 sGLCrystalConfig.mViewAngle=mViewAngle;
3047 for(
int i=0;i<4;++i) sGLCrystalConfig.mQuat[i]=mQuat[i];
3048 sGLCrystalConfig.mShowAtomName=mShowAtomName;
3049 sGLCrystalConfig.mShowCursor=mShowCursor;
3051 sGLCrystalConfig.mcellbbox.xMin=mcellbbox.xMin;
3052 sGLCrystalConfig.mcellbbox.xMax=mcellbbox.xMax;
3053 sGLCrystalConfig.mcellbbox.yMin=mcellbbox.yMin;
3054 sGLCrystalConfig.mcellbbox.yMax=mcellbbox.yMax;
3055 sGLCrystalConfig.mcellbbox.zMin=mcellbbox.zMin;
3056 sGLCrystalConfig.mcellbbox.zMax=mcellbbox.zMax;
3058 sGLCrystalConfig.mmapbbox.xMin=mmapbbox.xMin;
3059 sGLCrystalConfig.mmapbbox.xMax=mmapbbox.xMax;
3060 sGLCrystalConfig.mmapbbox.yMin=mmapbbox.yMin;
3061 sGLCrystalConfig.mmapbbox.yMax=mmapbbox.yMax;
3062 sGLCrystalConfig.mmapbbox.zMin=mmapbbox.zMin;
3063 sGLCrystalConfig.mmapbbox.zMax=mmapbbox.zMax;
3065 sGLCrystalConfig.mViewCntr.x=mViewCntr.x;
3066 sGLCrystalConfig.mViewCntr.y=mViewCntr.y;
3067 sGLCrystalConfig.mViewCntr.z=mViewCntr.z;
3068 sGLCrystalConfig.mSaved=
true;
3069 delete mpwxGLContext;
3072 void WXGLCrystalCanvas::OnExit(wxCommandEvent &event)
3077 void WXGLCrystalCanvas::OnPaint(wxPaintEvent &event)
3079 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnPaint()",7)
3082 if(false==mIsGLInit)
3090 GetClientSize(& width, & height);
3093 glViewport(0, 0, width, height);
3094 glMatrixMode(GL_PROJECTION);
3096 if( (width>0)&&(height>0))
3097 gluPerspective(mViewAngle,(
float)width/(
float)height,1.f,2.*mDist);
3100 glMatrixMode( GL_MODELVIEW );
3103 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3104 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
3109 glTranslatef( 0, 0, -mDist );
3110 build_rotmatrix( m,mQuat);
3111 glMultMatrixf( &m[0][0] );
3112 glTranslatef( mX0, mY0, mZ0 );
3115 for(
unsigned int passnum = 0; passnum<2; passnum++)
3119 glDepthMask(GL_TRUE);
3120 glAlphaFunc(GL_GREATER,0.99);
3124 glDepthMask(GL_FALSE);
3125 glAlphaFunc(GL_LEQUAL,0.99);
3129 GetClientSize(& w, & h);
3130 const GLfloat colour2 [] = {1.00, 1.00, 1.00, 0.3};
3131 glMaterialfv(GL_FRONT, GL_EMISSION, colour2);
3134 glMatrixMode(GL_PROJECTION);
3137 gluOrtho2D(0,w,0,h);
3138 glColor3f(1.0,1.0,1.0);
3139 glRasterPos2i(2,h-12);
3141 sprintf(c,
"%5.3f<x<%5.3f\n",mcellbbox.xMin,mcellbbox.xMax);
3144 glRasterPos2i(2, h-24);
3145 sprintf(c,
"%5.3f<y<%5.3f\n",mcellbbox.yMin,mcellbbox.yMax);
3148 glRasterPos2i(2, h-36);
3149 sprintf(c,
"%5.3f<z<%5.3f\n",mcellbbox.zMin,mcellbbox.zMax);
3152 glMatrixMode( GL_MODELVIEW );
3158 glColor3f(1.0, 1.0, 1.0);
3159 glTranslatef(0, 0, -mDist);
3160 glMultMatrixf(&m[0][0]);
3161 glTranslatef(mX0, mY0, mZ0);
3162 glCallList(mpWXCrystal->GetCrystalGLDisplayList());
3166 glColor3f(1.0,1.0,1.0);
3167 glTranslatef( -0.3, 0, -mDist+1. );
3168 glMultMatrixf( &m[0][0] );
3169 glTranslatef( mX0, mY0, mZ0 );
3170 glCallList(mpWXCrystal->GetCrystalGLDisplayList(
true));
3177 glTranslatef( 0, 0, -mDist);
3178 glMultMatrixf( &m[0][0] );
3179 const GLfloat colour0 [] = {0.00, 0.00, 0.00, 0.00};
3180 const GLfloat colour1 [] = {1.0f, 1.0f, 1.0f, 1.00};
3181 glMaterialfv(GL_FRONT, GL_AMBIENT, colour0);
3182 glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0);
3183 glMaterialfv(GL_FRONT, GL_SPECULAR, colour0);
3184 glMaterialfv(GL_FRONT, GL_EMISSION, colour1);
3185 glMaterialfv(GL_FRONT, GL_SHININESS, colour0);
3187 glVertex3f(-1.0f, 0.0f, 0.0f);
3188 glVertex3f( 1.0f, 0.0f, 0.0f);
3190 glVertex3f( 0.0f,-1.0f, 0.0f);
3191 glVertex3f( 0.0f, 1.0f, 0.0f);
3193 glVertex3f( 0.0f, 0.0f,-1.0f);
3194 glVertex3f( 0.0f, 0.0f, 1.0f);
3199 wxString statusText;
3203 mpWXCrystal->GetCrystal().OrthonormalToFractionalCoords(x,y,z);
3204 x=(mcellbbox.xMax+mcellbbox.xMin)/2.-x;
3205 y=(mcellbbox.yMax+mcellbbox.yMin)/2.-y;
3206 z=(mcellbbox.zMax+mcellbbox.zMin)/2.-z;
3207 statusText.Printf(_T(
"Center@(%5.3f,%5.3f,%5.3f)"),x,y,z);
3208 for(
unsigned int i=0;i<mvpUnitCellMap.size();++i)
3210 statusText+=_T(
", map(") + wxString::FromAscii(mvpUnitCellMap[i]->GetName().c_str())
3211 +wxString::Format(_T(
")=%5.2fe"),mvpUnitCellMap[i]->GetValue(x,y,z));
3213 mpParentFrame->SetStatusText(statusText);
3215 if (mShowFourier && (passnum==0))
3217 glAlphaFunc(GL_ALWAYS,1);
3219 glTranslatef( 0, 0, -mDist );
3220 build_rotmatrix( m,mQuat);
3221 glMultMatrixf( &m[0][0] );
3222 glTranslatef( mX0, mY0, mZ0 );
3225 BBox cellbbox = this->GetCellBBox();
3226 REAL xc=(cellbbox.xMin+cellbbox.xMax)/2.;
3227 REAL yc=(cellbbox.yMin+cellbbox.yMax)/2.;
3228 REAL zc=(cellbbox.zMin+cellbbox.zMax)/2.;
3229 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(xc, yc, zc);
3230 glTranslatef(-xc, -yc, -zc);
3232 vector<boost::shared_ptr<UnitCellMapGLList> >::const_iterator pos;
3233 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos)
3234 if((*pos)->Show()) (*pos)->Draw();
3238 glDepthMask(GL_TRUE);
3239 glAlphaFunc(GL_ALWAYS,1);
3242 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::OnPaint():End",7)
3245 void WXGLCrystalCanvas::OnEraseBackground(wxEraseEvent& event)
3249 void WXGLCrystalCanvas::OnKeyDown(wxKeyEvent& event)
3251 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown()",2)
3252 switch(event.GetKeyCode())
3256 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():Bigger",2)
3258 GetClientSize(& width, & height);
3261 glMatrixMode(GL_PROJECTION);
3263 if( (width>0)&&(height>0))
3264 gluPerspective(mViewAngle,(
float)width/(
float)height,
3265 (mDist>100)?(mDist-100):1.,mDist+100);
3271 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():Smaller",2)
3273 GetClientSize(& width, & height);
3276 glMatrixMode(GL_PROJECTION);
3278 if( (width>0)&&(height>0))
3279 gluPerspective(mViewAngle,(
float)width/(
float)height,
3280 (mDist>100)?(mDist-100):1.,mDist+100);
3284 case(WXK_INSERT): mY0 += 0.1; Refresh(FALSE); break;
3285 case(WXK_DELETE): mY0 -= 0.1; Refresh(FALSE); break;
3286 case(WXK_HOME): mX0 -= 0.1; Refresh(FALSE); break;
3287 case(WXK_END): mX0 += 0.1; Refresh(FALSE); break;
3288 case(WXK_PAGEUP): mZ0 -= 0.1; Refresh(FALSE); break;
3289 case(WXK_PAGEDOWN): mZ0 += 0.1; Refresh(FALSE); break;
3292 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate left",2)
3294 trackball(spin_quat,0,0,-.05,0);
3295 add_quats( spin_quat, mQuat, mQuat );
3301 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate right",2)
3303 trackball(spin_quat,0,0,.05,0);
3304 add_quats( spin_quat, mQuat, mQuat );
3310 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate down",2)
3312 trackball(spin_quat,0,0,0,-.05);
3313 add_quats( spin_quat, mQuat, mQuat );
3319 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate up",2)
3321 trackball(spin_quat,0,0,0,.05);
3322 add_quats( spin_quat, mQuat, mQuat );
3328 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate left",2)
3330 trackball(spin_quat,0,0,-.05,0);
3331 add_quats( spin_quat, mQuat, mQuat );
3337 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate right",2)
3339 trackball(spin_quat,0,0,.05,0);
3340 add_quats( spin_quat, mQuat, mQuat );
3346 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate down",2)
3348 trackball(spin_quat,0,0,0,-.05);
3349 add_quats( spin_quat, mQuat, mQuat );
3355 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyDown():rotate up",2)
3357 trackball(spin_quat,0,0,0,.05);
3358 add_quats( spin_quat, mQuat, mQuat );
3366 void WXGLCrystalCanvas::OnKeyUp(wxKeyEvent& event)
3368 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnKeyUp():"<<event.GetKeyCode(),2)
3371 void WXGLCrystalCanvas::OnEnterWindow( wxMouseEvent& event )
3373 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnEnterWindow()",5)
3376 void WXGLCrystalCanvas::OnMouse( wxMouseEvent& event )
3378 if(event.Leaving())
return;
3379 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse()"
3380 <<endl<<
"IsButton():"<<event.IsButton()
3381 <<endl<<
"ButtonDown():"<<
event.ButtonDown()
3382 <<endl<<
"Dragging():"<<
event.Dragging()
3383 <<endl<<
"Entering():"<<
event.Entering()
3384 <<endl<<
"Leaving():"<<
event.Leaving()
3385 <<endl<<
"GetButton()"<<
event.GetButton()
3386 <<endl<<
"GetWheelAxis():"<<
event.GetWheelAxis()
3387 <<endl<<
"GetWheelDelta():"<<
event.GetWheelDelta()
3388 <<endl<<
"GetWheelRotation():"<<
event.GetWheelRotation()
3389 <<endl<<
"Moving():"<<
event.Moving()
3391 if (event.Dragging())
3394 GetClientSize(& width, & height);
3395 if(event.LeftIsDown())
3397 if(event.ShiftDown())
3399 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Left Button",2)
3401 REAL vx1=mTrackBallLastX,vy1=mTrackBallLastY,vz1,
3402 vx2=event.GetX(), vy2=event.GetY(), vz2;
3404 this->UnProject(vx1,vy1,vz1);
3405 this->UnProject(vx2,vy2,vz2);
3411 VFN_DEBUG_MESSAGE("Origin (ortho) = "<<mX0<<", "<<mY0<<", "<<mZ0,2)
3416 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Left Button",2)
3419 trackball(spin_quat,
3420 (2.0*mTrackBallLastX - width) / (width+.001),
3421 ( height - 2.0*mTrackBallLastY) / (height+.001),
3422 ( 2.0*event.GetX() - width) / (width+.001),
3423 ( height - 2.0*event.GetY()) / (height+.001));
3425 add_quats( spin_quat, mQuat, mQuat );
3429 if(event.MiddleIsDown())
3431 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Dragging Middle Button",2)
3432 const
float v= (mTrackBallLastY-event.GetY())/(
float)height;
3433 const
float h= (mTrackBallLastX-event.GetX())/(
float)width;
3435 mDist *= (1.+v)/(1.+h);
3436 mViewAngle *=(1.+h);
3438 glMatrixMode(GL_PROJECTION);
3440 if( (width>0)&&(height>0))
3441 gluPerspective(mViewAngle,(
float)width/(
float)height,
3442 (mDist>101)?(mDist-100):1.,mDist+100);
3444 VFN_DEBUG_MESSAGE(mViewAngle <<" "<<mDist,2)
3448 else if(event.RightIsDown())
3450 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse():Right Button",2)
3451 if(mpWXCrystal->GetCrystal().IsBeingRefined())
3453 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE,
false);
3454 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY,
false);
3455 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD,
false);
3456 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,
false);
3460 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE,
true);
3461 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY,
true);
3462 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD,
true);
3463 mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,
true);
3466 this->PopupMenu(mpPopUpMenu, event.GetX(),
event.GetY() );
3468 else if (event.GetWheelDelta()>0)
3470 if(event.ControlDown())
3472 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse(): Mouse Wheel / double touch + control (OSX: command)",2)
3475 GetClientSize(& width, & height);
3476 const
int delta=event.GetWheelDelta();
3477 const
int rotation=event.GetWheelRotation();
3479 if(event.GetWheelAxis()==0) mDist *= (1.+
float(rotation)/100.);
3482 mDist /= (1.+float(rotation)/100.);
3483 mViewAngle *=(1.+float(rotation)/100.);
3486 glMatrixMode(GL_PROJECTION);
3488 if( (width>0)&&(height>0))
3489 gluPerspective(mViewAngle,(
float)width/(
float)height,
3490 (mDist>101)?(mDist-100):1.,mDist+100);
3492 VFN_DEBUG_MESSAGE(mViewAngle <<
" "<<mDist,2)
3496 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnMouse(): Mouse Wheel / double touch",2)
3499 GetClientSize(& width, & height);
3500 const
int delta=event.GetWheelDelta();
3502 if(event.GetWheelAxis()==1) dx=-event.GetWheelRotation();
3503 else dy=event.GetWheelRotation();
3505 trackball(spin_quat,
3506 (2.0*mTrackBallLastX - width) / (width+.001),
3507 ( height - 2.0*mTrackBallLastY) / (height+.001),
3508 (2.0*(mTrackBallLastX+dx) - width) / (width+.001),
3509 ( height - 2.0*(mTrackBallLastY+dy)) / (height+.001));
3511 add_quats( spin_quat, mQuat, mQuat );
3516 mTrackBallLastX = event.GetX();
3517 mTrackBallLastY = event.GetY();
3521 void WXGLCrystalCanvas::OnUpdate(wxCommandEvent & WXUNUSED(event))
3523 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnUpdate()",4)
3524 mpWXCrystal->UpdateGL(false,
3525 mcellbbox.xMin,mcellbbox.xMax,
3526 mcellbbox.yMin,mcellbbox.yMax,
3527 mcellbbox.zMin,mcellbbox.zMax);
3528 VFN_DEBUG_EXIT("WXGLCrystalCanvas::OnUpdate()",4)
3531 void WXGLCrystalCanvas::CrystUpdate()
3534 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::CrystUpdate():"<<wxThread::IsMain(),10)
3536 if(mpFourierMapListWin!=0) mpFourierMapListWin->mMutex.Lock();
3538 for(vector<boost::shared_ptr<UnitCellMap> >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();)
3541 if((*pos)->GetType()==3) keep=
true;
3542 if(((*pos)->GetType()==0)||((*pos)->GetType()==2))
3549 if(mpWXCrystal->GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0)
3550 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
3551 if((*pos)->GetData()->GetFhklObsSq().numElements()>0)
3554 if((*pos)->GetType()==1)
3556 if(mpWXCrystal->GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0)
3557 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
3560 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::CrystUpdate()"<<(*pos)->GetName()<<(*pos)->GetType()<<
": keep="<<keep,8)
3564 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
3565 posgl=mvpUnitCellMapGLList.begin();posgl!=mvpUnitCellMapGLList.end();)
3567 if(&(**pos)==&((*posgl)->GetMap()))
3569 VFN_DEBUG_MESSAGE(
"Erasing GL map:"<<(*posgl)->GetName(),8)
3570 posgl=mvpUnitCellMapGLList.erase(posgl);
3573 pos=mvpUnitCellMap.erase(pos);
3577 if((*pos)->GetType()!=3)
3581 if( (mvpUnitCellMapGLList.size()>0)
3582 ||(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3583 ||(mpFourierMapListWin!=0))
3584 (*pos)->CalcFourierMap(*((*pos)->GetData()),(*pos)->GetType(),mSharpenMap);
3592 if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
3593 for(
int i=0;i<mpWXCrystal->GetCrystal().GetClientRegistry().GetNb();++i)
3595 ScatteringData* data=
dynamic_cast<ScatteringData *
>(&(mpWXCrystal->GetCrystal().GetClientRegistry().GetObj(i)));
3600 bool addCalcMap=
true,addObsDiffMaps=
true;
3601 for(vector<boost::shared_ptr<UnitCellMap> >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos)
3602 if((*pos)->GetData()==data)
3604 if((*pos)->GetType()==1) addCalcMap=
false;
3605 if((*pos)->GetType()==0) addObsDiffMaps=
false;
3609 if(addCalcMap&&(data->GetNbRefl()>0))
3611 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(
new UnitCellMap(mpWXCrystal->GetCrystal())));
3612 mvpUnitCellMap.back()->CalcFourierMap(*data,1);
3613 VFN_DEBUG_MESSAGE(
"Added GL map:"<<mvpUnitCellMap.back()->GetName(),8)
3615 if(addObsDiffMaps && (data->GetFhklObsSq().numElements()>0) )
3617 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(
new UnitCellMap(mpWXCrystal->GetCrystal())));
3618 mvpUnitCellMap.back()->CalcFourierMap(*data,0);
3619 VFN_DEBUG_MESSAGE(
"Added GL map:"<<mvpUnitCellMap.back()->GetName()<<
":"<<data->GetFhklObsSq().numElements(),8)
3620 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(
new UnitCellMap(mpWXCrystal->GetCrystal())));
3621 mvpUnitCellMap.back()->CalcFourierMap(*data,2);
3622 VFN_DEBUG_MESSAGE(
"Added GL map:"<<mvpUnitCellMap.back()->GetName()<<
":"<<data->GetFhklObsSq().numElements(),8)
3628 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
3629 pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos)
3634 if(mpFourierMapListWin!=0) mpFourierMapListWin->mMutex.Unlock();
3635 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::CrystUpdate()",10)
3637 wxUpdateUIEvent event(ID_GLCRYSTAL_UPDATEUI);
3638 wxPostEvent(this,event);
3651 void WXGLCrystalCanvas::OnUpdateUI(wxUpdateUIEvent&event)
3653 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::OnUpdateUI()",5)
3654 if(mpFourierMapListWin!=0)
3656 mpFourierMapListWin->mIsUpdating=
true;
3657 mpFourierMapListWin->mMutex.Lock();
3660 for(vector<boost::shared_ptr<UnitCellMap> >::iterator
3661 pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos)
3662 maps.Add( wxString::FromAscii((*pos)->GetName().c_str()));
3663 if(mpFourierMapListWin->mpAvailableMapList->GetStrings()!=maps)
3664 mpFourierMapListWin->mpAvailableMapList->Set(maps);
3666 wxArrayString glmaps;
3667 for(vector<boost::shared_ptr<UnitCellMapGLList> >::iterator
3668 pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos)
3669 glmaps.Add( wxString::FromAscii((*pos)->GetName().c_str()));
3670 if(mpFourierMapListWin->mpDisplayedMapList->GetStrings()!=glmaps)
3671 mpFourierMapListWin->mpDisplayedMapList->Set(glmaps);
3673 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0)
3675 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
3676 mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T(
"min=%5.2f max=%5.2f sigma=%5.2f"),
3677 pMap->Min(),pMap->Max(),pMap->StandardDeviation()));
3679 mpFourierMapListWin->mMutex.Unlock();
3680 mpFourierMapListWin->mIsUpdating=
false;
3682 this->Refresh(
false);
3684 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::OnUpdateUI()",5)
3687 void WXGLCrystalCanvas::SetCurrent()
3689 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::SetCurrent()",4)
3690 this->wxGLCanvas::SetCurrent(*mpwxGLContext);
3692 this->BuildGLFont();
3693 sFontDisplayListBase=mGLFontDisplayListBase;
3695 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::SetCurrent()",4)
3698 void WXGLCrystalCanvas::NotifyDeleteFourierWin()
3700 mpFourierMapListWin=0;
3703 void WXGLCrystalCanvas::InitGL()
3706 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
3707 wxPostEvent(
this,event);
3709 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::InitGL()",8)
3712 static bool needglutinit=
true;
3717 char **argv=
new char*;
3719 glutInit(&argc,argv);
3724 GetClientSize(& width, & height);
3725 glViewport(0, 0, width, height);
3727 glEnable(GL_DEPTH_TEST);
3728 glEnable(GL_ALPHA_TEST);
3729 glEnable(GL_LIGHTING);
3730 glEnable (GL_BLEND);
3731 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3733 const GLfloat colour_Ambient [] = {0.4, 0.4, 0.4, 1.00};
3734 const GLfloat colour_Diffuse [] = {0.6, 0.6, 0.6, 1.00};
3735 const GLfloat colour_Specular[] = {0.2, 0.2, 0.2, 1.00};
3737 glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
3739 const GLfloat LightPosition[]= { -10.0f, 10.0f, 10.0f, 0.0f };
3740 glLightfv(GL_LIGHT1, GL_AMBIENT, colour_Ambient);
3741 glLightfv(GL_LIGHT1, GL_DIFFUSE, colour_Diffuse);
3742 glLightfv(GL_LIGHT1, GL_SPECULAR, colour_Specular);
3743 glLightfv(GL_LIGHT1, GL_SHININESS,colour_Specular);
3744 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
3745 glEnable(GL_LIGHT1);
3747 glEnable(GL_NORMALIZE);
3748 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
3749 glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
3751 if(sGLCrystalConfig.mSaved==
false)
3754 trackball(mQuat,0.,0.,0.,0.);
3757 wxPostEvent(
this,ev);
3760 this->CrystUpdate();
3761 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::InitGL()",8)
3763 void WXGLCrystalCanvas::OnChangeLimits(wxCommandEvent &event)
3765 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits()",10)
3766 if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_FULLCELL)
3774 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
3775 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
3777 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
3781 if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL)
3783 mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin();
3784 mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin();
3785 mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin();
3786 mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax();
3787 mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax();
3788 mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax();
3789 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
3790 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
3792 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
3796 if(event.GetId()==ID_GLCRYSTAL_MENU_CHANGELIMITS)
3798 UserSelectBoundingBox *BoxDlg =
new UserSelectBoundingBox(
this,
3799 "Set bounding box for display of\natoms (fractional coordinates)",
3801 if (BoxDlg->ShowModal() == wxID_OK )
3803 mcellbbox = BoxDlg->GetBBox();
3804 mpWXCrystal->UpdateGL(
false,
3805 mcellbbox.xMin,mcellbbox.xMax,
3806 mcellbbox.yMin,mcellbbox.yMax,
3807 mcellbbox.zMin,mcellbbox.zMax);
3808 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
3809 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
3811 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
3814 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits (X: " <<
3815 mcellbbox.xMin <<
", " << mcellbbox.xMax <<
3817 mcellbbox.yMin <<
", " << mcellbbox.yMax <<
3819 mcellbbox.zMin <<
", " << mcellbbox.zMax <<
3824 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3825 mpWXCrystal->UpdateGL(
false,
3826 mcellbbox.xMin,mcellbbox.xMax,
3827 mcellbbox.yMin,mcellbbox.yMax,
3828 mcellbbox.zMin,mcellbbox.zMax);
3830 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnChangeLimits():UserSelectBoundingBox done",10)
3833 void WXGLCrystalCanvas::OnShowCrystal( wxCommandEvent & WXUNUSED(event))
3835 if(mShowCrystal) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Show Crystal"));
3836 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T(
"Hide Crystal"));
3837 mShowCrystal = !mShowCrystal;
3838 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
3841 void WXGLCrystalCanvas::OnShowAtomLabel( wxCommandEvent & WXUNUSED(event))
3843 if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Show Atom Labels"));
3844 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T(
"Hide Atom Labels"));
3845 mShowAtomName= !mShowAtomName;
3846 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
3849 void WXGLCrystalCanvas::OnShowHydrogens( wxCommandEvent & WXUNUSED(event))
3851 if(mShowHydrogens) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Show Hydrogens"));
3852 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T(
"Hide Hydrogens"));
3853 mShowHydrogens= !mShowHydrogens;
3854 if(!(mpWXCrystal->GetCrystal().IsBeingRefined()))
3856 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE);
3857 wxPostEvent(
this,event);
3861 bool WXGLCrystalCanvas::GetShowHydrogens()
const {
return mShowHydrogens;}
3863 void WXGLCrystalCanvas::OnShowCursor( wxCommandEvent & WXUNUSED(event))
3865 if(mShowCursor) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Show Cursor"));
3866 else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T(
"Hide Cursor"));
3867 mShowCursor= !mShowCursor;
3868 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
3871 void WXGLCrystalCanvas::OnSetCursor( wxCommandEvent & WXUNUSED(event))
3873 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnSetCursor",1)
3877 mpWXCrystal->GetCrystal().OrthonormalToFractionalCoords(x,y,z);
3879 mViewCntr.x = (mcellbbox.xMax+mcellbbox.xMin)/2. - x;
3880 mViewCntr.y = (mcellbbox.yMax+mcellbbox.yMin)/2. - y;
3881 mViewCntr.z = (mcellbbox.zMax+mcellbbox.zMin)/2. - z;
3882 UserXYZBox *BoxDlg = new UserXYZBox(this,
3883 wxString("Set fractional coordinates for view\ncenter and cursor position"),
3885 if (BoxDlg->ShowModal() == wxID_OK ) {
3886 mViewCntr = BoxDlg->GetXYZ();
3887 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::OnSetCursor (frac) = " <<
3888 mViewCntr.x <<
"," << mViewCntr.y <<
"," << mViewCntr.z,1)
3889 mX0 = (mcellbbox.xMax+mcellbbox.xMin)/2. - mViewCntr.x;
3890 mY0 = (mcellbbox.yMax+mcellbbox.yMin)/2. - mViewCntr.y;
3891 mZ0 = (mcellbbox.zMax+mcellbbox.zMin)/2. - mViewCntr.z;
3892 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(mX0, mY0, mZ0);
3893 VFN_DEBUG_MESSAGE("...ortho" << mX0 << "," << mY0 << "," << mZ0,1)
3897 void WXGLCrystalCanvas::OnFourier(wxCommandEvent &event)
3899 if(event.GetId()==ID_GLCRYSTAL_MENU_FOURIER)
3901 if(mpFourierMapListWin!=0)
return;
3902 if(mpWXCrystal->GetCrystal().IsBeingRefined())
3904 wxMessageBox(_T(
"The Fourier maps dialog \ncannot be opened during an optimization"), _T(
"Error"), wxOK,
this);
3907 wxFrame *frame=
new wxMiniFrame(
this,-1, wxString::FromAscii((
"Available Fourier maps for "+mpWXCrystal->GetCrystal().GetName()).c_str()),
3908 wxDefaultPosition,wxSize(500,500),wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU);
3909 mpFourierMapListWin=
new WXFourierMapList(
this,frame);
3910 mpFourierMapListWin->mpWireFrame->SetValue(
true);
3911 mpFourierMapListWin->mpShowFourier->SetValue(mShowFourier);
3912 mpFourierMapListWin->mpSharpenMap->SetValue(mSharpenMap);
3914 mpWXCrystal->GetCrystal().UpdateDisplay();
3917 if(mpFourierMapListWin==0)
return;
3918 if(mpFourierMapListWin->mIsUpdating)
return;
3919 if( (event.GetId()==ID_GLCRYSTAL_FOURIER_UPDATE)
3920 ||(event.GetId()==ID_GLCRYSTAL_FOURIER_CONTOUR))
3922 mpFourierMapListWin->mMutex.Lock();
3924 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
3925 if(wxNOT_FOUND!=choice)
3928 mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour);
3929 wxColour col(mpFourierMapListWin->mpColourPicker->GetColour());
3930 if(abs((
float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001)
3932 mvpUnitCellMapGLList[choice]->SetContour((
float)contour);
3933 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
3935 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
3936 mvpUnitCellMapGLList[choice]->GenList();
3939 mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5);
3941 mpFourierMapListWin->mMutex.Unlock();
3944 if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTMAP)
3946 mpFourierMapListWin->mMutex.Lock();
3947 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0)
3949 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
3950 mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T(
"min=%5.2f max=%5.2f sigma=%5.2f"),
3951 pMap->Min(),pMap->Max(),pMap->StandardDeviation()));
3953 mpFourierMapListWin->mMutex.Unlock();
3955 if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTGLMAP)
3957 mpFourierMapListWin->mMutex.Lock();
3958 if(mpFourierMapListWin->mpDisplayedMapList->GetSelection()>=0)
3960 boost::shared_ptr<UnitCellMapGLList> pMap=mvpUnitCellMapGLList[mpFourierMapListWin->mpDisplayedMapList->GetSelection()];
3961 mpFourierMapListWin->mpContourValue->SetValue(wxString::Format(_T(
"%5.2f"),pMap->GetContour()));
3962 mpFourierMapListWin->mpColourPicker->SetColour(wxColour(pMap->GetColour()[0]*255,pMap->GetColour()[1]*255,
3963 pMap->GetColour()[2]*255,pMap->GetColour()[3]*255));
3965 mpFourierMapListWin->mMutex.Unlock();
3967 if((event.GetId()==ID_GLCRYSTAL_FOURIER_ADD)||(event.GetId()==ID_GLCRYSTAL_FOURIER_NEWCONTOUR))
3969 mpFourierMapListWin->mMutex.Lock();
3970 if(mpFourierMapListWin->mpAvailableMapList->GetSelection()!=wxNOT_FOUND)
3972 boost::shared_ptr<ObjCryst::UnitCellMap> pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()];
3974 wxString scontour=mpFourierMapListWin->mpNewContourValue->GetValue();
3975 if(scontour==_T(
"")) contour=pMap->Min()+pMap->StandardDeviation()*3;
3976 else scontour.ToDouble(&contour);
3977 wxColor ncolor(255,0,0);
3978 ncolor = wxGetColourFromUser((wxWindow*)
this, ncolor);
3980 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
3981 mvpUnitCellMapGLList.push_back(boost::shared_ptr<UnitCellMapGLList>(
new UnitCellMapGLList(*pMap,
this,
true,(
float)contour)));
3982 mvpUnitCellMapGLList.back()->SetName(pMap->GetName());
3983 mvpUnitCellMapGLList.back()->SetColour(ncolor.Red()/255.0,ncolor.Green()/255.0,ncolor.Blue()/255.0,0.5);
3984 mpFourierMapListWin->mMutex.Unlock();
3985 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
3988 mvpUnitCellMapGLList.back()->GenList();
3992 if(event.GetId()==ID_GLCRYSTAL_FOURIER_REMOVE)
3994 mpFourierMapListWin->mMutex.Lock();
3995 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
3996 if(wxNOT_FOUND!=choice)
3997 mvpUnitCellMapGLList.erase(mvpUnitCellMapGLList.begin()+choice);
3998 mpFourierMapListWin->mMutex.Unlock();
4000 if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHOW)
4002 mpFourierMapListWin->mMutex.Lock();
4003 mShowFourier=mpFourierMapListWin->mpShowFourier->GetValue();
4004 mpFourierMapListWin->mMutex.Unlock();
4006 if(event.GetId()==ID_GLCRYSTAL_FOURIER_WIREFRAME)
4008 mpFourierMapListWin->mMutex.Lock();
4009 vector<boost::shared_ptr<UnitCellMapGLList> >::iterator pos;
4010 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++)
4011 (*pos)->ToggleShowWire();
4012 mpFourierMapListWin->mMutex.Unlock();
4015 if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHARPEN)
4017 mpFourierMapListWin->mMutex.Lock();
4018 mSharpenMap=mpFourierMapListWin->mpSharpenMap->GetValue();
4019 mpFourierMapListWin->mMutex.Unlock();
4023 if(
false==mpWXCrystal->GetCrystal().IsBeingRefined())
4024 this->CrystUpdate();
4027 void WXGLCrystalCanvas::OnLoadFourierGRD( wxCommandEvent & WXUNUSED(event))
4029 wxFileDialog fd((wxWindow*)
this, _T(
"Choose a file containing a Fourier Map"),
4030 _T(
""), _T(
""), _T(
"Fourier Map files (*.grd)|*.grd"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
4032 if(fd.ShowModal() == wxID_OK)
4034 const string filename(fd.GetPath().ToAscii());
4035 UnitCellMap *pMap=
new UnitCellMap(mpWXCrystal->GetCrystal());
4036 if (pMap->ImportGRD(filename) == 0)
4038 string tmp=
"Error reading Fourier file:"+filename;
4039 wxMessageBox( wxString::FromAscii(tmp.c_str()), _T(
"File error"), wxOK,
this);
4042 this->AddFourier(pMap);
4046 void WXGLCrystalCanvas::OnLoadFourierDSN6( wxCommandEvent & WXUNUSED(event))
4048 wxFileDialog fd((wxWindow*)
this, _T(
"Choose a file containing a Fourier Map"),
4049 _T(
""), _T(
""), _T(
"Fourier Map files (*.DN6)|*.DN6"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
4051 if(fd.ShowModal() == wxID_OK)
4053 const string filename(fd.GetPath().ToAscii());
4054 UnitCellMap *pMap=
new UnitCellMap(mpWXCrystal->GetCrystal());
4055 if (pMap->ImportDSN6(filename) == 0)
4057 string tmp=
"Error reading Fourier file:"+filename;
4058 wxMessageBox( wxString::FromAscii(tmp.c_str()), _T(
"File error"), wxOK,
this);
4061 this->AddFourier(pMap);
4065 void WXGLCrystalCanvas::AddFourier(UnitCellMap *map)
4067 mvpUnitCellMap.push_back(boost::shared_ptr<UnitCellMap>(map));
4068 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4070 float contour=map->Mean()+2*map->StandardDeviation();
4071 if(contour>map->Max()) contour=map->Mean()+0.75*(map->Max()-map->Mean());
4072 mvpUnitCellMapGLList.push_back(boost::shared_ptr<UnitCellMapGLList>(
new UnitCellMapGLList(*map,
this)));
4073 switch(mvpUnitCellMapGLList.size())
4075 case 1: mvpUnitCellMapGLList.back()->SetColour(1.,0.,0.,.5);
break;
4076 case 2: mvpUnitCellMapGLList.back()->SetColour(0.,0.,1.,.5);
break;
4077 default:mvpUnitCellMapGLList.back()->SetColour(0.,1.,0.,.5);
break;
4080 mvpUnitCellMapGLList.back()->GenList();
4081 mvpUnitCellMapGLList.back()->SetName(map->GetName());
4083 if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate();
4087 void WXGLCrystalCanvas::OnFourierChangeColour(wxColourPickerEvent &event)
4089 mpFourierMapListWin->mMutex.Lock();
4091 unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection();
4092 if(wxNOT_FOUND!=choice)
4095 mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour);
4096 wxColour col(mpFourierMapListWin->mpColourPicker->GetColour());
4097 if(abs((
float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001)
4099 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4100 mvpUnitCellMapGLList[choice]->SetContour((
float)contour);
4101 mvpUnitCellMapGLList[choice]->GenList();
4103 mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5);
4105 mpFourierMapListWin->mMutex.Unlock();
4106 mpWXCrystal->GetCrystal().UpdateDisplay();
4135 void WXGLCrystalCanvas::OnPOVRay( wxCommandEvent & WXUNUSED(event))
4138 wxFileDialog save(
this,_T(
"Choose filename"),_T(
""),_T(
""),_T(
"*.pov"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
4139 if(save.ShowModal() != wxID_OK)
return;
4140 this->POVRayOutput(
string(save.GetPath().char_str()));
4143 void WXGLCrystalCanvas::POVRayOutput(
const std::string &filename)
4145 ofstream os(filename.c_str());
4147 os <<
"#version 3.6 ;"<<endl
4148 <<
"// This File was created by FOX/ObjCryst++ (http://objcryst.sf.net)"<<endl
4150 <<
"// You can produce a ray-traced image using POV-Ray, freely available"<<endl
4151 <<
"//from http://www.povray.org"<<endl
4153 <<
"// Example command line to produce an anti-aliase 640x480 image: "<<endl
4154 <<
"// povray +Ifile.pov +.pov +W640 +H480 +A +Q11"<<endl
4155 <<
"// You can add '+UA' at the end to have a transparent background"<<endl
4156 <<
"// You can add '+kff10' to generate 10 rotated images for an animation"<<endl
4157 <<
"// (see the 'clock' in the 'OrientPitch' definition below)"<<endl
4159 <<
"// Notes:"<<endl
4160 <<
"// - This POVRay file is written to produce a 4/3 image, e.g. 640x480"<<endl
4161 <<
"// If your image in the FOX 3D view was not 4/3, some parts may be cut"<<endl
4162 <<
"// You can then get the full structure by increasing the 'angle' "<<endl
4163 <<
"// (viewing angle) in the camera settings below."<<endl
4164 <<
"// You can change the aspect ratio (e.g. to produce a square image)"<<endl
4165 <<
"// by changing the 'right <-1.33,0,0>' statement in the camera definition"<<endl
4166 <<
"// - You can change the orientation of the view by changing the"<<endl
4167 <<
"// OrientRoll, OrientPitch and OrientYaw angles just below (in degrees)"<<endl
4168 <<
"// - You can change the aspects of atoms by altering the macros below."<<endl
4169 <<
"// The radius of atoms is by default 1/3 of their tabulated atomic radius,"<<endl
4170 <<
"// i.e. as in the FOX/ObjCryst++ 3D Crystal view. To modify this you can"<<endl
4171 <<
"// change the second line of the 'ObjCrystAtom' macro to (e.g. for full radius):"<<endl
4172 <<
"// '{ <atomx,atomy,atomz>,atomr*1.0'"<<endl
4173 <<
"// - The colour of atoms, bonds (free and non-free torsions) can be changed"<<endl
4174 <<
"// in the 'GLOBAL DECLARATIONS FOR ATOMS & BONDS' section"<<endl
4175 <<
"// - Just for fun, you can try getting *very close* to one of the atoms,"<<endl
4176 <<
"// and, in the 'ObjCrystAtom' macro at the end of the 'finish'"<<endl
4177 <<
"// statement, change the 'reflection' value to 1.0, "<<endl
4178 <<
"// to get a mirror effect on the atoms..."<<endl
4180 <<
"// See http://povray.org/documentation/ for more options"<<endl
4181 <<
"//"<<endl<<endl;
4183 os <<
"// Description of Crystal :" << mpWXCrystal->GetCrystal().GetName() <<endl;
4184 os <<
"global_settings { assumed_gamma 2.2 ambient_light rgb <1,1,1>}"<<endl;
4186 REAL xcam=0,ycam=0,zcam=mDist;
4187 build_rotmatrix( m,mQuat);
4189 REAL x=(mcellbbox.xMin+mcellbbox.xMax)/2.;
4190 REAL y=(mcellbbox.yMin+mcellbbox.yMax)/2.;
4191 REAL z=(mcellbbox.zMin+mcellbbox.zMax)/2.;
4192 mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(x,y,z);
4197 const REAL q1=mQuat[0];
const REAL q2=mQuat[1];
4198 const REAL q3=mQuat[2];
const REAL q4=mQuat[3];
4200 REAL yaw =(q4*q4 + q1*q1 - q2*q2 - q3*q3);
4201 if(abs(yaw)>1e-6) yaw =atan( 2*(q1*q2+q4*q3) /yaw )*RAD2DEG;
4202 else {
if((q1*q2+q4*q3)>0) yaw =90.;
else yaw =-90;}
4204 const REAL pitch=asin(-2*(q1*q3-q4*q2))*RAD2DEG;
4206 REAL roll=(q4*q4 - q1*q1 - q2*q2 + q3*q3);
4207 if(abs(roll)>1e-6) roll =atan( 2*(q4*q1+q2*q3) /roll)*RAD2DEG;
4208 else {
if((q4*q1+q2*q3)>0) roll=90.;
else roll=-90;}
4210 if((q4*q4 + q1*q1 - q2*q2 - q3*q3)<0) yaw +=180;
4211 if((q4*q4 - q1*q1 - q2*q2 + q3*q3)<0) roll +=180;
4214 os <<
"#declare OrientRoll="<<roll<<
";"<<endl;
4215 os <<
"#declare OrientPitch="<<pitch<<
"+360*clock;"<<endl;
4216 os <<
"#declare OrientYaw="<<yaw<<
";"<<endl<<endl;
4219 os <<
"camera" <<endl;
4221 os <<
" location <"<<xcam+x<<
","<<ycam+y<<
","<<zcam+z<<
">"<<endl
4222 <<
" look_at <" << x <<
"," << y <<
"," << z <<
">"<<endl
4223 <<
" angle "<< mViewAngle*1.2 <<endl
4224 <<
" right <-1.33,0,0> //change handedness as in OpenGL, aspect ratio=4/3"<<endl
4225 <<
" translate <" <<-x <<
"," <<-y <<
"," <<-z <<
">"<<endl
4226 <<
" rotate <OrientRoll,0,0>" <<endl
4227 <<
" rotate <0,OrientPitch,0>" <<endl
4228 <<
" rotate <0,0,OrientYaw>" <<endl
4229 <<
" translate <" << x <<
"," << y <<
"," << z <<
">"<<endl
4232 REAL xlight=-1000,ylight=1000,zlight=1000;
4233 os <<
"light_source"<<endl;
4235 <<
" <"<<xlight<<
","<<ylight<<
","<<zlight<<
">"<<endl
4236 <<
" colour rgb <1.0,1.0,1.0>" <<endl
4237 <<
" //shadowless" <<endl
4238 <<
" translate <" <<-x <<
"," <<-y <<
"," <<-z <<
">"<<endl
4239 <<
" rotate <OrientRoll,0,0>" <<endl
4240 <<
" rotate <0,OrientPitch,0>" <<endl
4241 <<
" rotate <0,0,OrientYaw>" <<endl
4242 <<
" translate <" << x <<
"," << y <<
"," << z <<
">"<<endl
4243 <<
"}" <<endl<<endl;
4245 os <<
"background { colour rgb <0.0, 0.0, 0.0> }"<<endl<<endl;
4247 CrystalPOVRayOptions options;
4248 options.mXmin=mcellbbox.xMin;
4249 options.mXmax=mcellbbox.xMax;
4250 options.mYmin=mcellbbox.yMin;
4251 options.mYmax=mcellbbox.yMax;
4252 options.mZmin=mcellbbox.zMin;
4253 options.mZmax=mcellbbox.zMax;
4254 options.mShowLabel=mShowAtomName;
4255 options.mShowHydrogens=mShowHydrogens;
4258 mpWXCrystal->GetCrystal().POVRayDescription(os,options);
4262 wxBusyInfo wait(_T(
"Processing Fourier Map..."));
4264 if (mmapbbox.xMin != mmapbbox.xMax)
4266 options.mXmin=mmapbbox.xMin;
4267 options.mXmax=mmapbbox.xMax;
4268 options.mYmin=mmapbbox.yMin;
4269 options.mYmax=mmapbbox.yMax;
4270 options.mZmin=mmapbbox.zMin;
4271 options.mZmax=mmapbbox.zMax;
4274 os<<
"/////////////////// FOURIER MAPS///////////////////////////"<<endl;
4275 vector<boost::shared_ptr<UnitCellMapGLList> >::const_iterator pos;
4276 for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos)
4278 const float *prgbf=(*pos)->GetColour();
4279 if((*pos)->ShowWire())
4281 os <<
"#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3,"
4282 <<
"nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<<endl
4283 <<
" cylinder"<<endl
4284 <<
" { <x1,y1,z1>,"<<endl
4285 <<
" <x2,y2,z2>,"<<endl
4287 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4288 <<
" pigment { colour rgb<"
4289 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4290 <<
" no_shadow"<<endl
4292 <<
" cylinder"<<endl
4293 <<
" { <x2,y2,z2>,"<<endl
4294 <<
" <x3,y3,z3>,"<<endl
4296 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4297 <<
" pigment { colour rgb<"
4298 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4299 <<
" no_shadow"<<endl
4301 <<
" cylinder"<<endl
4302 <<
" { <x1,y1,z1>,"<<endl
4303 <<
" <x3,y3,z3>,"<<endl
4305 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4306 <<
" pigment { colour rgb<"
4307 <<*(prgbf+0)<<
","<<*(prgbf+1)<<
","<<*(prgbf+2)<<
">}"<<endl
4308 <<
" no_shadow"<<endl
4310 <<
"#end"<<endl<<endl;
4311 (*pos)->GetMap().POVRayDescription(os,(*pos)->GetContour(),options);
4315 os <<
"#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3,"
4316 <<
"nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<<endl
4317 <<
" smooth_triangle"<<endl
4318 <<
" {<x1,y1,z1>,<nx1,ny1,nz1>"<<endl
4319 <<
" <x2,y2,z2>,<nx2,ny2,nz2>"<<endl
4320 <<
" <x3,y3,z3>,<nx3,ny3,nz3>}"<<endl
4321 <<
"#end"<<endl<<endl;
4324 (*pos)->GetMap().POVRayDescription(os,(*pos)->GetContour(),options);
4325 os <<
" texture"<<endl
4327 <<
" finish {ambient 0.5 diffuse 0.4}"<<endl
4328 <<
" pigment { colour rgb<"
4331 os <<*prgbf++<<
">}"<<endl
4333 <<
" no_shadow"<<endl
4343 BBox WXGLCrystalCanvas::GetCellBBox() {
4347 BBox WXGLCrystalCanvas::GetMapBBox() {
4351 void WXGLCrystalCanvas::UnProject(REAL &x, REAL &y, REAL &z)
4353 GLdouble vx,vy,vz,junk;
4355 GLdouble modelMatrix[16];
4356 GLdouble projMatrix[16];
4360 glMatrixMode( GL_MODELVIEW );
4362 glTranslatef( 0, 0, -mDist );
4364 glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
4365 glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
4366 glGetIntegerv(GL_VIEWPORT,viewport);
4369 gluProject(0, 0, 0 ,modelMatrix,projMatrix,viewport,&junk,&junk,&z0);
4371 gluUnProject(x,y,z0,modelMatrix,projMatrix,viewport,&vx,&vy,&vz);
4375 build_rotmatrix( m,mQuat);
4377 x= m[0][0]* vx + m[0][1]*vy + m[0][2]*vz -mX0;
4378 y= m[1][0]* vx + m[1][1]*vy + m[1][2]*vz -mY0;
4379 z= m[2][0]* vx + m[2][1]*vy + m[2][2]*vz -mZ0;
4380 VFN_DEBUG_MESSAGE(
"WXGLCrystalCanvas::UnProject():X Y Z = "<<x<<
" , "<<y<<
" , "<<z,5)
4383 void WXGLCrystalCanvas::BuildGLFont()
4385 if(mIsGLFontBuilt)
return;
4386 VFN_DEBUG_ENTRY(
"WXGLCrystalCanvas::BuildGLFont()-gldisplay",6)
4389 XFontStruct *fontInfo=NULL;
4391 mGLFontDisplayListBase = glGenLists(96);
4393 dpy = XOpenDisplay(NULL);
4395 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-bold-*-r-*-10-*-*-*-*-*-*-*");
4396 if (fontInfo == NULL)
4397 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-bold-*-*-*-10-*-*-*-*-*-*-*");
4398 if (fontInfo == NULL)
4399 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-bold-*-r-*-10-*-*-*-*-*-*-*");
4400 if (fontInfo == NULL)
4401 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-medium-*-*-*-12-*-*-*-*-*-*-*");
4402 if (fontInfo == NULL)
4403 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-medium-*-*-*-12-*-*-*-*-*-*-*");
4404 if (fontInfo == NULL)
4405 fontInfo = XLoadQueryFont(dpy,
"-adobe-helvetica-*-*-*-*-12-*-*-*-*-*-*-*");
4406 if (fontInfo == NULL)
4407 fontInfo = XLoadQueryFont(dpy,
"-adobe-times-*-*-*-*-12-*-*-*-*-*-*-*");
4408 if (fontInfo == NULL)
4409 fontInfo = XLoadQueryFont(dpy,
"fixed");
4410 if (fontInfo == NULL) cout <<
"no X font available..."<<endl;
4412 glXUseXFont(fontInfo->fid, 32, 96, mGLFontDisplayListBase);
4413 XFreeFont(dpy, fontInfo);
4420 HDC hDC = (HDC)dc.GetHDC();
4422 wxSize s = dc.GetPPI();
4423 int height = int(round(3 * (s.GetHeight() + s.GetWidth()) / 2 / 25.4));
4424 mGLFontDisplayListBase = 100;
4425 font = CreateFont(-height,
4435 CLIP_DEFAULT_PRECIS,
4436 ANTIALIASED_QUALITY,
4437 FF_DONTCARE|DEFAULT_PITCH,
4440 oldfont = (HFONT)SelectObject(hDC, font);
4441 wglUseFontBitmaps(hDC, 0, 128, mGLFontDisplayListBase);
4442 SelectObject(hDC, oldfont);
4445 mIsGLFontBuilt=
true;
4446 sFontDisplayListBase=mGLFontDisplayListBase;
4447 VFN_DEBUG_EXIT(
"WXGLCrystalCanvas::BuildGLFont()",6)
4450 void WXGLCrystalCanvas::DeleteGLFont()
const
4452 if(!mIsGLFontBuilt)
return;
4453 glDeleteLists(mGLFontDisplayListBase, 96);
4454 mIsGLFontBuilt=
false;
4455 mGLFontDisplayListBase=0;
4465 BEGIN_EVENT_TABLE(UserSelectBoundingBox, wxDialog)
4466 EVT_BUTTON(wxID_OK, UserSelectBoundingBox::OnOk)
4469 UserSelectBoundingBox::UserSelectBoundingBox (wxWindow *parent, const
char * title,
4471 : wxDialog((wxWindow *)parent, -1, _T("Set bounding box"), wxDefaultPosition,
4472 wxSize(250, 250), wxDEFAULT_DIALOG_STYLE)
4474 wxBoxSizer *dialogSizer =
new wxBoxSizer(wxVERTICAL);
4475 wxFlexGridSizer *inputSizer =
new wxFlexGridSizer(4, 3, 10, 10);
4477 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"")), 0, wxALIGN_CENTRE_VERTICAL);
4478 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"minimum")), 0, wxALIGN_CENTER);
4479 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"maximum")), 0, wxALIGN_CENTER);
4481 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"a")), 0, wxALIGN_CENTRE_VERTICAL);
4482 inputSizer->Add(mpXminCtrl =
new wxTextCtrl(
this, -1,
4483 wxString::Format(_T(
"%f"),bbox.xMin)),
4484 0, wxALIGN_CENTRE_VERTICAL);
4485 inputSizer->Add(mpXmaxCtrl =
new wxTextCtrl(
this, -1,
4486 wxString::Format(_T(
"%f"),bbox.xMax)),
4487 0, wxALIGN_CENTRE_VERTICAL);
4489 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"b")), 0, wxALIGN_CENTRE_VERTICAL);
4490 inputSizer->Add(mpYminCtrl =
new wxTextCtrl(
this, -1,
4491 wxString::Format(_T(
"%f"),bbox.yMin)),
4492 0, wxALIGN_CENTRE_VERTICAL);
4493 inputSizer->Add(mpYmaxCtrl =
new wxTextCtrl(
this, -1,
4494 wxString::Format(_T(
"%f"),bbox.yMax)),
4495 0, wxALIGN_CENTRE_VERTICAL);
4497 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"c")), 0, wxALIGN_CENTRE_VERTICAL);
4498 inputSizer->Add(mpZminCtrl =
new wxTextCtrl(
this, -1,
4499 wxString::Format(_T(
"%f"),bbox.zMin)),
4500 0, wxALIGN_CENTRE_VERTICAL);
4501 inputSizer->Add(mpZmaxCtrl =
new wxTextCtrl(
this, -1,
4502 wxString::Format(_T(
"%f"),bbox.zMax)),
4503 0, wxALIGN_CENTRE_VERTICAL);
4505 wxFlexGridSizer *buttonSizer =
new wxFlexGridSizer(1, 2, 10, 10);
4506 buttonSizer->Add(
new wxButton(
this, wxID_OK, _T(
"OK")),
4507 0, wxALIGN_CENTRE_VERTICAL);
4508 buttonSizer->Add(
new wxButton(
this, wxID_CANCEL, _T(
"Cancel")),
4509 0, wxALIGN_CENTRE_VERTICAL);
4511 dialogSizer->Add(10, 10);
4512 dialogSizer->Add(
new wxStaticText(
this, -1, wxString::FromAscii(title)), 0,
4514 dialogSizer->Add(10, 10);
4515 dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER);
4516 dialogSizer->Add(20, 20);
4517 dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
4519 SetSizer(dialogSizer);
4520 SetAutoLayout(TRUE);
4524 UserSelectBoundingBox::~UserSelectBoundingBox () {
4531 void UserSelectBoundingBox::OnOk (wxCommandEvent & WXUNUSED(event)) {
4534 mpXminCtrl->GetValue().ToDouble(&val);
4536 mpXmaxCtrl->GetValue().ToDouble(&val);
4538 if (mbbox.xMin == mbbox.xMax) {wxMessageBox(_T(
"Sorry, Xmin must be less than Xmax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
4539 if (mbbox.xMin > mbbox.xMax) {
4540 float tmp = mbbox.xMax;
4541 mbbox.xMax = mbbox.xMin;
4544 VFN_DEBUG_MESSAGE(
"Xmin " << mbbox.xMin <<
" Xmax " << mbbox.xMax,1)
4546 mpYminCtrl->GetValue().ToDouble(&val);
4548 mpYmaxCtrl->GetValue().ToDouble(&val);
4550 if (mbbox.yMin == mbbox.yMax) {wxMessageBox(_T(
"Sorry, Ymin must be less than Ymax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
4551 if (mbbox.yMin > mbbox.yMax) {
4552 float tmp = mbbox.yMax;
4553 mbbox.yMax = mbbox.yMin;
4556 VFN_DEBUG_MESSAGE(
"Ymin " << mbbox.yMin <<
" Ymax " << mbbox.yMax,1)
4558 mpZminCtrl->GetValue().ToDouble(&val);
4560 mpZmaxCtrl->GetValue().ToDouble(&val);
4562 if (mbbox.zMin == mbbox.zMax) {wxMessageBox(_T(
"Sorry, Zmin must be less than Zmax!"), _T(
"Zero bounding volume"), wxOK,
this);
return;}
4563 if (mbbox.zMin > mbbox.zMax) {
4564 float tmp = mbbox.zMax;
4565 mbbox.zMax = mbbox.zMin;
4568 VFN_DEBUG_MESSAGE(
"Zmin " << mbbox.zMin <<
" Zmax " << mbbox.zMax,1)
4574 BBox UserSelectBoundingBox::GetBBox () {
4584 BEGIN_EVENT_TABLE(UserXYZBox, wxDialog)
4585 EVT_BUTTON(wxID_OK, UserXYZBox::OnOk)
4588 UserXYZBox::UserXYZBox (wxWindow *parent, const wxString &title,
4590 : wxDialog((wxWindow *)parent, -1, _T("Set position"), wxDefaultPosition,
4591 wxSize(250, 250), wxDEFAULT_DIALOG_STYLE)
4593 wxBoxSizer *dialogSizer =
new wxBoxSizer(wxVERTICAL);
4594 wxFlexGridSizer *inputSizer =
new wxFlexGridSizer(3, 2, 10, 10);
4596 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"x")), 0, wxALIGN_CENTRE_VERTICAL);
4597 inputSizer->Add(mpXCtrl =
new wxTextCtrl(
this, -1,
4598 wxString::Format(_T(
"%.3f"),xyz.x)),
4599 0, wxALIGN_CENTRE_VERTICAL);
4601 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"y")), 0, wxALIGN_CENTRE_VERTICAL);
4602 inputSizer->Add(mpYCtrl =
new wxTextCtrl(
this, -1,
4603 wxString::Format(_T(
"%.3f"),xyz.y)),
4604 0, wxALIGN_CENTRE_VERTICAL);
4606 inputSizer->Add(
new wxStaticText(
this, -1, _T(
"z")), 0, wxALIGN_CENTRE_VERTICAL);
4607 inputSizer->Add(mpZCtrl =
new wxTextCtrl(
this, -1,
4608 wxString::Format(_T(
"%.3f"),xyz.z)),
4609 0, wxALIGN_CENTRE_VERTICAL);
4611 wxFlexGridSizer *buttonSizer =
new wxFlexGridSizer(1, 2, 10, 10);
4612 buttonSizer->Add(
new wxButton(
this, wxID_OK, _T(
"OK")),
4613 0, wxALIGN_CENTRE_VERTICAL);
4614 buttonSizer->Add(
new wxButton(
this, wxID_CANCEL, _T(
"Cancel")),
4615 0, wxALIGN_CENTRE_VERTICAL);
4617 dialogSizer->Add(10, 10);
4618 dialogSizer->Add(
new wxStaticText(
this, -1, title), 0,
4620 dialogSizer->Add(10, 10);
4621 dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER);
4622 dialogSizer->Add(20, 20);
4623 dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
4625 SetSizer(dialogSizer);
4626 SetAutoLayout(TRUE);
4630 UserXYZBox::~UserXYZBox () {
4633 void UserXYZBox::OnOk (wxCommandEvent & WXUNUSED(event)) {
4637 val = mpXCtrl->GetValue().ToAscii();
4638 mXYZ.x = strtod(val, &strptr);
4639 if (val == strptr) {wxMessageBox(_T(
"Invalid value for X!"), _T(
"Position error"), wxOK,
this);
return;}
4641 val = mpYCtrl->GetValue().ToAscii();
4642 mXYZ.y = strtod(val, &strptr);
4643 if (val == strptr) {wxMessageBox(_T(
"Invalid value for Y!"), _T(
"Position error"), wxOK,
this);
return;}
4645 val = mpZCtrl->GetValue().ToAscii();
4646 mXYZ.z = strtod(val, &strptr);
4647 if (val == strptr) {wxMessageBox(_T(
"Invalid value for Z!"), _T(
"Position error"), wxOK,
this);
return;}
4653 Triple UserXYZBox::GetXYZ () {
4658 #endif // #ifdef OBJCRYST_GL
WXCrystal * mpWXCrystal
The WXCrystal window which created this window, and who should be told if it is destroyed.
T * WXDialogChooseFromRegistry(ObjRegistry< T > ®, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
void PrintMinDistanceTable(const REAL minDistance=0.1, ostream &os=cout) const
Print the minimum distance table between all scattering centers (atoms) in the crystal.
bool mIsSelfUpdating
Flag to indicate that we are updating values in the wxGrid data, and that it is not the user inputing...
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be...
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
bool OnChangeName(const int id)
When a WXFieldName has been changed by the user, it is handled here.
void Print(ostream &os=cout) const
Prints some info about the crystal.
Structure to store the scattering power parameters.
Simple chronometer class, with microsecond precision.
REAL GetBumpMergeCost() const
Get the Anti-bumping/pro-Merging cost function.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
std::map< wxWindowID, std::pair< wxPoint, wxSize > > gvWindowPosition
Used to remember window positions.
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
wxMutex mMutexGLUpdate
Mutex used when updating the OpenGL display List, between background and main thread.
void AddScatterer(Scatterer *scatt)
Add a scatterer to the crystal.
REAL GetBondValenceCost() const
Get the Bond-Valence cost function, which compares the expected valence to the one computed from Bond...
REAL GetBondAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3)
Get The Bond Angle of 3 atoms.
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
ObjRegistry< ScatteringPower > & GetScatteringPowerRegistry()
Get the registry of ScatteringPower included in this Crystal.
virtual void CIFOutput(ostream &os, double mindist=0.5) const
output Crystal structure as a cif file (EXPERIMENTAL !)
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
The Scattering Power for an Atom.
virtual void GLInitDisplayList(const bool onlyIndependentAtoms=false, const REAL xMin=-.1, const REAL xMax=1.1, const REAL yMin=-.1, const REAL yMax=1.1, const REAL zMin=-.1, const REAL zMax=1.1, const bool displayNames=false, const bool hideHydrogens=false) const
Create an OpenGL DisplayList of the crystal.
Molecule * ZScatterer2Molecule(ZScatterer *scatt)
Conversion from ZScatterer to the newer Molecule object. (in WXZScatterer.cpp)
wxCondition * mpConditionGLUpdate
wxCondition used when updating the OpenGL display List, between background and main thread ...
virtual const string & GetName() const
Name of the object.
Crystal class: Unit cell, spacegroup, scatterers.
void(* fpObjCrystInformUser)(const string &)
Pointer to a function for passing info to the user during or after long/important processes (use scar...
ScatteringPower & GetScatteringPower(const string &name)
Find a ScatteringPower from its name. Names must be unique in a given Crystal.
void AddScatteringPower(ScatteringPower *scattPow)
Add a ScatteringPower for this Crystal.
const RefParType * gpRefParTypeObjCryst
Top RefParType for the ObjCryst++ library.
void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
std::map< pair< const ScatteringPower *, const ScatteringPower * >, Crystal::BumpMergePar > VBumpMergePar
Anti-bump parameters.
virtual bool OnChangeName(const int id)
When a WXFieldName has been changed by the user, it is handled here.
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal...